New upstream version 1.1.0
IOhannes m zmölnig (Debian/GNU)
1 year, 9 months ago
14 | 14 | Since I (erikd), do almost zero Android development, I am happy accept patches |
15 | 15 | for this documentation and script to improve its utility for real Android |
16 | 16 | developers. |
17 | ||
18 | --- | |
19 | ||
20 | ## Using CMake | |
21 | ||
22 | (Tested on Linux) | |
23 | ||
24 | For convenience, export the following variables: | |
25 | ||
26 | ``` | |
27 | export ANDROID_ABI=arm64-v8a | |
28 | export ANDROID_PLATFORM_API_LEVEL=29 | |
29 | export NDK_ROOT=/path/to/android/ndk | |
30 | ``` | |
31 | ||
32 | Set `ANDROID_ABI`, `ANDROID_PLATFORM_API_LEVEL` according to your target system. Now cd into the libsndfile root directory, and run | |
33 | ||
34 | ``` | |
35 | cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake -DANDROID_ABI=$ANDROID_ABI -DANDROID_PLATFORM=$ANDROID_PLATFORM_API_LEVEL | |
36 | ``` | |
37 | ||
38 | cd into `build` and run make | |
39 | ||
40 | ``` | |
41 | cd build | |
42 | make [-j <number of parallel jobs>] | |
43 | ``` | |
44 | ||
45 | This will build libsndfile for android. |
0 | # Changelog | |
1 | ||
2 | All notable changes to this project will be documented in this file. | |
3 | ||
4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | |
5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | |
6 | ||
7 | ## [Unreleased] | |
8 | ||
9 | ## [1.1.0] - 2022-03-27 | |
10 | ||
11 | ### Added | |
12 | ||
13 | * MPEG Encode/Decode Support. | |
14 | ||
15 | Uses libmpg123 for decode, liblame for encode. Encoding and decoding support | |
16 | is independent of each other and is split into separate files. MPEG support | |
17 | is generalized as subformats, `SF_FORMAT_MPEG_LAYER`(I,II,III) so that it | |
18 | might be used by other containers (`MPEG1WAVEFORMAT` for example), but also | |
19 | contains a major format `SF_FORMAT_MPEG` for 'mp3 files.' | |
20 | ||
21 | Encoding Status: | |
22 | * Layer III encoding | |
23 | * ID3v1 writing | |
24 | * ID3v2 writing | |
25 | * Lame/Xing Tag writing | |
26 | * Bitrate selection command | |
27 | * VBR or CBR | |
28 | ||
29 | Decoding Status: | |
30 | * Layers I/II/III decoding | |
31 | * ID3v1 reading | |
32 | * ID3v2 reading | |
33 | * Seeking | |
34 | * New fuzzer for OSS-Fuzz, thanks @DavidKorczynski. | |
35 | * This `CHANGELOG.md`. All notable changes to this project will be documented in | |
36 | this file. The old `NEWS` file has been renamed to `NEWS.OLD` and is no longer | |
37 | updated. | |
38 | * Add support for decoding MPEG III Audio in WAV files. | |
39 | * `SECURITY.md` file to give people instructions for reporting security | |
40 | vulnerabilities, thanks @zidingz. | |
41 | * Support for [Vcpkg manifest mode](https://vcpkg.readthedocs.io/en/latest/users/manifests/). | |
42 | ||
43 | If you have problems with manifest mode, disable it with `VCPKG_MANIFEST_MODE` | |
44 | switch. | |
45 | * [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) | |
46 | * CIFuzz fuzzer, thanks to @AdamKorcz (PR #796) | |
47 | ||
48 | ### Changed | |
49 | ||
50 | * `SFC_SET_DITHER_ON_READ` and `SFC_SET_DITHER_ON_WRITE` enums comments in | |
51 | public header, thanks @SmiVan (issue #677). | |
52 | * `ENABLE_SNDFILE_WINDOWS_PROTOTYPES` define is deprecated and not needed | |
53 | anymore. | |
54 | ||
55 | Previously, in order for the [`sf_wchar_open`()](http://libsndfile.github.io/libsndfile/api.html#open) | |
56 | function to become available on the Windows platform, it was required to | |
57 | perform certain actions: | |
58 | ||
59 | ```c | |
60 | #include <windows.h> | |
61 | #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1 | |
62 | #including <sndfile.h> | |
63 | ``` | |
64 | ||
65 | These steps are no longer required and the `sf_wchar_open`() function is | |
66 | always available on the Windows platform. | |
67 | * Use UTF-8 as internal path encoding on Windows platform. | |
68 | ||
69 | This is an internal change to unify and simplify the handling of file paths. | |
70 | ||
71 | On the Windows platform, the file path is always converted to UTF-8 and | |
72 | converted to UTF-16 only for calls to WinAPI functions. | |
73 | ||
74 | The behavior of the functions for opening files on other platforms does not | |
75 | change. | |
76 | * Switch to .xz over .bz2 for release tarballs. | |
77 | * Disable static builds using Autotools by default. If you want static | |
78 | libraries, pass --enable-static to ./configure | |
79 | ||
80 | ### Fixed | |
81 | ||
82 | * Typo in `docs/index.md`. | |
83 | * Typo in `programs/sndfile-convert.c`, thanks @fjl. | |
84 | * Memory leak in `caf_read_header`(), credit to OSS-Fuzz ([issue 30375](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=30375)). | |
85 | * Stack overflow in `guess_file_type`(), thanks @bobsayshilol, credit to | |
86 | OSS-Fuzz ([issue 29339](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=29339)). | |
87 | * Abort in fuzzer, thanks @bobsayshilol, credit to OSS-Fuzz | |
88 | ([issue 26257](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=26257)). | |
89 | * Infinite loop in `svx_read_header`(), thanks @bobsayshilol, credit to OSS-Fuzz | |
90 | ([issue 25442](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25442)). | |
91 | * GCC and Clang pedantic warnings, thanks @bobsayshilol. | |
92 | * Normalisation issue when scaling floating point data to `int` in | |
93 | `replace_read_f2i`(), thanks @bobsayshilol, (issue #702). | |
94 | * Missing samples when doing a partial read of Ogg file from index till the end | |
95 | of file, thanks @arthurt (issue #643). | |
96 | * sndfile-salvage: Handle files > 4 GB on Windows OS | |
97 | * Undefined shift in `dyn_get_32bit`(), credit to OSS-Fuzz | |
98 | ([issue 27366](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=27366)). | |
99 | * Integer overflow in `nms_adpcm_update`(), credit to OSS-Fuzz | |
100 | ([issue 25522](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25522)). | |
101 | * Integer overflow in `psf_log_printf`(), credit to OSS-Fuzz | |
102 | ([issue 28441](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28441)), | |
103 | ([issue 25624](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25624)). | |
104 | * ABI version incompatibility between Autotools and CMake build on Apple | |
105 | platforms. | |
106 | ||
107 | Now ABI must be compatible with Autotools builds. Note that this change | |
108 | requires CMake >= 3.17 for building dylib on Apple platforms. | |
109 | ||
110 | * Fix build with Autotools + MinGW toolchain on Windows platform. | |
111 | ||
112 | See https://github.com/msys2/MINGW-packages/issues/5803 for details. | |
113 | ||
114 | ### Security | |
115 | ||
116 | * Heap buffer overflow in `wavlike_ima_decode_block`(), thanks @bobsayshilol, | |
117 | credit to OSS-Fuzz ([issue 25530](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25530)). | |
118 | * Heap buffer overflow in `msadpcm_decode_block`(), thanks @bobsayshilol, | |
119 | credit to OSS-Fuzz ([issue 26803](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=26803)). | |
120 | * Heap buffer overflow in `psf_binheader_readf`(), thanks @bobsayshilol, | |
121 | credit to OSS-Fuzz ([issue 26026](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=26026)). | |
122 | * Index out of bounds in `psf_nms_adpcm_decode_block`(), credit to OSS-Fuzz | |
123 | ([issue 25561](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25561)). | |
124 | * Heap buffer overflow in `flac_buffer_copy`(), thanks @yuawn, @bobsayshilol. | |
125 | * Heap buffer overflow in `copyPredictorTo24`(), thanks @bobsayshilol, | |
126 | credit to OSS-Fuzz ([issue 27503](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=27503)). | |
127 | * Uninitialized variable in `psf_binheader_readf`(), thanks @shao-hua-li, | |
128 | credit to OSS-Fuzz ([issue 25364](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25364)). | |
129 | ||
130 | [Unreleased]: https://github.com/libsndfile/libsndfile/compare/1.1.0...HEAD | |
131 | [1.1.0]: https://github.com/libsndfile/libsndfile/compare/1.0.31...1.1.0 |
14 | 14 | endif () |
15 | 15 | endif () |
16 | 16 | |
17 | project(libsndfile VERSION 1.0.31) | |
17 | option (ENABLE_EXTERNAL_LIBS "Enable FLAC, Vorbis, and Opus codecs" ON) | |
18 | if (ENABLE_EXTERNAL_LIBS) | |
19 | list (APPEND VCPKG_MANIFEST_FEATURES "external-libs") | |
20 | endif () | |
21 | ||
22 | option (ENABLE_MPEG "Enable MPEG codecs" ON) | |
23 | if (ENABLE_MPEG) | |
24 | list (APPEND VCPKG_MANIFEST_FEATURES "mpeg") | |
25 | endif () | |
26 | ||
27 | option (ENABLE_EXPERIMENTAL "Enable experimental code" OFF) | |
28 | if (ENABLE_EXPERIMENTAL) | |
29 | list (APPEND VCPKG_MANIFEST_FEATURES "speex") | |
30 | endif () | |
31 | ||
32 | option (BUILD_REGTEST "Build regtest" OFF) | |
33 | if (BUILD_REGTEST) | |
34 | list (APPEND VCPKG_MANIFEST_FEATURES "regtest") | |
35 | endif () | |
36 | ||
37 | project(libsndfile VERSION 1.1.0) | |
18 | 38 | |
19 | 39 | # |
20 | 40 | # Variables |
53 | 73 | option (BUILD_PROGRAMS "Build programs" ON) |
54 | 74 | option (BUILD_EXAMPLES "Build examples" ON) |
55 | 75 | option (ENABLE_CPACK "Enable CPack support" ON) |
56 | option (ENABLE_EXPERIMENTAL "Enable experimental code" OFF) | |
57 | 76 | option (ENABLE_BOW_DOCS "Enable black-on-white html docs" OFF) |
58 | 77 | if (MSVC AND (DEFINED ENABLE_STATIC_RUNTIME)) |
59 | 78 | option (ENABLE_STATIC_RUNTIME "Enable static runtime" ${ENABLE_STATIC_RUNTIME}) |
74 | 93 | |
75 | 94 | include(SndFileChecks) |
76 | 95 | |
77 | ||
78 | cmake_dependent_option (BUILD_REGTEST "Build regtest" ON "SQLITE3_FOUND" OFF) | |
79 | cmake_dependent_option (ENABLE_EXTERNAL_LIBS "Enable FLAC, Vorbis, and Opus codecs" ON "Vorbis_FOUND;FLAC_FOUND;OPUS_FOUND" OFF) | |
96 | if (ENABLE_EXTERNAL_LIBS AND NOT (Vorbis_FOUND OR FLAC_FOUND OR OPUS_FOUND)) | |
97 | set (ENABLE_EXTERNAL_LIBS OFF) | |
98 | endif() | |
99 | if(ENABLE_MPEG AND (NOT HAVE_MPEG_LIBS)) | |
100 | set (ENABLE_MPEG OFF) | |
101 | endif() | |
102 | if (BUILD_REGTEST AND (NOT SQLITE3_FOUND)) | |
103 | set (BUILD_REGTEST OFF) | |
104 | endif() | |
105 | ||
80 | 106 | cmake_dependent_option (ENABLE_CPU_CLIP "Enable tricky cpu specific clipper" ON "CPU_CLIPS_POSITIVE;CPU_CLIPS_NEGATIVE" OFF) |
81 | 107 | if (NOT ENABLE_CPU_CLIP) |
82 | 108 | set (CPU_CLIPS_POSITIVE FALSE) |
103 | 129 | set (HAVE_SNDIO_H ${SNDIO_FOUND}) |
104 | 130 | |
105 | 131 | set (ENABLE_EXPERIMENTAL_CODE ${ENABLE_EXPERIMENTAL}) |
132 | set (HAVE_MPEG ${ENABLE_MPEG}) | |
106 | 133 | set (HAVE_SPEEX ${ENABLE_EXPERIMENTAL}) |
107 | set (HAVE_OPUS ${ENABLE_EXPERIMENTAL}) | |
108 | 134 | |
109 | 135 | add_feature_info (BUILD_SHARED_LIBS BUILD_SHARED_LIBS "build shared libraries") |
110 | 136 | add_feature_info (ENABLE_EXTERNAL_LIBS ENABLE_EXTERNAL_LIBS "enable FLAC, Vorbis, and Opus codecs") |
137 | add_feature_info (ENABLE_MPEG ENABLE_MPEG "enable MPEG audio (including mp3) codecs") | |
111 | 138 | add_feature_info (ENABLE_EXPERIMENTAL ENABLE_EXPERIMENTAL "enable experimental code") |
112 | 139 | add_feature_info (BUILD_TESTING BUILD_TESTING "build tests") |
113 | 140 | add_feature_info (BUILD_REGTEST BUILD_REGTEST "build regtest") |
145 | 172 | URL "www.xiph.org/flac/" |
146 | 173 | DESCRIPTION "Free Lossless Audio Codec Library" |
147 | 174 | PURPOSE "Enables FLAC support" |
175 | ) | |
176 | set_package_properties (Lame PROPERTIES | |
177 | TYPE RECOMMENDED | |
178 | URL "https://lame.sourceforge.io/" | |
179 | DESCRIPTION "High quality MPEG Audio Layer III (MP3) encoder" | |
180 | PURPOSE "Enables MPEG layer III (MP3) writing support" | |
181 | ) | |
182 | set_package_properties (MPG123 PROPERTIES | |
183 | TYPE RECOMMENDED | |
184 | URL "https://www.mpg123.de/" | |
185 | DESCRIPTION "MPEG Audio Layer I/II/III decoder" | |
186 | PURPOSE "Enables MPEG Audio reading support" | |
148 | 187 | ) |
149 | 188 | set_package_properties(Opus PROPERTIES |
150 | 189 | TYPE RECOMMENDED |
193 | 232 | set (EXTERNAL_XIPH_REQUIRE "flac ogg vorbis vorbisenc opus") |
194 | 233 | if (ENABLE_EXPERIMENTAL) |
195 | 234 | set (EXTERNAL_XIPH_REQUIRE "${EXTERNAL_XIPH_REQUIRE} speex") |
235 | endif () | |
236 | endif () | |
237 | if (ENABLE_MPEG) | |
238 | set (EXTERNAL_MPEG_REQUIRE "libmpg123") | |
239 | get_filename_component(LAME_WE ${LAME_LIBRARY} NAME_WE) | |
240 | if (LAME_HIP_LIBRARY) | |
241 | get_filename_component(LAME_HIP_WE ${LAME_HIP_LIBRARY} NAME_WE) | |
242 | endif () | |
243 | if (CMAKE_IMPORT_LIBRARY_PREFIX) | |
244 | string (REGEX REPLACE "^${CMAKE_IMPORT_LIBRARY_PREFIX}" "" LAME_WE_NO_PREFIX ${LAME_WE}) | |
245 | if (LAME_HIP_LIBRARY) | |
246 | string (REGEX REPLACE "^${CMAKE_IMPORT_LIBRARY_PREFIX}" "" LAME_HIP_WE_NO_PREFIX ${LAME_HIP_WE}) | |
247 | endif () | |
248 | endif () | |
249 | set (EXTERNAL_MPEG_LIBS "-l${LAME_WE_NO_PREFIX}") | |
250 | if (LAME_HIP_LIBRARY) | |
251 | set (EXTERNAL_MPEG_LIBS "${MPEG_LIBS} -l${LAME_HIP_WE}") | |
196 | 252 | endif () |
197 | 253 | endif () |
198 | 254 | |
246 | 302 | src/ogg.c |
247 | 303 | src/chanmap.h |
248 | 304 | src/chanmap.c |
305 | src/id3.h | |
249 | 306 | src/id3.c |
250 | 307 | $<$<BOOL:${WIN32}>:src/windows.c> |
251 | 308 | src/sndfile.c |
283 | 340 | src/ogg_speex.c |
284 | 341 | src/ogg_pcm.c |
285 | 342 | src/ogg_opus.c |
343 | src/ogg_vcomment.h | |
286 | 344 | src/ogg_vcomment.c |
287 | 345 | src/nms_adpcm.c |
346 | src/mpeg.c | |
347 | src/mpeg_decode.c | |
348 | src/mpeg_l3_encode.c | |
288 | 349 | src/GSM610/config.h |
289 | 350 | src/GSM610/gsm.h |
290 | 351 | src/GSM610/gsm610_priv.h |
348 | 409 | $<$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>:FLAC::FLAC> |
349 | 410 | $<$<AND:$<BOOL:${ENABLE_EXPERIMENTAL}>,$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>,$<BOOL:${HAVE_SPEEX}>>:Speex::Speex> |
350 | 411 | $<$<BOOL:${HAVE_EXTERNAL_XIPH_LIBS}>:Opus::opus> |
412 | $<$<BOOL:${HAVE_MPEG}>:MPG123::libmpg123> | |
413 | $<$<BOOL:${HAVE_MPEG}>:Lame::Lame> | |
351 | 414 | ) |
352 | 415 | set_target_properties (sndfile PROPERTIES |
353 | 416 | PUBLIC_HEADER "${sndfile_HDRS}" |
367 | 430 | |
368 | 431 | if (BUILD_SHARED_LIBS) |
369 | 432 | |
433 | # | |
434 | # ABI version of library. | |
435 | # | |
436 | ||
437 | # | |
438 | # Read libtool version from `configure.ac` and set libsndfile ABI version: | |
439 | # | |
440 | # SNDFILE_ABI_VERSION_MAJOR | |
441 | # SNDFILE_ABI_VERSION_MINOR | |
442 | # SNDFILE_ABI_VERSION_PATCH | |
443 | # SNDFILE_ABI_VERSION | |
444 | # | |
445 | # and Mach-O current and compatibility versions: | |
446 | # | |
447 | # SNDFILE_MACHO_CURRENT_VERSION | |
448 | # SNDFILE_MACHO_COMPATIBILITY_VERSION | |
449 | # | |
450 | ||
451 | include (SetupABIVersions) | |
452 | ||
453 | setup_abi_versions() | |
454 | ||
370 | 455 | if (WIN32) |
371 | 456 | set (VERSION_MAJOR ${CPACK_PACKAGE_VERSION_MAJOR}) |
372 | 457 | set (GEN_TOOL cmake) |
379 | 464 | target_sources (sndfile PRIVATE ${PROJECT_BINARY_DIR}/src/version-metadata.rc) |
380 | 465 | endif () |
381 | 466 | |
467 | ||
382 | 468 | set_target_properties (sndfile PROPERTIES |
383 | SOVERSION ${PROJECT_VERSION_MAJOR} | |
384 | VERSION ${PROJECT_VERSION} | |
385 | ) | |
469 | SOVERSION ${SNDFILE_ABI_VERSION_MAJOR} | |
470 | VERSION ${SNDFILE_ABI_VERSION} | |
471 | ) | |
472 | ||
473 | if (APPLE) | |
474 | if (NOT (CMAKE_VERSION VERSION_LESS 3.17)) | |
475 | set_target_properties (sndfile PROPERTIES | |
476 | MACHO_CURRENT_VERSION ${SNDFILE_MACHO_CURRENT_VERSION} | |
477 | MACHO_COMPATIBILITY_VERSION ${SNDFILE_MACHO_COMPATIBILITY_VERSION} | |
478 | ) | |
479 | else () | |
480 | message (FATAL_ERROR "Apple platform requires cmake >= 3.17 to build dylib.") | |
481 | endif () | |
482 | endif () | |
386 | 483 | |
387 | 484 | # Symbol files generation |
388 | 485 | |
403 | 500 | if (DEFINED SYMBOL_OS) |
404 | 501 | add_custom_command ( |
405 | 502 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME} |
406 | COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/src/create_symbols_file.py ${SYMBOL_OS} ${PROJECT_VERSION} > ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME} | |
503 | COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/src/create_symbols_file.py ${SYMBOL_OS} ${SNDFILE_ABI_VERSION} > ${CMAKE_CURRENT_BINARY_DIR}/src/${SYMBOL_FILENAME} | |
407 | 504 | COMMENT "Generating ${SYMBOL_FILENAME}..." |
408 | 505 | ) |
409 | 506 | |
646 | 743 | $<$<BOOL:${LIBM_REQUIRED}>:m> |
647 | 744 | ) |
648 | 745 | |
746 | # generate | |
747 | ||
748 | add_executable (generate examples/generate.c) | |
749 | target_link_libraries (generate PRIVATE sndfile) | |
750 | ||
649 | 751 | # sndfilehandle |
650 | 752 | |
651 | 753 | add_executable (sndfilehandle examples/sndfilehandle.cc) |
657 | 759 | make_sine |
658 | 760 | sfprocess |
659 | 761 | list_formats |
762 | generate | |
660 | 763 | sndfilehandle |
661 | 764 | ) |
662 | 765 | |
715 | 818 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} |
716 | 819 | ) |
717 | 820 | |
821 | export (EXPORT SndFileTargets NAMESPACE SndFile:: FILE ${PROJECT_BINARY_DIR}/SndFileTargets.cmake) | |
822 | ||
718 | 823 | include (CMakePackageConfigHelpers) |
719 | 824 | |
720 | 825 | if (ENABLE_EXTERNAL_LIBS) |
723 | 828 | set (SndFile_WITH_EXTERNAL_LIBS 0) |
724 | 829 | endif () |
725 | 830 | |
831 | if(ENABLE_MPEG) | |
832 | set (SndFile_WITH_MPEG 1) | |
833 | else () | |
834 | set (SndFile_WITH_MPEG 0) | |
835 | endif () | |
836 | ||
726 | 837 | set (INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}) |
727 | 838 | configure_package_config_file(cmake/SndFileConfig.cmake.in SndFileConfig.cmake |
839 | INSTALL_DESTINATION ${PROJECT_BINARY_DIR} | |
840 | INSTALL_PREFIX ${PROJECT_BINARY_DIR} | |
841 | PATH_VARS INCLUDE_INSTALL_DIR | |
842 | ) | |
843 | configure_package_config_file(cmake/SndFileConfig.cmake.in SndFileConfig2.cmake | |
728 | 844 | INSTALL_DESTINATION ${CMAKE_INSTALL_PACKAGEDIR} |
729 | 845 | PATH_VARS INCLUDE_INSTALL_DIR |
730 | 846 | ) |
735 | 851 | DESTINATION ${CMAKE_INSTALL_PACKAGEDIR} |
736 | 852 | ) |
737 | 853 | install( |
854 | FILES ${CMAKE_CURRENT_BINARY_DIR}/SndFileConfig2.cmake | |
855 | RENAME SndFileConfig.cmake | |
856 | DESTINATION ${CMAKE_INSTALL_PACKAGEDIR} | |
857 | ) | |
858 | install( | |
738 | 859 | FILES |
739 | ${CMAKE_CURRENT_BINARY_DIR}/SndFileConfig.cmake | |
740 | 860 | ${CMAKE_CURRENT_BINARY_DIR}/SndFileConfigVersion.cmake |
741 | 861 | DESTINATION ${CMAKE_INSTALL_PACKAGEDIR} |
742 | 862 | ) |
1180 | 1300 | $<$<BOOL:${LIBM_REQUIRED}>:m> |
1181 | 1301 | ) |
1182 | 1302 | |
1303 | add_executable (mpeg_test tests/mpeg_test.c) | |
1304 | target_link_libraries (mpeg_test | |
1305 | PRIVATE | |
1306 | sndfile | |
1307 | test_utils | |
1308 | $<$<BOOL:${LIBM_REQUIRED}>:m> | |
1309 | ) | |
1310 | ||
1183 | 1311 | add_executable (stdin_test tests/stdin_test.c) |
1184 | 1312 | target_link_libraries (stdin_test |
1185 | 1313 | PRIVATE |
1410 | 1538 | add_test (compression_size_test_opus compression_size_test opus) |
1411 | 1539 | add_test (lossy_comp_test_ogg_opus lossy_comp_test ogg_opus) |
1412 | 1540 | add_test (string_test_opus string_test opus) |
1541 | ||
1542 | ### mpeg-tests ### | |
1543 | add_test (mpeg_test mpeg_test) | |
1544 | add_test (compression_size_test_mpeg compression_size_test mpeg) | |
1413 | 1545 | |
1414 | 1546 | ### io-tests |
1415 | 1547 | add_test (stdio_test stdio_test) |
1466 | 1598 | endif () |
1467 | 1599 | |
1468 | 1600 | if (ENABLE_CPACK) |
1601 | if ((NOT CPACK_PACKAGE_VERSION) AND CPACK_PACKAGE_VERSION_STAGE) | |
1602 | set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_FULL}") | |
1603 | endif () | |
1469 | 1604 | include (CPack) |
1470 | 1605 | endif () |
17 | 17 | * Patches should always be submitted via a either Github "pull request" or a |
18 | 18 | via emailed patches created using "git format-patch". |
19 | 19 | * Patches for new features should include tests and documentation. |
20 | * Commit messages should follow the ["How to Write a Git Commit Message"](https://chris.beams.io/posts/git-commit/) guide: | |
21 | 1. Separate subject from body with a blank line | |
22 | 2. Limit the subject line to 50 characters | |
23 | 3. Capitalize the subject line | |
24 | 4. Do not end the subject line with a period | |
25 | 5. Use the imperative mood in the subject line | |
26 | 6. Wrap the body at 72 characters | |
27 | 7. Use the body to explain what and why vs. how | |
28 | ||
29 | Additional rule: the commit message may contain a prefix. The prefix must | |
30 | contain the name of the feature or source file related to the commit and must | |
31 | end with a colon followed by the message body. | |
32 | ||
33 | Examples of good commit messages: | |
34 | 1. Fix typo | |
35 | 2. Update CHANGELOG.md | |
36 | 3. Add ACT file format support | |
37 | 4. ogg_vorbis: Fix granule position when seeking Vorbis streams | |
38 | ||
39 | Examples of bad commit messages: | |
40 | 1. Fixed bug (rule 5) | |
41 | 2. update docs (rule 3) | |
42 | 3. Add very cool feature. (rule 4) | |
43 | ||
20 | 44 | * Patches to fix bugs should either pass all tests, or modify the tests in some |
21 | 45 | sane way. |
22 | 46 | * When a new feature is added for a particular file format and that feature |
12 | 12 | endif |
13 | 13 | |
14 | 14 | EXTRA_DIST = libsndfile.spec.in sndfile.pc.in Scripts/android-configure.sh \ |
15 | Scripts/linux-to-win-cross-configure.sh \ | |
16 | CMakeLists.txt $(cmake_files) Win32 | |
15 | NEWS.OLD CHANGELOG.md Scripts/linux-to-win-cross-configure.sh \ | |
16 | CMakeLists.txt $(cmake_files) Win32 SECURITY.md | |
17 | 17 | |
18 | 18 | cmake_files = cmake/ClipMode.cmake cmake/FindFLAC.cmake \ |
19 | 19 | cmake/CMakeAutoGen.cmake cmake/CMakeAutoGenScript.cmake \ |
22 | 22 | cmake/SndFileChecks.cmake cmake/TestInline.cmake \ |
23 | 23 | cmake/TestLargeFiles.cmake cmake/TestInline.c.in \ |
24 | 24 | cmake/FindOpus.cmake cmake/SndFileConfig.cmake.in \ |
25 | cmake/CheckCPUArch.cmake cmake/CheckCPUArch.c.in | |
25 | cmake/CheckCPUArch.cmake cmake/CheckCPUArch.c.in \ | |
26 | cmake/SetupABIVersions.cmake | |
26 | 27 | |
27 | 28 | pkgconfig_DATA = sndfile.pc |
28 | 29 | |
61 | 62 | lib_LTLIBRARIES = src/libsndfile.la |
62 | 63 | include_HEADERS = include/sndfile.hh |
63 | 64 | nodist_include_HEADERS = include/sndfile.h |
64 | src_libsndfile_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS) | |
65 | src_libsndfile_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS) $(MPEG_CFLAGS) | |
65 | 66 | # MinGW requires -no-undefined if a DLL is to be built. |
66 | 67 | src_libsndfile_la_LDFLAGS = -no-undefined -version-info $(SHARED_VERSION_INFO) $(SHLIB_VERSION_ARG) |
67 | 68 | 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 \ |
68 | 69 | 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 \ |
69 | 70 | 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 \ |
70 | src/ogg_vorbis.c src/ogg_speex.c src/ogg_pcm.c src/ogg_opus.c src/ogg_vcomment.c \ | |
71 | 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 | |
71 | 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 \ | |
72 | src/common.h src/sfconfig.h src/sfendian.h src/wavlike.h src/sf_unistd.h src/chanmap.h src/mpeg.c | |
72 | 73 | nodist_src_libsndfile_la_SOURCES = $(nodist_include_HEADERS) |
73 | 74 | src_libsndfile_la_LIBADD = src/GSM610/libgsm.la src/G72x/libg72x.la src/ALAC/libalac.la \ |
74 | src/libcommon.la $(EXTERNAL_XIPH_LIBS) -lm | |
75 | src/libcommon.la $(EXTERNAL_XIPH_LIBS) -lm $(MPEG_LIBS) | |
75 | 76 | EXTRA_src_libsndfile_la_DEPENDENCIES = $(SYMBOL_FILES) |
76 | 77 | |
77 | 78 | noinst_LTLIBRARIES = src/libcommon.la |
78 | src_libcommon_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS) | |
79 | src_libcommon_la_CFLAGS = $(EXTERNAL_XIPH_CFLAGS) $(MPEG_CFLAGS) | |
79 | 80 | src_libcommon_la_SOURCES = src/common.c src/file_io.c src/command.c src/pcm.c src/ulaw.c src/alaw.c \ |
80 | 81 | src/float32.c src/double64.c src/ima_adpcm.c src/ms_adpcm.c src/gsm610.c src/dwvw.c src/vox_adpcm.c \ |
81 | 82 | src/interleave.c src/strings.c src/dither.c src/cart.c src/broadcast.c src/audio_detect.c \ |
82 | src/ima_oki_adpcm.c src/ima_oki_adpcm.h src/alac.c src/chunk.c src/ogg.c src/chanmap.c \ | |
83 | src/windows.c src/id3.c src/nms_adpcm.c $(WIN_VERSION_FILE) | |
83 | src/ima_oki_adpcm.c src/ima_oki_adpcm.h src/alac.c src/chunk.c src/chanmap.c \ | |
84 | 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) | |
84 | 85 | |
85 | 86 | check_PROGRAMS = src/test_main |
86 | 87 | src_test_main_SOURCES = src/test_main.c src/test_main.h src/test_conversions.c src/test_float.c src/test_endswap.c \ |
134 | 135 | SYMBOL_SCRIPT = $(top_srcdir)/src/create_symbols_file.py |
135 | 136 | |
136 | 137 | src/Symbols.gnu-binutils: $(SYMBOL_SCRIPT) |
137 | $(PYTHON) $(SYMBOL_SCRIPT) linux $(VERSION) > $(top_srcdir)/$@ | |
138 | $(PYTHON) $(SYMBOL_SCRIPT) linux $(ABI_VERSION) > $(top_srcdir)/$@ | |
138 | 139 | |
139 | 140 | src/Symbols.darwin: $(SYMBOL_SCRIPT) |
140 | $(PYTHON) $(SYMBOL_SCRIPT) darwin $(VERSION) > $(top_srcdir)/$@ | |
141 | $(PYTHON) $(SYMBOL_SCRIPT) darwin $(ABI_VERSION) > $(top_srcdir)/$@ | |
141 | 142 | |
142 | 143 | src/libsndfile-1.def: $(SYMBOL_SCRIPT) |
143 | $(PYTHON) $(SYMBOL_SCRIPT) win32 $(VERSION) > $(top_srcdir)/$@ | |
144 | $(PYTHON) $(SYMBOL_SCRIPT) win32 $(ABI_VERSION) > $(top_srcdir)/$@ | |
144 | 145 | |
145 | 146 | src/Symbols.os2: $(SYMBOL_SCRIPT) |
146 | $(PYTHON) $(SYMBOL_SCRIPT) os2 $(VERSION) > $(top_srcdir)/$@ | |
147 | $(PYTHON) $(SYMBOL_SCRIPT) os2 $(ABI_VERSION) > $(top_srcdir)/$@ | |
147 | 148 | |
148 | 149 | src/Symbols.static: $(SYMBOL_SCRIPT) |
149 | $(PYTHON) $(SYMBOL_SCRIPT) static $(VERSION) > $(top_srcdir)/$@ | |
150 | $(PYTHON) $(SYMBOL_SCRIPT) static $(ABI_VERSION) > $(top_srcdir)/$@ | |
150 | 151 | |
151 | 152 | #=============================================================================== |
152 | 153 | # Building windows resource files (if needed). |
220 | 221 | tests/locale_test tests/win32_ordinal_test tests/ogg_test tests/compression_size_test \ |
221 | 222 | tests/checksum_test tests/external_libs_test tests/rdwr_test tests/format_check_test $(CPP_TEST) \ |
222 | 223 | tests/channel_test tests/long_read_write_test tests/stdin_test tests/stdout_test \ |
223 | tests/dither_test tests/fix_this tests/largefile_test tests/benchmark tests/ogg_opus_test | |
224 | tests/dither_test tests/fix_this tests/largefile_test tests/benchmark tests/ogg_opus_test \ | |
225 | tests/mpeg_test | |
224 | 226 | |
225 | 227 | BUILT_SOURCES += \ |
226 | 228 | tests/write_read_test.c \ |
376 | 378 | tests_checksum_test_SOURCES = tests/checksum_test.c tests/utils.c tests/utils.h |
377 | 379 | tests_checksum_test_LDADD = src/libsndfile.la |
378 | 380 | |
381 | tests_mpeg_test_SOURCES = tests/mpeg_test.c tests/utils.c tests/utils.h | |
382 | tests_mpeg_test_LDADD = src/libsndfile.la | |
383 | ||
379 | 384 | # Lite remove start |
380 | 385 | tests_dwvw_test_SOURCES = tests/dwvw_test.c tests/utils.c tests/utils.h |
381 | 386 | tests_dwvw_test_LDADD = src/libsndfile.la |
456 | 461 | |
457 | 462 | if USE_OSSFUZZERS |
458 | 463 | noinst_PROGRAMS += \ |
459 | ossfuzz/sndfile_fuzzer | |
464 | ossfuzz/sndfile_fuzzer \ | |
465 | ossfuzz/sndfile_alt_fuzzer | |
460 | 466 | |
461 | 467 | noinst_LTLIBRARIES += \ |
462 | 468 | ossfuzz/libstandaloneengine.la |
466 | 472 | ossfuzz_sndfile_fuzzer_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG) |
467 | 473 | ossfuzz_sndfile_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static |
468 | 474 | ossfuzz_sndfile_fuzzer_LDADD = src/libsndfile.la $(FUZZ_LDADD) |
475 | ||
476 | ossfuzz_sndfile_alt_fuzzer_SOURCES = ossfuzz/sndfile_alt_fuzzer.cc | |
477 | ossfuzz_sndfile_alt_fuzzer_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG) | |
478 | ossfuzz_sndfile_alt_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static | |
479 | ossfuzz_sndfile_alt_fuzzer_LDADD = src/libsndfile.la $(FUZZ_LDADD) | |
469 | 480 | |
470 | 481 | ossfuzz_libstandaloneengine_la_SOURCES = ossfuzz/standaloneengine.cc ossfuzz/testinput.h |
471 | 482 | ossfuzz_libstandaloneengine_la_CXXFLAGS = $(AM_CXXFLAGS) |
0 | Version 1.0.31 (2021-01-24) | |
1 | ||
2 | * The releaser of libsndfile starting from this version is the libsndfile team | |
3 | member @SoapGentoo, see AUTHORS for details. | |
4 | * Implement fast SSE2 optimized psf_lrintf() and psf_lrintf() functions to | |
5 | improve perfomance when libsndfile is built using Visual C++ (especially) | |
6 | and other compilers on x86 and AMD64 platforms. See also description of | |
7 | ENABLE_SSE2 CMake option in README.md. | |
8 | * Documentation: | |
9 | * Move site to new URL: http://libsndfile.github.io/libsndfile/ | |
10 | * Convert documentation pages from HTML to Markdown | |
11 | * Use GitHub's Jekyll static site generator to generate static HTML pages | |
12 | for site | |
13 | * Fix api.md table error, thanks to @zodf0055980 | |
14 | * Other docuemntation fixes and updates | |
15 | * Change CMake's project name from sndfile to libsndfile as it should be. | |
16 | * Change behaviour of ENABLE_STATIC_RUNTIME option. In short: | |
17 | * You can use ENABLE_STATIC_RUNTIME for CMake >= 3.15 without error. | |
18 | * You can use your our method to set MSVC runtime library flags if none of | |
19 | ENABLE_STATIC_RUNTIME and CMAKE_MSVC_RUNTIME_LIBRARY were set. | |
20 | Advanced information: | |
21 | * If this option is defined (set to ON or OFF), set CMP0091 policy to OLD | |
22 | (we handle MSVC runtime library flags using compiler flags), set | |
23 | corresponding compiler flags for user. | |
24 | * NEW: If this option is not defined, set CMP0091 policy to OLD (we handle | |
25 | MSVC runtime library flags using compiler flags), don't touch compiler | |
26 | options, allow user to set it manually. | |
27 | * NEW: If new CMake option CMAKE_MSVC_RUNTIME_LIBRARY is set, change | |
28 | CMP0091 policy to NEW (we handle MSVC runtime library flags using that | |
29 | option), don't touch compiler flags. | |
30 | * NEW: If both ENABLE_STATIC_RUNTIME and CMAKE_MSVC_RUNTIME_LIBRARY are set, | |
31 | terminate configuration with fatal error. | |
32 | * For MinGW toolchain this option is experimental. If you enabled it and | |
33 | then disabled again, you need to clear CMake cache (delete | |
34 | CMakeCache.txt). | |
35 | * Make CMake clip test faster. | |
36 | * Fix CMake bug with sndio library dependency, thanks to @drhenault. | |
37 | * Fix memory leak in wav_read_smpl_chunk() function, credit to OSS-Fuzz. | |
38 | * Fix aiff_read_header() memory leak(), credit to OSS-Fuzz. | |
39 | * Fix leak in wav_read_header(), credit to OSS-Fuzz. | |
40 | * Fix leak in wavlike_read_cart_chunk(), credit to OSS-Fuzz. | |
41 | * Fix memory leak in wav_read_acid_chunk(), credit to OSS-Fuzz. | |
42 | * Fix memory leak in aiff_read_basc_chunk(), credit to OSS-Fuzz. | |
43 | * Fix memory leak in wavlike_read_peak_chunk(), credit to OSS-Fuzz. | |
44 | * Fix memory leak in aiff_read_header(), credit to OSS-Fuzz. | |
45 | * Fix use of uninitialized value in exif_subchunk_parse(), credit to OSS-Fuzz. | |
46 | * Fix use of uninitialized value in endswap_int64_t_array(), credit to | |
47 | OSS-Fuzz. | |
48 | * Fix up the fuzzer so that it can't under or overseek, | |
49 | thanks to Max Dymond <cmeister2@gmail.com>. | |
50 | * Fix Autotools configure on macOS, thanks to @tmcguire and @nwh. | |
51 | * Exclude repository-configuration from git-archive, thanks to @umlaeute. | |
52 | * Use version-script when compiling with clang on Unix with Autotools, thanks | |
53 | to @tstellar. | |
54 | * Improve handling of SMPL chunks in WAV files, thanks to @zodf0055980. | |
55 | ||
56 | Version 1.0.30 (2020-09-18) | |
57 | ||
58 | * Fix critical CMake bug with broken ABI of shared libsndfile library. | |
59 | * CMake build system considered to be stable. | |
60 | * Move sndfile.h.in from src/ to include/ directory. To avoid problems, | |
61 | delete old generated sndfile.h from $(top_builddir)/src. | |
62 | * Huge documentation update. | |
63 | * Fix opus test failures on BE platforms, thanks to | |
64 | Arthur Taylor <art@ified.ca>. | |
65 | * Fix bug when sf_open_fd() function sometimes leaves filehandle open, even | |
66 | if `close_desc` parameter is TRUE, thanks to @umläute. | |
67 | * Fix infinite loops on some pathological SD2 files, thanks to | |
68 | Jeremy Friesner <jaf@meyersound.com>. | |
69 | * Switch to GitHub Actions for continuous integration. | |
70 | * Add OSS-Fuzz tests to GitHub Actions workflow, thanks to | |
71 | Max Dymond <cmeister2@gmail.com>. | |
72 | * Fix memory leak in wavlike_read_bext_chunk() function, credit to OSS-Fuzz. | |
73 | * Fix undefined behavior in avr-read_header() function, credit to OSS-Fuzz. | |
74 | * Add INSTALL_PKGCONFIG_MODULE CMake option to control sndfile.pc file | |
75 | installation, see README.md for details. | |
76 | * Add INSTALL_MANPAGES CMake option, see README.md for details. | |
77 | * Fix ENABLE_COMPATIBLE_LIBSNDFILE_NAME CMake option, now it works on MinGW | |
78 | platform too. | |
79 | * Fix ENABLE_CPACK CMake option, see README.md for details. | |
80 | * Fix ENABLE_STATIC_RUNTIME and CMAKE_MSVC_RUNTIME_LIBRARY behavior, see | |
81 | README.md for details. | |
82 | * Fix CMake man pages installation bug when sndfile-deinterleave.1 and | |
83 | sndfile-metadata-set.1 were not installed. | |
84 | * Fix sndfile-regtest paths handling on Windows platform, thanks to | |
85 | Gisle Vanem <gvanem@yahoo.no>. | |
86 | ||
87 | Version 1.0.29 (2020-08-15) | |
88 | * Add support for Opus files. | |
89 | * Autotool build system improvements. | |
90 | * CMake build system improvements. | |
91 | * Fixes for: CVE-2017-12562, CVE-2017-17456, CVE-2017-17457, CVE-2018-19661, | |
92 | CVE-2018-19662, CVE-2018-19758 and CVE-2019-3832. | |
93 | * Add BWF v2 loudness parameters. | |
94 | * Wave64: Permit and skip arbitrary chunks prior to the data chunk. | |
95 | * Fix ASAN crash in wavlike_ima_seek(). | |
96 | * Fix IMA-ADPCM encoding for AIFF files. | |
97 | * sndfile-convert: Handle gsm, vox and opus extensions the same way. | |
98 | * Add SFC_SET_OGG_PAGE_LATENCY_MS command to get Ogg page latency for Ogg Opus | |
99 | files. | |
100 | * Fix parsing of some SD2 files. | |
101 | * Documentation updates. | |
102 | * Minor bug fixes and improvements. | |
103 | ||
104 | Version 1.0.28 (2017-04-02) | |
105 | * Fix buffer overruns in FLAC and ID3 handling code. | |
106 | * Move to variable length header storage. | |
107 | * Fix detection of Large File Support for 32 bit systems. | |
108 | * Remove large stack allocations in ALAC handling code. | |
109 | * Remove all use of Variable Length Arrays. | |
110 | * Minor bug fixes and improvements. | |
111 | ||
112 | Version 1.0.27 (2016-06-19) | |
113 | * Fix an SF_INFO seekable flag regression introduced in 1.0.26. | |
114 | * Fix potential infinite loops on malformed input files. | |
115 | * Add string metadata read/write for CAF and RF64. | |
116 | * Add handling of CUE chunks. | |
117 | * Fix endian-ness issues in PAF files. | |
118 | * Minor bug fixes and improvements. | |
119 | ||
120 | Version 1.0.26 (2015-11-22) | |
121 | * Fix for CVE-2014-9496, SD2 buffer read overflow. | |
122 | * Fix for CVE-2014-9756, file_io.c divide by zero. | |
123 | * Fix for CVE-2015-7805, AIFF heap write overflow. | |
124 | * Add support for ALAC encoder in a CAF container. | |
125 | * Add support for Cart chunks in WAV files. | |
126 | * Minor bug fixes and improvements. | |
127 | ||
128 | Version 1.0.25 (2011-07-13) | |
129 | * Fix for Secunia Advisory SA45125, heap overflow in PAF file handler. | |
130 | * Accept broken WAV files with blockalign == 0. | |
131 | * Minor bug fixes and improvements. | |
132 | ||
133 | Version 1.0.24 (2011-03-23) | |
134 | * WAV files now have an 18 byte u-law and A-law fmt chunk. | |
135 | * Document virtual I/O functionality. | |
136 | * Two new methods rawHandle() and takeOwnership() in sndfile.hh. | |
137 | * AIFF fix for non-zero offset value in SSND chunk. | |
138 | * Minor bug fixes and improvements. | |
139 | ||
140 | Version 1.0.23 (2010-10-10) | |
141 | * Add version metadata to Windows DLL. | |
142 | * Add a missing 'inline' to sndfile.hh. | |
143 | * Update docs. | |
144 | * Minor bug fixes and improvements. | |
145 | ||
146 | Version 1.0.22 (2010-10-04) | |
147 | * Couple of fixes for SDS file writer. | |
148 | * Fixes arising from static analysis. | |
149 | * Handle FLAC files with ID3 meta data at start of file. | |
150 | * Handle FLAC files which report zero length. | |
151 | * Other minor bug fixes and improvements. | |
152 | ||
153 | Version 1.0.21 (2009-12-13) | |
154 | * Add a couple of new binary programs to programs/ dir. | |
155 | * Remove sndfile-jackplay (now in sndfile-tools package). | |
156 | * Add windows only function sf_wchar_open(). | |
157 | * Bunch of minor bug fixes. | |
158 | ||
159 | Version 1.0.20 (2009-05-14) | |
160 | * Fix potential heap overflow in VOC file parser (Tobias Klein, http://www.trapkit.de/). | |
161 | ||
162 | Version 1.0.19 (2009-03-02) | |
163 | * Fix for CVE-2009-0186 (Alin Rad Pop, Secunia Research). | |
164 | * Huge number of minor bug fixes as a result of static analysis. | |
165 | ||
166 | Version 1.0.18 (2009-02-07) | |
167 | * Add Ogg/Vorbis support (thanks to John ffitch). | |
168 | * Remove captive FLAC library. | |
169 | * Many new features and bug fixes. | |
170 | * Generate Win32 and Win64 pre-compiled binaries. | |
171 | ||
172 | Version 1.0.17 (2006-08-31) | |
173 | * Add sndfile.hh C++ wrapper. | |
174 | * Update Win32 MinGW build instructions. | |
175 | * Minor bug fixes and cleanups. | |
176 | ||
177 | Version 1.0.16 (2006-04-30) | |
178 | * Add support for Broadcast (BEXT) chunks in WAV files. | |
179 | * Implement new commands SFC_GET_SIGNAL_MAX and SFC_GET_MAX_ALL_CHANNELS. | |
180 | * Add support for RIFX (big endian WAV variant). | |
181 | * Fix configure script bugs. | |
182 | * Fix bug in INST and MARK chunk writing for AIFF files. | |
183 | ||
184 | Version 1.0.15 (2006-03-16) | |
185 | * Fix some ia64 issues. | |
186 | * Fix precompiled DLL. | |
187 | * Minor bug fixes. | |
188 | ||
189 | Version 1.0.14 (2006-02-19) | |
190 | * Really fix MinGW compile problems. | |
191 | * Minor bug fixes. | |
192 | ||
193 | Version 1.0.13 (2006-01-21) | |
194 | * Fix for MinGW compiler problems. | |
195 | * Allow readin/write of instrument chunks from WAV and AIFF files. | |
196 | * Compile problem fix for Solaris compiler. | |
197 | * Minor cleanups and bug fixes. | |
198 | ||
199 | Version 1.0.12 (2005-09-30) | |
200 | * Add support for FLAC and Apple's Core Audio Format (CAF). | |
201 | * Add virtual I/O interface (still needs docs). | |
202 | * Cygwin and other Win32 fixes. | |
203 | * Minor bug fixes and cleanups. | |
204 | ||
205 | Version 1.0.11 (2004-11-15) | |
206 | * Add support for SD2 files. | |
207 | * Add read support for loop info in WAV and AIFF files. | |
208 | * Add more tests. | |
209 | * Improve type safety. | |
210 | * Minor optimisations and bug fixes. | |
211 | ||
212 | Version 1.0.10 (2004-06-15) | |
213 | * Fix AIFF read/write mode bugs. | |
214 | * Add support for compiling Win32 DLLS using MinGW. | |
215 | * Fix problems resulting in failed compiles with gcc-2.95. | |
216 | * Improve test suite. | |
217 | * Minor bug fixes. | |
218 | ||
219 | Version 1.0.9 (2004-03-30) | |
220 | * Add handling of AVR (Audio Visual Research) files. | |
221 | * Improve handling of WAVEFORMATEXTENSIBLE WAV files. | |
222 | * Fix for using pipes on Win32. | |
223 | ||
224 | Version 1.0.8 (2004-03-14) | |
225 | * Correct peak chunk handing for files with > 16 tracks. | |
226 | * Fix for WAV files with huge number of CUE chunks. | |
227 | ||
228 | Version 1.0.7 (2004-02-25) | |
229 | * Fix clip mode detection on ia64, MIPS and other CPUs. | |
230 | * Fix two MacOSX build problems. | |
231 | ||
232 | Version 1.0.6 (2004-02-08) | |
233 | * Added support for native Win32 file access API (Ross Bencina). | |
234 | * New mode to add clippling then a converting from float/double to integer | |
235 | would otherwise wrap around. | |
236 | * Fixed a bug in reading/writing files > 2Gig on Linux, Solaris and others. | |
237 | * Many minor bug fixes. | |
238 | * Other random fixes for Win32. | |
239 | ||
240 | Version 1.0.5 (2003-05-03) | |
241 | * Added support for HTK files. | |
242 | * Added new function sf_open_fd() to allow for secure opening of temporary | |
243 | files as well as reading/writing sound files embedded within larger | |
244 | container files. | |
245 | * Added string support for AIFF files. | |
246 | * Minor bug fixes and code cleanups. | |
247 | ||
248 | Version 1.0.4 (2003-02-02) | |
249 | * Added suport of PVF and XI files. | |
250 | * Added functionality for setting and retreiving strings from sound files. | |
251 | * Minor code cleanups and bug fixes. | |
252 | ||
253 | Version 1.0.3 (2002-12-09) | |
254 | * Minor bug fixes. | |
255 | ||
256 | Version 1.0.2 (2002-11-24) | |
257 | * Added support for VOX ADPCM. | |
258 | * Improved error reporting. | |
259 | * Added version scripting on Linux and Solaris. | |
260 | * Minor bug fixes. | |
261 | ||
262 | Version 1.0.1 (2002-09-14) | |
263 | * Added MAT and MAT5 file formats. | |
264 | * Minor bug fixes. | |
265 | ||
266 | Version 1.0.0 (2002-08-16) | |
267 | * Final release for 1.0.0. | |
268 | ||
269 | Version 1.0.0rc6 (2002-08-14) | |
270 | * Release candidate 6 for the 1.0.0 series. | |
271 | * MacOS9 fixes. | |
272 | ||
273 | Version 1.0.0rc5 (2002-08-10) | |
274 | * Release candidate 5 for the 1.0.0 series. | |
275 | * Changed the definition of sf_count_t which was causing problems when | |
276 | libsndfile was compiled with other libraries (ie WxWindows). | |
277 | * Minor bug fixes. | |
278 | * Documentation cleanup. | |
279 | ||
280 | Version 1.0.0rc4 (2002-08-03) | |
281 | * Release candidate 4 for the 1.0.0 series. | |
282 | * Minor bug fixes. | |
283 | * Fix broken Win32 "make check". | |
284 | ||
285 | Version 1.0.0rc3 (2002-08-02) | |
286 | * Release candidate 3 for the 1.0.0 series. | |
287 | * Fix bug where libsndfile was reading beyond the end of the data chunk. | |
288 | * Added on-the-fly header updates on write. | |
289 | * Fix a couple of documentation issues. | |
290 | ||
291 | Version 1.0.0rc2 (2002-06-24) | |
292 | * Release candidate 2 for the 1.0.0 series. | |
293 | * Fix compile problem for Win32. | |
294 | ||
295 | Version 1.0.0rc1 (2002-06-24) | |
296 | * Release candidate 1 for the 1.0.0 series. | |
297 | ||
298 | Version 0.0.28 (2002-04-27) | |
299 | * Last offical release of 0.0.X series of the library. | |
300 | ||
301 | Version 0.0.8 (1999-02-16) | |
302 | * First offical release. |
0 | Version 1.0.31 (2021-01-24) | |
1 | ||
2 | * The releaser of libsndfile starting from this version is the libsndfile team | |
3 | member @SoapGentoo, see AUTHORS for details. | |
4 | * Implement fast SSE2 optimized psf_lrintf() and psf_lrintf() functions to | |
5 | improve perfomance when libsndfile is built using Visual C++ (especially) | |
6 | and other compilers on x86 and AMD64 platforms. See also description of | |
7 | ENABLE_SSE2 CMake option in README.md. | |
8 | * Documentation: | |
9 | * Move site to new URL: http://libsndfile.github.io/libsndfile/ | |
10 | * Convert documentation pages from HTML to Markdown | |
11 | * Use GitHub's Jekyll static site generator to generate static HTML pages | |
12 | for site | |
13 | * Fix api.md table error, thanks to @zodf0055980 | |
14 | * Other docuemntation fixes and updates | |
15 | * Change CMake's project name from sndfile to libsndfile as it should be. | |
16 | * Change behaviour of ENABLE_STATIC_RUNTIME option. In short: | |
17 | * You can use ENABLE_STATIC_RUNTIME for CMake >= 3.15 without error. | |
18 | * You can use your our method to set MSVC runtime library flags if none of | |
19 | ENABLE_STATIC_RUNTIME and CMAKE_MSVC_RUNTIME_LIBRARY were set. | |
20 | Advanced information: | |
21 | * If this option is defined (set to ON or OFF), set CMP0091 policy to OLD | |
22 | (we handle MSVC runtime library flags using compiler flags), set | |
23 | corresponding compiler flags for user. | |
24 | * NEW: If this option is not defined, set CMP0091 policy to OLD (we handle | |
25 | MSVC runtime library flags using compiler flags), don't touch compiler | |
26 | options, allow user to set it manually. | |
27 | * NEW: If new CMake option CMAKE_MSVC_RUNTIME_LIBRARY is set, change | |
28 | CMP0091 policy to NEW (we handle MSVC runtime library flags using that | |
29 | option), don't touch compiler flags. | |
30 | * NEW: If both ENABLE_STATIC_RUNTIME and CMAKE_MSVC_RUNTIME_LIBRARY are set, | |
31 | terminate configuration with fatal error. | |
32 | * For MinGW toolchain this option is experimental. If you enabled it and | |
33 | then disabled again, you need to clear CMake cache (delete | |
34 | CMakeCache.txt). | |
35 | * Make CMake clip test faster. | |
36 | * Fix CMake bug with sndio library dependency, thanks to @drhenault. | |
37 | * Fix memory leak in wav_read_smpl_chunk() function, credit to OSS-Fuzz. | |
38 | * Fix aiff_read_header() memory leak(), credit to OSS-Fuzz. | |
39 | * Fix leak in wav_read_header(), credit to OSS-Fuzz. | |
40 | * Fix leak in wavlike_read_cart_chunk(), credit to OSS-Fuzz. | |
41 | * Fix memory leak in wav_read_acid_chunk(), credit to OSS-Fuzz. | |
42 | * Fix memory leak in aiff_read_basc_chunk(), credit to OSS-Fuzz. | |
43 | * Fix memory leak in wavlike_read_peak_chunk(), credit to OSS-Fuzz. | |
44 | * Fix memory leak in aiff_read_header(), credit to OSS-Fuzz. | |
45 | * Fix use of uninitialized value in exif_subchunk_parse(), credit to OSS-Fuzz. | |
46 | * Fix use of uninitialized value in endswap_int64_t_array(), credit to | |
47 | OSS-Fuzz. | |
48 | * Fix up the fuzzer so that it can't under or overseek, | |
49 | thanks to Max Dymond <cmeister2@gmail.com>. | |
50 | * Fix Autotools configure on macOS, thanks to @tmcguire and @nwh. | |
51 | * Exclude repository-configuration from git-archive, thanks to @umlaeute. | |
52 | * Use version-script when compiling with clang on Unix with Autotools, thanks | |
53 | to @tstellar. | |
54 | * Improve handling of SMPL chunks in WAV files, thanks to @zodf0055980. | |
55 | ||
56 | Version 1.0.30 (2020-09-18) | |
57 | ||
58 | * Fix critical CMake bug with broken ABI of shared libsndfile library. | |
59 | * CMake build system considered to be stable. | |
60 | * Move sndfile.h.in from src/ to include/ directory. To avoid problems, | |
61 | delete old generated sndfile.h from $(top_builddir)/src. | |
62 | * Huge documentation update. | |
63 | * Fix opus test failures on BE platforms, thanks to | |
64 | Arthur Taylor <art@ified.ca>. | |
65 | * Fix bug when sf_open_fd() function sometimes leaves filehandle open, even | |
66 | if `close_desc` parameter is TRUE, thanks to @umläute. | |
67 | * Fix infinite loops on some pathological SD2 files, thanks to | |
68 | Jeremy Friesner <jaf@meyersound.com>. | |
69 | * Switch to GitHub Actions for continuous integration. | |
70 | * Add OSS-Fuzz tests to GitHub Actions workflow, thanks to | |
71 | Max Dymond <cmeister2@gmail.com>. | |
72 | * Fix memory leak in wavlike_read_bext_chunk() function, credit to OSS-Fuzz. | |
73 | * Fix undefined behavior in avr-read_header() function, credit to OSS-Fuzz. | |
74 | * Add INSTALL_PKGCONFIG_MODULE CMake option to control sndfile.pc file | |
75 | installation, see README.md for details. | |
76 | * Add INSTALL_MANPAGES CMake option, see README.md for details. | |
77 | * Fix ENABLE_COMPATIBLE_LIBSNDFILE_NAME CMake option, now it works on MinGW | |
78 | platform too. | |
79 | * Fix ENABLE_CPACK CMake option, see README.md for details. | |
80 | * Fix ENABLE_STATIC_RUNTIME and CMAKE_MSVC_RUNTIME_LIBRARY behavior, see | |
81 | README.md for details. | |
82 | * Fix CMake man pages installation bug when sndfile-deinterleave.1 and | |
83 | sndfile-metadata-set.1 were not installed. | |
84 | * Fix sndfile-regtest paths handling on Windows platform, thanks to | |
85 | Gisle Vanem <gvanem@yahoo.no>. | |
86 | ||
87 | Version 1.0.29 (2020-08-15) | |
88 | * Add support for Opus files. | |
89 | * Autotool build system improvements. | |
90 | * CMake build system improvements. | |
91 | * Fixes for: CVE-2017-12562, CVE-2017-17456, CVE-2017-17457, CVE-2018-19661, | |
92 | CVE-2018-19662, CVE-2018-19758 and CVE-2019-3832. | |
93 | * Add BWF v2 loudness parameters. | |
94 | * Wave64: Permit and skip arbitrary chunks prior to the data chunk. | |
95 | * Fix ASAN crash in wavlike_ima_seek(). | |
96 | * Fix IMA-ADPCM encoding for AIFF files. | |
97 | * sndfile-convert: Handle gsm, vox and opus extensions the same way. | |
98 | * Add SFC_SET_OGG_PAGE_LATENCY_MS command to get Ogg page latency for Ogg Opus | |
99 | files. | |
100 | * Fix parsing of some SD2 files. | |
101 | * Documentation updates. | |
102 | * Minor bug fixes and improvements. | |
103 | ||
104 | Version 1.0.28 (2017-04-02) | |
105 | * Fix buffer overruns in FLAC and ID3 handling code. | |
106 | * Move to variable length header storage. | |
107 | * Fix detection of Large File Support for 32 bit systems. | |
108 | * Remove large stack allocations in ALAC handling code. | |
109 | * Remove all use of Variable Length Arrays. | |
110 | * Minor bug fixes and improvements. | |
111 | ||
112 | Version 1.0.27 (2016-06-19) | |
113 | * Fix an SF_INFO seekable flag regression introduced in 1.0.26. | |
114 | * Fix potential infinite loops on malformed input files. | |
115 | * Add string metadata read/write for CAF and RF64. | |
116 | * Add handling of CUE chunks. | |
117 | * Fix endian-ness issues in PAF files. | |
118 | * Minor bug fixes and improvements. | |
119 | ||
120 | Version 1.0.26 (2015-11-22) | |
121 | * Fix for CVE-2014-9496, SD2 buffer read overflow. | |
122 | * Fix for CVE-2014-9756, file_io.c divide by zero. | |
123 | * Fix for CVE-2015-7805, AIFF heap write overflow. | |
124 | * Add support for ALAC encoder in a CAF container. | |
125 | * Add support for Cart chunks in WAV files. | |
126 | * Minor bug fixes and improvements. | |
127 | ||
128 | Version 1.0.25 (2011-07-13) | |
129 | * Fix for Secunia Advisory SA45125, heap overflow in PAF file handler. | |
130 | * Accept broken WAV files with blockalign == 0. | |
131 | * Minor bug fixes and improvements. | |
132 | ||
133 | Version 1.0.24 (2011-03-23) | |
134 | * WAV files now have an 18 byte u-law and A-law fmt chunk. | |
135 | * Document virtual I/O functionality. | |
136 | * Two new methods rawHandle() and takeOwnership() in sndfile.hh. | |
137 | * AIFF fix for non-zero offset value in SSND chunk. | |
138 | * Minor bug fixes and improvements. | |
139 | ||
140 | Version 1.0.23 (2010-10-10) | |
141 | * Add version metadata to Windows DLL. | |
142 | * Add a missing 'inline' to sndfile.hh. | |
143 | * Update docs. | |
144 | * Minor bug fixes and improvements. | |
145 | ||
146 | Version 1.0.22 (2010-10-04) | |
147 | * Couple of fixes for SDS file writer. | |
148 | * Fixes arising from static analysis. | |
149 | * Handle FLAC files with ID3 meta data at start of file. | |
150 | * Handle FLAC files which report zero length. | |
151 | * Other minor bug fixes and improvements. | |
152 | ||
153 | Version 1.0.21 (2009-12-13) | |
154 | * Add a couple of new binary programs to programs/ dir. | |
155 | * Remove sndfile-jackplay (now in sndfile-tools package). | |
156 | * Add windows only function sf_wchar_open(). | |
157 | * Bunch of minor bug fixes. | |
158 | ||
159 | Version 1.0.20 (2009-05-14) | |
160 | * Fix potential heap overflow in VOC file parser (Tobias Klein, http://www.trapkit.de/). | |
161 | ||
162 | Version 1.0.19 (2009-03-02) | |
163 | * Fix for CVE-2009-0186 (Alin Rad Pop, Secunia Research). | |
164 | * Huge number of minor bug fixes as a result of static analysis. | |
165 | ||
166 | Version 1.0.18 (2009-02-07) | |
167 | * Add Ogg/Vorbis support (thanks to John ffitch). | |
168 | * Remove captive FLAC library. | |
169 | * Many new features and bug fixes. | |
170 | * Generate Win32 and Win64 pre-compiled binaries. | |
171 | ||
172 | Version 1.0.17 (2006-08-31) | |
173 | * Add sndfile.hh C++ wrapper. | |
174 | * Update Win32 MinGW build instructions. | |
175 | * Minor bug fixes and cleanups. | |
176 | ||
177 | Version 1.0.16 (2006-04-30) | |
178 | * Add support for Broadcast (BEXT) chunks in WAV files. | |
179 | * Implement new commands SFC_GET_SIGNAL_MAX and SFC_GET_MAX_ALL_CHANNELS. | |
180 | * Add support for RIFX (big endian WAV variant). | |
181 | * Fix configure script bugs. | |
182 | * Fix bug in INST and MARK chunk writing for AIFF files. | |
183 | ||
184 | Version 1.0.15 (2006-03-16) | |
185 | * Fix some ia64 issues. | |
186 | * Fix precompiled DLL. | |
187 | * Minor bug fixes. | |
188 | ||
189 | Version 1.0.14 (2006-02-19) | |
190 | * Really fix MinGW compile problems. | |
191 | * Minor bug fixes. | |
192 | ||
193 | Version 1.0.13 (2006-01-21) | |
194 | * Fix for MinGW compiler problems. | |
195 | * Allow readin/write of instrument chunks from WAV and AIFF files. | |
196 | * Compile problem fix for Solaris compiler. | |
197 | * Minor cleanups and bug fixes. | |
198 | ||
199 | Version 1.0.12 (2005-09-30) | |
200 | * Add support for FLAC and Apple's Core Audio Format (CAF). | |
201 | * Add virtual I/O interface (still needs docs). | |
202 | * Cygwin and other Win32 fixes. | |
203 | * Minor bug fixes and cleanups. | |
204 | ||
205 | Version 1.0.11 (2004-11-15) | |
206 | * Add support for SD2 files. | |
207 | * Add read support for loop info in WAV and AIFF files. | |
208 | * Add more tests. | |
209 | * Improve type safety. | |
210 | * Minor optimisations and bug fixes. | |
211 | ||
212 | Version 1.0.10 (2004-06-15) | |
213 | * Fix AIFF read/write mode bugs. | |
214 | * Add support for compiling Win32 DLLS using MinGW. | |
215 | * Fix problems resulting in failed compiles with gcc-2.95. | |
216 | * Improve test suite. | |
217 | * Minor bug fixes. | |
218 | ||
219 | Version 1.0.9 (2004-03-30) | |
220 | * Add handling of AVR (Audio Visual Research) files. | |
221 | * Improve handling of WAVEFORMATEXTENSIBLE WAV files. | |
222 | * Fix for using pipes on Win32. | |
223 | ||
224 | Version 1.0.8 (2004-03-14) | |
225 | * Correct peak chunk handing for files with > 16 tracks. | |
226 | * Fix for WAV files with huge number of CUE chunks. | |
227 | ||
228 | Version 1.0.7 (2004-02-25) | |
229 | * Fix clip mode detection on ia64, MIPS and other CPUs. | |
230 | * Fix two MacOSX build problems. | |
231 | ||
232 | Version 1.0.6 (2004-02-08) | |
233 | * Added support for native Win32 file access API (Ross Bencina). | |
234 | * New mode to add clippling then a converting from float/double to integer | |
235 | would otherwise wrap around. | |
236 | * Fixed a bug in reading/writing files > 2Gig on Linux, Solaris and others. | |
237 | * Many minor bug fixes. | |
238 | * Other random fixes for Win32. | |
239 | ||
240 | Version 1.0.5 (2003-05-03) | |
241 | * Added support for HTK files. | |
242 | * Added new function sf_open_fd() to allow for secure opening of temporary | |
243 | files as well as reading/writing sound files embedded within larger | |
244 | container files. | |
245 | * Added string support for AIFF files. | |
246 | * Minor bug fixes and code cleanups. | |
247 | ||
248 | Version 1.0.4 (2003-02-02) | |
249 | * Added suport of PVF and XI files. | |
250 | * Added functionality for setting and retreiving strings from sound files. | |
251 | * Minor code cleanups and bug fixes. | |
252 | ||
253 | Version 1.0.3 (2002-12-09) | |
254 | * Minor bug fixes. | |
255 | ||
256 | Version 1.0.2 (2002-11-24) | |
257 | * Added support for VOX ADPCM. | |
258 | * Improved error reporting. | |
259 | * Added version scripting on Linux and Solaris. | |
260 | * Minor bug fixes. | |
261 | ||
262 | Version 1.0.1 (2002-09-14) | |
263 | * Added MAT and MAT5 file formats. | |
264 | * Minor bug fixes. | |
265 | ||
266 | Version 1.0.0 (2002-08-16) | |
267 | * Final release for 1.0.0. | |
268 | ||
269 | Version 1.0.0rc6 (2002-08-14) | |
270 | * Release candidate 6 for the 1.0.0 series. | |
271 | * MacOS9 fixes. | |
272 | ||
273 | Version 1.0.0rc5 (2002-08-10) | |
274 | * Release candidate 5 for the 1.0.0 series. | |
275 | * Changed the definition of sf_count_t which was causing problems when | |
276 | libsndfile was compiled with other libraries (ie WxWindows). | |
277 | * Minor bug fixes. | |
278 | * Documentation cleanup. | |
279 | ||
280 | Version 1.0.0rc4 (2002-08-03) | |
281 | * Release candidate 4 for the 1.0.0 series. | |
282 | * Minor bug fixes. | |
283 | * Fix broken Win32 "make check". | |
284 | ||
285 | Version 1.0.0rc3 (2002-08-02) | |
286 | * Release candidate 3 for the 1.0.0 series. | |
287 | * Fix bug where libsndfile was reading beyond the end of the data chunk. | |
288 | * Added on-the-fly header updates on write. | |
289 | * Fix a couple of documentation issues. | |
290 | ||
291 | Version 1.0.0rc2 (2002-06-24) | |
292 | * Release candidate 2 for the 1.0.0 series. | |
293 | * Fix compile problem for Win32. | |
294 | ||
295 | Version 1.0.0rc1 (2002-06-24) | |
296 | * Release candidate 1 for the 1.0.0 series. | |
297 | ||
298 | Version 0.0.28 (2002-04-27) | |
299 | * Last offical release of 0.0.X series of the library. | |
300 | ||
301 | Version 0.0.8 (1999-02-16) | |
302 | * First offical release. |
0 | This is libsndfile, 1.0.29 | |
0 | This is libsndfile, 1.1.0 | |
1 | 1 | |
2 | 2 | libsndfile is a library of C routines for reading and writing |
3 | 3 | files containing sampled audio data. |
17 | 17 | ## Hacking |
18 | 18 | |
19 | 19 | The canonical source code repository for libsndfile is at |
20 | [http://libsndfile.github.io/libsndfile/][github]. | |
20 | <https://github.com/libsndfile/libsndfile>. | |
21 | 21 | |
22 | 22 | You can grab the source code using: |
23 | 23 | |
32 | 32 | Setting up a build environment for libsndfile on Debian or Ubuntu is as simple as: |
33 | 33 | |
34 | 34 | sudo apt install autoconf autogen automake build-essential libasound2-dev \ |
35 | libflac-dev libogg-dev libtool libvorbis-dev libopus-dev pkg-config python | |
35 | libflac-dev libogg-dev libtool libvorbis-dev libopus-dev libmp3lame-dev \ | |
36 | libmpg123-dev pkg-config python | |
36 | 37 | |
37 | 38 | For other Linux distributions or any of the *BSDs, the setup should be similar |
38 | 39 | although the package install tools and package names may be slightly different. |
39 | 40 | |
40 | 41 | Similarly on Mac OS X, assuming [brew] is already installed: |
41 | 42 | |
42 | brew install autoconf autogen automake flac libogg libtool libvorbis opus pkg-config | |
43 | brew install autoconf autogen automake flac libogg libtool libvorbis opus mpg123 pkg-config | |
43 | 44 | |
44 | 45 | Once the build environment has been set up, building and testing libsndfile is |
45 | 46 | as simple as: |
133 | 134 | `ON` by default. Setting `BUILD_SHARED_LIBS` to `ON` disables this option. |
134 | 135 | * `ENABLE_EXTERNAL_LIBS` - enable Ogg, Vorbis, FLAC and Opus support. This |
135 | 136 | option is available and set to `ON` if all dependency libraries were found. |
137 | * `ENABLE_MPEG` - MP3 support. This option is available and set to `ON` if all | |
138 | dependency libraries were found. | |
136 | 139 | * `ENABLE_CPU_CLIP` - enable tricky cpu specific clipper. Enabled and set to |
137 | 140 | `ON` when CPU clips negative\positive. Don't touch it if you are not sure |
138 | 141 | * `ENABLE_BOW_DOCS` - enable black-on-white documentation theme, `OFF` by |
231 | 234 | |
232 | 235 | C/C++ -> Code Generation -> Runtime Library |
233 | 236 | |
234 | Dynamic version of system CRT library is defaut and it means that end user needs | |
237 | Dynamic version of system CRT library is default and it means that end user needs | |
235 | 238 | to have the same runtime library installed on his system. Most likely it is so, |
236 | 239 | but if it is not, the user will see this error message using libsndfile DLL: |
237 | 240 | |
269 | 272 | |
270 | 273 | Second advice is about Ogg, Vorbis FLAC and Opus support. Searching external |
271 | 274 | libraries under Windows is a little bit tricky. The best way is to use |
272 | [Vcpkg](https://github.com/Microsoft/vcpkg). You need to install static libogg, | |
273 | libvorbis, libflac and libopus libraries: | |
274 | ||
275 | vcpkg install libogg:x64-windows-static libvorbis:x64-windows-static | |
276 | libflac:x64-windows-static opus:x64-windows-static libogg:x86-windows-static | |
277 | libvorbis:x86-windows-static libflac:x86-windows-static opus:x86-windows-static | |
278 | ||
279 | Then and add this parameter to cmake command line: | |
275 | [Vcpkg](https://github.com/Microsoft/vcpkg). | |
276 | ||
277 | Install Vcpkg and then add this parameter to cmake command line: | |
280 | 278 | |
281 | 279 | -DCMAKE_TOOLCHAIN_FILE=<path-to-vcpkg>/scripts/buildsystems/vcpkg.cmake |
282 | 280 | |
283 | You also need to set `VCPKG_TARGET_TRIPLET` because you use static libraries: | |
281 | You also need to set `VCPKG_TARGET_TRIPLET` if you want to use static libraries: | |
284 | 282 | |
285 | 283 | -DVCPKG_TARGET_TRIPLET=x64-windows-static |
284 | ||
285 | Then you need to install static libogg, libvorbis, libflac, libopus, mpg123 and | |
286 | mp3lame Vcpkg packages. | |
287 | ||
288 | After 1.1.0beta2 you don't need to install dependencies manually. Libsndfile | |
289 | now supports [Vcpkg manifest mode](https://vcpkg.readthedocs.io/en/latest/users/manifests/) | |
290 | and all dependencies are installed automatically. | |
291 | ||
292 | However, you can turn off the manifest mode and return to the classic mode using | |
293 | the `VCPKG_MANIFEST_MODE` parameter from the command line: | |
294 | ||
295 | -DVCPKG_MANIFEST_MODE=OFF | |
296 | ||
297 | In classic mode, you need to install the required libraries manually: | |
298 | ||
299 | vcpkg install libvorbis:x64-windows-static libflac:x64-windows-static | |
300 | opus:x64-windows-static mp3lame:x86-windows-static mpg123:x86-windows-static | |
301 | libvorbis:x86-windows-static libflac:x86-windows-static | |
302 | opus:x86-windows-static mp3lame:x86-windows-static mpg123:x86-windows-static | |
286 | 303 | |
287 | 304 | **Note**: Use must use the same CRT library for external libraries and the |
288 | 305 | libsndfile library itself. For `*-static` triplets Vcpkg uses |
0 | # Security Policy | |
1 | ||
2 | ## Supported Versions | |
3 | ||
4 | | Version | Supported | | |
5 | | ------- | ------------------ | | |
6 | | 1.1.x | :white_check_mark: | | |
7 | ||
8 | ## Reporting a Vulnerability | |
9 | ||
10 | Please send report privately to evpobry@gmail.com, and include how would you like to be credited. |
0 | # - Find lame | |
1 | # Find the native lame includes and libraries | |
2 | # | |
3 | # LAME_INCLUDE_DIRS - where to find lame.h, etc. | |
4 | # LAME_LIBRARIES - List of libraries when using lame. | |
5 | # LAME_FOUND - True if Lame found. | |
6 | ||
7 | if (LAME_INCLUDE_DIR) | |
8 | # Already in cache, be silent | |
9 | set(LAME_FIND_QUIETLY TRUE) | |
10 | endif () | |
11 | ||
12 | find_path (LAME_INCLUDE_DIR lame/lame.h | |
13 | HINTS | |
14 | ${LAME_ROOT} | |
15 | ) | |
16 | ||
17 | # MSVC built lame may be named mp3lame_static. | |
18 | # The provided project files name the library with the lib prefix. | |
19 | ||
20 | find_library (LAME_LIBRARY | |
21 | NAMES | |
22 | mp3lame | |
23 | mp3lame_static | |
24 | libmp3lame | |
25 | libmp3lame_static | |
26 | libmp3lame-static | |
27 | HINTS | |
28 | ${LAME_ROOT} | |
29 | ) | |
30 | ||
31 | find_library (LAME_HIP_LIBRARY | |
32 | NAMES | |
33 | mpghip-static | |
34 | libmpghip-static | |
35 | HINTS | |
36 | ${LAME_ROOT} | |
37 | ) | |
38 | ||
39 | # Handle the QUIETLY and REQUIRED arguments and set LAME_FOUND | |
40 | # to TRUE if all listed variables are TRUE. | |
41 | include(FindPackageHandleStandardArgs) | |
42 | find_package_handle_standard_args (Lame | |
43 | REQUIRED_VARS | |
44 | LAME_LIBRARY | |
45 | LAME_INCLUDE_DIR | |
46 | ) | |
47 | ||
48 | if (LAME_FOUND) | |
49 | set (LAME_LIBRARIES ${LAME_LIBRARY} ${LAME_HIP_LIBRARY}) | |
50 | set (LAME_INCLUDE_DIRS ${LAME_INCLUDE_DIR}) | |
51 | ||
52 | if (NOT TARGET Lame::Lame) | |
53 | add_library (Lame::Lame UNKNOWN IMPORTED) | |
54 | set_target_properties (Lame::Lame PROPERTIES | |
55 | INTERFACE_INCLUDE_DIRECTORIES "${LAME_INCLUDE_DIRS}" | |
56 | IMPORTED_LOCATION "${LAME_LIBRARY}" | |
57 | ) | |
58 | if (LAME_HIP_LIBRARY) | |
59 | set_property (TARGET Lame::Lame APPEND PROPERTY | |
60 | INTERFACE_LINK_LIBRARIES "${LAME_HIP_LIBRARY}") | |
61 | endif () | |
62 | endif () | |
63 | endif () | |
64 | ||
65 | mark_as_advanced(LAME_INCLUDE_DIR LAME_LIBRARY LAME_HIP_LIBRARY) |
0 | # - Find mpg123 | |
1 | # Find the native mpg123 includes and libraries | |
2 | # | |
3 | # MPG123_INCLUDE_DIRS - where to find mpg123.h, etc. | |
4 | # MPG123_LIBRARIES - List of libraries when using mpg123. | |
5 | # MPG123_FOUND - True if Mpg123 found. | |
6 | ||
7 | if (MPG123_INCLUDE_DIR) | |
8 | # Already in cache, be silent | |
9 | set(MPG123_FIND_QUIETLY TRUE) | |
10 | endif () | |
11 | ||
12 | find_package (PkgConfig QUIET) | |
13 | pkg_check_modules(PC_MPG123 QUIET libmpg123>=1.25.10) | |
14 | ||
15 | set (MPG123_VERSION ${PC_MPG123_VERSION}) | |
16 | ||
17 | find_path (MPG123_INCLUDE_DIR mpg123.h | |
18 | HINTS | |
19 | ${PC_MPG123_INCLUDEDIR} | |
20 | ${PC_MPG123_INCLUDE_DIRS} | |
21 | ${MPG123_ROOT} | |
22 | ) | |
23 | ||
24 | # MSVC built mpg123 may be named mpg123_static. | |
25 | # The provided project files name the library with the lib prefix. | |
26 | ||
27 | find_library (MPG123_LIBRARY | |
28 | NAMES | |
29 | mpg123 | |
30 | mpg123_static | |
31 | libmpg123 | |
32 | libmpg123_static | |
33 | HINTS | |
34 | ${PC_MPG123_LIBDIR} | |
35 | ${PC_MPG123_LIBRARY_DIRS} | |
36 | ${MPG123_ROOT} | |
37 | ) | |
38 | ||
39 | # Handle the QUIETLY and REQUIRED arguments and set MPG123_FOUND | |
40 | # to TRUE if all listed variables are TRUE. | |
41 | include(FindPackageHandleStandardArgs) | |
42 | find_package_handle_standard_args (Mpg123 | |
43 | REQUIRED_VARS | |
44 | MPG123_LIBRARY | |
45 | MPG123_INCLUDE_DIR | |
46 | VERSION_VAR | |
47 | MPG123_VERSION | |
48 | ) | |
49 | ||
50 | if (MPG123_FOUND) | |
51 | set (MPG123_LIBRARIES ${MPG123_LIBRARY}) | |
52 | set (MPG123_INCLUDE_DIRS ${MPG123_INCLUDE_DIR}) | |
53 | ||
54 | if (NOT TARGET MPG123::libmpg123) | |
55 | add_library (MPG123::libmpg123 UNKNOWN IMPORTED) | |
56 | set_target_properties (MPG123::libmpg123 PROPERTIES | |
57 | INTERFACE_INCLUDE_DIRECTORIES "${MPG123_INCLUDE_DIRS}" | |
58 | IMPORTED_LOCATION "${MPG123_LIBRARIES}" | |
59 | ) | |
60 | endif () | |
61 | endif () | |
62 | ||
63 | mark_as_advanced(MPG123_INCLUDE_DIR MPG123_LIBRARY) |
0 | # Inspiration: https://github.com/ros2-dotnet/Fast-RTPS | |
1 | ||
2 | macro (SETUP_ABI_VERSIONS) | |
3 | ||
4 | file (STRINGS ${PROJECT_SOURCE_DIR}/configure.ac CONFIGURE_AC_CONTENT) | |
5 | file (STRINGS | |
6 | configure.ac | |
7 | SNDFILE_LT_CURRENT_TMP | |
8 | REGEX "^m4_define\\(\\[?lt_current\\]?, *\\[?[0-9]+\\]?\\)" | |
9 | ) | |
10 | string (REGEX REPLACE "m4_define\\(\\[?lt_current\\]?, *\\[?([0-9]+)\\]?\\)" | |
11 | "\\1" | |
12 | SNDFILE_LT_CURRENT | |
13 | ${SNDFILE_LT_CURRENT_TMP} | |
14 | ) | |
15 | ||
16 | file (STRINGS | |
17 | configure.ac | |
18 | SNDFILE_LT_REVISION_TMP | |
19 | REGEX "^m4_define\\(\\[?lt_revision\\]?, *\\[?[0-9]+\\]?\\)" | |
20 | ) | |
21 | string (REGEX REPLACE "m4_define\\(\\[?lt_revision\\]?, *\\[?([0-9]+)\\]?\\)" | |
22 | "\\1" | |
23 | SNDFILE_LT_REVISION | |
24 | ${SNDFILE_LT_REVISION_TMP} | |
25 | ) | |
26 | ||
27 | file (STRINGS | |
28 | configure.ac | |
29 | SNDFILE_LT_AGE_TMP | |
30 | REGEX "^m4_define\\(\\[?lt_age\\]?, *\\[?[0-9]+\\]?\\)" | |
31 | ) | |
32 | string (REGEX REPLACE "m4_define\\(\\[?lt_age\\]?, *\\[?([0-9]+)\\]?\\)" | |
33 | "\\1" | |
34 | SNDFILE_LT_AGE | |
35 | ${SNDFILE_LT_AGE_TMP} | |
36 | ) | |
37 | ||
38 | # | |
39 | # Calculate CMake compatible ABI version from libtool version. | |
40 | # | |
41 | ||
42 | math (EXPR SNDFILE_ABI_VERSION_MAJOR "${SNDFILE_LT_CURRENT} - ${SNDFILE_LT_AGE}") | |
43 | set (SNDFILE_ABI_VERSION_MINOR ${SNDFILE_LT_AGE}) | |
44 | set (SNDFILE_ABI_VERSION_PATCH ${SNDFILE_LT_REVISION}) | |
45 | set (SNDFILE_ABI_VERSION "${SNDFILE_ABI_VERSION_MAJOR}.${SNDFILE_ABI_VERSION_MINOR}.${SNDFILE_ABI_VERSION_PATCH}") | |
46 | ||
47 | # | |
48 | # Apple platform current and compatibility versions. | |
49 | # | |
50 | ||
51 | math (EXPR SNDFILE_MACHO_CURRENT_VERSION_MAJOR "${SNDFILE_ABI_VERSION_MAJOR} + ${SNDFILE_ABI_VERSION_MINOR} + 1") | |
52 | set (SNDFILE_MACHO_CURRENT_VERSION "${SNDFILE_MACHO_CURRENT_VERSION_MAJOR}.${SNDFILE_ABI_VERSION_PATCH}.0") | |
53 | set (SNDFILE_MACHO_COMPATIBILITY_VERSION "${SNDFILE_MACHO_CURRENT_VERSION_MAJOR}.0.0") | |
54 | ||
55 | endmacro (SETUP_ABI_VERSIONS) |
54 | 54 | else () |
55 | 55 | set (HAVE_EXTERNAL_XIPH_LIBS 0) |
56 | 56 | endif () |
57 | ||
58 | find_package (Lame) | |
59 | find_package (Mpg123 1.25.10) | |
60 | if (LAME_FOUND AND (TARGET MPG123::libmpg123)) | |
61 | set (HAVE_MPEG_LIBS 1) | |
62 | else () | |
63 | set (HAVE_MPEG_LIBS 0) | |
64 | endif() | |
57 | 65 | |
58 | 66 | find_package (Speex) |
59 | 67 | find_package (SQLite3) |
69 | 77 | check_include_file (sys/types.h HAVE_SYS_TYPES_H) |
70 | 78 | check_include_file (unistd.h HAVE_UNISTD_H) |
71 | 79 | check_include_file (immintrin.h HAVE_IMMINTRIN_H) |
80 | check_include_file (stdbool.h HAVE_STDBOOL_H) | |
72 | 81 | |
73 | 82 | check_cpu_arch_x86 (CPU_IS_X86) |
74 | 83 | check_cpu_arch_x64 (CPU_IS_X64) |
3 | 3 | set(SndFile_VERSION_PATCH @PROJECT_VERSION_PATCH@) |
4 | 4 | |
5 | 5 | set (SndFile_WITH_EXTERNAL_LIBS @SndFile_WITH_EXTERNAL_LIBS@) |
6 | set (SndFile_WITH_MPEG @SndFile_WITH_MPEG@) | |
6 | 7 | |
7 | 8 | @PACKAGE_INIT@ |
8 | 9 | |
13 | 14 | find_dependency (Vorbis) |
14 | 15 | find_dependency (FLAC) |
15 | 16 | find_dependency (Opus) |
17 | endif () | |
18 | ||
19 | if (SndFile_WITH_MPEG AND NOT @BUILD_SHARED_LIBS@) | |
20 | find_dependency (Lame) | |
21 | find_dependency (MPG123) | |
16 | 22 | endif () |
17 | 23 | |
18 | 24 | include (${CMAKE_CURRENT_LIST_DIR}/SndFileTargets.cmake) |
0 | dnl Copyright (C) 1999-2021 Erik de Castro Lopo <erikd@mega-nerd.com>. | |
0 | dnl Copyright (C) 1999-2022 Erik de Castro Lopo <erikd@mega-nerd.com>. | |
1 | 1 | |
2 | 2 | dnl Require autoconf version >= 2.69 |
3 | 3 | AC_PREREQ([2.69]) |
4 | 4 | |
5 | AC_INIT([libsndfile],[1.0.31],[sndfile@mega-nerd.com], | |
5 | AC_INIT([libsndfile],[1.1.0],[sndfile@mega-nerd.com], | |
6 | 6 | [libsndfile],[http://libsndfile.github.io/libsndfile/]) |
7 | 7 | |
8 | 8 | dnl Check whether we want to set defaults for CFLAGS, CXXFLAGS, CPPFLAGS and LDFLAGS |
29 | 29 | AC_CONFIG_MACRO_DIR([m4]) |
30 | 30 | AC_CONFIG_HEADERS([src/config.h]) |
31 | 31 | |
32 | AM_INIT_AUTOMAKE([1.14 foreign dist-bzip2 no-dist-gzip serial-tests subdir-objects]) | |
32 | AM_INIT_AUTOMAKE([1.14 foreign dist-xz no-dist-gzip serial-tests subdir-objects]) | |
33 | 33 | AM_SILENT_RULES([yes]) |
34 | 34 | |
35 | 35 | dnl ==================================================================================== |
56 | 56 | AC_PROG_SED |
57 | 57 | AM_PROG_AR |
58 | 58 | |
59 | LT_INIT([win32-dll]) | |
59 | LT_INIT([disable-static win32-dll]) | |
60 | 60 | LT_PROG_RC |
61 | 61 | |
62 | 62 | AC_PROG_INSTALL |
83 | 83 | dnl age. |
84 | 84 | dnl 6. If any interfaces have been removed since the last public release, then set age |
85 | 85 | dnl to 0. |
86 | SHARED_VERSION_INFO="1:31:0" | |
86 | ||
87 | dnl This is libtool version of library, we add it to `--version-info` property. | |
88 | ||
89 | m4_define([lt_current], [1]) | |
90 | m4_define([lt_revision], [34]) | |
91 | m4_define([lt_age], [0]) | |
92 | ||
93 | dnl This is ABI version for linker scripts, CMake uses the same format for | |
94 | dnl VERSION property of shared library. | |
95 | dnl The formula is: c:r:a -> c-a:a:r | |
96 | ||
97 | m4_define([abi_version_major], [m4_eval(lt_current - lt_age)]) | |
98 | m4_define([abi_version_minor], [lt_age]) | |
99 | m4_define([abi_version_patch], [lt_revision]) | |
87 | 100 | |
88 | 101 | dnl ------------------------------------------------------------------------------------ |
89 | ||
90 | AC_HEADER_STDC | |
91 | 102 | |
92 | 103 | AC_CHECK_HEADERS([endian.h]) |
93 | 104 | AC_CHECK_HEADERS([byteswap.h]) |
94 | 105 | AC_CHECK_HEADERS([locale.h]) |
95 | 106 | AC_CHECK_HEADERS([sys/time.h]) |
96 | 107 | AC_CHECK_HEADERS([immintrin.h]) |
108 | AC_CHECK_HEADERS([stdbool.h]) | |
97 | 109 | |
98 | 110 | AC_HEADER_SYS_WAIT |
99 | 111 | |
128 | 140 | AC_ARG_ENABLE([werror], |
129 | 141 | [AS_HELP_STRING([--enable-werror], [enable -Werror in all Makefiles])]) |
130 | 142 | |
131 | AC_ARG_ENABLE([stack-smash-protection], | |
132 | [AS_HELP_STRING([--enable-stack-smash-protection], [Enable GNU GCC stack smash protection])]) | |
133 | ||
134 | 143 | AC_ARG_ENABLE([cpu-clip], |
135 | 144 | [AS_HELP_STRING([--disable-cpu-clip], [disable tricky cpu specific clipper])]) |
136 | 145 | |
145 | 154 | |
146 | 155 | AC_ARG_ENABLE([external-libs], |
147 | 156 | [AS_HELP_STRING([--disable-external-libs], [disable use of FLAC, Ogg and Vorbis [[default=no]]])]) |
157 | ||
158 | AC_ARG_ENABLE([mpeg], | |
159 | [AS_HELP_STRING([--disable-mpeg], [disable use of LAME/MPG123 for MPEG (MP3) [[defaults=no]]])]) | |
148 | 160 | |
149 | 161 | AC_ARG_ENABLE(octave, |
150 | 162 | [AS_HELP_STRING([--enable-octave], [enable building of GNU Octave module])]) |
373 | 385 | fi |
374 | 386 | ], [ |
375 | 387 | AS_ECHO([""]) |
376 | AC_MSG_WARN([[*** One or more of the external libraries (ie libflac, libogg and]]) | |
377 | AC_MSG_WARN([[*** libvorbis) is either missing (possibly only the development]]) | |
388 | AC_MSG_WARN([[*** One or more of the external libraries (ie libflac, libogg,]]) | |
389 | AC_MSG_WARN([[*** libvorbis and libopus) is either missing (possibly only the development]]) | |
378 | 390 | AC_MSG_WARN([[*** headers) or is of an unsupported version.]]) |
379 | 391 | AC_MSG_WARN([[***]]) |
380 | 392 | AC_MSG_WARN([[*** Unfortunately, for ease of maintenance, the external libs]]) |
385 | 397 | ]) |
386 | 398 | |
387 | 399 | AC_DEFINE_UNQUOTED([HAVE_EXTERNAL_XIPH_LIBS], [$HAVE_EXTERNAL_XIPH_LIBS], [Will be set to 1 if flac, ogg, vorbis, and opus are available.]) |
400 | ||
401 | dnl ==================================================================================== | |
402 | dnl Check for MPEG libraris liblame | |
403 | ||
404 | ac_cv_lame="no" | |
405 | ac_cv_mpg123="no" | |
406 | HAVE_MPEG=0 | |
407 | EXTERNAL_MPEG_REQUIRE="" | |
408 | EXTERNAL_MPEG_LIBS="" | |
409 | ||
410 | AS_IF([test -n "$PKG_CONFIG"], [ | |
411 | AS_IF([test "x$enable_mpeg" = "xno"], [ | |
412 | AC_MSG_WARN([[*** MPEG (Lame/MPG123) disabled. ***]]) | |
413 | ], [ | |
414 | AC_CHECK_HEADER(lame/lame.h, | |
415 | lame_header_found="yes", | |
416 | lame_header_found="no") | |
417 | AC_SEARCH_LIBS(lame_set_VBR_q, [lame mp3lame], [lame_lib_found="yes"], [lame_lib_found="no"]) | |
418 | AS_IF([test "x$lame_lib_found$lame_header_found" = "xyesyes"], [ | |
419 | ac_cv_lame="yes" | |
420 | ], [ | |
421 | AC_MSG_WARN([["MPEG support selected but external Lame library cannot be found.]]) | |
422 | ]) | |
423 | ||
424 | PKG_CHECK_MOD_VERSION([MPG123], [libmpg123 >= 1.25.10], [ | |
425 | ac_cv_mpg123="yes" | |
426 | ], [ | |
427 | AC_MSG_WARN([["MPEG support selected but external MPG123 library cannot be found.]]) | |
428 | ]) | |
429 | ||
430 | AS_IF([test "x$ac_cv_lame$ac_cv_mpg123" = "xyesyes"], [ | |
431 | enable_mpeg="yes" | |
432 | HAVE_MPEG=1 | |
433 | EXTERNAL_MPEG_REQUIRE="libmpg123" | |
434 | EXTERNAL_MPEG_LIBS="-lmp3lame" | |
435 | MPEG_CFLAGS="$MPG123_CFLAGS" | |
436 | MPEG_LIBS="$MPG123_LIBS" | |
437 | ], [ | |
438 | enable_mpeg="no" | |
439 | AS_ECHO([""]) | |
440 | AC_MSG_WARN([[*** MPEG support disabled.]]) | |
441 | AS_ECHO([""]) | |
442 | ]) | |
443 | ]) | |
444 | ]) | |
445 | ||
446 | AC_DEFINE_UNQUOTED([HAVE_MPEG], [$HAVE_MPEG], [Will be set to 1 if lame, mpg123 mpeg support is available.]) | |
388 | 447 | |
389 | 448 | dnl ==================================================================================== |
390 | 449 | dnl Check for libsqlite3 (only used in regtest). |
573 | 632 | AC_LANG_POP([C++]) |
574 | 633 | ]) |
575 | 634 | |
576 | common_flags="-Wall -Wextra -Wpointer-arith -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wundef -Wuninitialized -Winit-self -Wno-format-truncation" | |
577 | AX_APPEND_COMPILE_FLAGS([${common_flags} -Wvla -Wbad-function-cast -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Waggregate-return], [CFLAGS]) | |
635 | common_flags="-Wall -Wextra -Wpointer-arith -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wundef -Wuninitialized -Winit-self" | |
636 | common_cflags="${common_flags}" | |
637 | dnl Clang doesn't know about -Wno-format-truncation | |
638 | dnl and would spew tons of warnings otherwise. | |
639 | AS_IF([test "x$ax_cv_c_compiler_vendor" = "xgnu"], [ | |
640 | common_cflags+=" -Wno-format-truncation" | |
641 | ]) | |
642 | common_cxxflags="${common_flags}" | |
643 | AS_IF([test "x$ax_cv_cxx_compiler_vendor" = "xgnu"], [ | |
644 | common_cxxflags+=" -Wno-format-truncation" | |
645 | ]) | |
646 | ||
647 | AX_APPEND_COMPILE_FLAGS([${common_cflags} -Wvla -Wbad-function-cast -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Waggregate-return], [CFLAGS]) | |
578 | 648 | |
579 | 649 | AC_LANG_PUSH([C++]) |
580 | AX_APPEND_COMPILE_FLAGS([${common_flags} -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wreorder -Wsign-promo], [CXXFLAGS]) | |
650 | AX_APPEND_COMPILE_FLAGS([${common_cxxflags} -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wreorder -Wsign-promo], [CXXFLAGS]) | |
581 | 651 | AC_LANG_POP([C++]) |
582 | ||
583 | AS_IF([test "x$enable_stack_smash_protection" = "xyes"], [ | |
584 | XIPH_GCC_STACK_PROTECTOR | |
585 | XIPH_GXX_STACK_PROTECTOR | |
586 | ]) | |
587 | 652 | |
588 | 653 | AS_IF([test "x$enable_test_coverage" = "xyes"], [ |
589 | 654 | AX_APPEND_COMPILE_FLAGS([-coverage], [CFLAGS]) |
637 | 702 | OS_SPECIFIC_LINKS=" -static-libgcc $OS_SPECIFIC_LINKS" |
638 | 703 | ]) |
639 | 704 | |
640 | WIN_RC_VERSION=`echo $PACKAGE_VERSION | $SED -e "s/p.*//" -e "s/\./,/g"` | |
705 | WIN_RC_VERSION=`echo $PACKAGE_VERSION | $SED -e "s/pre.*//" -e "s/beta.*//" -e "s/\./,/g"` | |
641 | 706 | |
642 | 707 | |
643 | 708 | AS_IF([test "x$enable_static" = "xno"], [ |
656 | 721 | AC_SUBST(HTML_FGCOLOUR) |
657 | 722 | |
658 | 723 | AC_SUBST(SHLIB_VERSION_ARG) |
659 | AC_SUBST(SHARED_VERSION_INFO) | |
724 | AC_SUBST([SHARED_VERSION_INFO], [lt_current:lt_revision:lt_age]) | |
725 | AC_SUBST([ABI_VERSION], [abi_version_major.abi_version_minor.abi_version_patch]) | |
660 | 726 | AC_SUBST(CLEAN_VERSION) |
661 | 727 | AC_SUBST(VERSION_MAJOR) |
662 | 728 | AC_SUBST(GEN_TOOL) |
664 | 730 | AC_SUBST(WIN_RC_VERSION) |
665 | 731 | |
666 | 732 | AC_SUBST(HAVE_EXTERNAL_XIPH_LIBS) |
733 | AC_SUBST(HAVE_MPEG) | |
667 | 734 | AC_SUBST(OS_SPECIFIC_CFLAGS) |
668 | 735 | AC_SUBST(OS_SPECIFIC_LINKS) |
669 | 736 | AC_SUBST(SNDIO_LIBS) |
671 | 738 | AC_SUBST(EXTERNAL_XIPH_CFLAGS) |
672 | 739 | AC_SUBST(EXTERNAL_XIPH_LIBS) |
673 | 740 | AC_SUBST(EXTERNAL_XIPH_REQUIRE) |
741 | AC_SUBST(EXTERNAL_MPEG_REQUIRE) | |
742 | AC_SUBST(MPG123_CFLAGS) | |
743 | AC_SUBST(MPG123_LIBS) | |
744 | AC_SUBST(MPEG_CFLAGS) | |
745 | AC_SUBST(MPEG_LIBS) | |
674 | 746 | AC_SUBST(SRC_BINDIR) |
675 | 747 | AC_SUBST(TEST_BINDIR) |
676 | 748 | |
716 | 788 | Experimental code : ................... ${enable_experimental:-no} |
717 | 789 | Using ALSA in example programs : ...... ${enable_alsa:-no} |
718 | 790 | External FLAC/Ogg/Vorbis/Opus : ....... ${enable_external_libs:-no} |
791 | External MPEG Lame/MPG123 : ........... ${enable_mpeg:-no} | |
719 | 792 | Building Octave interface : ........... ${OCTAVE_BUILD} |
720 | 793 | |
721 | 794 | Tools : |
724 | 797 | CXX Compiler Vendor is : .............. ${ax_cv_cxx_compiler_vendor} (${ax_cv_cxx_compiler_version}) |
725 | 798 | |
726 | 799 | Sanitizer enabled : ................... ${enable_sanitizer:-no} |
727 | Stack smash protection : .............. ${enable_stack_smash_protection:-no} | |
728 | 800 | |
729 | 801 | Installation directories : |
730 | 802 |
437 | 437 | |
438 | 438 | ## Q20 : Why doesn't libsndfile support MP3? {#Q020} |
439 | 439 | |
440 | In the past, MP3 was not supported because the technology behind MP3 was | |
440 | ~~In the past, MP3 was not supported because the technology behind MP3 was | |
441 | 441 | patented. Those patents have now expired and there is an |
442 | 442 | [open ticket](https://github.com/libsndfile/libsndfile/issues/258) to implement |
443 | MP3 support. | |
443 | MP3 support.~~ | |
444 | ||
445 | **Update :** Starting from version 1.1.0 libsndfile supports MP3 format. | |
444 | 446 | |
445 | 447 | ## Q21 : How do I use libsndfile in a closed source or commercial program and comply with the license? {#Q021} |
446 | 448 |
0 | 0 | --- |
1 | 1 | author: "The libsndfile team" |
2 | version: "1.0.31" | |
2 | version: "1.1.0" | |
3 | 3 | |
4 | 4 | markdown: kramdown |
5 | 5 | plugins: |
11 | 11 | <a href="#history">History</a> -+- |
12 | 12 | <a href="#features">Features</a> -+- |
13 | 13 | <a href="#similar-or-related-projects">Similar or related projects</a> -+- |
14 | <a href="https://github.com/libsndfile/libsndfile/blob/master/NEWS">News</a> | |
14 | <a href="https://github.com/libsndfile/libsndfile/blob/master/CHANGELOG.md">News</a> | |
15 | 15 | <br> |
16 | 16 | <a href="development.html">Development</a> -+- |
17 | 17 | <a href="api.html">Programming interface</a> -+- |
96 | 96 | the caller has to set the **samplerate**, **channels** and **format** fields to |
97 | 97 | valid values. All other fields of the structure are filled in by the library. |
98 | 98 | |
99 | **Note:** The libsndfile library will reject values for **samplerate** field | |
100 | that are greater than `655350` and values for field **channels** that are | |
101 | greater than `1024`. These values represent the maximum theoretical limit and | |
102 | may be less for specific formats. | |
103 | ||
99 | 104 | When opening a file for write, the caller must fill in structure members |
100 | 105 | **samplerate**, **channels**, and **format**. |
101 | 106 | |
106 | 111 | also include bitmasks for separating major and minor file types. Not all |
107 | 112 | combinations of endian-ness and major and minor file types are valid. |
108 | 113 | |
109 | | Name | Value | Description | | |
110 | |:-----------------------|:-----------|:-------------------------------------------| | |
111 | | **Major formats.** | | |
112 | | SF_FORMAT_WAV | 0x010000 | Microsoft WAV format (little endian). | | |
113 | | SF_FORMAT_AIFF | 0x020000 | Apple/SGI AIFF format (big endian). | | |
114 | | SF_FORMAT_AU | 0x030000 | Sun/NeXT AU format (big endian). | | |
115 | | SF_FORMAT_RAW | 0x040000 | RAW PCM data. | | |
116 | | SF_FORMAT_PAF | 0x050000 | Ensoniq PARIS file format. | | |
117 | | SF_FORMAT_SVX | 0x060000 | Amiga IFF / SVX8 / SV16 format. | | |
118 | | SF_FORMAT_NIST | 0x070000 | Sphere NIST format. | | |
119 | | SF_FORMAT_VOC | 0x080000 | VOC files. | | |
120 | | SF_FORMAT_IRCAM | 0x0A0000 | Berkeley/IRCAM/CARL | | |
121 | | SF_FORMAT_W64 | 0x0B0000 | Sonic Foundry's 64 bit RIFF/WAV | | |
122 | | SF_FORMAT_MAT4 | 0x0C0000 | Matlab (tm) V4.2 / GNU Octave 2.0 | | |
123 | | SF_FORMAT_MAT5 | 0x0D0000 | Matlab (tm) V5.0 / GNU Octave 2.1 | | |
124 | | SF_FORMAT_PVF | 0x0E0000 | Portable Voice Format | | |
125 | | SF_FORMAT_XI | 0x0F0000 | Fasttracker 2 Extended Instrument | | |
126 | | SF_FORMAT_HTK | 0x100000 | HMM Tool Kit format | | |
127 | | SF_FORMAT_SDS | 0x110000 | Midi Sample Dump Standard | | |
128 | | SF_FORMAT_AVR | 0x120000 | Audio Visual Research | | |
129 | | SF_FORMAT_WAVEX | 0x130000 | MS WAVE with WAVEFORMATEX | | |
130 | | SF_FORMAT_SD2 | 0x160000 | Sound Designer 2 | | |
131 | | SF_FORMAT_FLAC | 0x170000 | FLAC lossless file format | | |
132 | | SF_FORMAT_CAF | 0x180000 | Core Audio File format | | |
133 | | SF_FORMAT_WVE | 0x190000 | Psion WVE format | | |
134 | | SF_FORMAT_OGG | 0x200000 | Xiph OGG container | | |
135 | | SF_FORMAT_MPC2K | 0x210000 | Akai MPC 2000 sampler | | |
136 | | SF_FORMAT_RF64 | 0x220000 | RF64 WAV file | | |
137 | | **Subtypes.** | | |
138 | | SF_FORMAT_PCM_S8 | 0x0001 | Signed 8 bit data | | |
139 | | SF_FORMAT_PCM_16 | 0x0002 | Signed 16 bit data | | |
140 | | SF_FORMAT_PCM_24 | 0x0003 | Signed 24 bit data | | |
141 | | SF_FORMAT_PCM_32 | 0x0004 | Signed 32 bit data | | |
142 | | SF_FORMAT_PCM_U8 | 0x0005 | Unsigned 8 bit data (WAV and RAW only) | | |
143 | | SF_FORMAT_FLOAT | 0x0006 | 32 bit float data | | |
144 | | SF_FORMAT_DOUBLE | 0x0007 | 64 bit float data | | |
145 | | SF_FORMAT_ULAW | 0x0010 | U-Law encoded. | | |
146 | | SF_FORMAT_ALAW | 0x0011 | A-Law encoded. | | |
147 | | SF_FORMAT_IMA_ADPCM | 0x0012 | IMA ADPCM. | | |
148 | | SF_FORMAT_MS_ADPCM | 0x0013 | Microsoft ADPCM. | | |
149 | | SF_FORMAT_GSM610 | 0x0020 | GSM 6.10 encoding. | | |
150 | | SF_FORMAT_VOX_ADPCM | 0x0021 | OKI / Dialogix ADPCM | | |
151 | | SF_FORMAT_NMS_ADPCM_16 | 0x0022 | 16kbs NMS G721-variant encoding. | | |
152 | | SF_FORMAT_NMS_ADPCM_24 | 0x0023 | 24kbs NMS G721-variant encoding. | | |
153 | | SF_FORMAT_NMS_ADPCM_32 | 0x0024 | 32kbs NMS G721-variant encoding. | | |
154 | | SF_FORMAT_G721_32 | 0x0030 | 32kbs G721 ADPCM encoding. | | |
155 | | SF_FORMAT_G723_24 | 0x0031 | 24kbs G723 ADPCM encoding. | | |
156 | | SF_FORMAT_G723_40 | 0x0032 | 40kbs G723 ADPCM encoding. | | |
157 | | SF_FORMAT_DWVW_12 | 0x0040 | 12 bit Delta Width Variable Word encoding. | | |
158 | | SF_FORMAT_DWVW_16 | 0x0041 | 16 bit Delta Width Variable Word encoding. | | |
159 | | SF_FORMAT_DWVW_24 | 0x0042 | 24 bit Delta Width Variable Word encoding. | | |
160 | | SF_FORMAT_DWVW_N | 0x0043 | N bit Delta Width Variable Word encoding. | | |
161 | | SF_FORMAT_DPCM_8 | 0x0050 | 8 bit differential PCM (XI only) | | |
162 | | SF_FORMAT_DPCM_16 | 0x0051 | 16 bit differential PCM (XI only) | | |
163 | | SF_FORMAT_VORBIS | 0x0060 | Xiph Vorbis encoding. | | |
164 | | SF_FORMAT_OPUS | 0x0064 | Xiph/Skype Opus encoding. | | |
165 | | SF_FORMAT_ALAC_16 | 0x0070 | Apple Lossless Audio Codec (16 bit). | | |
166 | | SF_FORMAT_ALAC_20 | 0x0071 | Apple Lossless Audio Codec (20 bit). | | |
167 | | SF_FORMAT_ALAC_24 | 0x0072 | Apple Lossless Audio Codec (24 bit). | | |
168 | | SF_FORMAT_ALAC_32 | 0x0073 | Apple Lossless Audio Codec (32 bit). | | |
169 | | **Endian-ness options.** | | |
170 | | SF_ENDIAN_FILE | 0x00000000 | Default file endian-ness. | | |
171 | | SF_ENDIAN_LITTLE | 0x10000000 | Force little endian-ness. | | |
172 | | SF_ENDIAN_BIG | 0x20000000 | Force big endian-ness. | | |
173 | | SF_ENDIAN_CPU | 0x30000000 | Force CPU endian-ness. | | |
174 | | SF_FORMAT_SUBMASK | 0x0000FFFF | | | |
175 | | SF_FORMAT_TYPEMASK | 0x0FFF0000 | | | |
176 | | SF_FORMAT_ENDMASK | 0x30000000 | | | |
114 | | Name | Value | Description | | |
115 | |:-------------------------|:-----------|:-------------------------------------------| | |
116 | | **Major formats.** | | |
117 | | SF_FORMAT_WAV | 0x010000 | Microsoft WAV format (little endian). | | |
118 | | SF_FORMAT_AIFF | 0x020000 | Apple/SGI AIFF format (big endian). | | |
119 | | SF_FORMAT_AU | 0x030000 | Sun/NeXT AU format (big endian). | | |
120 | | SF_FORMAT_RAW | 0x040000 | RAW PCM data. | | |
121 | | SF_FORMAT_PAF | 0x050000 | Ensoniq PARIS file format. | | |
122 | | SF_FORMAT_SVX | 0x060000 | Amiga IFF / SVX8 / SV16 format. | | |
123 | | SF_FORMAT_NIST | 0x070000 | Sphere NIST format. | | |
124 | | SF_FORMAT_VOC | 0x080000 | VOC files. | | |
125 | | SF_FORMAT_IRCAM | 0x0A0000 | Berkeley/IRCAM/CARL | | |
126 | | SF_FORMAT_W64 | 0x0B0000 | Sonic Foundry's 64 bit RIFF/WAV | | |
127 | | SF_FORMAT_MAT4 | 0x0C0000 | Matlab (tm) V4.2 / GNU Octave 2.0 | | |
128 | | SF_FORMAT_MAT5 | 0x0D0000 | Matlab (tm) V5.0 / GNU Octave 2.1 | | |
129 | | SF_FORMAT_PVF | 0x0E0000 | Portable Voice Format | | |
130 | | SF_FORMAT_XI | 0x0F0000 | Fasttracker 2 Extended Instrument | | |
131 | | SF_FORMAT_HTK | 0x100000 | HMM Tool Kit format | | |
132 | | SF_FORMAT_SDS | 0x110000 | Midi Sample Dump Standard | | |
133 | | SF_FORMAT_AVR | 0x120000 | Audio Visual Research | | |
134 | | SF_FORMAT_WAVEX | 0x130000 | MS WAVE with WAVEFORMATEX | | |
135 | | SF_FORMAT_SD2 | 0x160000 | Sound Designer 2 | | |
136 | | SF_FORMAT_FLAC | 0x170000 | FLAC lossless file format | | |
137 | | SF_FORMAT_CAF | 0x180000 | Core Audio File format | | |
138 | | SF_FORMAT_WVE | 0x190000 | Psion WVE format | | |
139 | | SF_FORMAT_OGG | 0x200000 | Xiph OGG container | | |
140 | | SF_FORMAT_MPC2K | 0x210000 | Akai MPC 2000 sampler | | |
141 | | SF_FORMAT_RF64 | 0x220000 | RF64 WAV file | | |
142 | | SF_FORMAT_MPEG | 0x230000 | MPEG-1/2 audio stream | | |
143 | | **Subtypes.** | | |
144 | | SF_FORMAT_PCM_S8 | 0x0001 | Signed 8 bit data | | |
145 | | SF_FORMAT_PCM_16 | 0x0002 | Signed 16 bit data | | |
146 | | SF_FORMAT_PCM_24 | 0x0003 | Signed 24 bit data | | |
147 | | SF_FORMAT_PCM_32 | 0x0004 | Signed 32 bit data | | |
148 | | SF_FORMAT_PCM_U8 | 0x0005 | Unsigned 8 bit data (WAV and RAW only) | | |
149 | | SF_FORMAT_FLOAT | 0x0006 | 32 bit float data | | |
150 | | SF_FORMAT_DOUBLE | 0x0007 | 64 bit float data | | |
151 | | SF_FORMAT_ULAW | 0x0010 | U-Law encoded. | | |
152 | | SF_FORMAT_ALAW | 0x0011 | A-Law encoded. | | |
153 | | SF_FORMAT_IMA_ADPCM | 0x0012 | IMA ADPCM. | | |
154 | | SF_FORMAT_MS_ADPCM | 0x0013 | Microsoft ADPCM. | | |
155 | | SF_FORMAT_GSM610 | 0x0020 | GSM 6.10 encoding. | | |
156 | | SF_FORMAT_VOX_ADPCM | 0x0021 | OKI / Dialogix ADPCM | | |
157 | | SF_FORMAT_NMS_ADPCM_16 | 0x0022 | 16kbs NMS G721-variant encoding. | | |
158 | | SF_FORMAT_NMS_ADPCM_24 | 0x0023 | 24kbs NMS G721-variant encoding. | | |
159 | | SF_FORMAT_NMS_ADPCM_32 | 0x0024 | 32kbs NMS G721-variant encoding. | | |
160 | | SF_FORMAT_G721_32 | 0x0030 | 32kbs G721 ADPCM encoding. | | |
161 | | SF_FORMAT_G723_24 | 0x0031 | 24kbs G723 ADPCM encoding. | | |
162 | | SF_FORMAT_G723_40 | 0x0032 | 40kbs G723 ADPCM encoding. | | |
163 | | SF_FORMAT_DWVW_12 | 0x0040 | 12 bit Delta Width Variable Word encoding. | | |
164 | | SF_FORMAT_DWVW_16 | 0x0041 | 16 bit Delta Width Variable Word encoding. | | |
165 | | SF_FORMAT_DWVW_24 | 0x0042 | 24 bit Delta Width Variable Word encoding. | | |
166 | | SF_FORMAT_DWVW_N | 0x0043 | N bit Delta Width Variable Word encoding. | | |
167 | | SF_FORMAT_DPCM_8 | 0x0050 | 8 bit differential PCM (XI only) | | |
168 | | SF_FORMAT_DPCM_16 | 0x0051 | 16 bit differential PCM (XI only) | | |
169 | | SF_FORMAT_VORBIS | 0x0060 | Xiph Vorbis encoding. | | |
170 | | SF_FORMAT_OPUS | 0x0064 | Xiph/Skype Opus encoding. | | |
171 | | SF_FORMAT_ALAC_16 | 0x0070 | Apple Lossless Audio Codec (16 bit). | | |
172 | | SF_FORMAT_ALAC_20 | 0x0071 | Apple Lossless Audio Codec (20 bit). | | |
173 | | SF_FORMAT_ALAC_24 | 0x0072 | Apple Lossless Audio Codec (24 bit). | | |
174 | | SF_FORMAT_ALAC_32 | 0x0073 | Apple Lossless Audio Codec (32 bit). | | |
175 | | SF_FORMAT_MPEG_LAYER_I | 0x0080 | MPEG-1 Audio Layer I. | | |
176 | | SF_FORMAT_MPEG_LAYER_II | 0x0081 | MPEG-1 Audio Layer II. | | |
177 | | SF_FORMAT_MPEG_LAYER_III | 0x0082 | MPEG-2 Audio Layer III. | | |
178 | | **Endian-ness options.** | | |
179 | | SF_ENDIAN_FILE | 0x00000000 | Default file endian-ness. | | |
180 | | SF_ENDIAN_LITTLE | 0x10000000 | Force little endian-ness. | | |
181 | | SF_ENDIAN_BIG | 0x20000000 | Force big endian-ness. | | |
182 | | SF_ENDIAN_CPU | 0x30000000 | Force CPU endian-ness. | | |
183 | | SF_FORMAT_SUBMASK | 0x0000FFFF | | | |
184 | | SF_FORMAT_TYPEMASK | 0x0FFF0000 | | | |
185 | | SF_FORMAT_ENDMASK | 0x30000000 | | | |
177 | 186 | |
178 | 187 | Every call to **sf_open**() should be matched with a call to |
179 | 188 | [**sf_close**()](#close) to free up memory allocated during the call to **sf_open**(). |
80 | 80 | | [SFC_RF64_AUTO_DOWNGRADE](#sfc_rf64_auto_downgrade) | Set auto downgrade from RF64 to WAV. | |
81 | 81 | | [SFC_GET_ORIGINAL_SAMPLERATE](#sfc_get_original_samplerate) | Get original samplerate metadata. | |
82 | 82 | | [SFC_SET_ORIGINAL_SAMPLERATE](#sfc_set_original_samplerate) | Set original samplerate metadata. | |
83 | | [SFC_GET_BITRATE_MODE](#sfc_get_bitrate_mode) | Get bitrate mode. | |
84 | | [SFC_SET_BITRATE_MODE](#sfc_set_bitrate_mode) | Set bitrate mode. | |
83 | 85 | |
84 | 86 | --- |
85 | 87 | |
1926 | 1928 | On write, can only succeed if no data has been written. On read, if successful, |
1927 | 1929 | [SFC_GET_CURRENT_SF_INFO](#sfc_get_current_sf_info) should be called to |
1928 | 1930 | determine the new frames count and samplerate |
1931 | ||
1932 | ## SFC_GET_BITRATE_MODE | |
1933 | ||
1934 | Get bitrate mode. | |
1935 | ||
1936 | The bitrate mode is one of: | |
1937 | ||
1938 | | Name | Value | Description | | |
1939 | |:-------------------------|:------|:------------------| | |
1940 | | SF_BITRATE_MODE_CONSTANT | 800 | Constant bitrate. | | |
1941 | | SF_BITRATE_MODE_AVERAGE | 801 | Average bitrate. | | |
1942 | | SF_BITRATE_MODE_VARIABLE | 802 | Variable bitrate. | | |
1943 | ||
1944 | ### Parameters | |
1945 | ||
1946 | sndfile | |
1947 | : A valid SNDFILE* pointer | |
1948 | ||
1949 | cmd | |
1950 | : SFC_GET_BITRATE_MODE | |
1951 | ||
1952 | data | |
1953 | : NULL | |
1954 | ||
1955 | datasize | |
1956 | : anything | |
1957 | ||
1958 | ### Return value | |
1959 | ||
1960 | Returns one of `SF_BITRATE_MODE_XXX` on success, `-1` otherwise. | |
1961 | ||
1962 | ## SFC_SET_BITRATE_MODE | |
1963 | ||
1964 | Set bitrate mode. | |
1965 | ||
1966 | The bitrate mode is one of: | |
1967 | ||
1968 | | Name | Value | Description | | |
1969 | |:-------------------------|:------|:------------------| | |
1970 | | SF_BITRATE_MODE_CONSTANT | 800 | Constant bitrate. | | |
1971 | | SF_BITRATE_MODE_AVERAGE | 801 | Average bitrate. | | |
1972 | | SF_BITRATE_MODE_VARIABLE | 802 | Variable bitrate. | | |
1973 | ||
1974 | ### Parameters | |
1975 | ||
1976 | sndfile | |
1977 | : A valid SNDFILE* pointer | |
1978 | ||
1979 | cmd | |
1980 | : SFC_SET_BITRATE_MODE | |
1981 | ||
1982 | data | |
1983 | : pointer to an integer | |
1984 | ||
1985 | datasize | |
1986 | : sizeof (int) | |
1987 | ||
1988 | ### Return value | |
1989 | ||
1990 | Returns `SF_TRUE` on success, `SF_FALSE` otherwise. |
8 | 8 | |
9 | 9 | The main repository can be found on Github: |
10 | 10 | |
11 | <http://libsndfile.github.io/libsndfile/"> | |
11 | <https://github.com/libsndfile/libsndfile/> | |
12 | 12 | |
13 | 13 | and includes [instuctions](https://github.com/libsndfile/libsndfile/blob/master/README.md) |
14 | 14 | on how to build libsndfile from the Git repo. |
39 | 39 | From version 1.0.29, libsndfile can read and write |
40 | 40 | [Ogg/Opus](https://opus-codec.org/). |
41 | 41 | |
42 | From version 1.1.0, libsndfile can read and write MP3. | |
43 | ||
42 | 44 | Some of the file formats I am also interested in adding are: |
43 | 45 | |
44 | 46 | - Kurzweil K2000 sampler files. |
45 | 47 | - Ogg Speex. |
46 | - MPEG Layer 3 (commonly known as MP3) | |
47 | 48 | |
48 | 49 | Other file formats may also be added on request. |
49 | 50 |
141 | 141 | problems, delete old generated sndfile.h from $(top_builddir)/src. |
142 | 142 | * Version 1.0.31 (January 24 2021) Bugfix release. Fix multiple memory leaks |
143 | 143 | reported by OSS-Fuzz. More SSE2-optimized functions for x86 and amd64. |
144 | * Version 1.1.0 (March 27 2022) Minor release, backward compatible with previous | |
145 | releases. Added long-awaited MP3 support. Numerous improvements and bugfixes. | |
144 | 146 | |
145 | 147 | ## Similar or Related Projects |
146 | 148 | |
193 | 195 | Check latest version on |
194 | 196 | [GitHub Releases page](https://github.com/libsndfile/libsndfile/releases/). |
195 | 197 | |
196 | Binatries and source packages are signed by current releaser David Seifert aka | |
198 | Binaries and source packages are signed by current releaser David Seifert aka | |
197 | 199 | @SoapGentoo. You can verify signatures with his public GPG key: |
198 | 200 | |
199 | 201 | ``` |
117 | 117 | exit (1) ; |
118 | 118 | } ; |
119 | 119 | |
120 | while ((readcount = sf_read_float (infile, buffer, BUFFER_LEN)) > 0) | |
120 | while ((readcount = (int) sf_read_float (infile, buffer, BUFFER_LEN)) > 0) | |
121 | 121 | sf_write_float (outfile, buffer, readcount) ; |
122 | 122 | |
123 | 123 | sf_close (infile) ; |
73 | 73 | |
74 | 74 | if (sfinfo.channels == 1) |
75 | 75 | { for (k = 0 ; k < SAMPLE_COUNT ; k++) |
76 | buffer [k] = AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI) ; | |
76 | buffer [k] = (int) (AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI)) ; | |
77 | 77 | } |
78 | 78 | else if (sfinfo.channels == 2) |
79 | 79 | { for (k = 0 ; k < SAMPLE_COUNT ; k++) |
80 | { buffer [2 * k] = AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI) ; | |
81 | buffer [2 * k + 1] = AMPLITUDE * sin (RIGHT_FREQ * 2 * k * M_PI) ; | |
80 | { buffer [2 * k] = (int) (AMPLITUDE * sin (LEFT_FREQ * 2 * k * M_PI)) ; | |
81 | buffer [2 * k + 1] = (int) (AMPLITUDE * sin (RIGHT_FREQ * 2 * k * M_PI)) ; | |
82 | 82 | } ; |
83 | 83 | } |
84 | 84 | else |
97 | 97 | |
98 | 98 | if (sfinfo.channels > MAX_CHANNELS) |
99 | 99 | { printf ("Not able to process more than %d channels\n", MAX_CHANNELS) ; |
100 | sf_close (infile) ; | |
100 | 101 | return 1 ; |
101 | 102 | } ; |
102 | 103 | /* Open the output file. */ |
103 | 104 | if (! (outfile = sf_open (outfilename, SFM_WRITE, &sfinfo))) |
104 | 105 | { printf ("Not able to open output file %s.\n", outfilename) ; |
105 | 106 | puts (sf_strerror (NULL)) ; |
107 | sf_close (infile) ; | |
106 | 108 | return 1 ; |
107 | 109 | } ; |
108 | 110 | |
109 | 111 | /* While there are.frames in the input file, read them, process |
110 | 112 | ** them and write them to the output file. |
111 | 113 | */ |
112 | while ((readcount = sf_read_double (infile, data, BUFFER_LEN))) | |
114 | while ((readcount = (int) sf_read_double (infile, data, BUFFER_LEN))) | |
113 | 115 | { process_data (data, readcount, sfinfo.channels) ; |
114 | 116 | sf_write_double (outfile, data, readcount) ; |
115 | 117 | } ; |
44 | 44 | #include <sndfile.h> |
45 | 45 | |
46 | 46 | #define BUFFER_LEN (1 << 14) |
47 | ||
48 | ||
49 | typedef struct | |
50 | { char *infilename, *outfilename ; | |
51 | SF_INFO infileinfo, outfileinfo ; | |
52 | } OptionData ; | |
53 | 47 | |
54 | 48 | const char * program_name (const char * argv0) ; |
55 | 49 | static void sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels) ; |
104 | 98 | /* Open the output file. */ |
105 | 99 | if ((outfile = sf_open (outfilename, SFM_WRITE, &out_sfinfo)) == NULL) |
106 | 100 | { printf ("Not able to open output file %s : %s\n", outfilename, sf_strerror (NULL)) ; |
101 | sf_close (infile) ; | |
107 | 102 | return 1 ; |
108 | 103 | } ; |
109 | 104 | |
142 | 137 | readcount = frames ; |
143 | 138 | |
144 | 139 | while (readcount > 0) |
145 | { readcount = sf_readf_int (infile, data, frames) ; | |
140 | { readcount = (int) sf_readf_int (infile, data, frames) ; | |
146 | 141 | sf_writef_int (outfile, data, readcount) ; |
147 | 142 | } ; |
148 | 143 |
59 | 59 | |
60 | 60 | } /* print_usage */ |
61 | 61 | |
62 | static void | |
62 | static int | |
63 | 63 | convert_to_text (SNDFILE * infile, FILE * outfile, int channels, int full_precision) |
64 | { float buf [BLOCK_SIZE] ; | |
64 | { float *buf ; | |
65 | 65 | sf_count_t frames ; |
66 | 66 | int k, m, readcount ; |
67 | 67 | |
68 | buf = malloc (BLOCK_SIZE * sizeof (float)) ; | |
69 | if (buf == NULL) | |
70 | { printf ("Error : Out of memory.\n\n") ; | |
71 | return 1 ; | |
72 | } ; | |
73 | ||
68 | 74 | frames = BLOCK_SIZE / channels ; |
69 | 75 | |
70 | while ((readcount = sf_readf_float (infile, buf, frames)) > 0) | |
76 | while ((readcount = (int) sf_readf_float (infile, buf, frames)) > 0) | |
71 | 77 | { for (k = 0 ; k < readcount ; k++) |
72 | 78 | { for (m = 0 ; m < channels ; m++) |
73 | 79 | if (full_precision) |
78 | 84 | } ; |
79 | 85 | } ; |
80 | 86 | |
81 | return ; | |
87 | free (buf) ; | |
88 | ||
89 | return 0 ; | |
82 | 90 | } /* convert_to_text */ |
83 | 91 | |
84 | 92 | int |
88 | 96 | FILE *outfile = NULL ; |
89 | 97 | SF_INFO sfinfo ; |
90 | 98 | int full_precision = 0 ; |
99 | int ret = 1 ; | |
91 | 100 | |
92 | 101 | progname = strrchr (argv [0], '/') ; |
93 | 102 | progname = progname ? progname + 1 : argv [0] ; |
96 | 105 | { case 4 : |
97 | 106 | if (!strcmp ("--full-precision", argv [3])) |
98 | 107 | { print_usage (progname) ; |
99 | return 1 ; | |
108 | goto cleanup ; | |
100 | 109 | } ; |
101 | 110 | full_precision = 1 ; |
102 | 111 | argv++ ; |
104 | 113 | break ; |
105 | 114 | default: |
106 | 115 | print_usage (progname) ; |
107 | return 1 ; | |
116 | goto cleanup ; | |
108 | 117 | } ; |
109 | 118 | |
110 | 119 | infilename = argv [1] ; |
113 | 122 | if (strcmp (infilename, outfilename) == 0) |
114 | 123 | { printf ("Error : Input and output filenames are the same.\n\n") ; |
115 | 124 | print_usage (progname) ; |
116 | return 1 ; | |
125 | goto cleanup ; | |
117 | 126 | } ; |
118 | 127 | |
119 | 128 | if (infilename [0] == '-') |
120 | 129 | { printf ("Error : Input filename (%s) looks like an option.\n\n", infilename) ; |
121 | 130 | print_usage (progname) ; |
122 | return 1 ; | |
131 | goto cleanup ; | |
123 | 132 | } ; |
124 | 133 | |
125 | 134 | if (outfilename [0] == '-') |
126 | 135 | { printf ("Error : Output filename (%s) looks like an option.\n\n", outfilename) ; |
127 | 136 | print_usage (progname) ; |
128 | return 1 ; | |
137 | goto cleanup ; | |
129 | 138 | } ; |
130 | 139 | |
131 | 140 | memset (&sfinfo, 0, sizeof (sfinfo)) ; |
133 | 142 | if ((infile = sf_open (infilename, SFM_READ, &sfinfo)) == NULL) |
134 | 143 | { printf ("Not able to open input file %s.\n", infilename) ; |
135 | 144 | puts (sf_strerror (NULL)) ; |
136 | return 1 ; | |
145 | goto cleanup ; | |
137 | 146 | } ; |
138 | 147 | |
139 | 148 | /* Open the output file. */ |
140 | 149 | if ((outfile = fopen (outfilename, "w")) == NULL) |
141 | 150 | { printf ("Not able to open output file %s : %s\n", outfilename, sf_strerror (NULL)) ; |
142 | return 1 ; | |
151 | goto cleanup ; | |
143 | 152 | } ; |
144 | 153 | |
145 | 154 | fprintf (outfile, "# Converted from file %s.\n", infilename) ; |
146 | 155 | fprintf (outfile, "# Channels %d, Sample rate %d\n", sfinfo.channels, sfinfo.samplerate) ; |
147 | 156 | |
148 | convert_to_text (infile, outfile, sfinfo.channels, full_precision) ; | |
157 | ret = convert_to_text (infile, outfile, sfinfo.channels, full_precision) ; | |
158 | ||
159 | cleanup : | |
149 | 160 | |
150 | 161 | sf_close (infile) ; |
151 | fclose (outfile) ; | |
162 | if (outfile != NULL) | |
163 | fclose (outfile) ; | |
152 | 164 | |
153 | return 0 ; | |
165 | return ret ; | |
154 | 166 | } /* main */ |
155 | 167 |
70 | 70 | SF_FORMAT_OGG = 0x200000, /* Xiph OGG container */ |
71 | 71 | SF_FORMAT_MPC2K = 0x210000, /* Akai MPC 2000 sampler */ |
72 | 72 | SF_FORMAT_RF64 = 0x220000, /* RF64 WAV file */ |
73 | SF_FORMAT_MPEG = 0x230000, /* MPEG-1/2 audio stream */ | |
73 | 74 | |
74 | 75 | /* Subtypes from here on. */ |
75 | 76 | |
114 | 115 | SF_FORMAT_ALAC_20 = 0x0071, /* Apple Lossless Audio Codec (20 bit). */ |
115 | 116 | SF_FORMAT_ALAC_24 = 0x0072, /* Apple Lossless Audio Codec (24 bit). */ |
116 | 117 | SF_FORMAT_ALAC_32 = 0x0073, /* Apple Lossless Audio Codec (32 bit). */ |
118 | ||
119 | SF_FORMAT_MPEG_LAYER_I = 0x0080, /* MPEG-1 Audio Layer I */ | |
120 | SF_FORMAT_MPEG_LAYER_II = 0x0081, /* MPEG-1 Audio Layer II */ | |
121 | SF_FORMAT_MPEG_LAYER_III = 0x0082, /* MPEG-2 Audio Layer III */ | |
117 | 122 | |
118 | 123 | /* Endian-ness options. */ |
119 | 124 | |
172 | 177 | |
173 | 178 | SFC_SET_RAW_START_OFFSET = 0x1090, |
174 | 179 | |
180 | /* Commands reserved for dithering, which is not implemented. */ | |
175 | 181 | SFC_SET_DITHER_ON_WRITE = 0x10A0, |
176 | 182 | SFC_SET_DITHER_ON_READ = 0x10A1, |
177 | 183 | |
215 | 221 | SFC_SET_COMPRESSION_LEVEL = 0x1301, |
216 | 222 | SFC_SET_OGG_PAGE_LATENCY_MS = 0x1302, |
217 | 223 | SFC_SET_OGG_PAGE_LATENCY = 0x1303, |
224 | ||
225 | SFC_GET_BITRATE_MODE = 0x1304, | |
226 | SFC_SET_BITRATE_MODE = 0x1305, | |
218 | 227 | |
219 | 228 | /* Cart Chunk support */ |
220 | 229 | SFC_SET_CART_INFO = 0x1400, |
332 | 341 | SF_CHANNEL_MAP_MAX |
333 | 342 | } ; |
334 | 343 | |
344 | /* Bitrate mode values (for use with SFC_GET/SET_BITRATE_MODE) | |
345 | */ | |
346 | enum | |
347 | { SF_BITRATE_MODE_CONSTANT = 0, | |
348 | SF_BITRATE_MODE_AVERAGE, | |
349 | SF_BITRATE_MODE_VARIABLE | |
350 | } ; | |
351 | ||
335 | 352 | |
336 | 353 | /* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */ |
337 | 354 | |
338 | typedef struct SNDFILE_tag SNDFILE ; | |
355 | typedef struct sf_private_tag SNDFILE ; | |
339 | 356 | |
340 | 357 | /* The following typedef is system specific and is defined when libsndfile is |
341 | 358 | ** compiled. sf_count_t will be a 64 bit value when the underlying OS allows |
385 | 402 | |
386 | 403 | /* |
387 | 404 | ** Enums and typedefs for adding dither on read and write. |
388 | ** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE | |
389 | ** and SFC_SET_DITHER_ON_READ. | |
405 | ** Reserved for future implementation. | |
390 | 406 | */ |
391 | 407 | |
392 | 408 | enum |
754 | 770 | /* The function sf_wchar_open() is Windows Only! |
755 | 771 | ** Open a file passing in a Windows Unicode filename. Otherwise, this is |
756 | 772 | ** the same as sf_open(). |
757 | ** | |
758 | ** In order for this to work, you need to do the following: | |
759 | ** | |
760 | ** #include <windows.h> | |
761 | ** #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1 | |
762 | ** #including <sndfile.h> | |
763 | */ | |
764 | ||
765 | #if (defined (ENABLE_SNDFILE_WINDOWS_PROTOTYPES) && ENABLE_SNDFILE_WINDOWS_PROTOTYPES) | |
766 | SNDFILE* sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ; | |
773 | */ | |
774 | ||
775 | #ifdef _WIN32 | |
776 | SNDFILE* sf_wchar_open (const wchar_t *wpath, int mode, SF_INFO *sfinfo) ; | |
767 | 777 | #endif |
768 | 778 | |
769 | 779 |
46 | 46 | ** |
47 | 47 | ** API documentation is in the doc/ directory of the source code tarball |
48 | 48 | ** and at http://libsndfile.github.io/libsndfile/api.html. |
49 | ** | |
50 | ** This file is intended to compile with C++98 and newer. | |
49 | 51 | */ |
50 | 52 | |
51 | 53 | #ifndef SNDFILE_HH |
56 | 58 | #include <string> |
57 | 59 | #include <new> // for std::nothrow |
58 | 60 | |
59 | #if __cplusplus < 201100 | |
60 | #ifndef nullptr | |
61 | #define nullptr NULL | |
62 | #endif | |
61 | #if ((defined (_MSC_VER) && (_MSC_VER >= 1600)) || (__cplusplus >= 201100L)) | |
62 | #define SF_NULL nullptr | |
63 | #else | |
64 | #define SF_NULL NULL | |
63 | 65 | #endif |
64 | 66 | |
65 | 67 | class SndfileHandle |
77 | 79 | |
78 | 80 | public : |
79 | 81 | /* Default constructor */ |
80 | SndfileHandle (void) : p (nullptr) {} ; | |
82 | SndfileHandle (void) : p (SF_NULL) {} ; | |
81 | 83 | SndfileHandle (const char *path, int mode = SFM_READ, |
82 | 84 | int format = 0, int channels = 0, int samplerate = 0) ; |
83 | 85 | SndfileHandle (std::string const & path, int mode = SFM_READ, |
87 | 89 | SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode = SFM_READ, |
88 | 90 | int format = 0, int channels = 0, int samplerate = 0) ; |
89 | 91 | |
90 | #ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES | |
91 | SndfileHandle (LPCWSTR wpath, int mode = SFM_READ, | |
92 | #ifdef _WIN32 | |
93 | SndfileHandle (const wchar_t *wpath, int mode = SFM_READ, | |
92 | 94 | int format = 0, int channels = 0, int samplerate = 0) ; |
93 | 95 | #endif |
94 | 96 | |
98 | 100 | SndfileHandle & operator = (const SndfileHandle &rhs) ; |
99 | 101 | |
100 | 102 | /* Mainly for debugging/testing. */ |
101 | int refCount (void) const { return (p == nullptr) ? 0 : p->ref ; } | |
102 | ||
103 | operator bool () const { return (p != nullptr) ; } | |
103 | int refCount (void) const { return (p == SF_NULL) ? 0 : p->ref ; } | |
104 | ||
105 | operator bool () const { return (p != SF_NULL) ; } | |
104 | 106 | |
105 | 107 | bool operator == (const SndfileHandle &rhs) const { return (p == rhs.p) ; } |
106 | 108 | |
160 | 162 | |
161 | 163 | inline |
162 | 164 | SndfileHandle::SNDFILE_ref::SNDFILE_ref (void) |
163 | : sf (nullptr), sfinfo (), ref (1) | |
165 | : sf (SF_NULL), sfinfo (), ref (1) | |
164 | 166 | {} |
165 | 167 | |
166 | 168 | inline |
167 | 169 | SndfileHandle::SNDFILE_ref::~SNDFILE_ref (void) |
168 | { if (sf != nullptr) sf_close (sf) ; } | |
170 | { if (sf != SF_NULL) sf_close (sf) ; } | |
169 | 171 | |
170 | 172 | inline |
171 | 173 | SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate) |
172 | : p (nullptr) | |
174 | : p (SF_NULL) | |
173 | 175 | { |
174 | 176 | p = new (std::nothrow) SNDFILE_ref () ; |
175 | 177 | |
176 | if (p != nullptr) | |
178 | if (p != SF_NULL) | |
177 | 179 | { p->ref = 1 ; |
178 | 180 | |
179 | 181 | p->sfinfo.frames = 0 ; |
191 | 193 | |
192 | 194 | inline |
193 | 195 | SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int chans, int srate) |
194 | : p (nullptr) | |
196 | : p (SF_NULL) | |
195 | 197 | { |
196 | 198 | p = new (std::nothrow) SNDFILE_ref () ; |
197 | 199 | |
198 | if (p != nullptr) | |
200 | if (p != SF_NULL) | |
199 | 201 | { p->ref = 1 ; |
200 | 202 | |
201 | 203 | p->sfinfo.frames = 0 ; |
213 | 215 | |
214 | 216 | inline |
215 | 217 | SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate) |
216 | : p (nullptr) | |
218 | : p (SF_NULL) | |
217 | 219 | { |
218 | 220 | if (fd < 0) |
219 | 221 | return ; |
220 | 222 | |
221 | 223 | p = new (std::nothrow) SNDFILE_ref () ; |
222 | 224 | |
223 | if (p != nullptr) | |
225 | if (p != SF_NULL) | |
224 | 226 | { p->ref = 1 ; |
225 | 227 | |
226 | 228 | p->sfinfo.frames = 0 ; |
238 | 240 | |
239 | 241 | inline |
240 | 242 | SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode, int fmt, int chans, int srate) |
241 | : p (nullptr) | |
243 | : p (SF_NULL) | |
242 | 244 | { |
243 | 245 | p = new (std::nothrow) SNDFILE_ref () ; |
244 | 246 | |
245 | if (p != nullptr) | |
247 | if (p != SF_NULL) | |
246 | 248 | { p->ref = 1 ; |
247 | 249 | |
248 | 250 | p->sfinfo.frames = 0 ; |
260 | 262 | |
261 | 263 | inline |
262 | 264 | SndfileHandle::~SndfileHandle (void) |
263 | { if (p != nullptr && -- p->ref == 0) | |
265 | { if (p != SF_NULL && -- p->ref == 0) | |
264 | 266 | delete p ; |
265 | 267 | } /* SndfileHandle destructor */ |
266 | 268 | |
268 | 270 | inline |
269 | 271 | SndfileHandle::SndfileHandle (const SndfileHandle &orig) |
270 | 272 | : p (orig.p) |
271 | { if (p != nullptr) | |
273 | { if (p != SF_NULL) | |
272 | 274 | ++ p->ref ; |
273 | 275 | } /* SndfileHandle copy constructor */ |
274 | 276 | |
277 | 279 | { |
278 | 280 | if (&rhs == this) |
279 | 281 | return *this ; |
280 | if (p != nullptr && -- p->ref == 0) | |
282 | if (p != SF_NULL && -- p->ref == 0) | |
281 | 283 | delete p ; |
282 | 284 | |
283 | 285 | p = rhs.p ; |
284 | if (p != nullptr) | |
286 | if (p != SF_NULL) | |
285 | 287 | ++ p->ref ; |
286 | 288 | |
287 | 289 | return *this ; |
406 | 408 | |
407 | 409 | inline SNDFILE * |
408 | 410 | SndfileHandle::rawHandle (void) |
409 | { return (p ? p->sf : nullptr) ; } | |
411 | { return (p ? p->sf : SF_NULL) ; } | |
410 | 412 | |
411 | 413 | inline SNDFILE * |
412 | 414 | SndfileHandle::takeOwnership (void) |
413 | 415 | { |
414 | if (p == nullptr || (p->ref != 1)) | |
415 | return nullptr ; | |
416 | if (p == SF_NULL || (p->ref != 1)) | |
417 | return SF_NULL ; | |
416 | 418 | |
417 | 419 | SNDFILE * sf = p->sf ; |
418 | p->sf = nullptr ; | |
420 | p->sf = SF_NULL ; | |
419 | 421 | delete p ; |
420 | p = nullptr ; | |
422 | p = SF_NULL ; | |
421 | 423 | return sf ; |
422 | 424 | } |
423 | 425 | |
424 | #ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES | |
425 | ||
426 | inline | |
427 | SndfileHandle::SndfileHandle (LPCWSTR wpath, int mode, int fmt, int chans, int srate) | |
428 | : p (nullptr) | |
426 | #ifdef _WIN32 | |
427 | ||
428 | inline | |
429 | SndfileHandle::SndfileHandle (const wchar_t *wpath, int mode, int fmt, int chans, int srate) | |
430 | : p (SF_NULL) | |
429 | 431 | { |
430 | 432 | p = new (std::nothrow) SNDFILE_ref () ; |
431 | 433 | |
432 | if (p != nullptr) | |
434 | if (p != SF_NULL) | |
433 | 435 | { p->ref = 1 ; |
434 | 436 | |
435 | 437 | p->sfinfo.frames = 0 ; |
0 | 0 | # =========================================================================== |
1 | # http://www.gnu.org/software/autoconf-archive/ax_add_fortify_source.html | |
1 | # https://www.gnu.org/software/autoconf-archive/ax_add_fortify_source.html | |
2 | 2 | # =========================================================================== |
3 | 3 | # |
4 | 4 | # SYNOPSIS |
8 | 8 | # DESCRIPTION |
9 | 9 | # |
10 | 10 | # Check whether -D_FORTIFY_SOURCE=2 can be added to CPPFLAGS without macro |
11 | # redefinition warnings. Some distributions (such as Gentoo Linux) enable | |
12 | # _FORTIFY_SOURCE globally in their compilers, leading to unnecessary | |
13 | # warnings in the form of | |
11 | # redefinition warnings, other cpp warnings or linker. Some distributions | |
12 | # (such as Gentoo Linux) enable _FORTIFY_SOURCE globally in their | |
13 | # compilers, leading to unnecessary warnings in the form of | |
14 | 14 | # |
15 | 15 | # <command-line>:0:0: error: "_FORTIFY_SOURCE" redefined [-Werror] |
16 | 16 | # <built-in>: note: this is the location of the previous definition |
19 | 19 | # _FORTIFY_SOURCE is already defined, and if not, adds -D_FORTIFY_SOURCE=2 |
20 | 20 | # to CPPFLAGS. |
21 | 21 | # |
22 | # Newer mingw-w64 msys2 package comes with a bug in | |
23 | # headers-git-7.0.0.5546.d200317d-1. It broke -D_FORTIFY_SOURCE support, | |
24 | # and would need -lssp or -fstack-protector. See | |
25 | # https://github.com/msys2/MINGW-packages/issues/5803. Try to actually | |
26 | # link it. | |
27 | # | |
22 | 28 | # LICENSE |
23 | 29 | # |
24 | 30 | # Copyright (c) 2017 David Seifert <soap@gentoo.org> |
31 | # Copyright (c) 2019 Reini Urban <rurban@cpan.org> | |
25 | 32 | # |
26 | 33 | # Copying and distribution of this file, with or without modification, are |
27 | 34 | # permitted in any medium without royalty provided the copyright notice |
28 | 35 | # and this notice are preserved. This file is offered as-is, without any |
29 | 36 | # warranty. |
30 | 37 | |
31 | #serial 1 | |
38 | #serial 4 | |
32 | 39 | |
33 | 40 | AC_DEFUN([AX_ADD_FORTIFY_SOURCE],[ |
41 | ac_save_cflags=$CFLAGS | |
42 | ac_cwerror_flag=yes | |
43 | AX_CHECK_COMPILE_FLAG([-Werror],[CFLAGS="$CFLAGS -Werror"]) | |
34 | 44 | AC_MSG_CHECKING([whether to add -D_FORTIFY_SOURCE=2 to CPPFLAGS]) |
35 | 45 | AC_LINK_IFELSE([ |
36 | AC_LANG_SOURCE( | |
46 | AC_LANG_PROGRAM([], | |
37 | 47 | [[ |
38 | int main() { | |
39 | 48 | #ifndef _FORTIFY_SOURCE |
40 | 49 | return 0; |
41 | 50 | #else |
42 | 51 | this_is_an_error; |
43 | 52 | #endif |
53 | ]] | |
54 | )], | |
55 | AC_LINK_IFELSE([ | |
56 | AC_LANG_SOURCE([[ | |
57 | #define _FORTIFY_SOURCE 2 | |
58 | #include <string.h> | |
59 | int main() { | |
60 | char *s = " "; | |
61 | strcpy(s, "x"); | |
62 | return strlen(s)-1; | |
44 | 63 | } |
45 | ]] | |
46 | )], [ | |
47 | AC_MSG_RESULT([yes]) | |
48 | CPPFLAGS="$CPPFLAGS -D_FORTIFY_SOURCE=2" | |
49 | ], [ | |
50 | AC_MSG_RESULT([no]) | |
51 | ]) | |
64 | ]] | |
65 | )], | |
66 | [ | |
67 | AC_MSG_RESULT([yes]) | |
68 | CFLAGS=$ac_save_cflags | |
69 | CPPFLAGS="$CPPFLAGS -D_FORTIFY_SOURCE=2" | |
70 | ], [ | |
71 | AC_MSG_RESULT([no]) | |
72 | CFLAGS=$ac_save_cflags | |
73 | ], | |
74 | ), | |
75 | [ | |
76 | AC_MSG_RESULT([no]) | |
77 | CFLAGS=$ac_save_cflags | |
78 | ]) | |
52 | 79 | ]) |
54 | 54 | CFLAGS=$pkg_link_saved_CFLAGS |
55 | 55 | LIBS=$pkg_link_saved_LIBS |
56 | 56 | |
57 | if test $pkg_link = no ; then | |
58 | $as_echo_n "link failed ... " | |
57 | AS_IF([test x$pkg_link = xno], [ | |
58 | AS_ECHO_N(["link failed ... "]) | |
59 | 59 | pkg_failed=yes |
60 | fi | |
60 | ]) | |
61 | 61 | |
62 | 62 | m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS |
63 | 63 | and $1[]_LIBS to avoid the need to call pkg-config. |
15 | 15 | |
16 | 16 | |
17 | 17 | AC_ARG_WITH(mkoctfile, |
18 | AC_HELP_STRING([--with-mkoctfile], [choose the mkoctfile version]), | |
18 | AS_HELP_STRING([--with-mkoctfile], [choose the mkoctfile version]), | |
19 | 19 | [ with_mkoctfile=$withval ]) |
20 | 20 | |
21 | 21 | test -z "$with_mkoctfile" && with_mkoctfile=mkoctfile |
28 | 28 | [ |
29 | 29 | |
30 | 30 | AC_ARG_WITH(octave, |
31 | AC_HELP_STRING([--with-octave], [choose the octave version]), | |
31 | AS_HELP_STRING([--with-octave], [choose the octave version]), | |
32 | 32 | [ with_octave=$withval ]) |
33 | 33 | |
34 | 34 | test -z "$with_octave" && with_octave=octave |
62 | 62 | [ |
63 | 63 | |
64 | 64 | AC_ARG_WITH(octave-config, |
65 | AC_HELP_STRING([--with-octave-config], [choose the octave-config version]), | |
65 | AS_HELP_STRING([--with-octave-config], [choose the octave-config version]), | |
66 | 66 | [ with_octave_config=$withval ]) |
67 | 67 | |
68 | 68 | test -z "$with_octave_config" && with_octave_config=octave-config |
0 | dnl Copyright (C) 2013 Xiph.org Foundation | |
1 | dnl | |
2 | dnl Redistribution and use in source and binary forms, with or without | |
3 | dnl modification, are permitted provided that the following conditions | |
4 | dnl are met: | |
5 | dnl | |
6 | dnl - Redistributions of source code must retain the above copyright | |
7 | dnl notice, this list of conditions and the following disclaimer. | |
8 | dnl | |
9 | dnl - Redistributions in binary form must reproduce the above copyright | |
10 | dnl notice, this list of conditions and the following disclaimer in the | |
11 | dnl documentation and/or other materials provided with the distribution. | |
12 | dnl | |
13 | dnl - Neither the name of the Xiph.org Foundation nor the names of its | |
14 | dnl contributors may be used to endorse or promote products derived from | |
15 | dnl this software without specific prior written permission. | |
16 | dnl | |
17 | dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
18 | dnl ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
19 | dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
20 | dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR | |
21 | dnl CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
22 | dnl EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
23 | dnl PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
24 | dnl PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
25 | dnl LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
26 | dnl NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
27 | dnl SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 | ||
29 | dnl Want to know of GCC stack protector works, botfor the C and for the C++ | |
30 | dnl compiler. | |
31 | dnl | |
32 | dnl Just checking if the compiler accepts the required CFLAGSs is not enough | |
33 | dnl because we have seen at least one instance where this check was | |
34 | dnl in-sufficient. | |
35 | dnl | |
36 | dnl Instead, try to compile and link a test program with the stack protector | |
37 | dnl flags. If that works, we use it. | |
38 | ||
39 | AC_DEFUN([XIPH_GCC_STACK_PROTECTOR], | |
40 | [AC_LANG_ASSERT(C) | |
41 | AC_MSG_CHECKING([if $CC supports stack smash protection]) | |
42 | xiph_stack_check_old_cflags="$CFLAGS" | |
43 | SSP_FLAGS="-fstack-protector --param ssp-buffer-size=4" | |
44 | CFLAGS=$SSP_FLAGS | |
45 | AC_TRY_LINK([ | |
46 | #include <stdio.h> | |
47 | ], | |
48 | [puts("Hello, World!"); return 0;], | |
49 | AC_MSG_RESULT([yes]) | |
50 | CFLAGS="$xiph_stack_check_old_cflags $SSP_FLAGS", | |
51 | AC_MSG_RESULT([no]) | |
52 | CFLAGS="$xiph_stack_check_old_cflags" | |
53 | ) | |
54 | ])# XIPH_GCC_STACK_PROTECTOR | |
55 | ||
56 | AC_DEFUN([XIPH_GXX_STACK_PROTECTOR], | |
57 | [AC_LANG_PUSH([C++]) | |
58 | AC_MSG_CHECKING([if $CXX supports stack smash protection]) | |
59 | xiph_stack_check_old_cflags="$CFLAGS" | |
60 | SSP_FLAGS="-fstack-protector --param ssp-buffer-size=4" | |
61 | CFLAGS=$SSP_FLAGS | |
62 | AC_TRY_LINK([ | |
63 | #include <cstdio> | |
64 | ], | |
65 | [puts("Hello, World!"); return 0;], | |
66 | AC_MSG_RESULT([yes]) | |
67 | CFLAGS="$xiph_stack_check_old_cflags $SSP_FLAGS", | |
68 | AC_MSG_RESULT([no]) | |
69 | CFLAGS="$xiph_stack_check_old_cflags" | |
70 | ) | |
71 | AC_LANG_POP([C++]) | |
72 | ])# XIPH_GXX_STACK_PROTECTOR |
0 | .Dd November 2, 2014 | |
0 | .Dd September 10, 2021 | |
1 | 1 | .Dt SNDFILE-PLAY 1 |
2 | 2 | .Os |
3 | 3 | .Sh NAME |
18 | 18 | sndio |
19 | 19 | .It FreeBSD |
20 | 20 | /dev/dsp (OSS) |
21 | .It NetBSD | |
22 | /dev/audio | |
21 | 23 | .It Solaris |
22 | 24 | /dev/audio |
23 | 25 | .It MacOSX 10.6 |
28 | 28 | |
29 | 29 | # Copy the fuzzer to the output directory. |
30 | 30 | cp -v ossfuzz/sndfile_fuzzer $OUT/ |
31 | cp -v ossfuzz/sndfile_alt_fuzzer $OUT/ |
0 | #include <stdlib.h> | |
1 | #include <string.h> | |
2 | #include <sys/types.h> | |
3 | #include <sndfile.h> | |
4 | #include <inttypes.h> | |
5 | ||
6 | #include "sndfile_fuzz_header.h" | |
7 | ||
8 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) | |
9 | { // One byte is needed for deciding which function to target. | |
10 | if (size == 0) | |
11 | return 0 ; | |
12 | ||
13 | const uint8_t decider = *data ; | |
14 | data += 1 ; | |
15 | size -= 1 ; | |
16 | ||
17 | SF_INFO sndfile_info ; | |
18 | VIO_DATA vio_data ; | |
19 | SF_VIRTUAL_IO vio ; | |
20 | SNDFILE *sndfile = NULL ; | |
21 | int err = sf_init_file(data, size, &sndfile, &vio_data, &vio, &sndfile_info) ; | |
22 | if (err) | |
23 | goto EXIT_LABEL ; | |
24 | ||
25 | // Just the right number of channels. Create some buffer space for reading. | |
26 | switch (decider % 3) | |
27 | { case 0 : | |
28 | { | |
29 | short* read_buffer = NULL ; | |
30 | read_buffer = (short*)malloc(sizeof(short) * size); | |
31 | if (read_buffer == NULL) | |
32 | abort() ; | |
33 | ||
34 | while (sf_read_short(sndfile, read_buffer, size)) | |
35 | { | |
36 | // Do nothing with the data. | |
37 | } | |
38 | free(read_buffer) ; | |
39 | } | |
40 | break ; | |
41 | case 1 : | |
42 | { | |
43 | int* read_buffer = NULL ; | |
44 | read_buffer = (int*)malloc(sizeof(int) * size) ; | |
45 | if (read_buffer == NULL) | |
46 | abort() ; | |
47 | ||
48 | while (sf_read_int(sndfile, read_buffer, size)) | |
49 | { | |
50 | // Do nothing with the data. | |
51 | } | |
52 | free(read_buffer) ; | |
53 | } | |
54 | break ; | |
55 | case 2 : | |
56 | { | |
57 | double* read_buffer = NULL ; | |
58 | read_buffer = (double*)malloc(sizeof(double) * size) ; | |
59 | if (read_buffer == NULL) | |
60 | abort() ; | |
61 | ||
62 | while (sf_read_double(sndfile, read_buffer, size)) | |
63 | { | |
64 | // Do nothing with the data. | |
65 | } | |
66 | free(read_buffer) ; | |
67 | } | |
68 | break ; | |
69 | default : | |
70 | break ; | |
71 | } ; | |
72 | ||
73 | EXIT_LABEL: | |
74 | if (sndfile != NULL) | |
75 | sf_close(sndfile); | |
76 | ||
77 | return 0 ; | |
78 | } |
0 | #ifndef SNDFILE_FUZZ_HEADER_H | |
1 | #define SNDFILE_FUZZ_HEADER_H | |
2 | ||
3 | typedef struct | |
4 | { | |
5 | sf_count_t offset ; | |
6 | sf_count_t length ; | |
7 | const unsigned char *data ; | |
8 | } VIO_DATA ; | |
9 | ||
10 | static sf_count_t vfget_filelen (void *user_data) | |
11 | { VIO_DATA *vf = (VIO_DATA *)user_data ; | |
12 | return vf->length ; | |
13 | } | |
14 | ||
15 | static sf_count_t vfseek (sf_count_t offset, int whence, void *user_data) | |
16 | { | |
17 | VIO_DATA *vf = (VIO_DATA *)user_data ; | |
18 | sf_count_t new_offset ; | |
19 | ||
20 | switch (whence) | |
21 | { case SEEK_SET : | |
22 | new_offset = offset ; | |
23 | break ; | |
24 | ||
25 | case SEEK_CUR : | |
26 | new_offset = vf->offset + offset ; | |
27 | break ; | |
28 | ||
29 | case SEEK_END : | |
30 | new_offset = vf->length + offset ; | |
31 | break ; | |
32 | ||
33 | default : | |
34 | break ; | |
35 | } | |
36 | ||
37 | /* Ensure you can't seek outside the data */ | |
38 | if (new_offset > vf->length) | |
39 | { /* Trying to seek past the end of the data */ | |
40 | printf("vf overseek: new_offset(%" PRId64 ") > vf->length(%" PRId64 ");" | |
41 | " whence(%d), vf->offset(%" PRId64 "), offset(%" PRId64 ")\n", | |
42 | new_offset, vf->length, whence, vf->offset, offset) ; | |
43 | new_offset = vf->length ; | |
44 | } | |
45 | else if (new_offset < 0) | |
46 | { /* Trying to seek before the start of the data */ | |
47 | printf("vf underseek: new_offset(%" PRId64 ") < 0; whence(%d), vf->offset" | |
48 | "(%" PRId64 "), vf->length(%" PRId64 "), offset(%" PRId64 ")\n", | |
49 | new_offset, whence, vf->offset, vf->length, offset) ; | |
50 | new_offset = 0 ; | |
51 | } | |
52 | vf->offset = new_offset ; | |
53 | ||
54 | return vf->offset ; | |
55 | } | |
56 | ||
57 | static sf_count_t vfread (void *ptr, sf_count_t count, void *user_data) | |
58 | { VIO_DATA *vf = (VIO_DATA *)user_data ; | |
59 | ||
60 | if (vf->offset + count > vf->length) | |
61 | count = vf->length - vf->offset ; | |
62 | ||
63 | memcpy(ptr, vf->data + vf->offset, count) ; | |
64 | vf->offset += count ; | |
65 | ||
66 | return count ; | |
67 | } | |
68 | ||
69 | static sf_count_t vfwrite (const void *ptr, sf_count_t count, void *user_data) | |
70 | { | |
71 | (void)ptr ; | |
72 | (void)count ; | |
73 | (void)user_data ; | |
74 | ||
75 | // Cannot write to this virtual file. | |
76 | return 0; | |
77 | } | |
78 | ||
79 | static sf_count_t vftell (void *user_data) | |
80 | { VIO_DATA *vf = (VIO_DATA *)user_data ; | |
81 | ||
82 | return vf->offset ; | |
83 | } | |
84 | ||
85 | int sf_init_file(const uint8_t *data, | |
86 | size_t size, | |
87 | SNDFILE **sndfile, | |
88 | VIO_DATA *vio_data, | |
89 | SF_VIRTUAL_IO *vio, SF_INFO *sndfile_info) | |
90 | { float* read_buffer = NULL ; | |
91 | ||
92 | // Initialize the virtual IO structure. | |
93 | vio->get_filelen = vfget_filelen ; | |
94 | vio->seek = vfseek ; | |
95 | vio->read = vfread ; | |
96 | vio->write = vfwrite ; | |
97 | vio->tell = vftell ; | |
98 | ||
99 | // Initialize the VIO user data. | |
100 | vio_data->data = data ; | |
101 | vio_data->length = size ; | |
102 | vio_data->offset = 0 ; | |
103 | ||
104 | memset(sndfile_info, 0, sizeof(SF_INFO)) ; | |
105 | ||
106 | // Try and open the virtual file. | |
107 | *sndfile = sf_open_virtual(vio, SFM_READ, sndfile_info, vio_data) ; | |
108 | ||
109 | if (sndfile_info->channels == 0) | |
110 | return -1 ; | |
111 | ||
112 | if (sndfile_info->channels > 1024 * 1024) | |
113 | return -1 ; | |
114 | ||
115 | return 0; | |
116 | } | |
117 | ||
118 | #endif |
4 | 4 | #include <sndfile.h> |
5 | 5 | #include <inttypes.h> |
6 | 6 | |
7 | typedef struct | |
8 | { | |
9 | sf_count_t offset; | |
10 | sf_count_t length; | |
11 | const unsigned char *data; | |
12 | } VIO_DATA; | |
13 | ||
14 | static sf_count_t vfget_filelen (void *user_data) | |
15 | { | |
16 | VIO_DATA *vf = (VIO_DATA *)user_data; | |
17 | return vf->length; | |
18 | } | |
19 | ||
20 | static sf_count_t vfseek (sf_count_t offset, int whence, void *user_data) | |
21 | { | |
22 | VIO_DATA *vf = (VIO_DATA *)user_data; | |
23 | sf_count_t new_offset; | |
24 | ||
25 | switch (whence) | |
26 | { | |
27 | case SEEK_SET: | |
28 | new_offset = offset; | |
29 | break ; | |
30 | ||
31 | case SEEK_CUR: | |
32 | new_offset = vf->offset + offset; | |
33 | break ; | |
34 | ||
35 | case SEEK_END: | |
36 | new_offset = vf->length + offset; | |
37 | break; | |
38 | ||
39 | default: | |
40 | break; | |
41 | } | |
42 | ||
43 | /* Ensure you can't seek outside the data */ | |
44 | if (new_offset > vf->length) | |
45 | { | |
46 | /* Trying to seek past the end of the data */ | |
47 | printf("vf overseek: new_offset(%" PRId64 ") > vf->length(%" PRId64 ");" | |
48 | " whence(%d), vf->offset(%" PRId64 "), offset(%" PRId64 ")\n", | |
49 | new_offset, vf->length, whence, vf->offset, offset); | |
50 | new_offset = vf->length; | |
51 | } | |
52 | else if (new_offset < 0) | |
53 | { | |
54 | /* Trying to seek before the start of the data */ | |
55 | printf("vf underseek: new_offset(%" PRId64 ") < 0; whence(%d), vf->offset" | |
56 | "(%" PRId64 "), vf->length(%" PRId64 "), offset(%" PRId64 ")\n", | |
57 | new_offset, whence, vf->offset, vf->length, offset); | |
58 | new_offset = 0; | |
59 | } | |
60 | vf->offset = new_offset; | |
61 | ||
62 | return vf->offset; | |
63 | } | |
64 | ||
65 | static sf_count_t vfread (void *ptr, sf_count_t count, void *user_data) | |
66 | { | |
67 | VIO_DATA *vf = (VIO_DATA *)user_data; | |
68 | ||
69 | if (vf->offset + count > vf->length) | |
70 | { | |
71 | count = vf->length - vf->offset; | |
72 | } | |
73 | ||
74 | memcpy(ptr, vf->data + vf->offset, count); | |
75 | vf->offset += count; | |
76 | ||
77 | return count; | |
78 | } | |
79 | ||
80 | static sf_count_t vfwrite (const void *ptr, sf_count_t count, void *user_data) | |
81 | { | |
82 | (void)ptr; | |
83 | (void)count; | |
84 | (void)user_data; | |
85 | ||
86 | // Cannot write to this virtual file. | |
87 | return 0; | |
88 | } | |
89 | ||
90 | static sf_count_t vftell (void *user_data) | |
91 | { VIO_DATA *vf = (VIO_DATA *)user_data; | |
92 | ||
93 | return vf->offset; | |
94 | } | |
7 | #include "sndfile_fuzz_header.h" | |
95 | 8 | |
96 | 9 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) |
97 | { | |
98 | VIO_DATA vio_data; | |
99 | SF_VIRTUAL_IO vio; | |
100 | SF_INFO sndfile_info; | |
101 | SNDFILE *sndfile = NULL; | |
102 | float* read_buffer = NULL; | |
10 | { VIO_DATA vio_data ; | |
11 | SF_VIRTUAL_IO vio ; | |
12 | SF_INFO sndfile_info ; | |
13 | SNDFILE *sndfile = NULL ; | |
14 | float* read_buffer = NULL ; | |
103 | 15 | |
104 | // Initialize the virtual IO structure. | |
105 | vio.get_filelen = vfget_filelen; | |
106 | vio.seek = vfseek; | |
107 | vio.read = vfread; | |
108 | vio.write = vfwrite; | |
109 | vio.tell = vftell; | |
16 | int err = sf_init_file(data, size, &sndfile, &vio_data, &vio, &sndfile_info) ; | |
17 | if (err) | |
18 | goto EXIT_LABEL ; | |
110 | 19 | |
111 | // Initialize the VIO user data. | |
112 | vio_data.data = data; | |
113 | vio_data.length = size; | |
114 | vio_data.offset = 0; | |
20 | // Just the right number of channels. Create some buffer space for reading. | |
21 | read_buffer = (float*)malloc(sizeof(float) * sndfile_info.channels); | |
22 | if (read_buffer == NULL) | |
23 | abort() ; | |
115 | 24 | |
116 | memset(&sndfile_info, 0, sizeof(SF_INFO)); | |
117 | ||
118 | // Try and open the virtual file. | |
119 | sndfile = sf_open_virtual(&vio, SFM_READ, &sndfile_info, &vio_data); | |
120 | ||
121 | if (sndfile_info.channels == 0) | |
122 | { | |
123 | // No sound channels in file. | |
124 | goto EXIT_LABEL; | |
125 | } | |
126 | else if (sndfile_info.channels > 1024 * 1024) | |
127 | { | |
128 | // Too many channels to handle. | |
129 | goto EXIT_LABEL; | |
130 | } | |
131 | ||
132 | // Just the right number of channels. Create some buffer space for reading. | |
133 | read_buffer = (float*)malloc(sizeof(float) * sndfile_info.channels); | |
134 | if (read_buffer == NULL) | |
135 | { | |
136 | abort(); | |
137 | } | |
138 | ||
139 | while (sf_readf_float(sndfile, read_buffer, 1)) | |
140 | { | |
141 | // Do nothing with the data. | |
142 | } | |
25 | while (sf_readf_float(sndfile, read_buffer, 1)) | |
26 | { | |
27 | // Do nothing with the data. | |
28 | } | |
143 | 29 | |
144 | 30 | EXIT_LABEL: |
145 | 31 | |
146 | if (sndfile != NULL) | |
147 | { | |
148 | sf_close(sndfile); | |
149 | } | |
32 | if (sndfile != NULL) | |
33 | sf_close(sndfile) ; | |
150 | 34 | |
151 | free(read_buffer); | |
35 | free(read_buffer) ; | |
152 | 36 | |
153 | return 0; | |
37 | return 0 ; | |
154 | 38 | } |
72 | 72 | { data [k] /= max ; |
73 | 73 | |
74 | 74 | if (!isfinite (data [k])) /* infinite or NaN */ |
75 | return 1; | |
75 | return 1 ; | |
76 | 76 | } |
77 | 77 | sf_writef_double (outfile, data, readcount) ; |
78 | 78 | } ; |
90 | 90 | readcount = frames ; |
91 | 91 | |
92 | 92 | while (readcount > 0) |
93 | { readcount = sf_readf_int (infile, data, frames) ; | |
93 | { readcount = (int) sf_readf_int (infile, data, frames) ; | |
94 | 94 | sf_writef_int (outfile, data, readcount) ; |
95 | 95 | } ; |
96 | 96 | |
118 | 118 | { case SF_FORMAT_PCM_16 : |
119 | 119 | case SF_FORMAT_PCM_24 : |
120 | 120 | case SF_FORMAT_PCM_32 : |
121 | case SF_FORMAT_MPEG_LAYER_III : | |
121 | 122 | break ; |
122 | 123 | |
123 | 124 | default : |
176 | 177 | /* Special case for coding_history because we may want to append. */ |
177 | 178 | if (info->coding_history != NULL) |
178 | 179 | { if (info->coding_hist_append) |
179 | { int slen = strlen (binfo.coding_history) ; | |
180 | { int slen = (int) strlen (binfo.coding_history) ; | |
180 | 181 | |
181 | 182 | while (slen > 1 && isspace (binfo.coding_history [slen - 1])) |
182 | 183 | slen -- ; |
188 | 189 | |
189 | 190 | memset (binfo.coding_history, 0, sizeof (binfo.coding_history)) ; |
190 | 191 | memcpy (binfo.coding_history, info->coding_history, slen) ; |
191 | binfo.coding_history_size = slen ; | |
192 | binfo.coding_history_size = (uint32_t) slen ; | |
192 | 193 | } ; |
193 | 194 | } ; |
194 | 195 | |
338 | 339 | { "caf", 0, SF_FORMAT_CAF }, |
339 | 340 | { "wve", 0, SF_FORMAT_WVE }, |
340 | 341 | { "prc", 0, SF_FORMAT_WVE }, |
341 | { "ogg", 0, SF_FORMAT_OGG }, | |
342 | 342 | { "oga", 0, SF_FORMAT_OGG }, |
343 | { "ogg", 0, SF_FORMAT_OGG | SF_FORMAT_VORBIS }, | |
343 | 344 | { "opus", 0, SF_FORMAT_OGG | SF_FORMAT_OPUS }, |
344 | 345 | { "mpc", 0, SF_FORMAT_MPC2K }, |
345 | 346 | { "rf64", 0, SF_FORMAT_RF64 }, |
347 | { "mp3", 0, SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III }, | |
346 | 348 | } ; /* format_map */ |
347 | 349 | |
348 | 350 | int |
452 | 454 | case SF_FORMAT_OGG : return "OGG" ; |
453 | 455 | case SF_FORMAT_MPC2K : return "MPC2K" ; |
454 | 456 | case SF_FORMAT_RF64 : return "RF64" ; |
457 | case SF_FORMAT_MPEG : return "MPEG" ; | |
455 | 458 | default : break ; |
456 | 459 | } ; |
457 | 460 | |
490 | 493 | case SF_FORMAT_ALAC_24 : return "24 bit ALAC" ; |
491 | 494 | case SF_FORMAT_ALAC_32 : return "32 bit ALAC" ; |
492 | 495 | case SF_FORMAT_OPUS : return "Opus" ; |
496 | case SF_FORMAT_MPEG_LAYER_I : return "MPEG layer 1" ; | |
497 | case SF_FORMAT_MPEG_LAYER_II : return "MPEG layer 2" ; | |
498 | case SF_FORMAT_MPEG_LAYER_III : return "MPEG layer 3" ; | |
493 | 499 | default : break ; |
494 | 500 | } ; |
495 | 501 | return "unknown" ; |
142 | 142 | sf_seek (wfile, 0, SEEK_END) ; |
143 | 143 | |
144 | 144 | while (readcount > 0) |
145 | { readcount = sf_readf_double (rofile, data, frames) ; | |
145 | { readcount = (int) sf_readf_double (rofile, data, frames) ; | |
146 | 146 | sf_writef_double (wfile, data, readcount) ; |
147 | 147 | } ; |
148 | 148 | |
160 | 160 | sf_seek (wfile, 0, SEEK_END) ; |
161 | 161 | |
162 | 162 | while (readcount > 0) |
163 | { readcount = sf_readf_int (rofile, data, frames) ; | |
163 | { readcount = (int) sf_readf_int (rofile, data, frames) ; | |
164 | 164 | sf_writef_int (wfile, data, readcount) ; |
165 | 165 | } ; |
166 | 166 |
280 | 280 | continue ; |
281 | 281 | } ; |
282 | 282 | |
283 | printf ("Error : Not able to decode argunment '%s'.\n", argv [k]) ; | |
283 | printf ("Error : Not able to decode argument '%s'.\n", argv [k]) ; | |
284 | 284 | exit (1) ; |
285 | 285 | } ; |
286 | 286 | |
353 | 353 | || (outfileminor == SF_FORMAT_DOUBLE) || (outfileminor == SF_FORMAT_FLOAT) |
354 | 354 | || (infileminor == SF_FORMAT_DOUBLE) || (infileminor == SF_FORMAT_FLOAT) |
355 | 355 | || (infileminor == SF_FORMAT_OPUS) || (outfileminor == SF_FORMAT_OPUS) |
356 | || (infileminor == SF_FORMAT_VORBIS) || (outfileminor == SF_FORMAT_VORBIS)) | |
356 | || (infileminor == SF_FORMAT_VORBIS) || (outfileminor == SF_FORMAT_VORBIS) | |
357 | || (infileminor == SF_FORMAT_MPEG_LAYER_I) | |
358 | || (infileminor == SF_FORMAT_MPEG_LAYER_II) | |
359 | || (infileminor == SF_FORMAT_MPEG_LAYER_III) || (outfileminor == SF_FORMAT_MPEG_LAYER_III)) | |
357 | 360 | { if (sfe_copy_data_fp (outfile, infile, sfinfo.channels, normalize) != 0) |
358 | 361 | { printf ("Error : Not able to decode input file %s.\n", infilename) ; |
359 | 362 | return 1 ; |
387 | 390 | memset (&binfo, 0, sizeof (binfo)) ; |
388 | 391 | |
389 | 392 | if (channels < ARRAY_LEN (chanmap)) |
390 | { size_t size = channels * sizeof (chanmap [0]) ; | |
393 | { int size = channels * sizeof (chanmap [0]) ; | |
391 | 394 | |
392 | 395 | if (sf_command (infile, SFC_GET_CHANNEL_MAP_INFO, chanmap, size) == SF_TRUE) |
393 | 396 | sf_command (outfile, SFC_SET_CHANNEL_MAP_INFO, chanmap, size) ; |
64 | 64 | |
65 | 65 | int |
66 | 66 | main (int argc, char **argv) |
67 | { STATE state ; | |
67 | { STATE *state = NULL ; | |
68 | 68 | SF_INFO sfinfo ; |
69 | 69 | char pathname [512], ext [32], *cptr ; |
70 | int ch, double_split ; | |
70 | int ch, double_split, ret = 1 ; | |
71 | 71 | |
72 | 72 | if (argc != 2) |
73 | 73 | { if (argc != 1) |
74 | 74 | puts ("\nError : need a single input file.\n") ; |
75 | 75 | usage_exit () ; |
76 | } ; | |
77 | ||
78 | memset (&state, 0, sizeof (state)) ; | |
76 | goto cleanup ; | |
77 | } ; | |
78 | ||
79 | state = calloc (1, sizeof (*state)) ; | |
80 | if (!state) | |
81 | { printf ("\nError : Out of memory.\n") ; | |
82 | goto cleanup ; | |
83 | } ; | |
79 | 84 | memset (&sfinfo, 0, sizeof (sfinfo)) ; |
80 | 85 | |
81 | if ((state.infile = sf_open (argv [1], SFM_READ, &sfinfo)) == NULL) | |
86 | if ((state->infile = sf_open (argv [1], SFM_READ, &sfinfo)) == NULL) | |
82 | 87 | { printf ("\nError : Not able to open input file '%s'\n%s\n", argv [1], sf_strerror (NULL)) ; |
83 | exit (1) ; | |
88 | goto cleanup ; | |
84 | 89 | } ; |
85 | 90 | |
86 | 91 | if (sfinfo.channels < 2) |
87 | 92 | { printf ("\nError : Input file '%s' only has one channel.\n", argv [1]) ; |
88 | exit (1) ; | |
93 | goto cleanup ; | |
89 | 94 | } ; |
90 | 95 | |
91 | 96 | if (sfinfo.channels > MAX_CHANNELS) |
92 | 97 | { printf ("\nError : Input file '%s' has too many (%d) channels. Limit is %d.\n", |
93 | 98 | argv [1], sfinfo.channels, MAX_CHANNELS) ; |
94 | exit (1) ; | |
95 | } ; | |
96 | ||
97 | ||
98 | state.channels = sfinfo.channels ; | |
99 | goto cleanup ; | |
100 | } ; | |
101 | ||
102 | ||
103 | state->channels = sfinfo.channels ; | |
99 | 104 | sfinfo.channels = 1 ; |
100 | 105 | |
101 | 106 | if (snprintf (pathname, sizeof (pathname), "%s", argv [1]) > (int) sizeof (pathname)) |
102 | 107 | { printf ("\nError : Length of provided filename '%s' exceeds MAX_PATH (%d).\n", argv [1], (int) sizeof (pathname)) ; |
103 | exit (1) ; | |
108 | goto cleanup ; | |
104 | 109 | } ; |
105 | 110 | |
106 | 111 | if ((cptr = strrchr (pathname, '.')) == NULL) |
113 | 118 | printf ("Input file : %s\n", pathname) ; |
114 | 119 | puts ("Output files :") ; |
115 | 120 | |
116 | for (ch = 0 ; ch < state.channels ; ch++) | |
121 | for (ch = 0 ; ch < state->channels ; ch++) | |
117 | 122 | { char filename [520] ; |
118 | 123 | size_t count ; |
119 | 124 | |
123 | 128 | { printf ("File name truncated to %s\n", filename) ; |
124 | 129 | } ; |
125 | 130 | |
126 | if ((state.outfile [ch] = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL) | |
131 | if ((state->outfile [ch] = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL) | |
127 | 132 | { printf ("Not able to open output file '%s'\n%s\n", filename, sf_strerror (NULL)) ; |
128 | exit (1) ; | |
133 | goto cleanup ; | |
129 | 134 | } ; |
130 | 135 | |
131 | 136 | printf (" %s\n", filename) ; |
144 | 149 | } ; |
145 | 150 | |
146 | 151 | if (double_split) |
147 | deinterleave_double (&state) ; | |
152 | deinterleave_double (state) ; | |
148 | 153 | else |
149 | deinterleave_int (&state) ; | |
150 | ||
151 | sf_close (state.infile) ; | |
152 | for (ch = 0 ; ch < MAX_CHANNELS ; ch++) | |
153 | if (state.outfile [ch] != NULL) | |
154 | sf_close (state.outfile [ch]) ; | |
155 | ||
156 | return 0 ; | |
154 | deinterleave_int (state) ; | |
155 | ||
156 | ret = 0 ; | |
157 | ||
158 | cleanup : | |
159 | ||
160 | if (state != NULL) | |
161 | { sf_close (state->infile) ; | |
162 | for (ch = 0 ; ch < MAX_CHANNELS ; ch++) | |
163 | if (state->outfile [ch] != NULL) | |
164 | sf_close (state->outfile [ch]) ; | |
165 | } ; | |
166 | ||
167 | free (state) ; | |
168 | ||
169 | return ret ; | |
157 | 170 | } /* main */ |
158 | 171 | |
159 | 172 | /*------------------------------------------------------------------------------ |
169 | 182 | "a_00.wav, a_01.wav and so on.\n" |
170 | 183 | ) ; |
171 | 184 | printf ("Using %s.\n\n", sf_version_string ()) ; |
172 | exit (1) ; | |
173 | 185 | } /* usage_exit */ |
174 | 186 | |
175 | 187 | static void |
178 | 190 | int ch, k ; |
179 | 191 | |
180 | 192 | do |
181 | { read_len = sf_readf_int (state->infile, state->din.i, BUFFER_LEN) ; | |
193 | { read_len = (int) sf_readf_int (state->infile, state->din.i, BUFFER_LEN) ; | |
182 | 194 | |
183 | 195 | for (ch = 0 ; ch < state->channels ; ch ++) |
184 | 196 | { for (k = 0 ; k < read_len ; k++) |
196 | 208 | int ch, k ; |
197 | 209 | |
198 | 210 | do |
199 | { read_len = sf_readf_double (state->infile, state->din.d, BUFFER_LEN) ; | |
211 | { read_len = (int) sf_readf_double (state->infile, state->din.d, BUFFER_LEN) ; | |
200 | 212 | |
201 | 213 | for (ch = 0 ; ch < state->channels ; ch ++) |
202 | 214 | { for (k = 0 ; k < read_len ; k++) |
109 | 109 | ** Print version and usage. |
110 | 110 | */ |
111 | 111 | |
112 | static double data [BUFFER_LEN] ; | |
113 | ||
114 | 112 | static void |
115 | 113 | usage_exit (const char *progname) |
116 | 114 | { printf ("Usage :\n %s <file> ...\n", progname) ; |
166 | 164 | |
167 | 165 | case SF_FORMAT_FLOAT : |
168 | 166 | case SF_FORMAT_DOUBLE : |
167 | case SF_FORMAT_VORBIS : | |
168 | case SF_FORMAT_OPUS : | |
169 | 169 | decibels = max / 1.0 ; |
170 | 170 | break ; |
171 | 171 | |
312 | 312 | printf (" Loop points : %d\n", inst.loop_count) ; |
313 | 313 | |
314 | 314 | for (k = 0 ; k < inst.loop_count ; k++) |
315 | 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) ; | |
315 | printf (" %-2d Mode : %s Start : %6" PRIu32 " End : %6" PRIu32 | |
316 | " Count : %6" PRIu32 "\n", k, str_of_type (inst.loops [k].mode), | |
317 | inst.loops [k].start, inst.loops [k].end, inst.loops [k].count) ; | |
316 | 318 | |
317 | 319 | putchar ('\n') ; |
318 | 320 | return 0 ; |
59 | 59 | } STATE ; |
60 | 60 | |
61 | 61 | |
62 | static void usage_exit (void) ; | |
62 | static void print_usage (void) ; | |
63 | 63 | static void interleave_int (STATE * state) ; |
64 | 64 | static void interleave_double (STATE * state) ; |
65 | 65 | |
66 | 66 | |
67 | 67 | int |
68 | 68 | main (int argc, char **argv) |
69 | { STATE state ; | |
69 | { STATE *state = NULL ; | |
70 | 70 | SF_INFO sfinfo ; |
71 | 71 | int k, double_merge = 0 ; |
72 | int ret = 1 ; | |
72 | 73 | |
73 | 74 | if (argc < 5) |
74 | 75 | { if (argc > 1) |
75 | 76 | puts ("\nError : need at least 2 input files.") ; |
76 | usage_exit () ; | |
77 | print_usage () ; | |
78 | goto cleanup ; | |
77 | 79 | } ; |
78 | 80 | |
79 | 81 | if (strcmp (argv [argc - 2], "-o") != 0) |
80 | 82 | { puts ("\nError : second last command line parameter should be '-o'.\n") ; |
81 | usage_exit () ; | |
83 | print_usage () ; | |
84 | goto cleanup ; | |
82 | 85 | } ; |
83 | 86 | |
84 | 87 | if (argc - 3 > MAX_INPUTS) |
85 | 88 | { printf ("\nError : Cannot handle more than %d input channels.\n\n", MAX_INPUTS) ; |
86 | exit (1) ; | |
87 | } ; | |
88 | ||
89 | memset (&state, 0, sizeof (state)) ; | |
89 | goto cleanup ; | |
90 | } ; | |
91 | ||
92 | state = calloc (1, sizeof (STATE)) ; | |
93 | if (state == NULL) | |
94 | { puts ("\nError : out of memory.\n") ; | |
95 | goto cleanup ; | |
96 | } ; | |
97 | ||
90 | 98 | memset (&sfinfo, 0, sizeof (sfinfo)) ; |
91 | 99 | |
92 | 100 | for (k = 1 ; k < argc - 2 ; k++) |
93 | 101 | { |
94 | if ((state.infile [k - 1] = sf_open (argv [k], SFM_READ, &sfinfo)) == NULL) | |
102 | if ((state->infile [k - 1] = sf_open (argv [k], SFM_READ, &sfinfo)) == NULL) | |
95 | 103 | { printf ("\nError : Not able to open input file '%s'\n%s\n", argv [k], sf_strerror (NULL)) ; |
96 | exit (1) ; | |
104 | goto cleanup ; | |
97 | 105 | } ; |
98 | 106 | |
99 | 107 | if (sfinfo.channels != 1) |
100 | 108 | { printf ("\bError : Input file '%s' should be mono (has %d channels).\n", argv [k], sfinfo.channels) ; |
101 | exit (1) ; | |
109 | goto cleanup ; | |
102 | 110 | } ; |
103 | 111 | |
104 | 112 | switch (sfinfo.format & SF_FORMAT_SUBMASK) |
112 | 120 | break ; |
113 | 121 | } ; |
114 | 122 | |
115 | state.channels ++ ; | |
116 | } ; | |
117 | ||
118 | sfinfo.channels = state.channels ; | |
123 | state->channels ++ ; | |
124 | } ; | |
125 | ||
126 | sfinfo.channels = state->channels ; | |
119 | 127 | sfinfo.format = sfe_file_type_of_ext (argv [argc - 1], sfinfo.format) ; |
120 | 128 | |
121 | if ((state.outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL) | |
129 | if ((state->outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL) | |
122 | 130 | { printf ("Not able to open output file '%s'\n%s\n", argv [argc - 1], sf_strerror (NULL)) ; |
123 | exit (1) ; | |
131 | goto cleanup ; | |
124 | 132 | } ; |
125 | 133 | |
126 | 134 | if (double_merge) |
127 | interleave_double (&state) ; | |
135 | interleave_double (state) ; | |
128 | 136 | else |
129 | interleave_int (&state) ; | |
130 | ||
131 | for (k = 0 ; k < MAX_INPUTS ; k++) | |
132 | if (state.infile [k] != NULL) | |
133 | sf_close (state.infile [k]) ; | |
134 | sf_close (state.outfile) ; | |
135 | ||
136 | return 0 ; | |
137 | interleave_int (state) ; | |
138 | ||
139 | ret = 0 ; | |
140 | ||
141 | cleanup : | |
142 | ||
143 | if (state != NULL) | |
144 | { for (k = 0 ; k < MAX_INPUTS ; k++) | |
145 | if (state->infile [k] != NULL) | |
146 | sf_close (state->infile [k]) ; | |
147 | sf_close (state->outfile) ; | |
148 | } | |
149 | ||
150 | free (state) ; | |
151 | ||
152 | return ret ; | |
137 | 153 | } /* main */ |
138 | 154 | |
139 | 155 | /*------------------------------------------------------------------------------ |
141 | 157 | |
142 | 158 | |
143 | 159 | static void |
144 | usage_exit (void) | |
160 | print_usage (void) | |
145 | 161 | { puts ("\nUsage : sndfile-interleave <input 1> <input 2> ... -o <output file>\n") ; |
146 | 162 | puts ("Merge two or more mono files into a single multi-channel file.\n") ; |
147 | 163 | printf ("Using %s.\n\n", sf_version_string ()) ; |
148 | exit (1) ; | |
149 | } /* usage_exit */ | |
164 | } /* print_usage */ | |
150 | 165 | |
151 | 166 | |
152 | 167 | static void |
158 | 173 | { max_read_len = 0 ; |
159 | 174 | |
160 | 175 | for (ch = 0 ; ch < state->channels ; ch ++) |
161 | { read_len = sf_read_int (state->infile [ch], state->din.i, BUFFER_LEN) ; | |
176 | { read_len = (int) sf_read_int (state->infile [ch], state->din.i, BUFFER_LEN) ; | |
162 | 177 | if (read_len < BUFFER_LEN) |
163 | 178 | memset (state->din.i + read_len, 0, sizeof (state->din.i [0]) * (BUFFER_LEN - read_len)) ; |
164 | 179 | |
184 | 199 | { max_read_len = 0 ; |
185 | 200 | |
186 | 201 | for (ch = 0 ; ch < state->channels ; ch ++) |
187 | { read_len = sf_read_double (state->infile [ch], state->din.d, BUFFER_LEN) ; | |
202 | { read_len = (int) sf_read_double (state->infile [ch], state->din.d, BUFFER_LEN) ; | |
188 | 203 | if (read_len < BUFFER_LEN) |
189 | 204 | memset (state->din.d + read_len, 0, sizeof (state->din.d [0]) * (BUFFER_LEN - read_len)) ; |
190 | 205 |
63 | 63 | #elif HAVE_SNDIO_H |
64 | 64 | #include <sndio.h> |
65 | 65 | |
66 | #elif (defined (sun) && defined (unix)) | |
66 | #elif (defined (sun) && defined (unix)) || defined(__NetBSD__) | |
67 | 67 | #include <fcntl.h> |
68 | 68 | #include <sys/ioctl.h> |
69 | 69 | #include <sys/audioio.h> |
327 | 327 | return 0 ; |
328 | 328 | break ; |
329 | 329 | |
330 | #if defined ESTRPIPE && ESTRPIPE != EPIPE | |
330 | 331 | case -ESTRPIPE : |
331 | 332 | fprintf (stderr, "alsa_write_float: Suspend event.n") ; |
332 | 333 | return 0 ; |
333 | 334 | break ; |
335 | #endif | |
334 | 336 | |
335 | 337 | case -EIO : |
336 | 338 | puts ("alsa_write_float: EIO") ; |
726 | 728 | ** Solaris. |
727 | 729 | */ |
728 | 730 | |
729 | #if (defined (sun) && defined (unix)) /* ie Solaris */ | |
731 | #if (defined (sun) && defined (unix)) || defined(__NetBSD__) | |
730 | 732 | |
731 | 733 | static void |
732 | 734 | solaris_play (int argc, char *argv []) |
763 | 765 | audio_info.play.channels = sfinfo.channels ; |
764 | 766 | audio_info.play.precision = 16 ; |
765 | 767 | audio_info.play.encoding = AUDIO_ENCODING_LINEAR ; |
766 | audio_info.play.gain = AUDIO_MAX_GAIN ; | |
767 | audio_info.play.balance = AUDIO_MID_BALANCE ; | |
768 | 768 | |
769 | 769 | if ((error = ioctl (audio_fd, AUDIO_SETINFO, &audio_info))) |
770 | 770 | { perror ("ioctl (AUDIO_SETINFO) failed") ; |
806 | 806 | return ; |
807 | 807 | } /* solaris_play */ |
808 | 808 | |
809 | #endif /* Solaris */ | |
809 | #endif /* Solaris or NetBSD */ | |
810 | 810 | |
811 | 811 | /*============================================================================== |
812 | 812 | ** Main function. |
844 | 844 | opensoundsys_play (argc, argv) ; |
845 | 845 | #elif HAVE_SNDIO_H |
846 | 846 | sndio_play (argc, argv) ; |
847 | #elif (defined (sun) && defined (unix)) | |
847 | #elif (defined (sun) && defined (unix)) || defined(__NetBSD__) | |
848 | 848 | solaris_play (argc, argv) ; |
849 | 849 | #elif (OS_IS_WIN32 == 1) |
850 | 850 | win32_play (argc, argv) ; |
55 | 55 | |
56 | 56 | #define NOT(x) (! (x)) |
57 | 57 | |
58 | #ifndef _WIN32 | |
59 | typedef off_t sf_off_t ; | |
60 | #else | |
61 | typedef long long sf_off_t ; | |
62 | #endif | |
63 | ||
58 | 64 | |
59 | 65 | static void usage_exit (const char *progname) ; |
60 | 66 | static void salvage_file (const char * broken_wav, const char * fixed_w64) ; |
73 | 79 | /*============================================================================== |
74 | 80 | */ |
75 | 81 | |
76 | static void lseek_or_die (int fd, off_t offset, int whence) ; | |
77 | static sf_count_t get_file_length (int fd, const char * name) ; | |
82 | static void lseek_or_die (int fd, sf_off_t offset, int whence) ; | |
83 | static sf_off_t get_file_length (int fd, const char * name) ; | |
78 | 84 | static sf_count_t find_data_offset (int fd, int format) ; |
79 | 85 | static void copy_data (int fd, SNDFILE * sndfile, int readsize) ; |
80 | 86 | |
179 | 185 | */ |
180 | 186 | |
181 | 187 | static void |
182 | lseek_or_die (int fd, off_t offset, int whence) | |
188 | lseek_or_die (int fd, sf_off_t offset, int whence) | |
183 | 189 | { |
190 | #ifndef _WIN32 | |
184 | 191 | if (lseek (fd, offset, whence) < 0) |
192 | #else | |
193 | if (_lseeki64 (fd, offset, whence) < 0) | |
194 | #endif | |
185 | 195 | { printf ("lseek failed : %s\n", strerror (errno)) ; |
186 | 196 | exit (1) ; |
187 | 197 | } ; |
190 | 200 | } /* lseek_or_die */ |
191 | 201 | |
192 | 202 | |
193 | static sf_count_t | |
203 | static sf_off_t | |
194 | 204 | get_file_length (int fd, const char * name) |
195 | { struct stat sbuf ; | |
205 | { | |
206 | #ifndef _WIN32 | |
207 | struct stat sbuf ; | |
208 | #else | |
209 | struct _stat64 sbuf ; | |
210 | #endif | |
196 | 211 | |
197 | 212 | if (sizeof (sbuf.st_size) != 8) |
198 | 213 | { puts ("Error : sizeof (sbuf.st_size) != 8. Was program compiled with\n" |
200 | 215 | exit (1) ; |
201 | 216 | } ; |
202 | 217 | |
218 | #ifndef _WIN32 | |
203 | 219 | if (fstat (fd, &sbuf) != 0) |
220 | #else | |
221 | if (_fstat64 (fd, &sbuf) != 0) | |
222 | #endif | |
204 | 223 | { printf ("Error : fstat ('%s') failed : %s\n", name, strerror (errno)) ; |
205 | 224 | exit (1) ; |
206 | 225 | } ; |
232 | 251 | exit (1) ; |
233 | 252 | } ; |
234 | 253 | |
235 | slen = strlen (target) ; | |
254 | slen = (int) strlen (target) ; | |
236 | 255 | |
237 | 256 | lseek_or_die (fd, 0, SEEK_SET) ; |
238 | 257 |
266 | 266 | int |
267 | 267 | db_list_all (REG_DB * db_handle) |
268 | 268 | { |
269 | printf ("%s : %p\n", __func__, db_handle) ; | |
269 | printf ("%s : %p\n", __func__, (void *) db_handle) ; | |
270 | 270 | return 0 ; |
271 | 271 | } /* db_list_all */ |
272 | 272 | |
273 | 273 | int |
274 | 274 | db_del_entry (REG_DB * db_handle, const char * entry) |
275 | 275 | { |
276 | printf ("%s : %p %s\n", __func__, db_handle, entry) ; | |
276 | printf ("%s : %p %s\n", __func__, (void *) db_handle, entry) ; | |
277 | 277 | return 0 ; |
278 | 278 | } /* db_del_entry */ |
279 | 279 | |
427 | 427 | get_filename_pathname (REGTEST_DB * db, const char *filepath) |
428 | 428 | { |
429 | 429 | const char * basename = db_basename (filepath) ; |
430 | int slen ; | |
430 | size_t slen ; | |
431 | 431 | |
432 | 432 | /* Test for a relative path |
433 | 433 | */ |
5 | 5 | Name: sndfile |
6 | 6 | Description: A library for reading and writing audio files |
7 | 7 | Requires: |
8 | Requires.private: @EXTERNAL_XIPH_REQUIRE@ | |
8 | Requires.private: @EXTERNAL_XIPH_REQUIRE@ @EXTERNAL_MPEG_REQUIRE@ | |
9 | 9 | Version: @VERSION@ |
10 | 10 | Libs: -L${libdir} -lsndfile |
11 | Libs.private: @EXTERNAL_MPEG_LIBS@ | |
11 | 12 | Cflags: -I${includedir} |
41 | 41 | |
42 | 42 | #if __GNUC__ |
43 | 43 | #define ALWAYS_INLINE __attribute__ ((always_inline)) |
44 | #elif defined _MSC_VER | |
45 | #define ALWAYS_INLINE __forceinline | |
44 | 46 | #else |
45 | 47 | #define ALWAYS_INLINE |
46 | 48 | #endif |
43 | 43 | |
44 | 44 | #if __GNUC__ |
45 | 45 | #define ALWAYS_INLINE __attribute__ ((always_inline)) |
46 | #elif defined _MSC_VER | |
47 | #define ALWAYS_INLINE __forceinline | |
46 | 48 | #else |
47 | 49 | #define ALWAYS_INLINE |
48 | 50 | #endif |
47 | 47 | { |
48 | 48 | int32_t mPredictor [ALAC_FRAME_LENGTH] ; |
49 | 49 | uint16_t mShiftBuffer [ALAC_FRAME_LENGTH] ; |
50 | } ; | |
50 | } u ; | |
51 | 51 | uint32_t mNumChannels ; |
52 | 52 | } ALAC_DECODER ; |
53 | 53 |
109 | 109 | |
110 | 110 | RequireAction (p->mConfig.compatibleVersion <= kALACVersion, return kALAC_IncompatibleVersion ;) ; |
111 | 111 | RequireAction ((p->mConfig.bitDepth >= 8 && p->mConfig.bitDepth <= 32), return kALAC_BadBitWidth ;) ; |
112 | RequireAction ((p->mMixBufferU != NULL) && (p->mMixBufferV != NULL) && (p->mPredictor != NULL), | |
112 | RequireAction ((p->mMixBufferU != NULL) && (p->mMixBufferV != NULL) && (p->u.mPredictor != NULL), | |
113 | 113 | status = kALAC_MemFullError ; goto Exit ;) ; |
114 | 114 | } |
115 | 115 | else |
246 | 246 | |
247 | 247 | // decompress |
248 | 248 | set_ag_params (&agParams, p->mConfig.mb, (pb * pbFactorU) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ; |
249 | status = dyn_decomp (&agParams, bits, p->mPredictor, numSamples, chanBits, &bits1) ; | |
249 | status = dyn_decomp (&agParams, bits, p->u.mPredictor, numSamples, chanBits, &bits1) ; | |
250 | 250 | RequireNoErr (status, goto Exit ;) ; |
251 | 251 | |
252 | 252 | if (modeU == 0) |
253 | 253 | { |
254 | unpc_block (p->mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; | |
254 | unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; | |
255 | 255 | } |
256 | 256 | else |
257 | 257 | { |
258 | 258 | // the special "numActive == 31" mode can be done in-place |
259 | unpc_block (p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0) ; | |
260 | unpc_block (p->mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; | |
259 | unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 0) ; | |
260 | unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; | |
261 | 261 | } |
262 | 262 | } |
263 | 263 | else |
299 | 299 | //Assert (shift <= 16) ; |
300 | 300 | |
301 | 301 | for (i = 0 ; i < numSamples ; i++) |
302 | p->mShiftBuffer [i] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; | |
302 | p->u.mShiftBuffer [i] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; | |
303 | 303 | } |
304 | 304 | |
305 | 305 | // convert 32-bit integers into output buffer |
317 | 317 | case 24: |
318 | 318 | out32 = sampleBuffer + channelIndex ; |
319 | 319 | if (bytesShifted != 0) |
320 | copyPredictorTo24Shift (p->mMixBufferU, p->mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ; | |
320 | copyPredictorTo24Shift (p->mMixBufferU, p->u.mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ; | |
321 | 321 | else |
322 | 322 | copyPredictorTo24 (p->mMixBufferU, out32, numChannels, numSamples) ; |
323 | 323 | break ; |
324 | 324 | case 32: |
325 | 325 | out32 = sampleBuffer + channelIndex ; |
326 | 326 | if (bytesShifted != 0) |
327 | copyPredictorTo32Shift (p->mMixBufferU, p->mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ; | |
327 | copyPredictorTo32Shift (p->mMixBufferU, p->u.mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ; | |
328 | 328 | else |
329 | 329 | copyPredictorTo32 (p->mMixBufferU, out32, numChannels, numSamples) ; |
330 | 330 | break ; |
407 | 407 | |
408 | 408 | // decompress and run predictor for "left" channel |
409 | 409 | set_ag_params (&agParams, p->mConfig.mb, (pb * pbFactorU) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ; |
410 | status = dyn_decomp (&agParams, bits, p->mPredictor, numSamples, chanBits, &bits1) ; | |
410 | status = dyn_decomp (&agParams, bits, p->u.mPredictor, numSamples, chanBits, &bits1) ; | |
411 | 411 | RequireNoErr (status, goto Exit ;) ; |
412 | 412 | |
413 | 413 | if (modeU == 0) |
414 | 414 | { |
415 | unpc_block (p->mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; | |
415 | unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; | |
416 | 416 | } |
417 | 417 | else |
418 | 418 | { |
419 | 419 | // the special "numActive == 31" mode can be done in-place |
420 | unpc_block (p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0) ; | |
421 | unpc_block (p->mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; | |
420 | unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 0) ; | |
421 | unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ; | |
422 | 422 | } |
423 | 423 | |
424 | 424 | // decompress and run predictor for "right" channel |
425 | 425 | set_ag_params (&agParams, p->mConfig.mb, (pb * pbFactorV) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ; |
426 | status = dyn_decomp (&agParams, bits, p->mPredictor, numSamples, chanBits, &bits2) ; | |
426 | status = dyn_decomp (&agParams, bits, p->u.mPredictor, numSamples, chanBits, &bits2) ; | |
427 | 427 | RequireNoErr (status, goto Exit ;) ; |
428 | 428 | |
429 | 429 | if (modeV == 0) |
430 | 430 | { |
431 | unpc_block (p->mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ; | |
431 | unpc_block (p->u.mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ; | |
432 | 432 | } |
433 | 433 | else |
434 | 434 | { |
435 | 435 | // the special "numActive == 31" mode can be done in-place |
436 | unpc_block (p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0) ; | |
437 | unpc_block (p->mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ; | |
436 | unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 0) ; | |
437 | unpc_block (p->u.mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ; | |
438 | 438 | } |
439 | 439 | } |
440 | 440 | else |
487 | 487 | |
488 | 488 | for (i = 0 ; i < (numSamples * 2) ; i += 2) |
489 | 489 | { |
490 | p->mShiftBuffer [i + 0] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; | |
491 | p->mShiftBuffer [i + 1] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; | |
490 | p->u.mShiftBuffer [i + 0] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; | |
491 | p->u.mShiftBuffer [i + 1] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ; | |
492 | 492 | } |
493 | 493 | } |
494 | 494 | |
507 | 507 | case 24: |
508 | 508 | out32 = sampleBuffer + channelIndex ; |
509 | 509 | unmix24 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples, |
510 | mixBits, mixRes, p->mShiftBuffer, bytesShifted) ; | |
510 | mixBits, mixRes, p->u.mShiftBuffer, bytesShifted) ; | |
511 | 511 | break ; |
512 | 512 | case 32: |
513 | 513 | out32 = sampleBuffer + channelIndex ; |
514 | 514 | unmix32 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples, |
515 | mixBits, mixRes, p->mShiftBuffer, bytesShifted) ; | |
515 | mixBits, mixRes, p->u.mShiftBuffer, bytesShifted) ; | |
516 | 516 | break ; |
517 | 517 | } |
518 | 518 | |
553 | 553 | } |
554 | 554 | } |
555 | 555 | |
556 | #if 0 // ! DEBUG | |
556 | #if 1 // ! DEBUG | |
557 | 557 | // 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) |
558 | 558 | // - this also protects us if the config does not match the bitstream or crap data bits follow the audio bits |
559 | 559 | if (channelIndex >= numChannels) |
33 | 33 | |
34 | 34 | #if __GNUC__ |
35 | 35 | #define ALWAYS_INLINE __attribute__ ((always_inline)) |
36 | #elif defined _MSC_VER | |
37 | #define ALWAYS_INLINE __forceinline | |
36 | 38 | #else |
37 | 39 | #define ALWAYS_INLINE |
38 | 40 | #endif |
32 | 32 | |
33 | 33 | #if __GNUC__ |
34 | 34 | #define ALWAYS_INLINE __attribute__ ((always_inline)) |
35 | #elif defined _MSC_VER | |
36 | #define ALWAYS_INLINE __forceinline | |
35 | 37 | #else |
36 | 38 | #define ALWAYS_INLINE |
37 | 39 | #endif |
17 | 17 | |
18 | 18 | #if __GNUC__ |
19 | 19 | #define ALWAYS_INLINE __attribute__ ((always_inline)) |
20 | #elif defined _MSC_VER | |
21 | #define ALWAYS_INLINE __forceinline | |
20 | 22 | #else |
21 | 23 | #define ALWAYS_INLINE |
22 | 24 | #endif |
107 | 107 | |
108 | 108 | #if __GNUC__ |
109 | 109 | #define ALWAYS_INLINE __attribute__ ((always_inline)) |
110 | #elif defined _MSC_VER | |
111 | #define ALWAYS_INLINE __forceinline | |
110 | 112 | #else |
111 | 113 | #define ALWAYS_INLINE |
112 | 114 | #endif |
293 | 293 | |
294 | 294 | #if __GNUC__ |
295 | 295 | #define ALWAYS_INLINE __attribute__ ((always_inline)) |
296 | #elif defined _MSC_VER | |
297 | #define ALWAYS_INLINE __forceinline | |
296 | 298 | #else |
297 | 299 | #define ALWAYS_INLINE |
298 | 300 | #endif |
233 | 233 | int |
234 | 234 | aiff_open (SF_PRIVATE *psf) |
235 | 235 | { COMM_CHUNK comm_fmt ; |
236 | int error, subformat ; | |
236 | int error = 0, subformat ; | |
237 | 237 | |
238 | 238 | memset (&comm_fmt, 0, sizeof (comm_fmt)) ; |
239 | 239 | |
506 | 506 | if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) |
507 | 507 | return SFE_MALLOC_FAILED ; |
508 | 508 | |
509 | /* read in rest of PEAK chunk. */ | |
509 | /* Read in rest of PEAK chunk. */ | |
510 | 510 | psf_binheader_readf (psf, "E44", &(psf->peak_info->version), &(psf->peak_info->timestamp)) ; |
511 | 511 | |
512 | 512 | if (psf->peak_info->version != 1) |
1002 | 1002 | ubuf.scbuf [0] = 0 ; |
1003 | 1003 | |
1004 | 1004 | /* The COMM chunk has an int aligned to an odd word boundary. Some |
1005 | ** procesors are not able to deal with this (ie bus fault) so we have | |
1005 | ** processors are not able to deal with this (ie bus fault) so we have | |
1006 | 1006 | ** to take special care. |
1007 | 1007 | */ |
1008 | 1008 |
50 | 50 | |
51 | 51 | |
52 | 52 | /* Can't have a decoder and an encoder at the same time so stick |
53 | ** them in an un-named union. | |
53 | ** them in a union. | |
54 | 54 | */ |
55 | 55 | union |
56 | 56 | { ALAC_DECODER decoder ; |
57 | 57 | ALAC_ENCODER encoder ; |
58 | } ; | |
58 | } u ; | |
59 | 59 | |
60 | 60 | char enctmpname [512] ; |
61 | 61 | FILE *enctmp ; |
168 | 168 | plac = psf->codec_data ; |
169 | 169 | |
170 | 170 | if (psf->file.mode == SFM_WRITE) |
171 | { ALAC_ENCODER *penc = &plac->encoder ; | |
171 | { ALAC_ENCODER *penc = &plac->u.encoder ; | |
172 | 172 | SF_CHUNK_INFO chunk_info ; |
173 | 173 | sf_count_t readcount ; |
174 | 174 | uint8_t kuki_data [1024] ; |
267 | 267 | /* Read in the ALAC cookie data and pass it to the init function. */ |
268 | 268 | kuki_size = alac_kuki_read (psf, info->kuki_offset, u.kuki, sizeof (u.kuki)) ; |
269 | 269 | |
270 | if ((error = alac_decoder_init (&plac->decoder, u.kuki, kuki_size)) != ALAC_noErr) | |
270 | if ((error = alac_decoder_init (&plac->u.decoder, u.kuki, kuki_size)) != ALAC_noErr) | |
271 | 271 | { psf_log_printf (psf, "*** alac_decoder_init() returned %s. ***\n", alac_error_string (error)) ; |
272 | 272 | return SFE_INTERNAL ; |
273 | 273 | } ; |
274 | 274 | |
275 | 275 | |
276 | if (plac->decoder.mNumChannels != (unsigned) psf->sf.channels) | |
277 | { psf_log_printf (psf, "*** Initialized decoder has %u channels, but it should be %d. ***\n", plac->decoder.mNumChannels, psf->sf.channels) ; | |
276 | if (plac->u.decoder.mNumChannels != (unsigned) psf->sf.channels) | |
277 | { psf_log_printf (psf, "*** Initialized decoder has %u channels, but it should be %d. ***\n", plac->u.decoder.mNumChannels, psf->sf.channels) ; | |
278 | 278 | return SFE_INTERNAL ; |
279 | 279 | } ; |
280 | 280 | |
356 | 356 | return SFE_ALAC_FAIL_TMPFILE ; |
357 | 357 | } ; |
358 | 358 | |
359 | alac_encoder_init (&plac->encoder, psf->sf.samplerate, psf->sf.channels, alac_format_flags, ALAC_FRAME_LENGTH) ; | |
359 | alac_encoder_init (&plac->u.encoder, psf->sf.samplerate, psf->sf.channels, alac_format_flags, ALAC_FRAME_LENGTH) ; | |
360 | 360 | |
361 | 361 | return 0 ; |
362 | 362 | } /* alac_writer_init */ |
401 | 401 | |
402 | 402 | static int |
403 | 403 | alac_decode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac) |
404 | { ALAC_DECODER *pdec = &plac->decoder ; | |
404 | { ALAC_DECODER *pdec = &plac->u.decoder ; | |
405 | 405 | uint32_t packet_size ; |
406 | 406 | BitBuffer bit_buffer ; |
407 | 407 | |
436 | 436 | |
437 | 437 | static int |
438 | 438 | alac_encode_block (ALAC_PRIVATE *plac) |
439 | { ALAC_ENCODER *penc = &plac->encoder ; | |
439 | { ALAC_ENCODER *penc = &plac->u.encoder ; | |
440 | 440 | uint32_t num_bytes = 0 ; |
441 | 441 | |
442 | 442 | alac_encode (penc, plac->partial_block_frames, plac->buffer, plac->byte_buffer, &num_bytes) ; |
470 | 470 | break ; |
471 | 471 | |
472 | 472 | readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ; |
473 | readcount = readcount > len ? len : readcount ; | |
473 | readcount = readcount > len ? (int) len : readcount ; | |
474 | 474 | |
475 | 475 | iptr = plac->buffer + plac->partial_block_frames * plac->channels ; |
476 | 476 | |
500 | 500 | break ; |
501 | 501 | |
502 | 502 | readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ; |
503 | readcount = readcount > len ? len : readcount ; | |
503 | readcount = readcount > len ? (int) len : readcount ; | |
504 | 504 | |
505 | 505 | iptr = plac->buffer + plac->partial_block_frames * plac->channels ; |
506 | 506 | |
533 | 533 | break ; |
534 | 534 | |
535 | 535 | readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ; |
536 | readcount = readcount > len ? len : readcount ; | |
536 | readcount = readcount > len ? (int) len : readcount ; | |
537 | 537 | |
538 | 538 | iptr = plac->buffer + plac->partial_block_frames * plac->channels ; |
539 | 539 | |
566 | 566 | break ; |
567 | 567 | |
568 | 568 | readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ; |
569 | readcount = readcount > len ? len : readcount ; | |
569 | readcount = readcount > len ? (int) len : readcount ; | |
570 | 570 | |
571 | 571 | iptr = plac->buffer + plac->partial_block_frames * plac->channels ; |
572 | 572 | |
647 | 647 | |
648 | 648 | while (len > 0) |
649 | 649 | { writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ; |
650 | writecount = (writecount == 0 || writecount > len) ? len : writecount ; | |
650 | writecount = (writecount == 0 || writecount > len) ? (int) len : writecount ; | |
651 | 651 | |
652 | 652 | iptr = plac->buffer + plac->partial_block_frames * plac->channels ; |
653 | 653 | |
678 | 678 | |
679 | 679 | while (len > 0) |
680 | 680 | { writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ; |
681 | writecount = (writecount == 0 || writecount > len) ? len : writecount ; | |
681 | writecount = (writecount == 0 || writecount > len) ? (int) len : writecount ; | |
682 | 682 | |
683 | 683 | iptr = plac->buffer + plac->partial_block_frames * plac->channels ; |
684 | 684 | |
712 | 712 | |
713 | 713 | while (len > 0) |
714 | 714 | { writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ; |
715 | writecount = (writecount == 0 || writecount > len) ? len : writecount ; | |
715 | writecount = (writecount == 0 || writecount > len) ? (int) len : writecount ; | |
716 | 716 | |
717 | 717 | iptr = plac->buffer + plac->partial_block_frames * plac->channels ; |
718 | 718 | |
745 | 745 | |
746 | 746 | while (len > 0) |
747 | 747 | { writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ; |
748 | writecount = (writecount == 0 || writecount > len) ? len : writecount ; | |
748 | writecount = (writecount == 0 || writecount > len) ? (int) len : writecount ; | |
749 | 749 | |
750 | 750 | iptr = plac->buffer + plac->partial_block_frames * plac->channels ; |
751 | 751 | |
823 | 823 | |
824 | 824 | pakt_size = chunk_info.datalen ; |
825 | 825 | chunk_info.data = pakt_data = malloc (pakt_size + 5) ; |
826 | if (!chunk_info.data) | |
827 | return NULL ; | |
826 | 828 | |
827 | 829 | if ((bcount = psf->get_chunk_data (psf, chunk_iterator, &chunk_info)) != SF_ERR_NO_ERROR) |
828 | 830 | { while (chunk_iterator) |
849 | 851 | |
850 | 852 | count ++ ; |
851 | 853 | if (count > 5 || bcount + count > pakt_size) |
852 | { printf ("%s %d : Ooops! count %d bcount %d\n", __func__, __LINE__, count, bcount) ; | |
854 | { printf ("%s %d : Ooops! count %" PRIi32 " bcount %" PRIu32 "\n", __func__, __LINE__, count, bcount) ; | |
853 | 855 | value = 0 ; |
854 | 856 | break ; |
855 | 857 | } ; |
291 | 291 | |
292 | 292 | static inline void |
293 | 293 | alaw2s_array (unsigned char *buffer, int count, short *ptr) |
294 | { while (--count >= 0) | |
295 | ptr [count] = alaw_decode [(int) buffer [count]] ; | |
294 | { for (int i = 0 ; i < count ; i++) | |
295 | ptr [i] = alaw_decode [(int) buffer [i]] ; | |
296 | 296 | } /* alaw2s_array */ |
297 | 297 | |
298 | 298 | static inline void |
299 | 299 | alaw2i_array (unsigned char *buffer, int count, int *ptr) |
300 | { while (--count >= 0) | |
301 | ptr [count] = ((uint32_t) alaw_decode [(int) buffer [count]]) << 16 ; | |
300 | { for (int i = 0 ; i < count ; i++) | |
301 | ptr [i] = ((uint32_t) alaw_decode [(int) buffer [i]]) << 16 ; | |
302 | 302 | } /* alaw2i_array */ |
303 | 303 | |
304 | 304 | static inline void |
305 | 305 | alaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact) |
306 | { while (--count >= 0) | |
307 | ptr [count] = normfact * alaw_decode [(int) buffer [count]] ; | |
306 | { for (int i = 0 ; i < count ; i++) | |
307 | ptr [i] = normfact * alaw_decode [(int) buffer [i]] ; | |
308 | 308 | } /* alaw2f_array */ |
309 | 309 | |
310 | 310 | static inline void |
311 | 311 | alaw2d_array (unsigned char *buffer, int count, double *ptr, double normfact) |
312 | { while (--count >= 0) | |
313 | ptr [count] = normfact * alaw_decode [(int) buffer [count]] ; | |
312 | { for (int i = 0 ; i < count ; i++) | |
313 | ptr [i] = normfact * alaw_decode [(int) buffer [i]] ; | |
314 | 314 | } /* alaw2d_array */ |
315 | 315 | |
316 | 316 | static inline void |
317 | 317 | s2alaw_array (const short *ptr, int count, unsigned char *buffer) |
318 | { while (--count >= 0) | |
319 | { if (ptr [count] >= 0) | |
320 | buffer [count] = alaw_encode [ptr [count] / 16] ; | |
318 | { for (int i = 0 ; i < count ; i++) | |
319 | { if (ptr [i] >= 0) | |
320 | buffer [i] = alaw_encode [ptr [i] / 16] ; | |
321 | 321 | else |
322 | buffer [count] = 0x7F & alaw_encode [ptr [count] / -16] ; | |
322 | buffer [i] = 0x7F & alaw_encode [ptr [i] / -16] ; | |
323 | 323 | } ; |
324 | 324 | } /* s2alaw_array */ |
325 | 325 | |
326 | 326 | static inline void |
327 | 327 | i2alaw_array (const int *ptr, int count, unsigned char *buffer) |
328 | { while (--count >= 0) | |
329 | { if (ptr [count] == INT_MIN) | |
330 | buffer [count] = alaw_encode [INT_MAX >> (16 + 4)] ; | |
331 | else if (ptr [count] >= 0) | |
332 | buffer [count] = alaw_encode [ptr [count] >> (16 + 4)] ; | |
328 | { for (int i = 0 ; i < count ; i++) | |
329 | { if (ptr [i] == INT_MIN) | |
330 | buffer [i] = alaw_encode [INT_MAX >> (16 + 4)] ; | |
331 | else if (ptr [i] >= 0) | |
332 | buffer [i] = alaw_encode [ptr [i] >> (16 + 4)] ; | |
333 | 333 | else |
334 | buffer [count] = 0x7F & alaw_encode [- ptr [count] >> (16 + 4)] ; | |
334 | buffer [i] = 0x7F & alaw_encode [- ptr [i] >> (16 + 4)] ; | |
335 | 335 | } ; |
336 | 336 | } /* i2alaw_array */ |
337 | 337 | |
338 | 338 | static inline void |
339 | 339 | f2alaw_array (const float *ptr, int count, unsigned char *buffer, float normfact) |
340 | { while (--count >= 0) | |
341 | { if (ptr [count] >= 0) | |
342 | buffer [count] = alaw_encode [psf_lrintf (normfact * ptr [count])] ; | |
340 | { for (int i = 0 ; i < count ; i++) | |
341 | { if (ptr [i] >= 0) | |
342 | buffer [i] = alaw_encode [psf_lrintf (normfact * ptr [i])] ; | |
343 | 343 | else |
344 | buffer [count] = 0x7F & alaw_encode [- psf_lrintf (normfact * ptr [count])] ; | |
344 | buffer [i] = 0x7F & alaw_encode [- psf_lrintf (normfact * ptr [i])] ; | |
345 | 345 | } ; |
346 | 346 | } /* f2alaw_array */ |
347 | 347 | |
348 | 348 | static inline void |
349 | 349 | d2alaw_array (const double *ptr, int count, unsigned char *buffer, double normfact) |
350 | { while (--count >= 0) | |
351 | { if (!isfinite (ptr [count])) | |
352 | buffer [count] = 0 ; | |
353 | else if (ptr [count] >= 0) | |
354 | buffer [count] = alaw_encode [psf_lrint (normfact * ptr [count])] ; | |
350 | { for (int i = 0 ; i < count ; i++) | |
351 | { if (!isfinite (ptr [i])) | |
352 | buffer [i] = 0 ; | |
353 | else if (ptr [i] >= 0) | |
354 | buffer [i] = alaw_encode [psf_lrint (normfact * ptr [i])] ; | |
355 | 355 | else |
356 | buffer [count] = 0x7F & alaw_encode [- psf_lrint (normfact * ptr [count])] ; | |
356 | buffer [i] = 0x7F & alaw_encode [- psf_lrint (normfact * ptr [i])] ; | |
357 | 357 | } ; |
358 | 358 | } /* d2alaw_array */ |
359 | 359 | |
371 | 371 | while (len > 0) |
372 | 372 | { if (len < bufferlen) |
373 | 373 | bufferlen = (int) len ; |
374 | readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
374 | readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
375 | 375 | alaw2s_array (ubuf.ucbuf, readcount, ptr + total) ; |
376 | 376 | total += readcount ; |
377 | 377 | if (readcount < bufferlen) |
393 | 393 | while (len > 0) |
394 | 394 | { if (len < bufferlen) |
395 | 395 | bufferlen = (int) len ; |
396 | readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
396 | readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
397 | 397 | alaw2i_array (ubuf.ucbuf, readcount, ptr + total) ; |
398 | 398 | total += readcount ; |
399 | 399 | if (readcount < bufferlen) |
418 | 418 | while (len > 0) |
419 | 419 | { if (len < bufferlen) |
420 | 420 | bufferlen = (int) len ; |
421 | readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
421 | readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
422 | 422 | alaw2f_array (ubuf.ucbuf, readcount, ptr + total, normfact) ; |
423 | 423 | total += readcount ; |
424 | 424 | if (readcount < bufferlen) |
442 | 442 | while (len > 0) |
443 | 443 | { if (len < bufferlen) |
444 | 444 | bufferlen = (int) len ; |
445 | readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
445 | readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
446 | 446 | alaw2d_array (ubuf.ucbuf, readcount, ptr + total, normfact) ; |
447 | 447 | total += readcount ; |
448 | 448 | if (readcount < bufferlen) |
468 | 468 | { if (len < bufferlen) |
469 | 469 | bufferlen = (int) len ; |
470 | 470 | s2alaw_array (ptr + total, bufferlen, ubuf.ucbuf) ; |
471 | writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
471 | writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
472 | 472 | total += writecount ; |
473 | 473 | if (writecount < bufferlen) |
474 | 474 | break ; |
490 | 490 | { if (len < bufferlen) |
491 | 491 | bufferlen = (int) len ; |
492 | 492 | i2alaw_array (ptr + total, bufferlen, ubuf.ucbuf) ; |
493 | writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
493 | writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
494 | 494 | total += writecount ; |
495 | 495 | if (writecount < bufferlen) |
496 | 496 | break ; |
515 | 515 | { if (len < bufferlen) |
516 | 516 | bufferlen = (int) len ; |
517 | 517 | f2alaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ; |
518 | writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
518 | writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
519 | 519 | total += writecount ; |
520 | 520 | if (writecount < bufferlen) |
521 | 521 | break ; |
540 | 540 | { if (len < bufferlen) |
541 | 541 | bufferlen = (int) len ; |
542 | 542 | d2alaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ; |
543 | writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
543 | writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
544 | 544 | total += writecount ; |
545 | 545 | if (writecount < bufferlen) |
546 | 546 | break ; |
26 | 26 | |
27 | 27 | #define TWOBIT_MARKER (MAKE_MARKER ('2', 'B', 'I', 'T')) |
28 | 28 | #define AVR_HDR_SIZE 128 |
29 | ||
30 | #define SFE_AVR_X 666 | |
31 | 29 | |
32 | 30 | /* |
33 | 31 | ** From: hyc@hanauma.Jpl.Nasa.Gov (Howard Chu) |
115 | 113 | psf_log_printf (psf, "%M\n", hdr.marker) ; |
116 | 114 | |
117 | 115 | if (hdr.marker != TWOBIT_MARKER) |
118 | return SFE_AVR_X ; | |
116 | return SFE_AVR_NOT_AVR ; | |
119 | 117 | |
120 | 118 | psf_log_printf (psf, " Name : %s\n", hdr.name) ; |
121 | 119 | |
144 | 142 | |
145 | 143 | default : |
146 | 144 | psf_log_printf (psf, "Error : bad rez/sign combination.\n") ; |
147 | return SFE_AVR_X ; | |
145 | return SFE_AVR_BAD_REZ_SIGN ; | |
148 | 146 | } ; |
149 | 147 | |
150 | 148 | psf_binheader_readf (psf, "E4444", &hdr.srate, &hdr.frames, &hdr.lbeg, &hdr.lend) ; |
83 | 83 | /* Force coding_history_size to be even. */ |
84 | 84 | len = strlen (psf->broadcast_16k->coding_history) ; |
85 | 85 | len += (len & 1) ? 1 : 0 ; |
86 | psf->broadcast_16k->coding_history_size = len ; | |
86 | psf->broadcast_16k->coding_history_size = (uint32_t) len ; | |
87 | 87 | |
88 | 88 | /* Currently writing this version. */ |
89 | 89 | psf->broadcast_16k->version = 2 ; |
145 | 145 | break ; |
146 | 146 | |
147 | 147 | default : |
148 | snprintf (chnstr, sizeof (chnstr), "%uchn", psfinfo->channels) ; | |
148 | snprintf (chnstr, sizeof (chnstr), "%dchn", psfinfo->channels) ; | |
149 | 149 | break ; |
150 | 150 | } ; |
151 | 151 | |
179 | 179 | } ; |
180 | 180 | |
181 | 181 | count = snprintf (added_history, added_history_max, |
182 | "A=PCM,F=%u,W=%d,M=%s,T=%s-%s\r\n", | |
182 | "A=PCM,F=%d,W=%d,M=%s,T=%s-%s\r\n", | |
183 | 183 | psfinfo->samplerate, width, chnstr, PACKAGE_NAME, PACKAGE_VERSION) ; |
184 | 184 | |
185 | 185 | if (count >= added_history_max) |
65 | 65 | |
66 | 66 | #define CAF_PEAK_CHUNK_SIZE(ch) ((int) (sizeof (int) + ch * (sizeof (float) + 8))) |
67 | 67 | |
68 | #define SFE_CAF_NOT_CAF 666 | |
69 | #define SFE_CAF_NO_DESC 667 | |
70 | #define SFE_CAF_BAD_PEAK 668 | |
71 | ||
72 | 68 | /*------------------------------------------------------------------------------ |
73 | 69 | ** Typedefs. |
74 | 70 | */ |
410 | 406 | { case peak_MARKER : |
411 | 407 | psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; |
412 | 408 | if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) |
413 | { psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; | |
409 | { psf_binheader_readf (psf, "j", (size_t) chunk_size) ; | |
414 | 410 | psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ; |
415 | 411 | return SFE_CAF_BAD_PEAK ; |
416 | 412 | } ; |
417 | 413 | |
414 | if (psf->peak_info) | |
415 | { psf_log_printf (psf, "*** Found existing peak info, using last one.\n") ; | |
416 | free (psf->peak_info) ; | |
417 | psf->peak_info = NULL ; | |
418 | } ; | |
418 | 419 | if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) |
419 | 420 | return SFE_MALLOC_FAILED ; |
420 | 421 | |
441 | 442 | case chan_MARKER : |
442 | 443 | if (chunk_size < 12) |
443 | 444 | { psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ; |
444 | psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; | |
445 | psf_binheader_readf (psf, "j", (size_t) chunk_size) ; | |
445 | 446 | break ; |
446 | 447 | } |
447 | 448 | |
453 | 454 | |
454 | 455 | case free_MARKER : |
455 | 456 | psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; |
456 | psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; | |
457 | psf_binheader_readf (psf, "j", (size_t) chunk_size) ; | |
457 | 458 | break ; |
458 | 459 | |
459 | 460 | case data_MARKER : |
478 | 479 | if (psf->datalength + psf->dataoffset < psf->filelength) |
479 | 480 | psf->dataend = psf->datalength + psf->dataoffset ; |
480 | 481 | |
481 | psf_binheader_readf (psf, "j", make_size_t (psf->datalength)) ; | |
482 | psf_binheader_readf (psf, "j", (size_t) psf->datalength) ; | |
482 | 483 | have_data = 1 ; |
483 | 484 | break ; |
484 | 485 | |
485 | 486 | case kuki_MARKER : |
486 | 487 | psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; |
487 | 488 | pcaf->alac.kuki_offset = psf_ftell (psf) - 12 ; |
488 | psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; | |
489 | psf_binheader_readf (psf, "j", (size_t) chunk_size) ; | |
489 | 490 | break ; |
490 | 491 | |
491 | 492 | case pakt_MARKER : |
517 | 518 | psf_log_printf (psf, "*** 'pakt' chunk header is all zero.\n") ; |
518 | 519 | |
519 | 520 | pcaf->alac.pakt_offset = psf_ftell (psf) - 12 ; |
520 | psf_binheader_readf (psf, "j", make_size_t (chunk_size) - 24) ; | |
521 | psf_binheader_readf (psf, "j", (size_t) chunk_size - 24) ; | |
521 | 522 | break ; |
522 | 523 | |
523 | 524 | case info_MARKER : |
536 | 537 | |
537 | 538 | default : |
538 | 539 | psf_log_printf (psf, "%M : %D (skipped)\n", marker, chunk_size) ; |
539 | psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; | |
540 | psf_binheader_readf (psf, "j", (size_t) chunk_size) ; | |
540 | 541 | break ; |
541 | 542 | } ; |
542 | 543 | |
844 | 845 | if ((buf = malloc (chunk_size + 1)) == NULL) |
845 | 846 | return (psf->error = SFE_MALLOC_FAILED) ; |
846 | 847 | |
847 | psf_binheader_readf (psf, "E4b", &count, buf, make_size_t (chunk_size)) ; | |
848 | psf_binheader_readf (psf, "E4b", &count, buf, (size_t) chunk_size) ; | |
848 | 849 | psf_log_printf (psf, " count: %u\n", count) ; |
849 | 850 | |
850 | 851 | /* Force terminate `buf` to make sure. */ |
78 | 78 | len = strlen (psf->cart_16k->tag_text) ; |
79 | 79 | len += (len & 1) ? 1 : 2 ; |
80 | 80 | |
81 | psf->cart_16k->tag_text_size = len ; | |
81 | psf->cart_16k->tag_text_size = (uint32_t) len ; | |
82 | 82 | |
83 | 83 | return SF_TRUE ; |
84 | 84 | } /* cart_var_set */ |
74 | 74 | hash = marker_len > 4 ? hash_of_str (marker_str) : u.marker ; |
75 | 75 | |
76 | 76 | memcpy (psf->iterator->id, marker_str, marker_len) ; |
77 | psf->iterator->id_size = marker_len ; | |
77 | psf->iterator->id_size = (unsigned) marker_len ; | |
78 | 78 | psf->iterator->hash = hash ; |
79 | 79 | } |
80 | 80 | |
111 | 111 | { pchk->used = 0 ; |
112 | 112 | pchk->count = 20 ; |
113 | 113 | pchk->chunks = calloc (pchk->count, sizeof (READ_CHUNK)) ; |
114 | if (!pchk->chunks) | |
115 | { return SFE_MALLOC_FAILED ; | |
116 | } ; | |
114 | 117 | } |
115 | 118 | else if (pchk->used > pchk->count) |
116 | 119 | return SFE_INTERNAL ; |
207 | 210 | rchunk.offset = offset ; |
208 | 211 | rchunk.len = len ; |
209 | 212 | |
210 | rchunk.id_size = marker_len > 64 ? 64 : marker_len ; | |
213 | rchunk.id_size = marker_len > 64 ? 64 : (unsigned) marker_len ; | |
211 | 214 | memcpy (rchunk.id, marker_str, rchunk.id_size) ; |
212 | 215 | |
213 | 216 | return psf_store_read_chunk (pchk, &rchunk) ; |
226 | 229 | { pchk->used = 0 ; |
227 | 230 | pchk->count = 20 ; |
228 | 231 | pchk->chunks = calloc (pchk->count, sizeof (WRITE_CHUNK)) ; |
232 | if (!pchk->chunks) | |
233 | { return SFE_MALLOC_FAILED ; | |
234 | } ; | |
229 | 235 | } |
230 | 236 | else if (pchk->used >= pchk->count) |
231 | 237 | { WRITE_CHUNK * old_ptr = pchk->chunks ; |
60 | 60 | }, |
61 | 61 | #endif |
62 | 62 | |
63 | #if HAVE_MPEG | |
64 | { SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III, | |
65 | "MPEG Layer 3", "mp3" | |
66 | }, | |
67 | #endif | |
68 | ||
63 | 69 | { SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, |
64 | 70 | "OKI Dialogic VOX ADPCM", "vox" |
65 | 71 | }, |
132 | 138 | { SF_FORMAT_MAT4, "MAT4 (GNU Octave 2.0 / Matlab 4.2)", "mat" }, |
133 | 139 | { SF_FORMAT_MAT5, "MAT5 (GNU Octave 2.1 / Matlab 5.0)", "mat" }, |
134 | 140 | { SF_FORMAT_MPC2K, "MPC (Akai MPC 2k)", "mpc" }, |
141 | #if HAVE_MPEG | |
142 | { SF_FORMAT_MPEG, "MPEG-1/2 Audio", "m1a" }, | |
143 | #endif | |
135 | 144 | #if HAVE_EXTERNAL_XIPH_LIBS |
136 | 145 | { SF_FORMAT_OGG, "OGG (OGG Container format)", "oga" }, |
137 | 146 | #endif |
214 | 223 | { SF_FORMAT_OPUS, "Opus", NULL }, |
215 | 224 | #endif |
216 | 225 | |
226 | #if HAVE_MPEG | |
227 | { SF_FORMAT_MPEG_LAYER_I, "MPEG Layer I", "mp1" }, | |
228 | { SF_FORMAT_MPEG_LAYER_II, "MPEG Layer II", "mp2" }, | |
229 | { SF_FORMAT_MPEG_LAYER_III, "MPEG Layer III", "mp3" }, | |
230 | #endif | |
231 | ||
217 | 232 | { SF_FORMAT_ALAC_16, "16 bit ALAC", NULL }, |
218 | 233 | { SF_FORMAT_ALAC_20, "20 bit ALAC", NULL }, |
219 | 234 | { SF_FORMAT_ALAC_24, "24 bit ALAC", NULL }, |
308 | 323 | len = ARRAY_LEN (ubuf.dbuf) - (ARRAY_LEN (ubuf.dbuf) % psf->sf.channels) ; |
309 | 324 | |
310 | 325 | for (readcount = 1, max_val = 0.0 ; readcount > 0 ; /* nothing */) |
311 | { readcount = sf_read_double ((SNDFILE*) psf, data, len) ; | |
326 | { readcount = (int) sf_read_double ((SNDFILE*) psf, data, len) ; | |
312 | 327 | for (k = 0 ; k < readcount ; k++) |
313 | 328 | { temp = fabs (data [k]) ; |
314 | 329 | max_val = temp > max_val ? temp : max_val ; |
353 | 368 | chan = 0 ; |
354 | 369 | readcount = len ; |
355 | 370 | while (readcount > 0) |
356 | { readcount = sf_read_double ((SNDFILE*) psf, data, len) ; | |
371 | { readcount = (int) sf_read_double ((SNDFILE*) psf, data, len) ; | |
357 | 372 | for (k = 0 ; k < readcount ; k++) |
358 | 373 | { temp = fabs (data [k]) ; |
359 | 374 | peaks [chan] = temp > peaks [chan] ? temp : peaks [chan] ; |
102 | 102 | void |
103 | 103 | psf_log_printf (SF_PRIVATE *psf, const char *format, ...) |
104 | 104 | { va_list ap ; |
105 | uint32_t u ; | |
106 | int d, tens, shift, width, width_specifier, left_align, slen ; | |
105 | uint32_t u, tens ; | |
106 | int d, shift, width, width_specifier, left_align, slen, precision ; | |
107 | 107 | char c, *strptr, istr [5], lead_char, sign_char ; |
108 | 108 | |
109 | 109 | va_start (ap, format) ; |
152 | 152 | while ((c = *format++) && isdigit (c)) |
153 | 153 | width_specifier = width_specifier * 10 + (c - '0') ; |
154 | 154 | |
155 | precision = 0 ; | |
156 | if (c == '.') | |
157 | { while ((c = *format++) && isdigit (c)) | |
158 | precision = precision * 10 + (c - '0') ; | |
159 | } ; | |
160 | ||
155 | 161 | switch (c) |
156 | 162 | { case 0 : /* NULL character. */ |
157 | 163 | va_end (ap) ; |
161 | 167 | strptr = va_arg (ap, char *) ; |
162 | 168 | if (strptr == NULL) |
163 | 169 | break ; |
164 | slen = strlen (strptr) ; | |
170 | if (precision > 0) | |
171 | slen = strnlen (strptr, precision) ; | |
172 | else | |
173 | slen = strlen (strptr) ; | |
165 | 174 | width_specifier = width_specifier >= slen ? width_specifier - slen : 0 ; |
166 | 175 | if (left_align == SF_FALSE) |
167 | 176 | while (width_specifier -- > 0) |
168 | 177 | log_putchar (psf, ' ') ; |
169 | while (*strptr) | |
178 | while (slen--) | |
170 | 179 | log_putchar (psf, *strptr++) ; |
171 | 180 | while (width_specifier -- > 0) |
172 | 181 | log_putchar (psf, ' ') ; |
176 | 185 | d = va_arg (ap, int) ; |
177 | 186 | |
178 | 187 | if (d < 0) |
179 | { d = -d ; | |
180 | sign_char = '-' ; | |
188 | { sign_char = '-' ; | |
181 | 189 | if (lead_char != '0' && left_align == SF_FALSE) |
182 | 190 | width_specifier -- ; |
183 | } ; | |
191 | ||
192 | u = - ((unsigned) d) ; | |
193 | } | |
194 | else | |
195 | { u = (unsigned) d ; | |
196 | } | |
184 | 197 | |
185 | 198 | tens = 1 ; |
186 | 199 | width = 1 ; |
187 | while (d / tens >= 10) | |
200 | while (u / tens >= 10) | |
188 | 201 | { tens *= 10 ; |
189 | 202 | width ++ ; |
190 | 203 | } ; |
214 | 227 | log_putchar (psf, lead_char) ; |
215 | 228 | |
216 | 229 | while (tens > 0) |
217 | { log_putchar (psf, '0' + d / tens) ; | |
218 | d %= tens ; | |
230 | { log_putchar (psf, '0' + u / tens) ; | |
231 | u %= tens ; | |
219 | 232 | tens /= 10 ; |
220 | 233 | } ; |
221 | 234 | |
224 | 237 | break ; |
225 | 238 | |
226 | 239 | case 'D': /* sf_count_t */ |
227 | { sf_count_t D, Tens ; | |
240 | { sf_count_t D ; | |
241 | uint64_t U, Tens ; | |
228 | 242 | |
229 | 243 | D = va_arg (ap, sf_count_t) ; |
230 | 244 | |
234 | 248 | log_putchar (psf, '0') ; |
235 | 249 | break ; |
236 | 250 | } |
237 | if (D < 0) | |
238 | { log_putchar (psf, '-') ; | |
239 | D = -D ; | |
240 | } ; | |
251 | else | |
252 | { if (D < 0) | |
253 | { log_putchar (psf, '-') ; | |
254 | U = -((uint64_t) D) ; | |
255 | } | |
256 | else | |
257 | { U = (uint64_t) D; | |
258 | } | |
259 | } | |
260 | ||
241 | 261 | Tens = 1 ; |
242 | 262 | width = 1 ; |
243 | while (D / Tens >= 10) | |
263 | while (U / Tens >= 10) | |
244 | 264 | { Tens *= 10 ; |
245 | 265 | width ++ ; |
246 | 266 | } ; |
251 | 271 | } ; |
252 | 272 | |
253 | 273 | while (Tens > 0) |
254 | { log_putchar (psf, '0' + D / Tens) ; | |
255 | D %= Tens ; | |
274 | { log_putchar (psf, '0' + U / Tens) ; | |
275 | U %= Tens ; | |
256 | 276 | Tens /= 10 ; |
257 | 277 | } ; |
258 | 278 | } ; |
524 | 544 | static inline void |
525 | 545 | header_put_be_8byte (SF_PRIVATE *psf, sf_count_t x) |
526 | 546 | { psf->header.ptr [psf->header.indx++] = (x >> 56) ; |
527 | psf->header.ptr [psf->header.indx++] = (x >> 48) ; | |
528 | psf->header.ptr [psf->header.indx++] = (x >> 40) ; | |
529 | psf->header.ptr [psf->header.indx++] = (x >> 32) ; | |
530 | psf->header.ptr [psf->header.indx++] = (x >> 24) ; | |
531 | psf->header.ptr [psf->header.indx++] = (x >> 16) ; | |
532 | psf->header.ptr [psf->header.indx++] = (x >> 8) ; | |
533 | psf->header.ptr [psf->header.indx++] = x ; | |
547 | psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 48) ; | |
548 | psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 40) ; | |
549 | psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 32) ; | |
550 | psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 24) ; | |
551 | psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 16) ; | |
552 | psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 8) ; | |
553 | psf->header.ptr [psf->header.indx++] = (unsigned char) x ; | |
534 | 554 | } /* header_put_be_8byte */ |
535 | 555 | |
536 | 556 | static inline void |
537 | 557 | header_put_le_8byte (SF_PRIVATE *psf, sf_count_t x) |
538 | { psf->header.ptr [psf->header.indx++] = x ; | |
539 | psf->header.ptr [psf->header.indx++] = (x >> 8) ; | |
540 | psf->header.ptr [psf->header.indx++] = (x >> 16) ; | |
541 | psf->header.ptr [psf->header.indx++] = (x >> 24) ; | |
542 | psf->header.ptr [psf->header.indx++] = (x >> 32) ; | |
543 | psf->header.ptr [psf->header.indx++] = (x >> 40) ; | |
544 | psf->header.ptr [psf->header.indx++] = (x >> 48) ; | |
558 | { psf->header.ptr [psf->header.indx++] = (unsigned char) x ; | |
559 | psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 8) ; | |
560 | psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 16) ; | |
561 | psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 24) ; | |
562 | psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 32) ; | |
563 | psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 40) ; | |
564 | psf->header.ptr [psf->header.indx++] = (unsigned char) (x >> 48) ; | |
545 | 565 | psf->header.ptr [psf->header.indx++] = (x >> 56) ; |
546 | 566 | } /* header_put_le_8byte */ |
547 | 567 | |
570 | 590 | while ((c = *format++)) |
571 | 591 | { |
572 | 592 | if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16)) |
573 | return count ; | |
593 | break ; | |
574 | 594 | |
575 | 595 | switch (c) |
576 | 596 | { case ' ' : /* Do nothing. Just used to space out format string. */ |
686 | 706 | size = strlen (strptr) + 1 ; |
687 | 707 | |
688 | 708 | 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))) |
689 | return count ; | |
709 | break ; | |
690 | 710 | |
691 | 711 | if (psf->rwf_endian == SF_ENDIAN_BIG) |
692 | 712 | header_put_be_int (psf, size + (size & 1)) ; |
707 | 727 | strptr = va_arg (argptr, char *) ; |
708 | 728 | size = strlen (strptr) ; |
709 | 729 | 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))) |
710 | return count ; | |
730 | break ; | |
711 | 731 | if (psf->rwf_endian == SF_ENDIAN_BIG) |
712 | 732 | header_put_be_int (psf, size) ; |
713 | 733 | else |
727 | 747 | size = (size > 254) ? 254 : size ; |
728 | 748 | |
729 | 749 | if (psf->header.indx + 1 + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, 1 + size)) |
730 | return count ; | |
750 | break ; | |
731 | 751 | |
732 | 752 | header_put_byte (psf, size) ; |
733 | 753 | memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size) ; |
740 | 760 | size = va_arg (argptr, size_t) ; |
741 | 761 | |
742 | 762 | if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size)) |
743 | return count ; | |
763 | break ; | |
744 | 764 | |
745 | 765 | memcpy (&(psf->header.ptr [psf->header.indx]), bindata, size) ; |
746 | 766 | psf->header.indx += size ; |
751 | 771 | size = va_arg (argptr, size_t) ; |
752 | 772 | |
753 | 773 | if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size)) |
754 | return count ; | |
774 | break ; | |
755 | 775 | |
756 | 776 | count += size ; |
757 | 777 | while (size) |
772 | 792 | size = va_arg (argptr, size_t) ; |
773 | 793 | |
774 | 794 | if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size)) |
775 | return count ; | |
795 | break ; | |
776 | 796 | |
777 | 797 | psf->header.indx += size ; |
778 | 798 | count += size ; |
782 | 802 | size = va_arg (argptr, size_t) ; |
783 | 803 | |
784 | 804 | if ((sf_count_t) size >= psf->header.len && psf_bump_header_allocation (psf, size)) |
785 | return count ; | |
805 | break ; | |
786 | 806 | |
787 | 807 | psf->header.indx = size ; |
788 | 808 | break ; |
876 | 896 | psf_bump_header_allocation (psf, position) ; |
877 | 897 | if (position > psf->header.len) |
878 | 898 | { /* Too much header to cache so just seek instead. */ |
879 | psf->header.indx = psf->header.end ; | |
899 | psf->header.indx = psf->header.end = 0 ; | |
880 | 900 | psf_fseek (psf, position, whence) ; |
881 | 901 | return ; |
882 | 902 | } ; |
953 | 973 | psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...) |
954 | 974 | { va_list argptr ; |
955 | 975 | sf_count_t *countptr, countdata ; |
956 | unsigned char *ucptr, sixteen_bytes [16] ; | |
976 | unsigned char *ucptr, sixteen_bytes [16] = { 0 } ; | |
957 | 977 | unsigned int *intptr, intdata ; |
958 | 978 | unsigned short *shortptr ; |
959 | 979 | char *charptr ; |
970 | 990 | while ((c = *format++)) |
971 | 991 | { |
972 | 992 | if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16)) |
973 | return count ; | |
993 | break ; | |
974 | 994 | |
975 | 995 | switch (c) |
976 | 996 | { case 'e' : /* All conversions are now from LE to host. */ |
1097 | 1117 | memset (charptr, 0, count) ; |
1098 | 1118 | |
1099 | 1119 | if (psf->header.indx + count >= psf->header.len && psf_bump_header_allocation (psf, count)) |
1100 | return 0 ; | |
1120 | break ; | |
1101 | 1121 | |
1102 | 1122 | byte_count += header_gets (psf, charptr, count) ; |
1103 | 1123 | break ; |
1126 | 1146 | byte_count += count ; |
1127 | 1147 | break ; |
1128 | 1148 | |
1149 | case '!' : /* Clear buffer, forcing re-read. */ | |
1150 | psf->header.end = psf->header.indx = 0 ; | |
1151 | break ; | |
1152 | ||
1129 | 1153 | default : |
1130 | 1154 | psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ; |
1131 | 1155 | psf->error = SFE_INTERNAL ; |
1220 | 1244 | /*======================================================================================== |
1221 | 1245 | */ |
1222 | 1246 | |
1247 | int | |
1248 | psf_isprint (int ch) | |
1249 | { return (ch >= ' ' && ch <= '~') ; | |
1250 | } /* psf_isprint */ | |
1251 | ||
1252 | void | |
1253 | psf_strlcat (char *dest, size_t n, const char *src) | |
1254 | { strncat (dest, src, n - strlen (dest) - 1) ; | |
1255 | dest [n - 1] = 0 ; | |
1256 | } /* psf_strlcat */ | |
1257 | ||
1258 | void | |
1259 | psf_strlcpy (char *dest, size_t n, const char *src) | |
1260 | { strncpy (dest, src, n - 1) ; | |
1261 | dest [n - 1] = 0 ; | |
1262 | } /* psf_strlcpy */ | |
1263 | ||
1264 | /*======================================================================================== | |
1265 | */ | |
1266 | ||
1267 | void * | |
1268 | psf_memdup (const void *src, size_t n) | |
1269 | { if (src == NULL) | |
1270 | return NULL ; | |
1271 | ||
1272 | void * mem = calloc (1, n & 3 ? n + 4 - (n & 3) : n) ; | |
1273 | if (mem != NULL) | |
1274 | memcpy (mem, src, n) ; | |
1275 | return mem ; | |
1276 | } /* psf_memdup */ | |
1277 | ||
1223 | 1278 | void* |
1224 | 1279 | psf_memset (void *s, int c, sf_count_t len) |
1225 | 1280 | { char *ptr ; |
1245 | 1300 | ** bodgy something up instead. |
1246 | 1301 | */ |
1247 | 1302 | |
1303 | #ifdef _MSC_VER | |
1248 | 1304 | typedef SF_CUES_VAR (0) SF_CUES_0 ; |
1305 | #else | |
1306 | typedef SF_CUES_VAR () SF_CUES_0 ; | |
1307 | #endif | |
1249 | 1308 | |
1250 | 1309 | /* calculate size of SF_CUES struct given number of cues */ |
1251 | 1310 | #define SF_CUES_VAR_SIZE(count) (sizeof (SF_CUES_0) + count * sizeof (SF_CUE_POINT)) |
1256 | 1315 | SF_CUES * |
1257 | 1316 | psf_cues_alloc (uint32_t cue_count) |
1258 | 1317 | { SF_CUES *pcues = calloc (1, SF_CUES_VAR_SIZE (cue_count)) ; |
1259 | ||
1260 | pcues->cue_count = cue_count ; | |
1318 | if (pcues) | |
1319 | { pcues->cue_count = cue_count ; | |
1320 | } ; | |
1261 | 1321 | return pcues ; |
1262 | 1322 | } /* psf_cues_alloc */ |
1263 | 1323 | |
1526 | 1586 | CASE_NAME (SF_FORMAT_CAF) ; |
1527 | 1587 | CASE_NAME (SF_FORMAT_WVE) ; |
1528 | 1588 | CASE_NAME (SF_FORMAT_OGG) ; |
1589 | CASE_NAME (SF_FORMAT_MPEG) ; | |
1529 | 1590 | default : |
1530 | 1591 | break ; |
1531 | 1592 | } ; |
1562 | 1623 | CASE_NAME (SF_FORMAT_DPCM_8) ; |
1563 | 1624 | CASE_NAME (SF_FORMAT_DPCM_16) ; |
1564 | 1625 | CASE_NAME (SF_FORMAT_VORBIS) ; |
1626 | CASE_NAME (SF_FORMAT_MPEG_LAYER_I) ; | |
1627 | CASE_NAME (SF_FORMAT_MPEG_LAYER_II) ; | |
1628 | CASE_NAME (SF_FORMAT_MPEG_LAYER_III) ; | |
1565 | 1629 | default : |
1566 | 1630 | break ; |
1567 | 1631 | } ; |
1605 | 1669 | { float normfact ; |
1606 | 1670 | |
1607 | 1671 | normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; |
1608 | while (--count >= 0) | |
1609 | dest [count] = psf_lrintf (src [count] * normfact) ; | |
1672 | for (int i = 0 ; i < count ; i++) | |
1673 | dest [i] = psf_lrintf (src [i] * normfact) ; | |
1610 | 1674 | |
1611 | 1675 | return ; |
1612 | 1676 | } /* psf_f2s_array */ |
1617 | 1681 | |
1618 | 1682 | normfact = normalize ? (1.0 * 0x8000) : 1.0 ; |
1619 | 1683 | |
1620 | while (--count >= 0) | |
1621 | { scaled_value = src [count] * normfact ; | |
1622 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) | |
1623 | { dest [count] = 0x7FFF ; | |
1684 | for (int i = 0 ; i < count ; i++) | |
1685 | { scaled_value = src [i] * normfact ; | |
1686 | #if CPU_CLIPS_POSITIVE == 0 | |
1687 | if (scaled_value >= (1.0 * 0x7FFF)) | |
1688 | { dest [i] = 0x7FFF ; | |
1624 | 1689 | continue ; |
1625 | 1690 | } ; |
1626 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) | |
1627 | { dest [count] = 0x8000 ; | |
1691 | #endif | |
1692 | #if CPU_CLIPS_NEGATIVE == 0 | |
1693 | if (scaled_value <= (-8.0 * 0x1000)) | |
1694 | { dest [i] = -0x7FFF - 1 ; | |
1628 | 1695 | continue ; |
1629 | 1696 | } ; |
1630 | ||
1631 | dest [count] = psf_lrintf (scaled_value) ; | |
1697 | #endif | |
1698 | ||
1699 | dest [i] = psf_lrintf (scaled_value) ; | |
1632 | 1700 | } ; |
1633 | 1701 | |
1634 | 1702 | return ; |
1639 | 1707 | { double normfact ; |
1640 | 1708 | |
1641 | 1709 | normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; |
1642 | while (--count >= 0) | |
1643 | dest [count] = psf_lrint (src [count] * normfact) ; | |
1710 | for (int i = 0 ; i < count ; i++) | |
1711 | dest [i] = psf_lrint (src [i] * normfact) ; | |
1644 | 1712 | |
1645 | 1713 | return ; |
1646 | 1714 | } /* psf_f2s_array */ |
1651 | 1719 | |
1652 | 1720 | normfact = normalize ? (1.0 * 0x8000) : 1.0 ; |
1653 | 1721 | |
1654 | while (--count >= 0) | |
1655 | { scaled_value = src [count] * normfact ; | |
1656 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) | |
1657 | { dest [count] = 0x7FFF ; | |
1722 | for (int i = 0 ; i < count ; i++) | |
1723 | { scaled_value = src [i] * normfact ; | |
1724 | #if CPU_CLIPS_POSITIVE == 0 | |
1725 | if (scaled_value >= (1.0 * 0x7FFF)) | |
1726 | { dest [i] = 0x7FFF ; | |
1658 | 1727 | continue ; |
1659 | 1728 | } ; |
1660 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) | |
1661 | { dest [count] = 0x8000 ; | |
1729 | #endif | |
1730 | #if CPU_CLIPS_NEGATIVE == 0 | |
1731 | if (scaled_value <= (-8.0 * 0x1000)) | |
1732 | { dest [i] = -0x7FFF - 1 ; | |
1662 | 1733 | continue ; |
1663 | 1734 | } ; |
1664 | ||
1665 | dest [count] = psf_lrint (scaled_value) ; | |
1735 | #endif | |
1736 | ||
1737 | dest [i] = psf_lrint (scaled_value) ; | |
1666 | 1738 | } ; |
1667 | 1739 | |
1668 | 1740 | return ; |
1674 | 1746 | { float normfact ; |
1675 | 1747 | |
1676 | 1748 | normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; |
1677 | while (--count >= 0) | |
1678 | dest [count] = psf_lrintf (src [count] * normfact) ; | |
1749 | for (int i = 0 ; i < count ; i++) | |
1750 | dest [i] = psf_lrintf (src [i] * normfact) ; | |
1679 | 1751 | |
1680 | 1752 | return ; |
1681 | 1753 | } /* psf_f2i_array */ |
1686 | 1758 | |
1687 | 1759 | normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; |
1688 | 1760 | |
1689 | while (--count >= 0) | |
1690 | { scaled_value = src [count] * normfact ; | |
1691 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
1692 | { dest [count] = 0x7FFFFFFF ; | |
1761 | for (int i = 0 ; i < count ; i++) | |
1762 | { scaled_value = src [i] * normfact ; | |
1763 | #if CPU_CLIPS_POSITIVE == 0 | |
1764 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
1765 | { dest [i] = 0x7FFFFFFF ; | |
1693 | 1766 | continue ; |
1694 | 1767 | } ; |
1695 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
1696 | { dest [count] = 0x80000000 ; | |
1768 | #endif | |
1769 | #if CPU_CLIPS_NEGATIVE == 0 | |
1770 | if (scaled_value <= (-8.0 * 0x10000000)) | |
1771 | { dest [i] = 0x80000000 ; | |
1697 | 1772 | continue ; |
1698 | 1773 | } ; |
1699 | ||
1700 | dest [count] = psf_lrintf (scaled_value) ; | |
1774 | #endif | |
1775 | ||
1776 | dest [i] = psf_lrintf (scaled_value) ; | |
1701 | 1777 | } ; |
1702 | 1778 | |
1703 | 1779 | return ; |
1708 | 1784 | { double normfact ; |
1709 | 1785 | |
1710 | 1786 | normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; |
1711 | while (--count >= 0) | |
1712 | dest [count] = psf_lrint (src [count] * normfact) ; | |
1787 | for (int i = 0 ; i < count ; i++) | |
1788 | dest [i] = psf_lrint (src [i] * normfact) ; | |
1713 | 1789 | |
1714 | 1790 | return ; |
1715 | 1791 | } /* psf_f2i_array */ |
1720 | 1796 | |
1721 | 1797 | normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; |
1722 | 1798 | |
1723 | while (--count >= 0) | |
1724 | { scaled_value = src [count] * normfact ; | |
1725 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
1726 | { dest [count] = 0x7FFFFFFF ; | |
1799 | for (int i = 0 ; i < count ; i++) | |
1800 | { scaled_value = src [i] * normfact ; | |
1801 | #if CPU_CLIPS_POSITIVE == 0 | |
1802 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
1803 | { dest [i] = 0x7FFFFFFF ; | |
1727 | 1804 | continue ; |
1728 | 1805 | } ; |
1729 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
1730 | { dest [count] = 0x80000000 ; | |
1806 | #endif | |
1807 | #if CPU_CLIPS_NEGATIVE == 0 | |
1808 | if (scaled_value <= (-8.0 * 0x10000000)) | |
1809 | { dest [i] = 0x80000000 ; | |
1731 | 1810 | continue ; |
1732 | 1811 | } ; |
1733 | ||
1734 | dest [count] = psf_lrint (scaled_value) ; | |
1812 | #endif | |
1813 | ||
1814 | dest [i] = psf_lrint (scaled_value) ; | |
1735 | 1815 | } ; |
1736 | 1816 | |
1737 | 1817 | return ; |
22 | 22 | |
23 | 23 | #include <stdlib.h> |
24 | 24 | #include <string.h> |
25 | #if HAVE_STDBOOL_H | |
26 | #include <stdbool.h> | |
27 | #endif | |
25 | 28 | |
26 | 29 | #if HAVE_INTTYPES_H |
27 | 30 | #include <inttypes.h> |
98 | 101 | |
99 | 102 | #define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0]))) |
100 | 103 | |
101 | #define NOT(x) (! (x)) | |
102 | ||
103 | #if COMPILER_IS_GCC | |
104 | #define SF_MAX(x, y) ({ \ | |
105 | typeof (x) sf_max_x1 = (x) ; \ | |
106 | typeof (y) sf_max_y1 = (y) ; \ | |
107 | (void) (&sf_max_x1 == &sf_max_y1) ; \ | |
108 | sf_max_x1 > sf_max_y1 ? sf_max_x1 : sf_max_y1 ; }) | |
109 | ||
110 | #define SF_MIN(x, y) ({ \ | |
111 | typeof (x) sf_min_x2 = (x) ; \ | |
112 | typeof (y) sf_min_y2 = (y) ; \ | |
113 | (void) (&sf_min_x2 == &sf_min_y2) ; \ | |
114 | sf_min_x2 < sf_min_y2 ? sf_min_x2 : sf_min_y2 ; }) | |
115 | #else | |
116 | 104 | #define SF_MAX(a, b) ((a) > (b) ? (a) : (b)) |
117 | 105 | #define SF_MIN(a, b) ((a) < (b) ? (a) : (b)) |
118 | #endif | |
119 | 106 | |
120 | 107 | |
121 | 108 | #define COMPILE_TIME_ASSERT(e) (sizeof (struct { int : - !! (e) ; })) |
122 | 109 | |
123 | 110 | |
124 | 111 | #define SF_MAX_CHANNELS 1024 |
112 | /* Max FLAC sample rate : https://xiph.org/flac/format.html */ | |
113 | #define SF_MAX_SAMPLERATE 655350 | |
125 | 114 | |
126 | 115 | |
127 | 116 | /* |
306 | 295 | |
307 | 296 | typedef SF_CART_INFO_VAR (16 * 1024) SF_CART_INFO_16K ; |
308 | 297 | |
298 | typedef struct | |
299 | { sf_count_t offset ; | |
300 | sf_count_t len ; | |
301 | unsigned minor_version ; | |
302 | } ID3V2_HEADER_INFO ; | |
303 | ||
309 | 304 | #if SIZEOF_WCHAR_T == 2 |
310 | 305 | typedef wchar_t sfwchar_t ; |
311 | 306 | #else |
313 | 308 | #endif |
314 | 309 | |
315 | 310 | |
316 | static inline void * | |
317 | psf_memdup (const void *src, size_t n) | |
318 | { void * mem = calloc (1, n & 3 ? n + 4 - (n & 3) : n) ; | |
319 | return memcpy (mem, src, n) ; | |
320 | } /* psf_memdup */ | |
311 | void *psf_memdup (const void *src, size_t n) ; | |
321 | 312 | |
322 | 313 | /* |
323 | 314 | ** This version of isprint specifically ignores any locale info. Its used for |
324 | 315 | ** determining which characters can be printed in things like hexdumps. |
325 | 316 | */ |
326 | static inline int | |
327 | psf_isprint (int ch) | |
328 | { return (ch >= ' ' && ch <= '~') ; | |
329 | } /* psf_isprint */ | |
317 | int psf_isprint (int ch) ; | |
330 | 318 | |
331 | 319 | /*======================================================================================= |
332 | 320 | ** SF_PRIVATE stuct - a pointer to this struct is passed back to the caller of the |
336 | 324 | |
337 | 325 | typedef struct |
338 | 326 | { |
339 | union | |
340 | { char c [SF_FILENAME_LEN] ; | |
341 | sfwchar_t wc [SF_FILENAME_LEN] ; | |
342 | } path ; | |
343 | ||
344 | union | |
345 | { char c [SF_FILENAME_LEN] ; | |
346 | sfwchar_t wc [SF_FILENAME_LEN] ; | |
347 | } dir ; | |
348 | ||
349 | union | |
350 | { char c [SF_FILENAME_LEN / 4] ; | |
351 | sfwchar_t wc [SF_FILENAME_LEN / 4] ; | |
352 | } name ; | |
327 | char path [SF_FILENAME_LEN] ; | |
328 | char dir [SF_FILENAME_LEN] ; | |
329 | char name [SF_FILENAME_LEN / 4] ; | |
353 | 330 | |
354 | 331 | #if USE_WINDOWS_API |
355 | 332 | /* |
356 | 333 | ** These fields can only be used in src/file_io.c. |
357 | 334 | ** They are basically the same as a windows file HANDLE. |
358 | 335 | */ |
359 | void *handle, *hsaved ; | |
360 | ||
361 | int use_wchar ; | |
336 | void *handle, *hsaved ; | |
362 | 337 | #else |
363 | 338 | /* These fields can only be used in src/file_io.c. */ |
364 | int filedes, savedes ; | |
365 | #endif | |
366 | ||
367 | int do_not_close_descriptor ; | |
368 | int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */ | |
339 | int filedes, savedes ; | |
340 | #endif | |
341 | ||
342 | int do_not_close_descriptor ; | |
343 | int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */ | |
369 | 344 | } PSF_FILE ; |
370 | 345 | |
371 | 346 | |
389 | 364 | |
390 | 365 | typedef struct sf_private_tag |
391 | 366 | { |
392 | /* Canary in a coal mine. */ | |
393 | union | |
394 | { /* Place a double here to encourage double alignment. */ | |
395 | double d [2] ; | |
396 | char c [16] ; | |
397 | } canary ; | |
398 | ||
399 | 367 | PSF_FILE file, rsrc ; |
400 | 368 | |
401 | 369 | char syserr [SF_SYSERR_LEN] ; |
553 | 521 | int (*get_chunk_data) (struct sf_private_tag*, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ; |
554 | 522 | |
555 | 523 | int cpu_flags ; |
524 | ||
525 | ID3V2_HEADER_INFO id3_header ; | |
556 | 526 | } SF_PRIVATE ; |
557 | 527 | |
558 | 528 | |
767 | 737 | |
768 | 738 | SFE_OPUS_BAD_SAMPLERATE, |
769 | 739 | |
740 | SFE_CAF_NOT_CAF, | |
741 | SFE_CAF_NO_DESC, | |
742 | SFE_CAF_BAD_PEAK, | |
743 | ||
744 | SFE_AVR_NOT_AVR, | |
745 | SFE_AVR_BAD_REZ_SIGN, | |
746 | ||
747 | SFE_MPC_NO_MARKER, | |
748 | ||
749 | SFE_MPEG_BAD_SAMPLERATE, | |
750 | ||
770 | 751 | SFE_MAX_ERROR /* This must be last in list. */ |
771 | 752 | } ; |
772 | 753 | |
881 | 862 | /* Open and close the resource fork of a file. */ |
882 | 863 | int psf_open_rsrc (SF_PRIVATE *psf) ; |
883 | 864 | int psf_close_rsrc (SF_PRIVATE *psf) ; |
865 | ||
866 | int psf_copy_filename (SF_PRIVATE *psf, const char *path) ; | |
884 | 867 | |
885 | 868 | /* |
886 | 869 | void psf_fclearerr (SF_PRIVATE *psf) ; |
920 | 903 | int ogg_opus_open (SF_PRIVATE *psf) ; |
921 | 904 | int ogg_open (SF_PRIVATE *psf) ; |
922 | 905 | |
906 | int mpeg_open (SF_PRIVATE *psf) ; | |
923 | 907 | |
924 | 908 | /* In progress. Do not currently work. */ |
925 | 909 | |
926 | int mpeg_open (SF_PRIVATE *psf) ; | |
927 | 910 | int rx2_open (SF_PRIVATE *psf) ; |
928 | 911 | int txw_open (SF_PRIVATE *psf) ; |
929 | 912 | int wve_open (SF_PRIVATE *psf) ; |
945 | 928 | int flac_init (SF_PRIVATE *psf) ; |
946 | 929 | int g72x_init (SF_PRIVATE * psf) ; |
947 | 930 | int alac_init (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info) ; |
931 | int mpeg_init (SF_PRIVATE *psf, int bitrate_mode, int write_metadata) ; | |
948 | 932 | |
949 | 933 | int dither_init (SF_PRIVATE *psf, int mode) ; |
950 | 934 | |
969 | 953 | int psf_find_read_chunk_iterator (const READ_CHUNKS * pchk, const SF_CHUNK_ITERATOR * marker) ; |
970 | 954 | |
971 | 955 | int psf_find_write_chunk (WRITE_CHUNKS * pchk, const char * marker) ; |
972 | ||
973 | static inline int | |
974 | fourcc_to_marker (const SF_CHUNK_INFO * chunk_info) | |
975 | { const unsigned char * cptr ; | |
976 | ||
977 | if (chunk_info->id_size != 4) | |
978 | return 0 ; | |
979 | ||
980 | cptr = (const unsigned char *) chunk_info->id ; | |
981 | return (cptr [3] << 24) + (cptr [2] << 16) + (cptr [1] << 8) + cptr [0] ; | |
982 | } /* fourcc_to_marker */ | |
983 | 956 | |
984 | 957 | /*------------------------------------------------------------------------------------ |
985 | 958 | ** Functions that work like OpenBSD's strlcpy/strlcat to replace strncpy/strncat. |
993 | 966 | ** compiler errors if code is carelessly converted from one to the other. |
994 | 967 | */ |
995 | 968 | |
996 | static inline void | |
997 | psf_strlcat (char *dest, size_t n, const char *src) | |
998 | { strncat (dest, src, n - strlen (dest) - 1) ; | |
999 | dest [n - 1] = 0 ; | |
1000 | } /* psf_strlcat */ | |
1001 | ||
1002 | static inline void | |
1003 | psf_strlcpy (char *dest, size_t n, const char *src) | |
1004 | { strncpy (dest, src, n - 1) ; | |
1005 | dest [n - 1] = 0 ; | |
1006 | } /* psf_strlcpy */ | |
969 | void psf_strlcat (char *dest, size_t n, const char *src) ; | |
970 | void psf_strlcpy (char *dest, size_t n, const char *src) ; | |
1007 | 971 | |
1008 | 972 | /*------------------------------------------------------------------------------------ |
1009 | 973 | ** SIMD optimized math functions. |
1060 | 1024 | |
1061 | 1025 | int audio_detect (SF_PRIVATE * psf, AUDIO_DETECT *ad, const unsigned char * data, int datalen) ; |
1062 | 1026 | int id3_skip (SF_PRIVATE * psf) ; |
1027 | const char *id3_lookup_v1_genre (int number) ; | |
1063 | 1028 | |
1064 | 1029 | void alac_get_desc_chunk_items (int subformat, uint32_t *fmt_flags, uint32_t *frames_per_packet) ; |
1065 | 1030 |
42 | 42 | /* Will be set to 1 if flac, ogg and vorbis are available. */ |
43 | 43 | #cmakedefine01 HAVE_EXTERNAL_XIPH_LIBS |
44 | 44 | |
45 | /* Will be set to 1 if lame and mpg123 are available. */ | |
46 | #cmakedefine01 HAVE_MPEG | |
47 | ||
45 | 48 | /* Define to 1 if you have the `floor' function. */ |
46 | 49 | #cmakedefine01 HAVE_FLOOR |
47 | 50 | |
173 | 176 | |
174 | 177 | /* Define to 1 if you have the <immintrin.h> header file. */ |
175 | 178 | #cmakedefine01 HAVE_IMMINTRIN_H |
179 | ||
180 | /* Define to 1 if you have the <stdbool.h> header file. */ | |
181 | #cmakedefine01 HAVE_STDBOOL_H | |
176 | 182 | |
177 | 183 | /* Define to 1 if you have the `vsnprintf' function. */ |
178 | 184 | #cmakedefine01 HAVE_VSNPRINTF |
241 | 241 | |
242 | 242 | dither_short (ptr, (short*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; |
243 | 243 | |
244 | thiswrite = pdither->write_short (psf, (short*) pdither->buffer, writecount) ; | |
244 | thiswrite = (int) pdither->write_short (psf, (short*) pdither->buffer, writecount) ; | |
245 | 245 | total += thiswrite ; |
246 | 246 | len -= thiswrite ; |
247 | 247 | if (thiswrite < writecount) |
287 | 287 | |
288 | 288 | dither_int (ptr, (int*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; |
289 | 289 | |
290 | thiswrite = pdither->write_int (psf, (int*) pdither->buffer, writecount) ; | |
290 | thiswrite = (int) pdither->write_int (psf, (int*) pdither->buffer, writecount) ; | |
291 | 291 | total += thiswrite ; |
292 | 292 | len -= thiswrite ; |
293 | 293 | if (thiswrite < writecount) |
326 | 326 | bufferlen = sizeof (pdither->buffer) / (sizeof (float)) ; |
327 | 327 | |
328 | 328 | while (len > 0) |
329 | { writecount = (len >= bufferlen) ? bufferlen : (float) len ; | |
329 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
330 | 330 | writecount /= psf->sf.channels ; |
331 | 331 | writecount *= psf->sf.channels ; |
332 | 332 | |
333 | 333 | dither_float (ptr, (float*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; |
334 | 334 | |
335 | thiswrite = pdither->write_float (psf, (float*) pdither->buffer, writecount) ; | |
335 | thiswrite = (int) pdither->write_float (psf, (float*) pdither->buffer, writecount) ; | |
336 | 336 | total += thiswrite ; |
337 | 337 | len -= thiswrite ; |
338 | 338 | if (thiswrite < writecount) |
372 | 372 | bufferlen = sizeof (pdither->buffer) / sizeof (double) ; |
373 | 373 | |
374 | 374 | while (len > 0) |
375 | { writecount = (len >= bufferlen) ? bufferlen : (double) len ; | |
375 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
376 | 376 | writecount /= psf->sf.channels ; |
377 | 377 | writecount *= psf->sf.channels ; |
378 | 378 | |
379 | 379 | dither_double (ptr, (double*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; |
380 | 380 | |
381 | thiswrite = pdither->write_double (psf, (double*) pdither->buffer, writecount) ; | |
381 | thiswrite = (int) pdither->write_double (psf, (double*) pdither->buffer, writecount) ; | |
382 | 382 | total += thiswrite ; |
383 | 383 | len -= thiswrite ; |
384 | 384 | if (thiswrite < writecount) |
485 | 485 | |
486 | 486 | static void |
487 | 487 | d2s_array (const double *src, int count, short *dest, double scale) |
488 | { while (--count >= 0) | |
489 | { dest [count] = psf_lrint (scale * src [count]) ; | |
488 | { for (int i = 0 ; i < count ; i++) | |
489 | { dest [i] = psf_lrint (scale * src [i]) ; | |
490 | 490 | } ; |
491 | 491 | } /* d2s_array */ |
492 | 492 | |
493 | 493 | static void |
494 | 494 | d2s_clip_array (const double *src, int count, short *dest, double scale) |
495 | { while (--count >= 0) | |
496 | { double tmp = scale * src [count] ; | |
495 | { for (int i = 0 ; i < count ; i++) | |
496 | { double tmp = scale * src [i] ; | |
497 | 497 | |
498 | 498 | if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0) |
499 | dest [count] = SHRT_MAX ; | |
499 | dest [i] = SHRT_MAX ; | |
500 | 500 | else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0) |
501 | dest [count] = SHRT_MIN ; | |
501 | dest [i] = SHRT_MIN ; | |
502 | 502 | else |
503 | dest [count] = psf_lrint (tmp) ; | |
503 | dest [i] = psf_lrint (tmp) ; | |
504 | 504 | } ; |
505 | 505 | } /* d2s_clip_array */ |
506 | 506 | |
507 | 507 | static void |
508 | 508 | d2i_array (const double *src, int count, int *dest, double scale) |
509 | { while (--count >= 0) | |
510 | { dest [count] = psf_lrint (scale * src [count]) ; | |
509 | { for (int i = 0 ; i < count ; i++) | |
510 | { dest [i] = psf_lrint (scale * src [i]) ; | |
511 | 511 | } ; |
512 | 512 | } /* d2i_array */ |
513 | 513 | |
514 | 514 | static void |
515 | 515 | d2i_clip_array (const double *src, int count, int *dest, double scale) |
516 | { while (--count >= 0) | |
517 | { float tmp = scale * src [count] ; | |
516 | { for (int i = 0 ; i < count ; i++) | |
517 | { float tmp = scale * src [i] ; | |
518 | 518 | |
519 | 519 | if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX)) |
520 | dest [count] = INT_MAX ; | |
520 | dest [i] = INT_MAX ; | |
521 | 521 | else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX)) |
522 | dest [count] = INT_MIN ; | |
522 | dest [i] = INT_MIN ; | |
523 | 523 | else |
524 | dest [count] = psf_lrint (tmp) ; | |
524 | dest [i] = psf_lrint (tmp) ; | |
525 | 525 | } ; |
526 | 526 | } /* d2i_clip_array */ |
527 | 527 | |
528 | 528 | static inline void |
529 | 529 | d2f_array (const double *src, int count, float *dest) |
530 | { while (--count >= 0) | |
531 | { dest [count] = src [count] ; | |
530 | { for (int i = 0 ; i < count ; i++) | |
531 | { dest [i] = src [i] ; | |
532 | 532 | } ; |
533 | 533 | } /* d2f_array */ |
534 | 534 | |
535 | 535 | static inline void |
536 | 536 | s2d_array (const short *src, double *dest, int count, double scale) |
537 | { while (--count >= 0) | |
538 | { dest [count] = scale * src [count] ; | |
537 | { for (int i = 0 ; i < count ; i++) | |
538 | { dest [i] = scale * src [i] ; | |
539 | 539 | } ; |
540 | 540 | } /* s2d_array */ |
541 | 541 | |
542 | 542 | static inline void |
543 | 543 | i2d_array (const int *src, double *dest, int count, double scale) |
544 | { while (--count >= 0) | |
545 | { dest [count] = scale * src [count] ; | |
544 | { for (int i = 0 ; i < count ; i++) | |
545 | { dest [i] = scale * src [i] ; | |
546 | 546 | } ; |
547 | 547 | } /* i2d_array */ |
548 | 548 | |
549 | 549 | static inline void |
550 | 550 | f2d_array (const float *src, double *dest, int count) |
551 | { while (--count >= 0) | |
552 | { dest [count] = src [count] ; | |
551 | { for (int i = 0 ; i < count ; i++) | |
552 | { dest [i] = src [i] ; | |
553 | 553 | } ; |
554 | 554 | } /* f2d_array */ |
555 | 555 | |
571 | 571 | while (len > 0) |
572 | 572 | { if (len < bufferlen) |
573 | 573 | bufferlen = (int) len ; |
574 | readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
574 | readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
575 | 575 | |
576 | 576 | if (psf->data_endswap == SF_TRUE) |
577 | 577 | endswap_double_array (ubuf.dbuf, readcount) ; |
601 | 601 | while (len > 0) |
602 | 602 | { if (len < bufferlen) |
603 | 603 | bufferlen = (int) len ; |
604 | readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
604 | readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
605 | 605 | |
606 | 606 | if (psf->data_endswap == SF_TRUE) |
607 | 607 | endswap_double_array (ubuf.dbuf, bufferlen) ; |
627 | 627 | while (len > 0) |
628 | 628 | { if (len < bufferlen) |
629 | 629 | bufferlen = (int) len ; |
630 | readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
630 | readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
631 | 631 | |
632 | 632 | if (psf->data_endswap == SF_TRUE) |
633 | 633 | endswap_double_array (ubuf.dbuf, readcount) ; |
694 | 694 | if (psf->data_endswap == SF_TRUE) |
695 | 695 | endswap_double_array (ubuf.dbuf, bufferlen) ; |
696 | 696 | |
697 | writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
697 | writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
698 | 698 | total += writecount ; |
699 | 699 | if (writecount < bufferlen) |
700 | 700 | break ; |
725 | 725 | if (psf->data_endswap == SF_TRUE) |
726 | 726 | endswap_double_array (ubuf.dbuf, bufferlen) ; |
727 | 727 | |
728 | writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
728 | writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
729 | 729 | total += writecount ; |
730 | 730 | if (writecount < bufferlen) |
731 | 731 | break ; |
754 | 754 | if (psf->data_endswap == SF_TRUE) |
755 | 755 | endswap_double_array (ubuf.dbuf, bufferlen) ; |
756 | 756 | |
757 | writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
757 | writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
758 | 758 | total += writecount ; |
759 | 759 | if (writecount < bufferlen) |
760 | 760 | break ; |
784 | 784 | |
785 | 785 | endswap_double_copy (ubuf.dbuf, ptr + total, bufferlen) ; |
786 | 786 | |
787 | writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
787 | writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
788 | 788 | total += writecount ; |
789 | 789 | if (writecount < bufferlen) |
790 | 790 | break ; |
810 | 810 | while (len > 0) |
811 | 811 | { if (len < bufferlen) |
812 | 812 | bufferlen = (int) len ; |
813 | readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
813 | readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
814 | 814 | |
815 | 815 | if (psf->data_endswap == SF_TRUE) |
816 | 816 | endswap_double_array (ubuf.dbuf, bufferlen) ; |
840 | 840 | while (len > 0) |
841 | 841 | { if (len < bufferlen) |
842 | 842 | bufferlen = (int) len ; |
843 | readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
843 | readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
844 | 844 | |
845 | 845 | if (psf->data_endswap == SF_TRUE) |
846 | 846 | endswap_double_array (ubuf.dbuf, bufferlen) ; |
868 | 868 | while (len > 0) |
869 | 869 | { if (len < bufferlen) |
870 | 870 | bufferlen = (int) len ; |
871 | readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
871 | readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
872 | 872 | |
873 | 873 | if (psf->data_endswap == SF_TRUE) |
874 | 874 | endswap_double_array (ubuf.dbuf, bufferlen) ; |
898 | 898 | while (len > 0) |
899 | 899 | { if (len < bufferlen) |
900 | 900 | bufferlen = (int) len ; |
901 | readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
901 | readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
902 | 902 | |
903 | 903 | if (psf->data_endswap == SF_TRUE) |
904 | 904 | endswap_double_array (ubuf.dbuf, readcount) ; |
939 | 939 | if (psf->data_endswap == SF_TRUE) |
940 | 940 | endswap_double_array (ubuf.dbuf, bufferlen) ; |
941 | 941 | |
942 | writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
942 | writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
943 | 943 | total += writecount ; |
944 | 944 | if (writecount < bufferlen) |
945 | 945 | break ; |
972 | 972 | if (psf->data_endswap == SF_TRUE) |
973 | 973 | endswap_double_array (ubuf.dbuf, bufferlen) ; |
974 | 974 | |
975 | writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
975 | writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
976 | 976 | total += writecount ; |
977 | 977 | if (writecount < bufferlen) |
978 | 978 | break ; |
1000 | 1000 | if (psf->data_endswap == SF_TRUE) |
1001 | 1001 | endswap_double_array (ubuf.dbuf, bufferlen) ; |
1002 | 1002 | |
1003 | writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
1003 | writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
1004 | 1004 | total += writecount ; |
1005 | 1005 | if (writecount < bufferlen) |
1006 | 1006 | break ; |
1033 | 1033 | if (psf->data_endswap == SF_TRUE) |
1034 | 1034 | endswap_double_array (ubuf.dbuf, bufferlen) ; |
1035 | 1035 | |
1036 | writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
1036 | writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; | |
1037 | 1037 | total += writecount ; |
1038 | 1038 | if (writecount < bufferlen) |
1039 | 1039 | break ; |
1048 | 1048 | |
1049 | 1049 | static void |
1050 | 1050 | d2bd_read (double *buffer, int count) |
1051 | { while (--count >= 0) | |
1052 | { buffer [count] = DOUBLE64_READ ((unsigned char *) (buffer + count)) ; | |
1051 | { for (int i = 0 ; i < count ; i++) | |
1052 | { buffer [i] = DOUBLE64_READ ((unsigned char *) &buffer [i]) ; | |
1053 | 1053 | } ; |
1054 | 1054 | } /* d2bd_read */ |
1055 | 1055 | |
1056 | 1056 | static void |
1057 | 1057 | bd2d_write (double *buffer, int count) |
1058 | { while (--count >= 0) | |
1059 | { DOUBLE64_WRITE (buffer [count], (unsigned char*) (buffer + count)) ; | |
1058 | { for (int i = 0 ; i < count ; i++) | |
1059 | { DOUBLE64_WRITE (buffer [i], (unsigned char*) &buffer [i]) ; | |
1060 | 1060 | } ; |
1061 | 1061 | } /* bd2d_write */ |
1062 | 1062 |
114 | 114 | ** No assumptions are made about the packing of this struct. |
115 | 115 | */ |
116 | 116 | typedef struct |
117 | { unsigned char major, minor, compression, channels, bitwidth ; | |
118 | unsigned short srate, maxval ; | |
119 | unsigned int id, datalen, frames, offset ; | |
117 | { uint8_t major, minor, compression, channels, bitwidth ; | |
118 | uint16_t srate, maxval ; | |
119 | uint32_t id, datalen, frames, offset ; | |
120 | 120 | } DWD_HEADER ; |
121 | 121 | |
122 | 122 | static int |
172 | 172 | |
173 | 173 | if (psf->filelength != dwdh.offset + dwdh.datalen) |
174 | 174 | { psf_log_printf (psf, " Data Length : %d (should be %D)\n", dwdh.datalen, psf->filelength - dwdh.offset) ; |
175 | dwdh.datalen = (unsigned int) (psf->filelength - dwdh.offset) ; | |
175 | dwdh.datalen = (uint32_t) (psf->filelength - dwdh.offset) ; | |
176 | 176 | } |
177 | 177 | else |
178 | 178 | psf_log_printf (psf, " Data Length : %d\n", dwdh.datalen) ; |
197 | 197 | iptr = ubuf.ibuf ; |
198 | 198 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
199 | 199 | while (len > 0) |
200 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
200 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
201 | 201 | count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; |
202 | 202 | for (k = 0 ; k < readcount ; k++) |
203 | 203 | ptr [total + k] = iptr [k] >> 16 ; |
254 | 254 | iptr = ubuf.ibuf ; |
255 | 255 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
256 | 256 | while (len > 0) |
257 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
257 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
258 | 258 | count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; |
259 | 259 | for (k = 0 ; k < readcount ; k++) |
260 | 260 | ptr [total + k] = normfact * (float) (iptr [k]) ; |
286 | 286 | iptr = ubuf.ibuf ; |
287 | 287 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
288 | 288 | while (len > 0) |
289 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
289 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
290 | 290 | count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; |
291 | 291 | for (k = 0 ; k < readcount ; k++) |
292 | 292 | ptr [total + k] = normfact * (double) (iptr [k]) ; |
376 | 376 | /* Load bits in bit reseviour. */ |
377 | 377 | while (pdwvw->bit_count < bit_count) |
378 | 378 | { if (pdwvw->b.index >= pdwvw->b.end) |
379 | { pdwvw->b.end = psf_fread (pdwvw->b.buffer, 1, sizeof (pdwvw->b.buffer), psf) ; | |
379 | { pdwvw->b.end = (int) psf_fread (pdwvw->b.buffer, 1, sizeof (pdwvw->b.buffer), psf) ; | |
380 | 380 | pdwvw->b.index = 0 ; |
381 | 381 | } ; |
382 | 382 | |
568 | 568 | iptr = ubuf.ibuf ; |
569 | 569 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
570 | 570 | while (len > 0) |
571 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
571 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
572 | 572 | for (k = 0 ; k < writecount ; k++) |
573 | 573 | iptr [k] = arith_shift_left (ptr [total + k], 16) ; |
574 | 574 | count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; |
625 | 625 | iptr = ubuf.ibuf ; |
626 | 626 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
627 | 627 | while (len > 0) |
628 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
628 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
629 | 629 | for (k = 0 ; k < writecount ; k++) |
630 | 630 | iptr [k] = psf_lrintf (normfact * ptr [total + k]) ; |
631 | 631 | count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; |
657 | 657 | iptr = ubuf.ibuf ; |
658 | 658 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
659 | 659 | while (len > 0) |
660 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
660 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
661 | 661 | for (k = 0 ; k < writecount ; k++) |
662 | 662 | iptr [k] = psf_lrint (normfact * ptr [total + k]) ; |
663 | 663 | count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; |
75 | 75 | |
76 | 76 | static void psf_log_syserr (SF_PRIVATE *psf, int error) ; |
77 | 77 | |
78 | int | |
79 | psf_copy_filename (SF_PRIVATE *psf, const char *path) | |
80 | { const char *ccptr ; | |
81 | char *cptr ; | |
82 | ||
83 | if (strlen (path) > 1 && strlen (path) - 1 >= sizeof (psf->file.path)) | |
84 | { psf->error = SFE_FILENAME_TOO_LONG ; | |
85 | return psf->error ; | |
86 | } ; | |
87 | ||
88 | snprintf (psf->file.path, sizeof (psf->file.path), "%s", path) ; | |
89 | if ((ccptr = strrchr (path, '/')) || (ccptr = strrchr (path, '\\'))) | |
90 | ccptr ++ ; | |
91 | else | |
92 | ccptr = path ; | |
93 | ||
94 | snprintf (psf->file.name, sizeof (psf->file.name), "%s", ccptr) ; | |
95 | ||
96 | /* Now grab the directory. */ | |
97 | snprintf (psf->file.dir, sizeof (psf->file.dir), "%s", path) ; | |
98 | if ((cptr = strrchr (psf->file.dir, '/')) || (cptr = strrchr (psf->file.dir, '\\'))) | |
99 | cptr [1] = 0 ; | |
100 | else | |
101 | psf->file.dir [0] = 0 ; | |
102 | ||
103 | return 0 ; | |
104 | } /* psf_copy_filename */ | |
105 | ||
78 | 106 | #if (USE_WINDOWS_API == 0) |
79 | 107 | |
80 | 108 | /*------------------------------------------------------------------------------ |
131 | 159 | return 0 ; |
132 | 160 | |
133 | 161 | /* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */ |
134 | count = snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s/..namedfork/rsrc", psf->file.path.c) ; | |
162 | count = snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s/..namedfork/rsrc", psf->file.path) ; | |
135 | 163 | psf->error = SFE_NO_ERROR ; |
136 | if (count < sizeof (psf->rsrc.path.c)) | |
164 | if (count < sizeof (psf->rsrc.path)) | |
137 | 165 | { if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0) |
138 | 166 | { psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ; |
139 | 167 | if (psf->rsrclength > 0 || (psf->rsrc.mode & SFM_WRITE)) |
152 | 180 | ** Now try for a resource fork stored as a separate file in the same |
153 | 181 | ** directory, but preceded with a dot underscore. |
154 | 182 | */ |
155 | count = snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s._%s", psf->file.dir.c, psf->file.name.c) ; | |
183 | count = snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s._%s", psf->file.dir, psf->file.name) ; | |
156 | 184 | psf->error = SFE_NO_ERROR ; |
157 | if (count < sizeof (psf->rsrc.path.c) && (psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0) | |
185 | if (count < sizeof (psf->rsrc.path) && (psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0) | |
158 | 186 | { psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ; |
159 | 187 | return SFE_NO_ERROR ; |
160 | 188 | } ; |
163 | 191 | ** Now try for a resource fork stored in a separate file in the |
164 | 192 | ** .AppleDouble/ directory. |
165 | 193 | */ |
166 | count = snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s.AppleDouble/%s", psf->file.dir.c, psf->file.name.c) ; | |
194 | count = snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s.AppleDouble/%s", psf->file.dir, psf->file.name) ; | |
167 | 195 | psf->error = SFE_NO_ERROR ; |
168 | if (count < sizeof (psf->rsrc.path.c)) | |
196 | if (count < sizeof (psf->rsrc.path)) | |
169 | 197 | { if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0) |
170 | 198 | { psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ; |
171 | 199 | return SFE_NO_ERROR ; |
571 | 599 | } ; |
572 | 600 | |
573 | 601 | if (mode == 0) |
574 | fd = open (pfile->path.c, oflag) ; | |
602 | fd = open (pfile->path, oflag) ; | |
575 | 603 | else |
576 | fd = open (pfile->path.c, oflag, mode) ; | |
604 | fd = open (pfile->path, oflag, mode) ; | |
577 | 605 | |
578 | 606 | return fd ; |
579 | 607 | } /* psf_open_fd */ |
601 | 629 | #endif |
602 | 630 | } /* psf_fsync */ |
603 | 631 | |
604 | #elif USE_WINDOWS_API | |
632 | #else | |
605 | 633 | |
606 | 634 | /* Win32 file i/o functions implemented using native Win32 API */ |
607 | 635 | |
619 | 647 | psf->error = 0 ; |
620 | 648 | psf->file.handle = psf_open_handle (&psf->file) ; |
621 | 649 | |
622 | if (psf->file.handle == NULL) | |
650 | if (psf->file.handle == INVALID_HANDLE_VALUE) | |
623 | 651 | psf_log_syserr (psf, GetLastError ()) ; |
624 | 652 | |
625 | 653 | return psf->error ; |
633 | 661 | return 0 ; |
634 | 662 | |
635 | 663 | if (psf->file.do_not_close_descriptor) |
636 | { psf->file.handle = NULL ; | |
664 | { psf->file.handle = INVALID_HANDLE_VALUE ; | |
637 | 665 | return 0 ; |
638 | 666 | } ; |
639 | 667 | |
640 | 668 | if ((retval = psf_close_handle (psf->file.handle)) == -1) |
641 | 669 | psf_log_syserr (psf, GetLastError ()) ; |
642 | 670 | |
643 | psf->file.handle = NULL ; | |
671 | psf->file.handle = INVALID_HANDLE_VALUE ; | |
644 | 672 | |
645 | 673 | return retval ; |
646 | 674 | } /* psf_fclose */ |
648 | 676 | /* USE_WINDOWS_API */ int |
649 | 677 | psf_open_rsrc (SF_PRIVATE *psf) |
650 | 678 | { |
651 | if (psf->rsrc.handle != NULL) | |
679 | if (psf->rsrc.handle != INVALID_HANDLE_VALUE) | |
652 | 680 | return 0 ; |
653 | 681 | |
654 | 682 | /* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */ |
655 | snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s/rsrc", psf->file.path.c) ; | |
683 | snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s/rsrc", psf->file.path) ; | |
656 | 684 | psf->error = SFE_NO_ERROR ; |
657 | if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL) | |
685 | if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != INVALID_HANDLE_VALUE) | |
658 | 686 | { psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ; |
659 | 687 | return SFE_NO_ERROR ; |
660 | 688 | } ; |
663 | 691 | ** Now try for a resource fork stored as a separate file in the same |
664 | 692 | ** directory, but preceded with a dot underscore. |
665 | 693 | */ |
666 | snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s._%s", psf->file.dir.c, psf->file.name.c) ; | |
694 | snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s._%s", psf->file.dir, psf->file.name) ; | |
667 | 695 | psf->error = SFE_NO_ERROR ; |
668 | if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL) | |
696 | if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != INVALID_HANDLE_VALUE) | |
669 | 697 | { psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ; |
670 | 698 | return SFE_NO_ERROR ; |
671 | 699 | } ; |
674 | 702 | ** Now try for a resource fork stored in a separate file in the |
675 | 703 | ** .AppleDouble/ directory. |
676 | 704 | */ |
677 | snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s.AppleDouble/%s", psf->file.dir.c, psf->file.name.c) ; | |
705 | snprintf (psf->rsrc.path, sizeof (psf->rsrc.path), "%s.AppleDouble/%s", psf->file.dir, psf->file.name) ; | |
678 | 706 | psf->error = SFE_NO_ERROR ; |
679 | if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL) | |
707 | if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != INVALID_HANDLE_VALUE) | |
680 | 708 | { psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ; |
681 | 709 | return SFE_NO_ERROR ; |
682 | 710 | } ; |
683 | 711 | |
684 | 712 | /* No resource file found. */ |
685 | if (psf->rsrc.handle == NULL) | |
713 | if (psf->rsrc.handle == INVALID_HANDLE_VALUE) | |
686 | 714 | psf_log_syserr (psf, GetLastError ()) ; |
687 | ||
688 | psf->rsrc.handle = NULL ; | |
689 | 715 | |
690 | 716 | return psf->error ; |
691 | 717 | } /* psf_open_rsrc */ |
737 | 763 | |
738 | 764 | /* USE_WINDOWS_API */ void |
739 | 765 | psf_init_files (SF_PRIVATE *psf) |
740 | { psf->file.handle = NULL ; | |
741 | psf->rsrc.handle = NULL ; | |
742 | psf->file.hsaved = NULL ; | |
766 | { psf->file.handle = INVALID_HANDLE_VALUE ; | |
767 | psf->rsrc.handle = INVALID_HANDLE_VALUE ; | |
768 | psf->file.hsaved = INVALID_HANDLE_VALUE ; | |
743 | 769 | } /* psf_init_files */ |
744 | 770 | |
745 | 771 | /* USE_WINDOWS_API */ void |
763 | 789 | DWORD dwShareMode ; |
764 | 790 | DWORD dwCreationDistribution ; |
765 | 791 | HANDLE handle ; |
792 | LPWSTR pwszPath = NULL ; | |
766 | 793 | |
767 | 794 | switch (pfile->mode) |
768 | 795 | { case SFM_READ : |
784 | 811 | break ; |
785 | 812 | |
786 | 813 | default : |
787 | return NULL ; | |
814 | return INVALID_HANDLE_VALUE ; | |
815 | } ; | |
816 | ||
817 | int nResult = MultiByteToWideChar (CP_UTF8, 0, pfile->path, -1, NULL, 0) ; | |
818 | pwszPath = malloc (nResult * sizeof (WCHAR)) ; | |
819 | if (!pwszPath) | |
820 | return INVALID_HANDLE_VALUE ; | |
821 | ||
822 | int nResult2 = MultiByteToWideChar (CP_UTF8, 0, pfile->path, -1, pwszPath, nResult) ; | |
823 | if (nResult != nResult2) | |
824 | { free (pwszPath) ; | |
825 | return INVALID_HANDLE_VALUE ; | |
788 | 826 | } ; |
789 | 827 | |
790 | 828 | #if defined (WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) |
791 | 829 | if (!pfile->use_wchar) |
792 | return NULL ; | |
830 | return INVALID_HANDLE_VALUE ; | |
793 | 831 | |
794 | 832 | CREATEFILE2_EXTENDED_PARAMETERS cfParams = { 0 } ; |
795 | 833 | cfParams.dwSize = sizeof (CREATEFILE2_EXTENDED_PARAMETERS) ; |
796 | 834 | cfParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL ; |
797 | 835 | |
798 | handle = CreateFile2 (pfile->path.wc, dwDesiredAccess, dwShareMode, dwCreationDistribution, &cfParams) ; | |
799 | ||
800 | if (handle == INVALID_HANDLE_VALUE) | |
801 | return NULL ; | |
836 | handle = CreateFile2 (pwszPath, dwDesiredAccess, dwShareMode, dwCreationDistribution, &cfParams) ; | |
837 | #else | |
838 | handle = CreateFileW ( | |
839 | pwszPath, /* pointer to name of the file */ | |
840 | dwDesiredAccess, /* access (read-write) mode */ | |
841 | dwShareMode, /* share mode */ | |
842 | 0, /* pointer to security attributes */ | |
843 | dwCreationDistribution, /* how to create */ | |
844 | FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */ | |
845 | NULL /* handle to file with attributes to copy */ | |
846 | ) ; | |
847 | #endif | |
848 | free (pwszPath) ; | |
802 | 849 | |
803 | 850 | return handle ; |
804 | #else | |
805 | if (pfile->use_wchar) | |
806 | handle = CreateFileW ( | |
807 | pfile->path.wc, /* pointer to name of the file */ | |
808 | dwDesiredAccess, /* access (read-write) mode */ | |
809 | dwShareMode, /* share mode */ | |
810 | 0, /* pointer to security attributes */ | |
811 | dwCreationDistribution, /* how to create */ | |
812 | FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */ | |
813 | NULL /* handle to file with attributes to copy */ | |
814 | ) ; | |
815 | else | |
816 | handle = CreateFileA ( | |
817 | pfile->path.c, /* pointer to name of the file */ | |
818 | dwDesiredAccess, /* access (read-write) mode */ | |
819 | dwShareMode, /* share mode */ | |
820 | 0, /* pointer to security attributes */ | |
821 | dwCreationDistribution, /* how to create */ | |
822 | FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */ | |
823 | NULL /* handle to file with attributes to copy */ | |
824 | ) ; | |
825 | ||
826 | if (handle == INVALID_HANDLE_VALUE) | |
827 | return NULL ; | |
828 | ||
829 | return handle ; | |
830 | #endif | |
831 | 851 | } /* psf_open_handle */ |
832 | 852 | |
833 | 853 | /* USE_WINDOWS_API */ static void |
859 | 879 | /* USE_WINDOWS_API */ int |
860 | 880 | psf_close_rsrc (SF_PRIVATE *psf) |
861 | 881 | { psf_close_handle (psf->rsrc.handle) ; |
862 | psf->rsrc.handle = NULL ; | |
882 | psf->rsrc.handle = INVALID_HANDLE_VALUE ; | |
863 | 883 | return 0 ; |
864 | 884 | } /* psf_close_rsrc */ |
865 | 885 | |
866 | 886 | |
867 | 887 | /* USE_WINDOWS_API */ int |
868 | 888 | psf_set_stdio (SF_PRIVATE *psf) |
869 | { HANDLE handle = NULL ; | |
889 | { HANDLE handle = INVALID_HANDLE_VALUE ; | |
870 | 890 | int error = 0 ; |
871 | 891 | |
872 | 892 | switch (psf->file.mode) |
908 | 928 | |
909 | 929 | /* USE_WINDOWS_API */ int |
910 | 930 | psf_file_valid (SF_PRIVATE *psf) |
911 | { if (psf->file.handle == NULL) | |
912 | return SF_FALSE ; | |
913 | if (psf->file.handle == INVALID_HANDLE_VALUE) | |
931 | { if (psf->file.handle == INVALID_HANDLE_VALUE) | |
914 | 932 | return SF_FALSE ; |
915 | 933 | return SF_TRUE ; |
916 | 934 | } /* psf_set_file */ |
1072 | 1090 | |
1073 | 1091 | /* USE_WINDOWS_API */ static int |
1074 | 1092 | psf_close_handle (HANDLE handle) |
1075 | { if (handle == NULL) | |
1093 | { if (handle == INVALID_HANDLE_VALUE) | |
1076 | 1094 | return 0 ; |
1077 | 1095 | |
1078 | 1096 | if (CloseHandle (handle) == 0) |
1186 | 1204 | return retval ; |
1187 | 1205 | } /* psf_ftruncate */ |
1188 | 1206 | |
1189 | ||
1190 | #else | |
1191 | /* Win32 file i/o functions implemented using Unix-style file i/o API */ | |
1192 | ||
1193 | /* Win32 has a 64 file offset seek function: | |
1194 | ** | |
1195 | ** __int64 _lseeki64 (int handle, __int64 offset, int origin) ; | |
1196 | ** | |
1197 | ** It also has a 64 bit fstat function: | |
1198 | ** | |
1199 | ** int fstati64 (int, struct _stati64) ; | |
1200 | ** | |
1201 | ** but the fscking thing doesn't work!!!!! The file size parameter returned | |
1202 | ** by this function is only valid up until more data is written at the end of | |
1203 | ** the file. That makes this function completely 100% useless. | |
1204 | */ | |
1205 | ||
1206 | #include <io.h> | |
1207 | #include <direct.h> | |
1208 | ||
1209 | /* Win32 */ int | |
1210 | psf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode) | |
1211 | { int oflag, mode ; | |
1212 | ||
1213 | switch (open_mode) | |
1214 | { case SFM_READ : | |
1215 | oflag = O_RDONLY | O_BINARY ; | |
1216 | mode = 0 ; | |
1217 | break ; | |
1218 | ||
1219 | case SFM_WRITE : | |
1220 | oflag = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ; | |
1221 | mode = S_IRUSR | S_IWUSR | S_IRGRP ; | |
1222 | break ; | |
1223 | ||
1224 | case SFM_RDWR : | |
1225 | oflag = O_RDWR | O_CREAT | O_BINARY ; | |
1226 | mode = S_IRUSR | S_IWUSR | S_IRGRP ; | |
1227 | break ; | |
1228 | ||
1229 | default : | |
1230 | psf->error = SFE_BAD_OPEN_MODE ; | |
1231 | return -1 ; | |
1232 | break ; | |
1233 | } ; | |
1234 | ||
1235 | if (mode == 0) | |
1236 | psf->file.filedes = open (pathname, oflag) ; | |
1237 | else | |
1238 | psf->file.filedes = open (pathname, oflag, mode) ; | |
1239 | ||
1240 | if (psf->file.filedes == -1) | |
1241 | psf_log_syserr (psf, errno) ; | |
1242 | ||
1243 | return psf->file.filedes ; | |
1244 | } /* psf_fopen */ | |
1245 | ||
1246 | /* Win32 */ sf_count_t | |
1247 | psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) | |
1248 | { sf_count_t new_position ; | |
1249 | ||
1250 | if (psf->virtual_io) | |
1251 | return psf->vio.seek (offset, whence, psf->vio_user_data) ; | |
1252 | ||
1253 | switch (whence) | |
1254 | { case SEEK_SET : | |
1255 | offset += psf->fileoffset ; | |
1256 | break ; | |
1257 | ||
1258 | case SEEK_END : | |
1259 | if (psf->file.mode == SFM_WRITE) | |
1260 | { new_position = _lseeki64 (psf->file.filedes, offset, whence) ; | |
1261 | ||
1262 | if (new_position < 0) | |
1263 | psf_log_syserr (psf, errno) ; | |
1264 | ||
1265 | return new_position - psf->fileoffset ; | |
1266 | } ; | |
1267 | ||
1268 | /* Transform SEEK_END into a SEEK_SET, ie find the file | |
1269 | ** length add the requested offset (should be <= 0) to | |
1270 | ** get the offset wrt the start of file. | |
1271 | */ | |
1272 | whence = SEEK_SET ; | |
1273 | offset = _lseeki64 (psf->file.filedes, 0, SEEK_END) + offset ; | |
1274 | break ; | |
1275 | ||
1276 | default : | |
1277 | /* No need to do anything about SEEK_CUR. */ | |
1278 | break ; | |
1279 | } ; | |
1280 | ||
1281 | /* | |
1282 | ** Bypass weird Win32-ism if necessary. | |
1283 | ** _lseeki64() returns an "invalid parameter" error if called with the | |
1284 | ** offset == 0 and whence == SEEK_CUR. | |
1285 | *** Use the _telli64() function instead. | |
1286 | */ | |
1287 | if (offset == 0 && whence == SEEK_CUR) | |
1288 | new_position = _telli64 (psf->file.filedes) ; | |
1289 | else | |
1290 | new_position = _lseeki64 (psf->file.filedes, offset, whence) ; | |
1291 | ||
1292 | if (new_position < 0) | |
1293 | psf_log_syserr (psf, errno) ; | |
1294 | ||
1295 | new_position -= psf->fileoffset ; | |
1296 | ||
1297 | return new_position ; | |
1298 | } /* psf_fseek */ | |
1299 | ||
1300 | /* Win32 */ sf_count_t | |
1301 | psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) | |
1302 | { sf_count_t total = 0 ; | |
1303 | ssize_t count ; | |
1304 | ||
1305 | if (psf->virtual_io) | |
1306 | return psf->vio.read (ptr, bytes*items, psf->vio_user_data) / bytes ; | |
1307 | ||
1308 | items *= bytes ; | |
1309 | ||
1310 | /* Do this check after the multiplication above. */ | |
1311 | if (items <= 0) | |
1312 | return 0 ; | |
1313 | ||
1314 | while (items > 0) | |
1315 | { /* Break the writes down to a sensible size. */ | |
1316 | count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; | |
1317 | ||
1318 | count = read (psf->file.filedes, ((char*) ptr) + total, (size_t) count) ; | |
1319 | ||
1320 | if (count == -1) | |
1321 | { if (errno == EINTR) | |
1322 | continue ; | |
1323 | ||
1324 | psf_log_syserr (psf, errno) ; | |
1325 | break ; | |
1326 | } ; | |
1327 | ||
1328 | if (count == 0) | |
1329 | break ; | |
1330 | ||
1331 | total += count ; | |
1332 | items -= count ; | |
1333 | } ; | |
1334 | ||
1335 | return total / bytes ; | |
1336 | } /* psf_fread */ | |
1337 | ||
1338 | /* Win32 */ sf_count_t | |
1339 | psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) | |
1340 | { sf_count_t total = 0 ; | |
1341 | ssize_t count ; | |
1342 | ||
1343 | if (psf->virtual_io) | |
1344 | return psf->vio.write (ptr, bytes*items, psf->vio_user_data) / bytes ; | |
1345 | ||
1346 | items *= bytes ; | |
1347 | ||
1348 | /* Do this check after the multiplication above. */ | |
1349 | if (items <= 0) | |
1350 | return 0 ; | |
1351 | ||
1352 | while (items > 0) | |
1353 | { /* Break the writes down to a sensible size. */ | |
1354 | count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : items ; | |
1355 | ||
1356 | count = write (psf->file.filedes, ((const char*) ptr) + total, count) ; | |
1357 | ||
1358 | if (count == -1) | |
1359 | { if (errno == EINTR) | |
1360 | continue ; | |
1361 | ||
1362 | psf_log_syserr (psf, errno) ; | |
1363 | break ; | |
1364 | } ; | |
1365 | ||
1366 | if (count == 0) | |
1367 | break ; | |
1368 | ||
1369 | total += count ; | |
1370 | items -= count ; | |
1371 | } ; | |
1372 | ||
1373 | return total / bytes ; | |
1374 | } /* psf_fwrite */ | |
1375 | ||
1376 | /* Win32 */ sf_count_t | |
1377 | psf_ftell (SF_PRIVATE *psf) | |
1378 | { sf_count_t pos ; | |
1379 | ||
1380 | if (psf->virtual_io) | |
1381 | return psf->vio.tell (psf->vio_user_data) ; | |
1382 | ||
1383 | pos = _telli64 (psf->file.filedes) ; | |
1384 | ||
1385 | if (pos == ((sf_count_t) -1)) | |
1386 | { psf_log_syserr (psf, errno) ; | |
1387 | return -1 ; | |
1388 | } ; | |
1389 | ||
1390 | return pos - psf->fileoffset ; | |
1391 | } /* psf_ftell */ | |
1392 | ||
1393 | /* Win32 */ int | |
1394 | psf_fclose (SF_PRIVATE *psf) | |
1395 | { int retval ; | |
1396 | ||
1397 | while ((retval = close (psf->file.filedes)) == -1 && errno == EINTR) | |
1398 | /* Do nothing. */ ; | |
1399 | ||
1400 | if (retval == -1) | |
1401 | psf_log_syserr (psf, errno) ; | |
1402 | ||
1403 | psf->file.filedes = -1 ; | |
1404 | ||
1405 | return retval ; | |
1406 | } /* psf_fclose */ | |
1407 | ||
1408 | /* Win32 */ sf_count_t | |
1409 | psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf) | |
1410 | { sf_count_t k = 0 ; | |
1411 | sf_count_t count ; | |
1412 | ||
1413 | while (k < bufsize - 1) | |
1414 | { count = read (psf->file.filedes, &(buffer [k]), 1) ; | |
1415 | ||
1416 | if (count == -1) | |
1417 | { if (errno == EINTR) | |
1418 | continue ; | |
1419 | ||
1420 | psf_log_syserr (psf, errno) ; | |
1421 | break ; | |
1422 | } ; | |
1423 | ||
1424 | if (count == 0 || buffer [k++] == '\n') | |
1425 | break ; | |
1426 | } ; | |
1427 | ||
1428 | buffer [k] = 0 ; | |
1429 | ||
1430 | return k ; | |
1431 | } /* psf_fgets */ | |
1432 | ||
1433 | /* Win32 */ int | |
1434 | psf_is_pipe (SF_PRIVATE *psf) | |
1435 | { struct stat statbuf ; | |
1436 | ||
1437 | if (psf->virtual_io) | |
1438 | return SF_FALSE ; | |
1439 | ||
1440 | /* Not sure if this works. */ | |
1441 | if (fstat (psf->file.filedes, &statbuf) == -1) | |
1442 | { psf_log_syserr (psf, errno) ; | |
1443 | /* Default to maximum safety. */ | |
1444 | return SF_TRUE ; | |
1445 | } ; | |
1446 | ||
1447 | /* These macros are defined in Win32/unistd.h. */ | |
1448 | if (S_ISFIFO (statbuf.st_mode) || S_ISSOCK (statbuf.st_mode)) | |
1449 | return SF_TRUE ; | |
1450 | ||
1451 | return SF_FALSE ; | |
1452 | } /* psf_checkpipe */ | |
1453 | ||
1454 | /* Win32 */ sf_count_t | |
1455 | psf_get_filelen (SF_PRIVATE *psf) | |
1456 | { | |
1457 | #if 0 | |
1458 | /* | |
1459 | ** Windoze is SOOOOO FUCKED!!!!!!! | |
1460 | ** This code should work but doesn't. Why? | |
1461 | ** Code below does work. | |
1462 | */ | |
1463 | struct _stati64 statbuf ; | |
1464 | ||
1465 | if (_fstati64 (psf->file.filedes, &statbuf)) | |
1466 | { psf_log_syserr (psf, errno) ; | |
1467 | return (sf_count_t) -1 ; | |
1468 | } ; | |
1469 | ||
1470 | return statbuf.st_size ; | |
1471 | #else | |
1472 | sf_count_t current, filelen ; | |
1473 | ||
1474 | if (psf->virtual_io) | |
1475 | return psf->vio.get_filelen (psf->vio_user_data) ; | |
1476 | ||
1477 | if ((current = _telli64 (psf->file.filedes)) < 0) | |
1478 | { psf_log_syserr (psf, errno) ; | |
1479 | return (sf_count_t) -1 ; | |
1480 | } ; | |
1481 | ||
1482 | /* | |
1483 | ** Lets face it, windoze if FUBAR!!! | |
1484 | ** | |
1485 | ** For some reason, I have to call _lseeki64() TWICE to get to the | |
1486 | ** end of the file. | |
1487 | ** | |
1488 | ** This might have been avoided if windows had implemented the POSIX | |
1489 | ** standard function fsync() but NO, that would have been too easy. | |
1490 | ** | |
1491 | ** I am VERY close to saying that windoze will no longer be supported | |
1492 | ** by libsndfile and changing the license to GPL at the same time. | |
1493 | */ | |
1494 | ||
1495 | _lseeki64 (psf->file.filedes, 0, SEEK_END) ; | |
1496 | ||
1497 | if ((filelen = _lseeki64 (psf->file.filedes, 0, SEEK_END)) < 0) | |
1498 | { psf_log_syserr (psf, errno) ; | |
1499 | return (sf_count_t) -1 ; | |
1500 | } ; | |
1501 | ||
1502 | if (filelen > current) | |
1503 | _lseeki64 (psf->file.filedes, current, SEEK_SET) ; | |
1504 | ||
1505 | switch (psf->file.mode) | |
1506 | { case SFM_WRITE : | |
1507 | filelen = filelen - psf->fileoffset ; | |
1508 | break ; | |
1509 | ||
1510 | case SFM_READ : | |
1511 | if (psf->fileoffset > 0 && psf->filelength > 0) | |
1512 | filelen = psf->filelength ; | |
1513 | break ; | |
1514 | ||
1515 | case SFM_RDWR : | |
1516 | /* | |
1517 | ** Cannot open embedded files SFM_RDWR so we don't need to | |
1518 | ** subtract psf->fileoffset. We already have the answer we | |
1519 | ** need. | |
1520 | */ | |
1521 | break ; | |
1522 | ||
1523 | default : | |
1524 | filelen = 0 ; | |
1525 | } ; | |
1526 | ||
1527 | return filelen ; | |
1528 | 1207 | #endif |
1529 | } /* psf_get_filelen */ | |
1530 | ||
1531 | /* Win32 */ int | |
1532 | psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) | |
1533 | { int retval ; | |
1534 | ||
1535 | /* Returns 0 on success, non-zero on failure. */ | |
1536 | if (len < 0) | |
1537 | return 1 ; | |
1538 | ||
1539 | /* The global village idiots at micorsoft decided to implement | |
1540 | ** nearly all the required 64 bit file offset functions except | |
1541 | ** for one, truncate. The fscking morons! | |
1542 | ** | |
1543 | ** This is not 64 bit file offset clean. Somone needs to clean | |
1544 | ** this up. | |
1545 | */ | |
1546 | if (len > 0x7FFFFFFF) | |
1547 | return -1 ; | |
1548 | ||
1549 | retval = chsize (psf->file.filedes, len) ; | |
1550 | ||
1551 | if (retval == -1) | |
1552 | psf_log_syserr (psf, errno) ; | |
1553 | ||
1554 | return retval ; | |
1555 | } /* psf_ftruncate */ | |
1556 | ||
1557 | ||
1558 | static void | |
1559 | psf_log_syserr (SF_PRIVATE *psf, int error) | |
1560 | { | |
1561 | /* Only log an error if no error has been set yet. */ | |
1562 | if (psf->error == 0) | |
1563 | { psf->error = SFE_SYSTEM ; | |
1564 | snprintf (psf->syserr, sizeof (psf->syserr), "System error : %s", strerror (error)) ; | |
1565 | } ; | |
1566 | ||
1567 | return ; | |
1568 | } /* psf_log_syserr */ | |
1569 | ||
1570 | #endif | |
1571 | ||
1208 |
126 | 126 | |
127 | 127 | static void |
128 | 128 | s2flac8_array (const short *src, int32_t *dest, int count) |
129 | { while (--count >= 0) | |
130 | dest [count] = src [count] >> 8 ; | |
129 | { for (int i = 0 ; i < count ; i++) | |
130 | dest [i] = src [i] >> 8 ; | |
131 | 131 | } /* s2flac8_array */ |
132 | 132 | |
133 | 133 | static void |
134 | 134 | s2flac16_array (const short *src, int32_t *dest, int count) |
135 | { while (--count >= 0) | |
136 | dest [count] = src [count] ; | |
135 | { for (int i = 0 ; i < count ; i++) | |
136 | dest [i] = src [i] ; | |
137 | 137 | } /* s2flac16_array */ |
138 | 138 | |
139 | 139 | static void |
140 | 140 | s2flac24_array (const short *src, int32_t *dest, int count) |
141 | { while (--count >= 0) | |
142 | dest [count] = src [count] << 8 ; | |
141 | { for (int i = 0 ; i < count ; i++) | |
142 | dest [i] = src [i] << 8 ; | |
143 | 143 | } /* s2flac24_array */ |
144 | 144 | |
145 | 145 | static void |
146 | 146 | i2flac8_array (const int *src, int32_t *dest, int count) |
147 | { while (--count >= 0) | |
148 | dest [count] = src [count] >> 24 ; | |
147 | { for (int i = 0 ; i < count ; i++) | |
148 | dest [i] = src [i] >> 24 ; | |
149 | 149 | } /* i2flac8_array */ |
150 | 150 | |
151 | 151 | static void |
152 | 152 | i2flac16_array (const int *src, int32_t *dest, int count) |
153 | 153 | { |
154 | while (--count >= 0) | |
155 | dest [count] = src [count] >> 16 ; | |
154 | for (int i = 0 ; i < count ; i++) | |
155 | dest [i] = src [i] >> 16 ; | |
156 | 156 | } /* i2flac16_array */ |
157 | 157 | |
158 | 158 | static void |
159 | 159 | i2flac24_array (const int *src, int32_t *dest, int count) |
160 | { while (--count >= 0) | |
161 | dest [count] = src [count] >> 8 ; | |
160 | { for (int i = 0 ; i < count ; i++) | |
161 | dest [i] = src [i] >> 8 ; | |
162 | 162 | } /* i2flac24_array */ |
163 | 163 | |
164 | 164 | static sf_count_t |
947 | 947 | /* Decode some more. */ |
948 | 948 | while (pflac->pos < pflac->len) |
949 | 949 | { if (FLAC__stream_decoder_process_single (pflac->fsd) == 0) |
950 | break ; | |
950 | { psf_log_printf (psf, "FLAC__stream_decoder_process_single returned false\n") ; | |
951 | /* Current frame is busted, so NULL the pointer. */ | |
952 | pflac->frame = NULL ; | |
953 | break ; | |
954 | } ; | |
951 | 955 | state = FLAC__stream_decoder_get_state (pflac->fsd) ; |
952 | 956 | if (state >= FLAC__STREAM_DECODER_END_OF_STREAM) |
953 | 957 | { psf_log_printf (psf, "FLAC__stream_decoder_get_state returned %s\n", FLAC__StreamDecoderStateString [state]) ; |
1175 | 1179 | |
1176 | 1180 | normfact = normalize ? (8.0 * 0x10) : 1.0 ; |
1177 | 1181 | |
1178 | while (--count >= 0) | |
1179 | { scaled_value = src [count] * normfact ; | |
1182 | for (int i = 0 ; i < count ; i++) | |
1183 | { scaled_value = src [i] * normfact ; | |
1180 | 1184 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7F)) |
1181 | { dest [count] = 0x7F ; | |
1185 | { dest [i] = 0x7F ; | |
1182 | 1186 | continue ; |
1183 | 1187 | } ; |
1184 | 1188 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10)) |
1185 | { dest [count] = -0x80 ; | |
1189 | { dest [i] = -0x80 ; | |
1186 | 1190 | continue ; |
1187 | 1191 | } ; |
1188 | dest [count] = psf_lrintf (scaled_value) ; | |
1192 | dest [i] = psf_lrintf (scaled_value) ; | |
1189 | 1193 | } ; |
1190 | 1194 | |
1191 | 1195 | return ; |
1197 | 1201 | |
1198 | 1202 | normfact = normalize ? (8.0 * 0x1000) : 1.0 ; |
1199 | 1203 | |
1200 | while (--count >= 0) | |
1201 | { scaled_value = src [count] * normfact ; | |
1204 | for (int i = 0 ; i < count ; i++) | |
1205 | { scaled_value = src [i] * normfact ; | |
1202 | 1206 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) |
1203 | { dest [count] = 0x7FFF ; | |
1207 | { dest [i] = 0x7FFF ; | |
1204 | 1208 | continue ; |
1205 | 1209 | } ; |
1206 | 1210 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) |
1207 | { dest [count] = -0x8000 ; | |
1211 | { dest [i] = -0x8000 ; | |
1208 | 1212 | continue ; |
1209 | 1213 | } ; |
1210 | dest [count] = psf_lrintf (scaled_value) ; | |
1214 | dest [i] = psf_lrintf (scaled_value) ; | |
1211 | 1215 | } ; |
1212 | 1216 | } /* f2flac16_clip_array */ |
1213 | 1217 | |
1217 | 1221 | |
1218 | 1222 | normfact = normalize ? (8.0 * 0x100000) : 1.0 ; |
1219 | 1223 | |
1220 | while (--count >= 0) | |
1221 | { scaled_value = src [count] * normfact ; | |
1224 | for (int i = 0 ; i < count ; i++) | |
1225 | { scaled_value = src [i] * normfact ; | |
1222 | 1226 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFF)) |
1223 | { dest [count] = 0x7FFFFF ; | |
1227 | { dest [i] = 0x7FFFFF ; | |
1224 | 1228 | continue ; |
1225 | 1229 | } ; |
1226 | 1230 | |
1227 | 1231 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000)) |
1228 | { dest [count] = -0x800000 ; | |
1232 | { dest [i] = -0x800000 ; | |
1229 | 1233 | continue ; |
1230 | 1234 | } |
1231 | dest [count] = psf_lrintf (scaled_value) ; | |
1235 | dest [i] = psf_lrintf (scaled_value) ; | |
1232 | 1236 | } ; |
1233 | 1237 | |
1234 | 1238 | return ; |
1238 | 1242 | f2flac8_array (const float *src, int32_t *dest, int count, int normalize) |
1239 | 1243 | { float normfact = normalize ? (1.0 * 0x7F) : 1.0 ; |
1240 | 1244 | |
1241 | while (--count >= 0) | |
1242 | dest [count] = psf_lrintf (src [count] * normfact) ; | |
1245 | for (int i = 0 ; i < count ; i++) | |
1246 | dest [i] = psf_lrintf (src [i] * normfact) ; | |
1243 | 1247 | } /* f2flac8_array */ |
1244 | 1248 | |
1245 | 1249 | static void |
1246 | 1250 | f2flac16_array (const float *src, int32_t *dest, int count, int normalize) |
1247 | 1251 | { float normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; |
1248 | 1252 | |
1249 | while (--count >= 0) | |
1250 | dest [count] = psf_lrintf (src [count] * normfact) ; | |
1253 | for (int i = 0 ; i < count ; i++) | |
1254 | dest [i] = psf_lrintf (src [i] * normfact) ; | |
1251 | 1255 | } /* f2flac16_array */ |
1252 | 1256 | |
1253 | 1257 | static void |
1254 | 1258 | f2flac24_array (const float *src, int32_t *dest, int count, int normalize) |
1255 | 1259 | { float normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; |
1256 | 1260 | |
1257 | while (--count >= 0) | |
1258 | dest [count] = psf_lrintf (src [count] * normfact) ; | |
1261 | for (int i = 0 ; i < count ; i++) | |
1262 | dest [i] = psf_lrintf (src [i] * normfact) ; | |
1259 | 1263 | } /* f2flac24_array */ |
1260 | 1264 | |
1261 | 1265 | static sf_count_t |
1306 | 1310 | |
1307 | 1311 | normfact = normalize ? (8.0 * 0x10) : 1.0 ; |
1308 | 1312 | |
1309 | while (--count >= 0) | |
1310 | { scaled_value = src [count] * normfact ; | |
1313 | for (int i = 0 ; i < count ; i++) | |
1314 | { scaled_value = src [i] * normfact ; | |
1311 | 1315 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7F)) |
1312 | { dest [count] = 0x7F ; | |
1316 | { dest [i] = 0x7F ; | |
1313 | 1317 | continue ; |
1314 | 1318 | } ; |
1315 | 1319 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10)) |
1316 | { dest [count] = -0x80 ; | |
1320 | { dest [i] = -0x80 ; | |
1317 | 1321 | continue ; |
1318 | 1322 | } ; |
1319 | dest [count] = psf_lrint (scaled_value) ; | |
1323 | dest [i] = psf_lrint (scaled_value) ; | |
1320 | 1324 | } ; |
1321 | 1325 | |
1322 | 1326 | return ; |
1328 | 1332 | |
1329 | 1333 | normfact = normalize ? (8.0 * 0x1000) : 1.0 ; |
1330 | 1334 | |
1331 | while (--count >= 0) | |
1332 | { scaled_value = src [count] * normfact ; | |
1335 | for (int i = 0 ; i < count ; i++) | |
1336 | { scaled_value = src [i] * normfact ; | |
1333 | 1337 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) |
1334 | { dest [count] = 0x7FFF ; | |
1338 | { dest [i] = 0x7FFF ; | |
1335 | 1339 | continue ; |
1336 | 1340 | } ; |
1337 | 1341 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) |
1338 | { dest [count] = -0x8000 ; | |
1342 | { dest [i] = -0x8000 ; | |
1339 | 1343 | continue ; |
1340 | 1344 | } ; |
1341 | dest [count] = psf_lrint (scaled_value) ; | |
1345 | dest [i] = psf_lrint (scaled_value) ; | |
1342 | 1346 | } ; |
1343 | 1347 | |
1344 | 1348 | return ; |
1350 | 1354 | |
1351 | 1355 | normfact = normalize ? (8.0 * 0x100000) : 1.0 ; |
1352 | 1356 | |
1353 | while (--count >= 0) | |
1354 | { scaled_value = src [count] * normfact ; | |
1357 | for (int i = 0 ; i < count ; i++) | |
1358 | { scaled_value = src [i] * normfact ; | |
1355 | 1359 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFF)) |
1356 | { dest [count] = 0x7FFFFF ; | |
1360 | { dest [i] = 0x7FFFFF ; | |
1357 | 1361 | continue ; |
1358 | 1362 | } ; |
1359 | 1363 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x100000)) |
1360 | { dest [count] = -0x800000 ; | |
1364 | { dest [i] = -0x800000 ; | |
1361 | 1365 | continue ; |
1362 | 1366 | } ; |
1363 | dest [count] = psf_lrint (scaled_value) ; | |
1367 | dest [i] = psf_lrint (scaled_value) ; | |
1364 | 1368 | } ; |
1365 | 1369 | |
1366 | 1370 | return ; |
1370 | 1374 | d2flac8_array (const double *src, int32_t *dest, int count, int normalize) |
1371 | 1375 | { double normfact = normalize ? (1.0 * 0x7F) : 1.0 ; |
1372 | 1376 | |
1373 | while (--count >= 0) | |
1374 | dest [count] = psf_lrint (src [count] * normfact) ; | |
1377 | for (int i = 0 ; i < count ; i++) | |
1378 | dest [i] = psf_lrint (src [i] * normfact) ; | |
1375 | 1379 | } /* d2flac8_array */ |
1376 | 1380 | |
1377 | 1381 | static void |
1378 | 1382 | d2flac16_array (const double *src, int32_t *dest, int count, int normalize) |
1379 | 1383 | { double normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; |
1380 | 1384 | |
1381 | while (--count >= 0) | |
1382 | dest [count] = psf_lrint (src [count] * normfact) ; | |
1385 | for (int i = 0 ; i < count ; i++) | |
1386 | dest [i] = psf_lrint (src [i] * normfact) ; | |
1383 | 1387 | } /* d2flac16_array */ |
1384 | 1388 | |
1385 | 1389 | static void |
1386 | 1390 | d2flac24_array (const double *src, int32_t *dest, int count, int normalize) |
1387 | 1391 | { double normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; |
1388 | 1392 | |
1389 | while (--count >= 0) | |
1390 | dest [count] = psf_lrint (src [count] * normfact) ; | |
1393 | for (int i = 0 ; i < count ; i++) | |
1394 | dest [i] = psf_lrint (src [i] * normfact) ; | |
1391 | 1395 | } /* d2flac24_array */ |
1392 | 1396 | |
1393 | 1397 | static sf_count_t |
436 | 436 | static void |
437 | 437 | f2s_array (const float *src, int count, short *dest, float scale) |
438 | 438 | { |
439 | while (--count >= 0) | |
440 | { dest [count] = psf_lrintf (scale * src [count]) ; | |
439 | for (int i = 0 ; i < count ; i++) | |
440 | { dest [i] = psf_lrintf (scale * src [i]) ; | |
441 | 441 | } ; |
442 | 442 | } /* f2s_array */ |
443 | 443 | |
444 | 444 | static void |
445 | 445 | f2s_clip_array (const float *src, int count, short *dest, float scale) |
446 | { while (--count >= 0) | |
447 | { float tmp = scale * src [count] ; | |
446 | { for (int i = 0 ; i < count ; i++) | |
447 | { float tmp = scale * src [i] ; | |
448 | 448 | |
449 | 449 | if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0) |
450 | dest [count] = SHRT_MAX ; | |
450 | dest [i] = SHRT_MAX ; | |
451 | 451 | else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0) |
452 | dest [count] = SHRT_MIN ; | |
452 | dest [i] = SHRT_MIN ; | |
453 | 453 | else |
454 | dest [count] = psf_lrintf (tmp) ; | |
454 | dest [i] = psf_lrintf (tmp) ; | |
455 | 455 | } ; |
456 | 456 | } /* f2s_clip_array */ |
457 | 457 | |
458 | 458 | static inline void |
459 | 459 | f2i_array (const float *src, int count, int *dest, float scale) |
460 | { while (--count >= 0) | |
461 | { dest [count] = psf_lrintf (scale * src [count]) ; | |
460 | { for (int i = 0 ; i < count ; i++) | |
461 | { dest [i] = psf_lrintf (scale * src [i]) ; | |
462 | 462 | } ; |
463 | 463 | } /* f2i_array */ |
464 | 464 | |
465 | 465 | static inline void |
466 | 466 | f2i_clip_array (const float *src, int count, int *dest, float scale) |
467 | { while (--count >= 0) | |
468 | { float tmp = scale * src [count] ; | |
467 | { for (int i = 0 ; i < count ; i++) | |
468 | { float tmp = scale * src [i] ; | |
469 | 469 | |
470 | 470 | if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX)) |
471 | dest [count] = INT_MAX ; | |
471 | dest [i] = INT_MAX ; | |
472 | 472 | else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX)) |
473 | dest [count] = INT_MIN ; | |
473 | dest [i] = INT_MIN ; | |
474 | 474 | else |
475 | dest [count] = psf_lrintf (tmp) ; | |
475 | dest [i] = psf_lrintf (tmp) ; | |
476 | 476 | } ; |
477 | 477 | } /* f2i_clip_array */ |
478 | 478 | |
479 | 479 | static inline void |
480 | 480 | f2d_array (const float *src, int count, double *dest) |
481 | { while (--count >= 0) | |
482 | { dest [count] = src [count] ; | |
481 | { for (int i = 0 ; i < count ; i++) | |
482 | { dest [i] = src [i] ; | |
483 | 483 | } ; |
484 | 484 | } /* f2d_array */ |
485 | 485 | |
486 | 486 | static inline void |
487 | 487 | s2f_array (const short *src, float *dest, int count, float scale) |
488 | { while (--count >= 0) | |
489 | { dest [count] = scale * src [count] ; | |
488 | { for (int i = 0 ; i < count ; i++) | |
489 | { dest [i] = scale * src [i] ; | |
490 | 490 | } ; |
491 | 491 | } /* s2f_array */ |
492 | 492 | |
493 | 493 | static inline void |
494 | 494 | i2f_array (const int *src, float *dest, int count, float scale) |
495 | { while (--count >= 0) | |
496 | { dest [count] = scale * src [count] ; | |
495 | { for (int i = 0 ; i < count ; i++) | |
496 | { dest [i] = scale * src [i] ; | |
497 | 497 | } ; |
498 | 498 | } /* i2f_array */ |
499 | 499 | |
500 | 500 | static inline void |
501 | 501 | d2f_array (const double *src, float *dest, int count) |
502 | { while (--count >= 0) | |
503 | { dest [count] = src [count] ; | |
502 | { for (int i = 0 ; i < count ; i++) | |
503 | { dest [i] = src [i] ; | |
504 | 504 | } ; |
505 | 505 | } /* d2f_array */ |
506 | 506 | |
522 | 522 | while (len > 0) |
523 | 523 | { if (len < bufferlen) |
524 | 524 | bufferlen = (int) len ; |
525 | readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
525 | readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
526 | 526 | |
527 | 527 | /* Fix me : Need lef2s_array */ |
528 | 528 | if (psf->data_endswap == SF_TRUE) |
553 | 553 | while (len > 0) |
554 | 554 | { if (len < bufferlen) |
555 | 555 | bufferlen = (int) len ; |
556 | readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
556 | readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
557 | 557 | |
558 | 558 | if (psf->data_endswap == SF_TRUE) |
559 | 559 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
582 | 582 | while (len > 0) |
583 | 583 | { if (len < bufferlen) |
584 | 584 | bufferlen = (int) len ; |
585 | readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
585 | readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
586 | 586 | |
587 | 587 | endswap_int_copy ((int*) (ptr + total), ubuf.ibuf, readcount) ; |
588 | 588 | |
606 | 606 | while (len > 0) |
607 | 607 | { if (len < bufferlen) |
608 | 608 | bufferlen = (int) len ; |
609 | readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
609 | readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
610 | 610 | |
611 | 611 | if (psf->data_endswap == SF_TRUE) |
612 | 612 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
644 | 644 | if (psf->data_endswap == SF_TRUE) |
645 | 645 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
646 | 646 | |
647 | writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
647 | writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
648 | 648 | total += writecount ; |
649 | 649 | if (writecount < bufferlen) |
650 | 650 | break ; |
675 | 675 | if (psf->data_endswap == SF_TRUE) |
676 | 676 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
677 | 677 | |
678 | writecount = psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ; | |
678 | writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ; | |
679 | 679 | total += writecount ; |
680 | 680 | if (writecount < bufferlen) |
681 | 681 | break ; |
705 | 705 | |
706 | 706 | endswap_int_copy (ubuf.ibuf, (const int*) (ptr + total), bufferlen) ; |
707 | 707 | |
708 | writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
708 | writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
709 | 709 | total += writecount ; |
710 | 710 | if (writecount < bufferlen) |
711 | 711 | break ; |
735 | 735 | if (psf->data_endswap == SF_TRUE) |
736 | 736 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
737 | 737 | |
738 | writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
738 | writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
739 | 739 | total += writecount ; |
740 | 740 | if (writecount < bufferlen) |
741 | 741 | break ; |
761 | 761 | while (len > 0) |
762 | 762 | { if (len < bufferlen) |
763 | 763 | bufferlen = (int) len ; |
764 | readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
764 | readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
765 | 765 | |
766 | 766 | if (psf->data_endswap == SF_TRUE) |
767 | 767 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
786 | 786 | float scale ; |
787 | 787 | |
788 | 788 | bufferlen = ARRAY_LEN (ubuf.fbuf) ; |
789 | scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ; | |
790 | ||
791 | while (len > 0) | |
792 | { if (len < bufferlen) | |
793 | bufferlen = (int) len ; | |
794 | readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
789 | scale = (psf->float_int_mult == 0) ? 1.0 : 2147483648.0f / psf->float_max ; | |
790 | ||
791 | while (len > 0) | |
792 | { if (len < bufferlen) | |
793 | bufferlen = (int) len ; | |
794 | readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
795 | 795 | |
796 | 796 | if (psf->data_endswap == SF_TRUE) |
797 | 797 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
821 | 821 | while (len > 0) |
822 | 822 | { if (len < bufferlen) |
823 | 823 | bufferlen = (int) len ; |
824 | readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
824 | readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
825 | 825 | |
826 | 826 | if (psf->data_endswap == SF_TRUE) |
827 | 827 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
850 | 850 | while (len > 0) |
851 | 851 | { if (len < bufferlen) |
852 | 852 | bufferlen = (int) len ; |
853 | readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
853 | readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
854 | 854 | |
855 | 855 | if (psf->data_endswap == SF_TRUE) |
856 | 856 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
890 | 890 | if (psf->data_endswap == SF_TRUE) |
891 | 891 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
892 | 892 | |
893 | writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
893 | writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
894 | 894 | total += writecount ; |
895 | 895 | if (writecount < bufferlen) |
896 | 896 | break ; |
923 | 923 | if (psf->data_endswap == SF_TRUE) |
924 | 924 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
925 | 925 | |
926 | writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
926 | writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
927 | 927 | total += writecount ; |
928 | 928 | if (writecount < bufferlen) |
929 | 929 | break ; |
956 | 956 | if (psf->data_endswap == SF_TRUE) |
957 | 957 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
958 | 958 | |
959 | writecount = psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ; | |
959 | writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ; | |
960 | 960 | total += writecount ; |
961 | 961 | if (writecount < bufferlen) |
962 | 962 | break ; |
987 | 987 | if (psf->data_endswap == SF_TRUE) |
988 | 988 | endswap_int_array (ubuf.ibuf, bufferlen) ; |
989 | 989 | |
990 | writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
990 | writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ; | |
991 | 991 | total += writecount ; |
992 | 992 | if (writecount < bufferlen) |
993 | 993 | break ; |
1002 | 1002 | |
1003 | 1003 | static void |
1004 | 1004 | bf2f_array (float *buffer, int count) |
1005 | { while (--count >= 0) | |
1006 | { buffer [count] = FLOAT32_READ ((unsigned char *) (buffer + count)) ; | |
1005 | { for (int i = 0 ; i < count ; i++) | |
1006 | { buffer [i] = FLOAT32_READ ((unsigned char *) &buffer [i]) ; | |
1007 | 1007 | } ; |
1008 | 1008 | } /* bf2f_array */ |
1009 | 1009 | |
1010 | 1010 | static void |
1011 | 1011 | f2bf_array (float *buffer, int count) |
1012 | { while (--count >= 0) | |
1013 | { FLOAT32_WRITE (buffer [count], (unsigned char*) (buffer + count)) ; | |
1012 | { for (int i = 0 ; i < count ; i++) | |
1013 | { FLOAT32_WRITE (buffer [i], (unsigned char*) &buffer [i]) ; | |
1014 | 1014 | } ; |
1015 | 1015 | } /* f2bf_array */ |
1016 | 1016 |
263 | 263 | sptr = ubuf.sbuf ; |
264 | 264 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
265 | 265 | while (len > 0) |
266 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
266 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
267 | 267 | count = g72x_read_block (psf, pg72x, sptr, readcount) ; |
268 | 268 | |
269 | 269 | for (k = 0 ; k < readcount ; k++) |
296 | 296 | sptr = ubuf.sbuf ; |
297 | 297 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
298 | 298 | while (len > 0) |
299 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
299 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
300 | 300 | count = g72x_read_block (psf, pg72x, sptr, readcount) ; |
301 | 301 | for (k = 0 ; k < readcount ; k++) |
302 | 302 | ptr [total + k] = normfact * sptr [k] ; |
328 | 328 | sptr = ubuf.sbuf ; |
329 | 329 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
330 | 330 | while (len > 0) |
331 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
331 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
332 | 332 | count = g72x_read_block (psf, pg72x, sptr, readcount) ; |
333 | 333 | for (k = 0 ; k < readcount ; k++) |
334 | 334 | ptr [total + k] = normfact * (double) (sptr [k]) ; |
504 | 504 | sptr = ubuf.sbuf ; |
505 | 505 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
506 | 506 | while (len > 0) |
507 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
507 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
508 | 508 | for (k = 0 ; k < writecount ; k++) |
509 | 509 | sptr [k] = ptr [total + k] >> 16 ; |
510 | 510 | count = g72x_write_block (psf, pg72x, sptr, writecount) ; |
535 | 535 | sptr = ubuf.sbuf ; |
536 | 536 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
537 | 537 | while (len > 0) |
538 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
538 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
539 | 539 | for (k = 0 ; k < writecount ; k++) |
540 | 540 | sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; |
541 | 541 | count = g72x_write_block (psf, pg72x, sptr, writecount) ; |
567 | 567 | sptr = ubuf.sbuf ; |
568 | 568 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
569 | 569 | while (len > 0) |
570 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
570 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
571 | 571 | for (k = 0 ; k < writecount ; k++) |
572 | 572 | sptr [k] = psf_lrint (normfact * ptr [total + k]) ; |
573 | 573 | count = g72x_write_block (psf, pg72x, sptr, writecount) ; |
197 | 197 | return 1 ; |
198 | 198 | } ; |
199 | 199 | |
200 | if ((k = psf_fread (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE) | |
200 | if ((k = (int) psf_fread (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE) | |
201 | 201 | psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, WAVLIKE_GSM610_BLOCKSIZE) ; |
202 | 202 | |
203 | 203 | if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0) |
225 | 225 | return 1 ; |
226 | 226 | } ; |
227 | 227 | |
228 | if ((k = psf_fread (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) | |
228 | if ((k = (int) psf_fread (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) | |
229 | 229 | psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, GSM610_BLOCKSIZE) ; |
230 | 230 | |
231 | 231 | if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0) |
301 | 301 | sptr = ubuf.sbuf ; |
302 | 302 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
303 | 303 | while (len > 0) |
304 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
304 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
305 | 305 | count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; |
306 | 306 | for (k = 0 ; k < readcount ; k++) |
307 | 307 | ptr [total + k] = arith_shift_left (sptr [k], 16) ; |
330 | 330 | sptr = ubuf.sbuf ; |
331 | 331 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
332 | 332 | while (len > 0) |
333 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
333 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
334 | 334 | count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; |
335 | 335 | for (k = 0 ; k < readcount ; k++) |
336 | 336 | ptr [total + k] = normfact * sptr [k] ; |
359 | 359 | sptr = ubuf.sbuf ; |
360 | 360 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
361 | 361 | while (len > 0) |
362 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
362 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
363 | 363 | count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; |
364 | 364 | for (k = 0 ; k < readcount ; k++) |
365 | 365 | ptr [total + k] = normfact * sptr [k] ; |
436 | 436 | gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ; |
437 | 437 | |
438 | 438 | /* Write the block to disk. */ |
439 | if ((k = psf_fwrite (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) | |
439 | if ((k = (int) psf_fwrite (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) | |
440 | 440 | psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, GSM610_BLOCKSIZE) ; |
441 | 441 | |
442 | 442 | pgsm610->samplecount = 0 ; |
457 | 457 | gsm_encode (pgsm610->gsm_data, pgsm610->samples+WAVLIKE_GSM610_SAMPLES / 2, pgsm610->block+WAVLIKE_GSM610_BLOCKSIZE / 2) ; |
458 | 458 | |
459 | 459 | /* Write the block to disk. */ |
460 | if ((k = psf_fwrite (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE) | |
460 | if ((k = (int) psf_fwrite (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE) | |
461 | 461 | psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, WAVLIKE_GSM610_BLOCKSIZE) ; |
462 | 462 | |
463 | 463 | pgsm610->samplecount = 0 ; |
531 | 531 | sptr = ubuf.sbuf ; |
532 | 532 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
533 | 533 | while (len > 0) |
534 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
534 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
535 | 535 | for (k = 0 ; k < writecount ; k++) |
536 | 536 | sptr [k] = ptr [total + k] >> 16 ; |
537 | 537 | count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; |
560 | 560 | sptr = ubuf.sbuf ; |
561 | 561 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
562 | 562 | while (len > 0) |
563 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
563 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
564 | 564 | for (k = 0 ; k < writecount ; k++) |
565 | 565 | sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; |
566 | 566 | count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; |
591 | 591 | sptr = ubuf.sbuf ; |
592 | 592 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
593 | 593 | while (len > 0) |
594 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
594 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
595 | 595 | for (k = 0 ; k < writecount ; k++) |
596 | 596 | sptr [k] = psf_lrint (normfact * ptr [total + k]) ; |
597 | 597 | count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; |
25 | 25 | #include "sndfile.h" |
26 | 26 | #include "sfendian.h" |
27 | 27 | #include "common.h" |
28 | #include "id3.h" | |
29 | ||
30 | #if HAVE_MPEG | |
31 | #include <lame/lame.h> | |
32 | ||
33 | struct id3v1_genre_handler_userdata | |
34 | { int number ; | |
35 | const char *ret ; | |
36 | } ; | |
37 | ||
38 | static void | |
39 | id3v1_genre_handler (int number, const char *description, void *userdata) | |
40 | { struct id3v1_genre_handler_userdata *data = (struct id3v1_genre_handler_userdata *) userdata ; | |
41 | if (data->number == number) | |
42 | data->ret = description ; | |
43 | } | |
44 | ||
45 | const char * | |
46 | id3_lookup_v1_genre (int number) | |
47 | { struct id3v1_genre_handler_userdata data ; | |
48 | ||
49 | data.number = number ; | |
50 | data.ret = NULL ; | |
51 | id3tag_genre_list (id3v1_genre_handler, &data) ; | |
52 | ||
53 | return data.ret ; | |
54 | } | |
55 | ||
56 | #else /* HAVE_MPEG */ | |
57 | ||
58 | const char * | |
59 | id3_lookup_v1_genre (int UNUSED (number)) | |
60 | { return NULL ; | |
61 | } | |
62 | ||
63 | #endif | |
28 | 64 | |
29 | 65 | int |
30 | 66 | id3_skip (SF_PRIVATE * psf) |
31 | 67 | { unsigned char buf [10] ; |
68 | int offset ; | |
32 | 69 | |
33 | 70 | memset (buf, 0, sizeof (buf)) ; |
34 | 71 | psf_binheader_readf (psf, "pb", 0, buf, 10) ; |
35 | 72 | |
36 | 73 | if (buf [0] == 'I' && buf [1] == 'D' && buf [2] == '3') |
37 | { int offset = buf [6] & 0x7f ; | |
74 | { psf->id3_header.minor_version = buf [3] ; | |
75 | offset = buf [6] & 0x7f ; | |
38 | 76 | offset = (offset << 7) | (buf [7] & 0x7f) ; |
39 | 77 | offset = (offset << 7) | (buf [8] & 0x7f) ; |
40 | 78 | offset = (offset << 7) | (buf [9] & 0x7f) ; |
41 | 79 | |
42 | psf_log_printf (psf, "ID3 length : %d\n--------------------\n", offset) ; | |
80 | /* | |
81 | ** ID3 count field is how many bytes of ID3v2 header FOLLOW the ten | |
82 | ** bytes of header magic and offset, NOT the total ID3v2 header len. | |
83 | */ | |
84 | psf->id3_header.len = offset + 10 ; | |
85 | psf->id3_header.offset = psf->fileoffset ; | |
86 | ||
87 | psf_log_printf (psf, " ID3v2.%d header length : %d\n----------------------------------------\n", | |
88 | psf->id3_header.minor_version, psf->id3_header.len) ; | |
43 | 89 | |
44 | 90 | /* Never want to jump backwards in a file. */ |
45 | 91 | if (offset < 0) |
46 | 92 | return 0 ; |
47 | 93 | |
48 | /* Calculate new file offset and position ourselves there. */ | |
49 | offset += 10 ; | |
50 | if (psf->fileoffset + offset < psf->filelength) | |
51 | { psf_binheader_readf (psf, "p", offset) ; | |
52 | psf->fileoffset += offset ; | |
94 | /* Position ourselves at the new file offset. */ | |
95 | if (psf->fileoffset + psf->id3_header.len < psf->filelength) | |
96 | { psf_binheader_readf (psf, "p!", psf->id3_header.len) ; | |
97 | psf->fileoffset += psf->id3_header.len ; | |
53 | 98 | return 1 ; |
54 | 99 | } ; |
55 | 100 | } ; |
56 | 101 | |
57 | 102 | return 0 ; |
58 | 103 | } /* id3_skip */ |
104 | ||
105 | const char * | |
106 | id3_process_v2_genre (const char *genre) | |
107 | { int num = 0 ; | |
108 | char c ; | |
109 | const char *ptr ; | |
110 | ||
111 | if (!genre) | |
112 | return NULL ; | |
113 | ||
114 | /* | |
115 | ** Genre may require more processing. | |
116 | ** | |
117 | ** It is allowed to have numeric references to the genre table from ID3v1. | |
118 | ** We'll just convert the simple case here, strings of the format "(nnn)". | |
119 | */ | |
120 | ptr = genre ; | |
121 | if (ptr [0] == '(' && (c = *++ ptr) && isdigit (c)) | |
122 | { num = c - '0' ; | |
123 | while ((c == *++ ptr) && isdigit (c)) | |
124 | num = num * 10 + (c - '0') ; | |
125 | if (c == ')' && (c = *++ ptr) == '\0' && num < 256) | |
126 | if ((ptr = id3_lookup_v1_genre (num))) | |
127 | return ptr ; | |
128 | } ; | |
129 | ||
130 | return genre ; | |
131 | } /* id3_process_v2_genre */ |
0 | /* | |
1 | ** Copyright (C) 2008-2019 Erik de Castro Lopo <erikd@mega-nerd.com> | |
2 | ** Copyright (C) 2019 Arthur Taylor <art@ified.ca> | |
3 | ** | |
4 | ** This program is free software ; you can redistribute it and/or modify | |
5 | ** it under the terms of the GNU Lesser General Public License as published by | |
6 | ** the Free Software Foundation ; either version 2.1 of the License, or | |
7 | ** (at your option) any later version. | |
8 | ** | |
9 | ** This program is distributed in the hope that it will be useful, | |
10 | ** but WITHOUT ANY WARRANTY ; without even the implied warranty of | |
11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | ** GNU Lesser General Public License for more details. | |
13 | ** | |
14 | ** You should have received a copy of the GNU Lesser General Public License | |
15 | ** along with this program ; if not, write to the Free Software | |
16 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
17 | */ | |
18 | ||
19 | #ifndef SF_SRC_ID3_H | |
20 | #define SF_SRC_ID3_H | |
21 | ||
22 | int id3_skip (SF_PRIVATE * psf) ; | |
23 | ||
24 | const char *id3_lookup_v1_genre (int number) ; | |
25 | ||
26 | const char *id3_process_v2_genre (const char *genre) ; | |
27 | ||
28 | #endif /* SF_SRC_ID3_H */ |
181 | 181 | if (psf->file.mode != SFM_READ) |
182 | 182 | return SFE_BAD_MODE_RW ; |
183 | 183 | |
184 | pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign * psf->sf.channels + 3 * psf->sf.channels * samplesperblock ; | |
184 | /* | |
185 | ** Allocate enough space for 1 more than a multiple of 8 samples | |
186 | ** to avoid having to branch when pulling apart the nibbles. | |
187 | */ | |
188 | count = ((samplesperblock - 2) | 7) + 2 ; | |
189 | pimasize = sizeof (IMA_ADPCM_PRIVATE) + psf->sf.channels * (blockalign + samplesperblock + sizeof(short) * count) ; | |
185 | 190 | |
186 | 191 | if (! (pima = calloc (1, pimasize))) |
187 | 192 | return SFE_MALLOC_FAILED ; |
267 | 272 | return 1 ; |
268 | 273 | } ; |
269 | 274 | |
270 | if ((k = psf_fread (pima->block, 1, pima->blocksize * pima->channels, psf)) != pima->blocksize * pima->channels) | |
275 | if ((k = (int) psf_fread (pima->block, 1, pima->blocksize * pima->channels, psf)) != pima->blocksize * pima->channels) | |
271 | 276 | psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ; |
272 | 277 | |
273 | 278 | /* Read and check the block header. */ |
372 | 377 | } ; |
373 | 378 | |
374 | 379 | /* Write the block to disk. */ |
375 | if ((k = psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize) | |
380 | if ((k = (int) psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize) | |
376 | 381 | psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->channels * pima->blocksize) ; |
377 | 382 | |
378 | 383 | memset (pima->block, 0, pima->channels * pima->blocksize) ; |
385 | 390 | static int |
386 | 391 | wavlike_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) |
387 | 392 | { int chan, k, predictor, blockindx, indx, indxstart, diff ; |
388 | short step, bytecode, stepindx [2] ; | |
393 | short step, bytecode, stepindx [2] = { 0 }; | |
389 | 394 | |
390 | 395 | pima->blockcount ++ ; |
391 | 396 | pima->samplecount = 0 ; |
395 | 400 | return 1 ; |
396 | 401 | } ; |
397 | 402 | |
398 | if ((k = psf_fread (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) | |
403 | if ((k = (int) psf_fread (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) | |
399 | 404 | psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ; |
400 | 405 | |
401 | 406 | /* Read and check the block header. */ |
551 | 556 | |
552 | 557 | /* Write the block to disk. */ |
553 | 558 | |
554 | if ((k = psf_fwrite (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) | |
559 | if ((k = (int) psf_fwrite (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) | |
555 | 560 | psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->blocksize) ; |
556 | 561 | |
557 | 562 | memset (pima->samples, 0, pima->samplesperblock * sizeof (short)) ; |
45 | 45 | #define HEADER_LENGTH 42 /* Sum of above data fields. */ |
46 | 46 | #define HEADER_NAME_LEN 17 /* Length of name string. */ |
47 | 47 | |
48 | #define SFE_MPC_NO_MARKER 666 | |
49 | ||
50 | 48 | /*------------------------------------------------------------------------------ |
51 | 49 | ** Private static functions. |
52 | 50 | */ |
130 | 128 | if (psf->is_pipe == SF_FALSE) |
131 | 129 | psf_fseek (psf, 0, SEEK_SET) ; |
132 | 130 | |
133 | snprintf (sample_name, sizeof (sample_name), "%-*.*s", HEADER_NAME_LEN, HEADER_NAME_LEN, psf->file.name.c) ; | |
131 | snprintf (sample_name, sizeof (sample_name), "%-*.*s", HEADER_NAME_LEN, HEADER_NAME_LEN, psf->file.name) ; | |
134 | 132 | |
135 | 133 | psf_binheader_writef (psf, "e11b", BHW1 (1), BHW1 (4), BHWv (sample_name), BHWz (HEADER_NAME_LEN)) ; |
136 | 134 | psf_binheader_writef (psf, "e111", BHW1 (100), BHW1 (0), BHW1 ((psf->sf.channels - 1) & 1)) ; |
0 | /* | |
1 | ** Copyright (C) 2019 Erik de Castro Lopo <erikd@mega-nerd.com> | |
2 | ** Copyright (C) 2021 Arthur Taylor <art@ified.ca> | |
3 | ** | |
4 | ** This program is free software ; you can redistribute it and/or modify | |
5 | ** it under the terms of the GNU Lesser General Public License as published by | |
6 | ** the Free Software Foundation ; either version 2.1 of the License, or | |
7 | ** (at your option) any later version. | |
8 | ** | |
9 | ** This program is distributed in the hope that it will be useful, | |
10 | ** but WITHOUT ANY WARRANTY ; without even the implied warranty of | |
11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | ** GNU Lesser General Public License for more details. | |
13 | ** | |
14 | ** You should have received a copy of the GNU Lesser General Public License | |
15 | ** along with this program ; if not, write to the Free Software | |
16 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
17 | */ | |
18 | ||
19 | #include "sfconfig.h" | |
20 | ||
21 | #include "sndfile.h" | |
22 | #include "common.h" | |
23 | ||
24 | #if HAVE_MPEG | |
25 | ||
26 | #include "mpeg.h" | |
27 | ||
28 | static int mpeg_write_header (SF_PRIVATE *psf, int calc_length) ; | |
29 | static int mpeg_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; | |
30 | ||
31 | /*------------------------------------------------------------------------------ | |
32 | * Private functions | |
33 | */ | |
34 | ||
35 | static int | |
36 | mpeg_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) | |
37 | { | |
38 | if (psf->have_written) | |
39 | return 0 ; | |
40 | ||
41 | return mpeg_l3_encoder_write_id3tag (psf) ; | |
42 | } | |
43 | ||
44 | static int | |
45 | mpeg_command (SF_PRIVATE *psf, int command, void *data, int datasize) | |
46 | { int bitrate_mode ; | |
47 | ||
48 | switch (command) | |
49 | { case SFC_SET_COMPRESSION_LEVEL : | |
50 | if (data == NULL || datasize != sizeof (double)) | |
51 | { psf->error = SFE_BAD_COMMAND_PARAM ; | |
52 | return SF_FALSE ; | |
53 | } ; | |
54 | if (psf->file.mode != SFM_WRITE) | |
55 | { psf->error = SFE_NOT_WRITEMODE ; | |
56 | return SF_FALSE ; | |
57 | } ; | |
58 | return mpeg_l3_encoder_set_quality (psf, *(double *) data) ; | |
59 | ||
60 | case SFC_SET_BITRATE_MODE : | |
61 | if (psf->file.mode != SFM_WRITE) | |
62 | { psf->error = SFE_NOT_WRITEMODE ; | |
63 | return SF_FALSE ; | |
64 | } ; | |
65 | if (data == NULL || datasize != sizeof (int)) | |
66 | { psf->error = SFE_BAD_COMMAND_PARAM ; | |
67 | return SF_FALSE ; | |
68 | } ; | |
69 | bitrate_mode = *(int *) data ; | |
70 | return mpeg_l3_encoder_set_bitrate_mode (psf, bitrate_mode) ; | |
71 | ||
72 | case SFC_GET_BITRATE_MODE : | |
73 | if (psf->file.mode == SFM_READ) | |
74 | return mpeg_decoder_get_bitrate_mode (psf) ; | |
75 | else | |
76 | return mpeg_l3_encoder_get_bitrate_mode (psf) ; | |
77 | ||
78 | default : | |
79 | return SF_FALSE ; | |
80 | } ; | |
81 | ||
82 | return SF_FALSE ; | |
83 | } /* mpeg_command */ | |
84 | ||
85 | /*------------------------------------------------------------------------------ | |
86 | * Public functions | |
87 | */ | |
88 | ||
89 | int | |
90 | mpeg_init (SF_PRIVATE *psf, int bitrate_mode, int write_metadata) | |
91 | { int error ; | |
92 | ||
93 | if (psf->file.mode == SFM_RDWR) | |
94 | return SFE_BAD_MODE_RW ; | |
95 | ||
96 | if (psf->file.mode == SFM_WRITE) | |
97 | { switch (SF_CODEC (psf->sf.format)) | |
98 | { case SF_FORMAT_MPEG_LAYER_III : | |
99 | if ((error = mpeg_l3_encoder_init (psf, write_metadata))) | |
100 | return error ; | |
101 | mpeg_l3_encoder_set_bitrate_mode (psf, bitrate_mode) ; | |
102 | if (write_metadata) | |
103 | { /* ID3 support */ | |
104 | psf->strings.flags = SF_STR_ALLOW_START ; | |
105 | psf->write_header = mpeg_write_header ; | |
106 | } ; | |
107 | break ; | |
108 | ||
109 | case SF_FORMAT_MPEG_LAYER_I : | |
110 | case SF_FORMAT_MPEG_LAYER_II : | |
111 | psf_log_printf (psf, "MPEG Layer I and II encoding is not yet supported.\n") ; | |
112 | return SFE_UNIMPLEMENTED ; | |
113 | ||
114 | default: | |
115 | psf_log_printf (psf, "%s: bad psf->sf.format 0x%x.\n", __func__, psf->sf.format) ; | |
116 | return SFE_INTERNAL ; | |
117 | } ; | |
118 | } ; | |
119 | ||
120 | if (psf->file.mode == SFM_READ) | |
121 | { if ((error = mpeg_decoder_init (psf))) | |
122 | return error ; | |
123 | } ; | |
124 | ||
125 | return 0 ; | |
126 | } /* mpeg_init */ | |
127 | ||
128 | int | |
129 | mpeg_open (SF_PRIVATE *psf) | |
130 | { int error ; | |
131 | ||
132 | /* Choose variable bitrate mode by default for standalone files.*/ | |
133 | if ((error = mpeg_init (psf, SF_BITRATE_MODE_VARIABLE, SF_TRUE))) | |
134 | return error ; | |
135 | ||
136 | psf->dataoffset = 0 ; | |
137 | psf->command = mpeg_command ; | |
138 | ||
139 | if (psf->filelength != SF_COUNT_MAX) | |
140 | psf->datalength = psf->filelength - psf->dataoffset ; | |
141 | else | |
142 | psf->datalength = SF_COUNT_MAX ; | |
143 | ||
144 | ||
145 | return 0 ; | |
146 | } /* mpeg_open */ | |
147 | ||
148 | #else /* HAVE_MPEG */ | |
149 | ||
150 | int | |
151 | mpeg_init (SF_PRIVATE *psf, int UNUSED (bitrate_mode) , int UNUSED (write_metadata)) | |
152 | { | |
153 | psf_log_printf (psf, "This version of libsndfile was compiled without MPEG support.\n") ; | |
154 | return SFE_UNIMPLEMENTED ; | |
155 | } /* mpeg_init */ | |
156 | ||
157 | int | |
158 | mpeg_open (SF_PRIVATE *psf) | |
159 | { | |
160 | psf_log_printf (psf, "This version of libsndfile was compiled without MP3 support.\n") ; | |
161 | return SFE_UNIMPLEMENTED ; | |
162 | } /* mpeg_open */ | |
163 | ||
164 | #endif |
0 | /* | |
1 | ** Copyright (C) 2019 Erik de Castro Lopo <erikd@mega-nerd.com> | |
2 | ** Copyright (C) 2019 Arthur Taylor <art@ified.ca> | |
3 | ** | |
4 | ** This program is free software ; you can redistribute it and/or modify | |
5 | ** it under the terms of the GNU Lesser General Public License as published by | |
6 | ** the Free Software Foundation ; either version 2.1 of the License, or | |
7 | ** (at your option) any later version. | |
8 | ** | |
9 | ** This program is distributed in the hope that it will be useful, | |
10 | ** but WITHOUT ANY WARRANTY ; without even the implied warranty of | |
11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | ** GNU Lesser General Public License for more details. | |
13 | ** | |
14 | ** You should have received a copy of the GNU Lesser General Public License | |
15 | ** along with this program ; if not, write to the Free Software | |
16 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
17 | */ | |
18 | ||
19 | #ifndef SNDFILE_MPEG_H | |
20 | #define SNDFILE_MPEG_H | |
21 | ||
22 | #include "common.h" | |
23 | ||
24 | int mpeg_decoder_init (SF_PRIVATE *psf) ; | |
25 | ||
26 | /* | |
27 | ** Get the file bitrate mode, returning one of the SF_BITRATE_MODE_ enum | |
28 | ** values. Purely informative, 'Frankenstein' files and VBR files without an | |
29 | ** Xing/LAME/Info header may not be detected properly. | |
30 | */ | |
31 | int mpeg_decoder_get_bitrate_mode (SF_PRIVATE *psf) ; | |
32 | ||
33 | ||
34 | /* | |
35 | ** Initialize an encoder instance for writing. If parameter info_tag is | |
36 | ** SF_TRUE, a Xing/LAME/Info header is written at the beginning of the file, | |
37 | ** (unless the file cannot seek.) | |
38 | */ | |
39 | int mpeg_l3_encoder_init (SF_PRIVATE *psf, int info_tag) ; | |
40 | ||
41 | ||
42 | /* | |
43 | ** Write an ID3v2 header from the sndfile string metadata. Must be called | |
44 | ** before any audio data is written. Writing an ID3v2 header will also cause | |
45 | ** a ID3v1 trailer to be written on close automatically. | |
46 | */ | |
47 | int mpeg_l3_encoder_write_id3tag (SF_PRIVATE *psf) ; | |
48 | ||
49 | /* | |
50 | ** Set the encoder quality setting. Argument to compression should be identical | |
51 | ** to that for SFC_SET_COMPRESSION_LEVEL; It should be in the range [0-1], | |
52 | ** with 0 being highest quality, least compression, and 1 being the opposite. | |
53 | ** Returns SF_TRUE on success, SF_FALSE otherwise. | |
54 | */ | |
55 | int mpeg_l3_encoder_set_quality (SF_PRIVATE *psf, double compression) ; | |
56 | ||
57 | /* | |
58 | ** Set the encoder bitrate mode. Can only be called before any data has been | |
59 | ** written. Argument mode should be one of the SF_BITRATE_MODE_ enum values. | |
60 | ** Returns SF_TRUE on success, SF_FALSE otherwise. The SF_BITRATE_MODE_FILE | |
61 | ** enum value should not be passed here but rather intercepted at the container | |
62 | ** level and translated according to the container. | |
63 | */ | |
64 | int mpeg_l3_encoder_set_bitrate_mode (SF_PRIVATE *psf, int mode) ; | |
65 | ||
66 | /* | |
67 | ** Get the encoder bitrate mode in use. Returns a SF_BITRATE_MODE_ enum value. | |
68 | ** Will not return SF_BITRATE_MODE_FILE. | |
69 | */ | |
70 | int mpeg_l3_encoder_get_bitrate_mode (SF_PRIVATE *psf) ; | |
71 | ||
72 | ||
73 | #endif /* SNDFILE_MPEG_H */ |
0 | /* | |
1 | ** Copyright (C) 2019 - 2021 Arthur Taylor <art@ified.ca> | |
2 | ** Copyright (C) 2019 Erik de Castro Lopo <erikd@mega-nerd.com> | |
3 | ** | |
4 | ** This program is free software ; you can redistribute it and/or modify | |
5 | ** it under the terms of the GNU Lesser General Public License as published by | |
6 | ** the Free Software Foundation ; either version 2.1 of the License, or | |
7 | ** (at your option) any later version. | |
8 | ** | |
9 | ** This program is distributed in the hope that it will be useful, | |
10 | ** but WITHOUT ANY WARRANTY ; without even the implied warranty of | |
11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | ** GNU Lesser General Public License for more details. | |
13 | ** | |
14 | ** You should have received a copy of the GNU Lesser General Public License | |
15 | ** along with this program ; if not, write to the Free Software | |
16 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
17 | */ | |
18 | ||
19 | #include "sfconfig.h" | |
20 | ||
21 | #include <math.h> | |
22 | ||
23 | #include "sndfile.h" | |
24 | #include "common.h" | |
25 | #include "mpeg.h" | |
26 | ||
27 | #if HAVE_MPEG | |
28 | ||
29 | #include "sfendian.h" | |
30 | #include "id3.h" | |
31 | ||
32 | #include <mpg123.h> | |
33 | ||
34 | typedef struct | |
35 | { mpg123_handle *pmh ; | |
36 | size_t header_remaining ; | |
37 | } MPEG_DEC_PRIVATE ; | |
38 | ||
39 | static int mpeg_dec_close (SF_PRIVATE *psf) ; | |
40 | static sf_count_t mpeg_dec_seek (SF_PRIVATE *psf, int whence, sf_count_t count) ; | |
41 | ||
42 | static ssize_t mpeg_dec_io_read (void *priv, void *buffer, size_t nbytes) ; | |
43 | static off_t mpeg_dec_io_lseek (void *priv, off_t offset, int whence) ; | |
44 | ||
45 | static ssize_t | |
46 | mpeg_dec_io_read (void *priv, void *buffer, size_t nbytes) | |
47 | { SF_PRIVATE *psf = (SF_PRIVATE *) priv ; | |
48 | MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; | |
49 | ||
50 | if (pmp3d->header_remaining) | |
51 | { if (pmp3d->header_remaining < nbytes) | |
52 | nbytes = pmp3d->header_remaining ; | |
53 | psf_binheader_readf (psf, "b", buffer, nbytes) ; | |
54 | pmp3d->header_remaining -= nbytes ; | |
55 | return nbytes ; | |
56 | } ; | |
57 | ||
58 | return psf_fread (buffer, 1, nbytes, psf) ; | |
59 | } /* mpeg_dec_io_read */ | |
60 | ||
61 | static off_t | |
62 | mpeg_dec_io_lseek (void *priv, off_t offset, int whence) | |
63 | { SF_PRIVATE *psf = (SF_PRIVATE *) priv ; | |
64 | ||
65 | return psf_fseek (psf, offset, whence) ; | |
66 | } /* mpeg_dec_io_lseek */ | |
67 | ||
68 | static int | |
69 | mpeg_dec_close (SF_PRIVATE *psf) | |
70 | { MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; | |
71 | ||
72 | if (pmp3d) | |
73 | { if (pmp3d->pmh) | |
74 | { mpg123_close (pmp3d->pmh) ; | |
75 | mpg123_delete (pmp3d->pmh) ; | |
76 | pmp3d->pmh = NULL ; | |
77 | } | |
78 | free (psf->codec_data) ; | |
79 | psf->codec_data = NULL ; | |
80 | } ; | |
81 | ||
82 | return 0 ; | |
83 | } /* mpeg_dec_close */ | |
84 | ||
85 | static sf_count_t | |
86 | mpeg_dec_decode (SF_PRIVATE *psf, float *ptr, sf_count_t len) | |
87 | { MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; | |
88 | size_t done ; | |
89 | int error ; | |
90 | ||
91 | error = mpg123_read (pmp3d->pmh, (unsigned char *) ptr, len * sizeof (float), &done) ; | |
92 | ||
93 | if (error == MPG123_OK) | |
94 | return done / sizeof (float) ; | |
95 | ||
96 | if (error == MPG123_DONE) | |
97 | return 0 ; | |
98 | ||
99 | if (error == MPG123_NEW_FORMAT) | |
100 | { psf->error = SFE_MALFORMED_FILE ; | |
101 | return -1 ; | |
102 | } ; | |
103 | ||
104 | psf->error = SFE_INTERNAL ; | |
105 | return -1 ; | |
106 | } /* mpeg_dec_decode */ | |
107 | ||
108 | static sf_count_t | |
109 | mpeg_dec_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) | |
110 | { BUF_UNION ubuf ; | |
111 | sf_count_t total, readlen ; | |
112 | void (*convert) (const float *, short *, int, int) ; | |
113 | const sf_count_t buflen = ARRAY_LEN (ubuf.fbuf) ; | |
114 | ||
115 | convert = (psf->add_clipping) ? psf_f2s_clip_array : psf_f2s_array ; | |
116 | for (total = 0 ; total < len ; total += readlen) | |
117 | { readlen = mpeg_dec_decode (psf, ubuf.fbuf, SF_MIN (buflen, len - total)) ; | |
118 | if (readlen <= 0) | |
119 | break ; | |
120 | ||
121 | convert (ubuf.fbuf, ptr + total, readlen, SF_TRUE) ; | |
122 | } ; | |
123 | ||
124 | return total ; | |
125 | } /*mpeg_dec_read_s */ | |
126 | ||
127 | static sf_count_t | |
128 | mpeg_dec_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) | |
129 | { BUF_UNION ubuf ; | |
130 | sf_count_t total, readlen ; | |
131 | void (*convert) (const float *, int *, int, int) ; | |
132 | const sf_count_t buflen = ARRAY_LEN (ubuf.fbuf) ; | |
133 | ||
134 | convert = (psf->add_clipping) ? psf_f2i_clip_array : psf_f2i_array ; | |
135 | for (total = 0 ; total < len ; total += readlen) | |
136 | { readlen = mpeg_dec_decode (psf, ubuf.fbuf, SF_MIN (buflen, len - total)) ; | |
137 | if (readlen <= 0) | |
138 | break ; | |
139 | ||
140 | convert (ubuf.fbuf, ptr + total, readlen, SF_TRUE) ; | |
141 | } ; | |
142 | ||
143 | return total ; | |
144 | } /* mpeg_dec_read_i */ | |
145 | ||
146 | static sf_count_t | |
147 | mpeg_dec_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) | |
148 | { sf_count_t readlen ; | |
149 | ||
150 | readlen = mpeg_dec_decode (psf, ptr, len) ; | |
151 | if (readlen <= 0) | |
152 | return 0 ; | |
153 | ||
154 | if (psf->norm_float == SF_FALSE) | |
155 | for (int i = 0 ; i < readlen ; i++) | |
156 | { ptr [i] *= (1.0f * 0x8000) ; | |
157 | } ; | |
158 | ||
159 | return readlen ; | |
160 | } /* mpeg_dec_read_f */ | |
161 | ||
162 | static inline void | |
163 | f2d_array (const float *src, int count, double *dest, double normfact) | |
164 | { for (int i = 0 ; i < count ; i++) | |
165 | { dest [i] = src [i] * normfact ; | |
166 | } | |
167 | } /* f2d_array */ | |
168 | ||
169 | static sf_count_t | |
170 | mpeg_dec_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) | |
171 | { BUF_UNION ubuf ; | |
172 | sf_count_t total, readlen ; | |
173 | double normfact ; | |
174 | const sf_count_t buflen = ARRAY_LEN (ubuf.fbuf) ; | |
175 | ||
176 | normfact = (psf->norm_double == SF_TRUE) ? 1.0 : (1.0 * 0x8000) ; | |
177 | ||
178 | for (total = 0 ; total < len ; total += readlen) | |
179 | { readlen = mpeg_dec_decode (psf, ubuf.fbuf, SF_MIN (buflen, len - total)) ; | |
180 | if (readlen <= 0) | |
181 | break ; | |
182 | ||
183 | f2d_array (ubuf.fbuf, readlen, ptr + total, normfact) ; | |
184 | } ; | |
185 | ||
186 | return total ; | |
187 | } /* mpeg_dec_read_d */ | |
188 | ||
189 | static sf_count_t | |
190 | mpeg_dec_seek (SF_PRIVATE *psf, int mode, sf_count_t count) | |
191 | { MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; | |
192 | off_t ret ; | |
193 | ||
194 | if (mode != SFM_READ || psf->file.mode != SFM_READ) | |
195 | { psf->error = SFE_BAD_SEEK ; | |
196 | return PSF_SEEK_ERROR ; | |
197 | } ; | |
198 | ||
199 | ret = mpg123_seek (pmp3d->pmh, count, SEEK_SET) ; | |
200 | ||
201 | if (ret < 0) | |
202 | return PSF_SEEK_ERROR ; | |
203 | ||
204 | return (sf_count_t) ret ; | |
205 | } /* mpeg_dec_seek */ | |
206 | ||
207 | static int | |
208 | mpeg_dec_fill_sfinfo (mpg123_handle *mh, SF_INFO *info) | |
209 | { int error ; | |
210 | int channels ; | |
211 | int encoding ; | |
212 | long rate ; | |
213 | off_t length ; | |
214 | ||
215 | error = mpg123_getformat (mh, &rate, &channels, &encoding) ; | |
216 | if (error != MPG123_OK) | |
217 | return error ; | |
218 | ||
219 | info->samplerate = rate ; | |
220 | info->channels = channels ; | |
221 | ||
222 | length = mpg123_length (mh) ; | |
223 | if (length >= 0) | |
224 | { info->frames = length ; | |
225 | info->seekable = SF_TRUE ; | |
226 | } | |
227 | else | |
228 | { info->frames = SF_COUNT_MAX ; | |
229 | info->seekable = SF_FALSE ; | |
230 | } | |
231 | ||
232 | /* Force 32-bit float samples. */ | |
233 | if (encoding != MPG123_ENC_FLOAT_32) | |
234 | { error = mpg123_format (mh, rate, channels, MPG123_ENC_FLOAT_32) ; | |
235 | } ; | |
236 | ||
237 | return error ; | |
238 | } /* mpeg_dec_fill_sfinfo */ | |
239 | ||
240 | static void | |
241 | mpeg_dec_print_frameinfo (SF_PRIVATE *psf, const struct mpg123_frameinfo *fi) | |
242 | { psf_log_printf (psf, "MPEG-1/2 Audio\n----------------------------------------\n") ; | |
243 | psf_log_printf (psf, " MPEG version : %s\n", | |
244 | fi->version == MPG123_1_0 ? "MPEG 1.0" : | |
245 | fi->version == MPG123_2_0 ? "MPEG 2.0" : | |
246 | fi->version == MPG123_2_5 ? "MPEG 2.5" : "???") ; | |
247 | psf_log_printf (psf, " layer : %d\n", fi->layer) ; | |
248 | psf_log_printf (psf, " rate : %d\n", fi->rate) ; | |
249 | psf_log_printf (psf, " mode : %s\n", | |
250 | fi->mode == MPG123_M_STEREO ? "stereo" : | |
251 | fi->mode == MPG123_M_JOINT ? "joint stereo" : | |
252 | fi->mode == MPG123_M_DUAL ? "dual channel" : | |
253 | fi->mode == MPG123_M_MONO ? "mono" : "???") ; | |
254 | psf_log_printf (psf, " mode ext : %d\n", fi->mode_ext) ; | |
255 | psf_log_printf (psf, " framesize : %d\n", fi->framesize) ; | |
256 | psf_log_printf (psf, " crc : %d\n", !! (fi->flags & MPG123_CRC)) ; | |
257 | psf_log_printf (psf, " copyright flag : %d\n", !! (fi->flags & MPG123_COPYRIGHT)) ; | |
258 | psf_log_printf (psf, " private flag : %d\n", !! (fi->flags & MPG123_PRIVATE)) ; | |
259 | psf_log_printf (psf, " original flag : %d\n", !! (fi->flags & MPG123_ORIGINAL)) ; | |
260 | psf_log_printf (psf, " emphasis : %d\n", fi->emphasis) ; | |
261 | psf_log_printf (psf, " bitrate mode : ") ; | |
262 | switch (fi->vbr) | |
263 | { case MPG123_CBR : | |
264 | psf_log_printf (psf, "constant\n") ; | |
265 | psf_log_printf (psf, " bitrate : %d kbps\n", fi->bitrate) ; | |
266 | break ; | |
267 | case MPG123_VBR : | |
268 | psf_log_printf (psf, "variable\n") ; | |
269 | break ; | |
270 | ||
271 | case MPG123_ABR : | |
272 | psf_log_printf (psf, "average\n") ; | |
273 | psf_log_printf (psf, " ABR target : %d\n", fi->abr_rate) ; | |
274 | break ; | |
275 | ||
276 | default : | |
277 | psf_log_printf (psf, "(%d) ???\n", fi->vbr) ; | |
278 | break ; | |
279 | } ; | |
280 | } /* mpeg_dec_print_frameinfo */ | |
281 | ||
282 | /* | |
283 | * Like strlcpy, except the size argument is the maximum size of the input, | |
284 | * always null terminates the output string. Thus, up to size + 1 bytes may be | |
285 | * written. | |
286 | * | |
287 | * Returns the length of the copied string. | |
288 | */ | |
289 | static int | |
290 | strcpy_inbounded (char *dest, size_t size, const char *src) | |
291 | { char *c = memccpy (dest, src, '\0', size) ; | |
292 | if (!c) | |
293 | c = dest + size ; | |
294 | *c = '\0' ; | |
295 | return c - dest ; | |
296 | } /* strcpy_inbounded */ | |
297 | ||
298 | static void | |
299 | mpeg_decoder_read_strings_id3v1 (SF_PRIVATE *psf, mpg123_id3v1 *tags) | |
300 | { const char *genre ; | |
301 | char buf [31] ; | |
302 | ||
303 | psf_log_printf (psf, "ID3v1 Tags\n") ; | |
304 | ||
305 | if (strcpy_inbounded (buf, ARRAY_LEN (tags->title), tags->title)) | |
306 | { psf_log_printf (psf, " Title : %s\n", buf) ; | |
307 | psf_store_string (psf, SF_STR_TITLE, buf) ; | |
308 | } ; | |
309 | ||
310 | if (strcpy_inbounded (buf, ARRAY_LEN (tags->artist), tags->artist)) | |
311 | { psf_log_printf (psf, " Artist : %s\n", buf) ; | |
312 | psf_store_string (psf, SF_STR_ARTIST, buf) ; | |
313 | } ; | |
314 | ||
315 | if (strcpy_inbounded (buf, ARRAY_LEN (tags->album), tags->album)) | |
316 | { psf_log_printf (psf, " Album : %s\n", buf) ; | |
317 | psf_store_string (psf, SF_STR_ALBUM, buf) ; | |
318 | } ; | |
319 | ||
320 | if (strcpy_inbounded (buf, ARRAY_LEN (tags->year), tags->year)) | |
321 | { psf_log_printf (psf, " Year : %s\n", buf) ; | |
322 | psf_store_string (psf, SF_STR_DATE, buf) ; | |
323 | } ; | |
324 | ||
325 | if (strcpy_inbounded (buf, ARRAY_LEN (tags->comment), tags->comment)) | |
326 | { psf_log_printf (psf, " Comment : %s\n", buf) ; | |
327 | psf_store_string (psf, SF_STR_COMMENT, buf) ; | |
328 | } ; | |
329 | ||
330 | /* ID3v1.1 Tracknumber */ | |
331 | if (tags->comment [28] == '\0' && tags->comment [29] != '\0') | |
332 | { snprintf (buf, ARRAY_LEN (buf), "%hhu", (unsigned char) tags->comment [29]) ; | |
333 | psf_log_printf (psf, " Tracknumber : %s\n", buf) ; | |
334 | psf_store_string (psf, SF_STR_TRACKNUMBER, buf) ; | |
335 | } ; | |
336 | ||
337 | if ((genre = id3_lookup_v1_genre (tags->genre)) != NULL) | |
338 | { psf_log_printf (psf, " Genre : %s\n", genre) ; | |
339 | psf_store_string (psf, SF_STR_GENRE, genre) ; | |
340 | } ; | |
341 | } /* mpeg_decoder_read_strings_id3v1 */ | |
342 | ||
343 | static void | |
344 | mpeg_decoder_read_strings_id3v2 (SF_PRIVATE *psf, mpg123_id3v2 *tags) | |
345 | { mpg123_text *text_frame ; | |
346 | size_t i ; | |
347 | uint32_t marker ; | |
348 | const char *title = NULL ; | |
349 | const char *copyright = NULL ; | |
350 | const char *software = NULL ; | |
351 | const char *artist = NULL ; | |
352 | const char *comment = NULL ; | |
353 | const char *date = NULL ; | |
354 | const char *album = NULL ; | |
355 | const char *license = NULL ; | |
356 | const char *tracknumber = NULL ; | |
357 | const char *genre = NULL ; | |
358 | const char *tlen = NULL ; | |
359 | ||
360 | psf_log_printf (psf, "ID3v2 Tags\n") ; | |
361 | ||
362 | // Read the parsed text tags | |
363 | for (i = 0 ; i < tags->texts ; i++) | |
364 | { text_frame = &tags->text [i] ; | |
365 | psf_log_printf (psf, " %.4s : %s\n", text_frame->id, text_frame->text.p) ; | |
366 | ||
367 | // Thankfully mpg123 translates v2.2 3-byte frames to v2.3 4-byte for us. | |
368 | marker = MAKE_MARKER (text_frame->id [0], text_frame->id [1], | |
369 | text_frame->id [2], text_frame->id [3]) ; | |
370 | ||
371 | /* Use our own map of frame types to metadata for text frames */ | |
372 | switch (marker) | |
373 | { case MAKE_MARKER ('T', 'I', 'T', '2') : | |
374 | title = text_frame->text.p ; | |
375 | break ; | |
376 | ||
377 | case MAKE_MARKER ('T', 'C', 'O', 'P') : | |
378 | copyright = text_frame->text.p ; | |
379 | break ; | |
380 | ||
381 | case MAKE_MARKER ('T', 'E', 'N', 'C') : | |
382 | case MAKE_MARKER ('T', 'S', 'S', 'E') : | |
383 | software = text_frame->text.p ; | |
384 | break ; | |
385 | ||
386 | case MAKE_MARKER ('T', 'P', 'E', '1') : | |
387 | artist = text_frame->text.p ; | |
388 | break ; | |
389 | ||
390 | case MAKE_MARKER ('T', 'A', 'L', 'B') : | |
391 | album = text_frame->text.p ; | |
392 | break ; | |
393 | ||
394 | case MAKE_MARKER ('T', 'R', 'C', 'K') : | |
395 | tracknumber = text_frame->text.p ; | |
396 | break ; | |
397 | ||
398 | case MAKE_MARKER ('T', 'Y', 'E', 'R') : | |
399 | case MAKE_MARKER ('T', 'D', 'R', 'C') : | |
400 | /* TODO (maybe) | |
401 | case MAKE_MARKER ('T', 'D', 'A', 'T') : | |
402 | case MAKE_MARKER ('T', 'I', 'M', 'E') : | |
403 | case MAKE_MARKER ('T', 'D', 'R', 'A') : | |
404 | */ | |
405 | date = text_frame->text.p ; | |
406 | break ; | |
407 | ||
408 | case MAKE_MARKER ('T', 'O', 'W', 'N') : | |
409 | tracknumber = text_frame->text.p ; | |
410 | break ; | |
411 | ||
412 | case MAKE_MARKER ('T', 'C', 'O', 'N') : | |
413 | genre = text_frame->text.p ; | |
414 | break ; | |
415 | ||
416 | case MAKE_MARKER ('T', 'L', 'E', 'N') : | |
417 | tlen = text_frame->text.p ; | |
418 | break ; | |
419 | } ; | |
420 | } ; | |
421 | ||
422 | /* Use mpg123's handling of comment headers, but print all the comment headers anyways. */ | |
423 | if (tags->comment) | |
424 | comment = tags->comment->p ; | |
425 | for (i = 0 ; i < tags->comments ; i++) | |
426 | { text_frame = &tags->comment_list [i] ; | |
427 | psf_log_printf (psf, " %.4s : (%s)[%s] %s\n", text_frame->id, | |
428 | text_frame->description. p, text_frame->lang, text_frame->text.p) ; | |
429 | } ; | |
430 | ||
431 | /* Print extra headers */ | |
432 | for (i = 0 ; i < tags->extras ; i++) | |
433 | { text_frame = &tags->extra [i] ; | |
434 | psf_log_printf (psf, " %.4s : (%s) %s\n", text_frame->id, | |
435 | text_frame->description.p, text_frame->text.p) ; | |
436 | } ; | |
437 | ||
438 | if (title != NULL) | |
439 | psf_store_string (psf, SF_STR_TITLE, title) ; | |
440 | if (copyright != NULL) | |
441 | psf_store_string (psf, SF_STR_COPYRIGHT, copyright) ; | |
442 | if (software != NULL) | |
443 | psf_store_string (psf, SF_STR_SOFTWARE, software) ; | |
444 | if (artist != NULL) | |
445 | psf_store_string (psf, SF_STR_ARTIST, artist) ; | |
446 | if (comment != NULL) | |
447 | psf_store_string (psf, SF_STR_COMMENT, comment) ; | |
448 | if (date != NULL) | |
449 | psf_store_string (psf, SF_STR_DATE, date) ; | |
450 | if (album != NULL) | |
451 | psf_store_string (psf, SF_STR_ALBUM, album) ; | |
452 | if (license != NULL) | |
453 | psf_store_string (psf, SF_STR_LICENSE, license) ; | |
454 | if (tracknumber != NULL) | |
455 | psf_store_string (psf, SF_STR_TRACKNUMBER, tracknumber) ; | |
456 | if (genre != NULL) | |
457 | psf_store_string (psf, SF_STR_GENRE, id3_process_v2_genre (genre)) ; | |
458 | if (tlen != NULL) | |
459 | { /* If non-seekable, set framecount? Can we trust it? */ | |
460 | } ; | |
461 | } /* mpeg_decoder_read_strings_id3v2 */ | |
462 | ||
463 | static void | |
464 | mpeg_decoder_read_strings (SF_PRIVATE *psf) | |
465 | { MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; | |
466 | mpg123_id3v1 *v1_tags ; | |
467 | mpg123_id3v2 *v2_tags ; | |
468 | ||
469 | if (mpg123_id3 (pmp3d->pmh, &v1_tags, &v2_tags) != MPG123_OK) | |
470 | return ; | |
471 | ||
472 | if (v1_tags != NULL) | |
473 | mpeg_decoder_read_strings_id3v1 (psf, v1_tags) ; | |
474 | ||
475 | if (v2_tags != NULL) | |
476 | mpeg_decoder_read_strings_id3v2 (psf, v2_tags) ; | |
477 | } /* mpeg_decoder_read_strings */ | |
478 | ||
479 | static int | |
480 | mpeg_dec_byterate (SF_PRIVATE *psf) | |
481 | { MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; | |
482 | struct mpg123_frameinfo fi ; | |
483 | ||
484 | if (mpg123_info (pmp3d->pmh, &fi) == MPG123_OK) | |
485 | return (fi.bitrate + 7) / 8 ; | |
486 | ||
487 | return -1 ; | |
488 | ||
489 | } /* mpeg_dec_byterate */ | |
490 | ||
491 | /*============================================================================== | |
492 | ** exported functions | |
493 | */ | |
494 | ||
495 | int | |
496 | mpeg_decoder_init (SF_PRIVATE *psf) | |
497 | { MPEG_DEC_PRIVATE *pmp3d ; | |
498 | struct mpg123_frameinfo fi ; | |
499 | int error ; | |
500 | ||
501 | if (! (psf->file.mode & SFM_READ)) | |
502 | return SFE_INTERNAL ; | |
503 | ||
504 | /* | |
505 | ** *** FIXME - Threading issues *** | |
506 | ** | |
507 | ** mpg123_init() is a global call that should only be called once, and | |
508 | ** should be paried with mpg123_exit() when done. libsndfile does not | |
509 | ** provide for these requirements. | |
510 | ** | |
511 | ** Currently this is a moot issue as mpg123_init() non-conditionally writes | |
512 | ** static areas with calculated data, and mpg123_exit() is a NOP, but this | |
513 | ** could change in a future version of it! | |
514 | ** | |
515 | ** From mpg123.h: | |
516 | ** > This should be called once in a non-parallel context. It is not explicitly | |
517 | ** > thread-safe, but repeated/concurrent calls still _should_ be safe as static | |
518 | ** > tables are filled with the same values anyway. | |
519 | ** | |
520 | ** Note that calling mpg123_init() after it has already completed is a NOP. | |
521 | ** | |
522 | ** Update 2021-07-04 | |
523 | ** mpg123 upstream has confirmed that mpg132_init() will become a NOP in future, | |
524 | ** so this is moot. | |
525 | */ | |
526 | if (mpg123_init () != MPG123_OK) | |
527 | return SFE_INTERNAL ; | |
528 | ||
529 | psf->codec_data = pmp3d = calloc (1, sizeof (MPEG_DEC_PRIVATE)) ; | |
530 | if (!psf->codec_data) | |
531 | return SFE_MALLOC_FAILED ; | |
532 | ||
533 | pmp3d->pmh = mpg123_new (NULL, &error) ; | |
534 | if (!pmp3d->pmh) | |
535 | { psf_log_printf (psf, "Could not obtain a mpg123 handle: %s\n", mpg123_plain_strerror (error)) ; | |
536 | return SFE_INTERNAL ; | |
537 | } ; | |
538 | ||
539 | psf->codec_close = mpeg_dec_close ; | |
540 | ||
541 | mpg123_replace_reader_handle (pmp3d->pmh, | |
542 | mpeg_dec_io_read, mpeg_dec_io_lseek, NULL) ; | |
543 | ||
544 | mpg123_param (pmp3d->pmh, MPG123_REMOVE_FLAGS, MPG123_AUTO_RESAMPLE, 1.0) ; | |
545 | mpg123_param (pmp3d->pmh, MPG123_ADD_FLAGS, MPG123_FORCE_FLOAT | MPG123_GAPLESS, 1.0) ; | |
546 | #if MPG123_API_VERSION >= 45 | |
547 | mpg123_param (pmp3d->pmh, MPG123_ADD_FLAGS, MPG123_NO_FRANKENSTEIN, 1.0) ; | |
548 | #endif | |
549 | ||
550 | /* | |
551 | ** Need to pass the first MPEG frame to libmpg123, but that frame was read | |
552 | ** into psf->binheader in order that we could identify the stream. | |
553 | */ | |
554 | if (psf->is_pipe) | |
555 | { /* | |
556 | ** Can't seek, so setup our libmpg123 io callbacks to read the binheader | |
557 | ** buffer first. | |
558 | */ | |
559 | psf_binheader_readf (psf, "p", psf->dataoffset) ; | |
560 | pmp3d->header_remaining = psf_binheader_readf (psf, NULL) - psf->dataoffset ; | |
561 | ||
562 | /* Tell libmpg123 we can't seek the file. */ | |
563 | mpg123_param (pmp3d->pmh, MPG123_ADD_FLAGS, MPG123_NO_PEEK_END, 1.0) ; | |
564 | } | |
565 | else | |
566 | { /* | |
567 | ** libmpg123 can parse the ID3v2 header. Undo the embedded file offset if the | |
568 | ** enclosing file data is the ID3v2 header. | |
569 | */ | |
570 | if (psf->id3_header.len > 0 && psf->id3_header.len + psf->id3_header.offset == psf->fileoffset) | |
571 | psf->fileoffset = psf->id3_header.offset ; | |
572 | ||
573 | psf_fseek (psf, 0, SEEK_SET) ; | |
574 | } ; | |
575 | ||
576 | error = mpg123_open_handle (pmp3d->pmh, psf) ; | |
577 | if (error != MPG123_OK) | |
578 | { psf_log_printf (psf, "mpg123 could not open the file: %s\n", mpg123_plain_strerror (error)) ; | |
579 | return SFE_BAD_FILE ; | |
580 | } ; | |
581 | ||
582 | if (mpeg_dec_fill_sfinfo (pmp3d->pmh, &psf->sf) != MPG123_OK) | |
583 | { psf_log_printf (psf, "Cannot get MPEG decoder configuration: %s\n", mpg123_plain_strerror (error)) ; | |
584 | return SFE_BAD_FILE ; | |
585 | } ; | |
586 | ||
587 | error = mpg123_info (pmp3d->pmh, &fi) ; | |
588 | if (error != MPG123_OK) | |
589 | { psf_log_printf (psf, "Cannot get MPEG frame info: %s\n", mpg123_plain_strerror (error)) ; | |
590 | return SFE_INTERNAL ; | |
591 | } | |
592 | ||
593 | switch (fi.layer) | |
594 | { case 1 : psf->sf.format |= SF_FORMAT_MPEG_LAYER_I ; break ; | |
595 | case 2 : psf->sf.format |= SF_FORMAT_MPEG_LAYER_II ; break ; | |
596 | case 3 : psf->sf.format |= SF_FORMAT_MPEG_LAYER_III ; break ; | |
597 | default : | |
598 | return SFE_BAD_FILE ; | |
599 | } ; | |
600 | mpeg_dec_print_frameinfo (psf, &fi) ; | |
601 | ||
602 | psf->read_short = mpeg_dec_read_s ; | |
603 | psf->read_int = mpeg_dec_read_i ; | |
604 | psf->read_float = mpeg_dec_read_f ; | |
605 | psf->read_double = mpeg_dec_read_d ; | |
606 | psf->seek = mpeg_dec_seek ; | |
607 | psf->byterate = mpeg_dec_byterate ; | |
608 | ||
609 | mpeg_decoder_read_strings (psf) ; | |
610 | ||
611 | return 0 ; | |
612 | } /* mpeg_decoder_init */ | |
613 | ||
614 | int | |
615 | mpeg_decoder_get_bitrate_mode (SF_PRIVATE *psf) | |
616 | { MPEG_DEC_PRIVATE *pmp3d = (MPEG_DEC_PRIVATE *) psf->codec_data ; | |
617 | struct mpg123_frameinfo fi ; | |
618 | ||
619 | if (mpg123_info (pmp3d->pmh, &fi) == MPG123_OK) | |
620 | { | |
621 | switch (fi.vbr) | |
622 | { case MPG123_CBR : return SF_BITRATE_MODE_CONSTANT ; | |
623 | case MPG123_ABR : return SF_BITRATE_MODE_AVERAGE ; | |
624 | case MPG123_VBR : return SF_BITRATE_MODE_VARIABLE ; | |
625 | default : break ; | |
626 | } ; | |
627 | } ; | |
628 | ||
629 | psf_log_printf (psf, "Cannot determine MPEG bitrate mode.\n") ; | |
630 | return -1 ; | |
631 | } /* mpeg_decoder_get_bitrate_mode */ | |
632 | ||
633 | #else /* HAVE_MPEG */ | |
634 | ||
635 | int mpeg_decoder_init (SF_PRIVATE *psf) | |
636 | { psf_log_printf (psf, "This version of libsndfile was compiled without MPEG decode support.\n") ; | |
637 | return SFE_UNIMPLEMENTED ; | |
638 | } /* mpeg_decoder_init */ | |
639 | ||
640 | #endif /* HAVE_MPEG */ |
0 | /* | |
1 | ** Copyright (C) 2020 Arthur Taylor <art@ified.ca> | |
2 | ** Copyright (C) 2019 Erik de Castro Lopo <erikd@mega-nerd.com> | |
3 | ** | |
4 | ** This program is free software ; you can redistribute it and/or modify | |
5 | ** it under the terms of the GNU Lesser General Public License as published by | |
6 | ** the Free Software Foundation ; either version 2.1 of the License, or | |
7 | ** (at your option) any later version. | |
8 | ** | |
9 | ** This program is distributed in the hope that it will be useful, | |
10 | ** but WITHOUT ANY WARRANTY ; without even the implied warranty of | |
11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | ** GNU Lesser General Public License for more details. | |
13 | ** | |
14 | ** You should have received a copy of the GNU Lesser General Public License | |
15 | ** along with this program ; if not, write to the Free Software | |
16 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
17 | */ | |
18 | ||
19 | #include "sfconfig.h" | |
20 | #include "sndfile.h" | |
21 | #include "common.h" | |
22 | #include "mpeg.h" | |
23 | ||
24 | ||
25 | #if HAVE_MPEG | |
26 | ||
27 | #include <lame/lame.h> | |
28 | ||
29 | /* | |
30 | * RANT RANT RANT | |
31 | * | |
32 | * Lame has 11 functions for inputing sample data of various types and | |
33 | * configurations, but due to bad definitions, or missing combinations, they | |
34 | * aren't really of much help to us. | |
35 | * | |
36 | */ | |
37 | ||
38 | typedef struct | |
39 | { lame_t lamef ; | |
40 | unsigned char *block ; | |
41 | size_t block_len ; | |
42 | int frame_samples ; | |
43 | double compression ; | |
44 | int initialized ; | |
45 | } MPEG_L3_ENC_PRIVATE ; | |
46 | ||
47 | ||
48 | /*----------------------------------------------------------------------------------------------- | |
49 | ** Private function prototypes. | |
50 | */ | |
51 | ||
52 | static int mpeg_l3_encoder_close (SF_PRIVATE *psf) ; | |
53 | static int mpeg_l3_encoder_construct (SF_PRIVATE *psf) ; | |
54 | static int mpeg_l3_encoder_byterate (SF_PRIVATE *psf) ; | |
55 | ||
56 | static sf_count_t mpeg_l3_encode_write_short_stereo (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; | |
57 | static sf_count_t mpeg_l3_encode_write_int_stereo (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; | |
58 | static sf_count_t mpeg_l3_encode_write_float_stereo (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; | |
59 | static sf_count_t mpeg_l3_encode_write_double_stereo (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; | |
60 | static sf_count_t mpeg_l3_encode_write_short_mono (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; | |
61 | static sf_count_t mpeg_l3_encode_write_int_mono (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; | |
62 | static sf_count_t mpeg_l3_encode_write_float_mono (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; | |
63 | static sf_count_t mpeg_l3_encode_write_double_mono (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; | |
64 | ||
65 | /*----------------------------------------------------------------------------------------------- | |
66 | ** Exported functions. | |
67 | */ | |
68 | ||
69 | int | |
70 | mpeg_l3_encoder_init (SF_PRIVATE *psf, int info_tag) | |
71 | { MPEG_L3_ENC_PRIVATE* pmpeg = NULL ; | |
72 | ||
73 | if (psf->file.mode == SFM_RDWR) | |
74 | return SFE_BAD_MODE_RW ; | |
75 | ||
76 | if (psf->file.mode != SFM_WRITE) | |
77 | return SFE_INTERNAL ; | |
78 | ||
79 | psf->codec_data = pmpeg = calloc (1, sizeof (MPEG_L3_ENC_PRIVATE)) ; | |
80 | if (!pmpeg) | |
81 | return SFE_MALLOC_FAILED ; | |
82 | ||
83 | if (psf->sf.channels < 1 || psf->sf.channels > 2) | |
84 | return SFE_BAD_OPEN_FORMAT ; | |
85 | ||
86 | if (! (pmpeg->lamef = lame_init ())) | |
87 | return SFE_MALLOC_FAILED ; | |
88 | ||
89 | pmpeg->compression = -1.0 ; /* Unset */ | |
90 | ||
91 | lame_set_in_samplerate (pmpeg->lamef, psf->sf.samplerate) ; | |
92 | lame_set_num_channels (pmpeg->lamef, psf->sf.channels) ; | |
93 | if (lame_set_out_samplerate (pmpeg->lamef, psf->sf.samplerate) < 0) | |
94 | return SFE_MPEG_BAD_SAMPLERATE ; | |
95 | ||
96 | lame_set_write_id3tag_automatic (pmpeg->lamef, 0) ; | |
97 | ||
98 | if (!info_tag || psf->is_pipe) | |
99 | { /* Can't seek back, so force disable Xing/Lame/Info header. */ | |
100 | lame_set_bWriteVbrTag (pmpeg->lamef, 0) ; | |
101 | } ; | |
102 | ||
103 | if (psf->sf.channels == 2) | |
104 | { psf->write_short = mpeg_l3_encode_write_short_stereo ; | |
105 | psf->write_int = mpeg_l3_encode_write_int_stereo ; | |
106 | psf->write_float = mpeg_l3_encode_write_float_stereo ; | |
107 | psf->write_double = mpeg_l3_encode_write_double_stereo ; | |
108 | } | |
109 | else | |
110 | { psf->write_short = mpeg_l3_encode_write_short_mono ; | |
111 | psf->write_int = mpeg_l3_encode_write_int_mono ; | |
112 | psf->write_float = mpeg_l3_encode_write_float_mono ; | |
113 | psf->write_double = mpeg_l3_encode_write_double_mono ; | |
114 | } | |
115 | ||
116 | psf->sf.seekable = 0 ; | |
117 | psf->codec_close = mpeg_l3_encoder_close ; | |
118 | psf->byterate = mpeg_l3_encoder_byterate ; | |
119 | psf->datalength = 0 ; | |
120 | ||
121 | return 0 ; | |
122 | } /* mpeg_l3_encoder_init */ | |
123 | ||
124 | int | |
125 | mpeg_l3_encoder_write_id3tag (SF_PRIVATE *psf) | |
126 | { MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; | |
127 | unsigned char *id3v2_buffer ; | |
128 | int i, id3v2_size ; | |
129 | ||
130 | if (psf->have_written) | |
131 | return 0 ; | |
132 | ||
133 | if ((i = mpeg_l3_encoder_construct (psf))) | |
134 | return i ; | |
135 | ||
136 | if (psf_fseek (psf, 0, SEEK_SET) != 0) | |
137 | return SFE_NOT_SEEKABLE ; | |
138 | ||
139 | /* Safe to call multiple times. */ | |
140 | id3tag_init (pmpeg->lamef) ; | |
141 | ||
142 | for (i = 0 ; i < SF_MAX_STRINGS ; i++) | |
143 | { switch (psf->strings.data [i].type) | |
144 | { case SF_STR_TITLE : | |
145 | id3tag_set_title (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; | |
146 | break ; | |
147 | ||
148 | case SF_STR_ARTIST : | |
149 | id3tag_set_artist (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; | |
150 | break ; | |
151 | ||
152 | case SF_STR_ALBUM : | |
153 | id3tag_set_album (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; | |
154 | break ; | |
155 | ||
156 | case SF_STR_DATE : | |
157 | id3tag_set_year (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; | |
158 | break ; | |
159 | ||
160 | case SF_STR_COMMENT : | |
161 | id3tag_set_comment (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; | |
162 | break ; | |
163 | ||
164 | case SF_STR_GENRE : | |
165 | id3tag_set_genre (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; | |
166 | break ; | |
167 | ||
168 | case SF_STR_TRACKNUMBER : | |
169 | id3tag_set_track (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; | |
170 | break ; | |
171 | ||
172 | default: | |
173 | break ; | |
174 | } ; | |
175 | } ; | |
176 | ||
177 | /* The header in this case is the ID3v2 tag header. */ | |
178 | id3v2_size = lame_get_id3v2_tag (pmpeg->lamef, 0, 0) ; | |
179 | if (id3v2_size > 0) | |
180 | { psf_log_printf (psf, "Writing ID3v2 header.\n") ; | |
181 | if (! (id3v2_buffer = malloc (id3v2_size))) | |
182 | return SFE_MALLOC_FAILED ; | |
183 | lame_get_id3v2_tag (pmpeg->lamef, id3v2_buffer, id3v2_size) ; | |
184 | psf_fwrite (id3v2_buffer, 1, id3v2_size, psf) ; | |
185 | psf->dataoffset = id3v2_size ; | |
186 | free (id3v2_buffer) ; | |
187 | } ; | |
188 | ||
189 | return 0 ; | |
190 | } | |
191 | ||
192 | int | |
193 | mpeg_l3_encoder_set_quality (SF_PRIVATE *psf, double compression) | |
194 | { MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; | |
195 | int bitrate_mode ; | |
196 | int bitrate ; | |
197 | int ret ; | |
198 | ||
199 | if (compression < 0.0 || compression > 1.0) | |
200 | return SF_FALSE ; | |
201 | ||
202 | /* | |
203 | ** Save the compression setting, as we may have to re-interpret it if | |
204 | ** the bitrate mode changes. | |
205 | */ | |
206 | pmpeg->compression = compression ; | |
207 | ||
208 | bitrate_mode = mpeg_l3_encoder_get_bitrate_mode (psf) ; | |
209 | if (bitrate_mode == SF_BITRATE_MODE_VARIABLE) | |
210 | { ret = lame_set_VBR_quality (pmpeg->lamef, compression * 10.0) ; | |
211 | } | |
212 | else | |
213 | { /* Choose a bitrate. */ | |
214 | if (psf->sf.samplerate >= 32000) | |
215 | { /* MPEG-1.0, bitrates are [32,320] kbps */ | |
216 | bitrate = (320.0 - (compression * (320.0 - 32.0))) ; | |
217 | } | |
218 | else if (psf->sf.samplerate >= 16000) | |
219 | { /* MPEG-2.0, bitrates are [8,160] */ | |
220 | bitrate = (160.0 - (compression * (160.0 - 8.0))) ; | |
221 | } | |
222 | else | |
223 | { /* MPEG-2.5, bitrates are [8,64] */ | |
224 | bitrate = (64.0 - (compression * (64.0 - 8.0))) ; | |
225 | } | |
226 | ||
227 | if (bitrate_mode == SF_BITRATE_MODE_AVERAGE) | |
228 | ret = lame_set_VBR_mean_bitrate_kbps (pmpeg->lamef, bitrate) ; | |
229 | else | |
230 | ret = lame_set_brate (pmpeg->lamef, bitrate) ; | |
231 | } ; | |
232 | ||
233 | if (ret == LAME_OKAY) | |
234 | return SF_TRUE ; | |
235 | ||
236 | psf_log_printf (psf, "Failed to set lame encoder quality.\n") ; | |
237 | return SF_FALSE ; | |
238 | } /* mpeg_l3_encoder_set_quality */ | |
239 | ||
240 | int | |
241 | mpeg_l3_encoder_set_bitrate_mode (SF_PRIVATE *psf, int mode) | |
242 | { MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; | |
243 | enum vbr_mode_e vbr_mode ; | |
244 | ||
245 | if (pmpeg->initialized) | |
246 | { psf->error = SFE_CMD_HAS_DATA ; | |
247 | return SF_FALSE ; | |
248 | } ; | |
249 | ||
250 | switch (mode) | |
251 | { case SF_BITRATE_MODE_CONSTANT : vbr_mode = vbr_off ; break ; | |
252 | case SF_BITRATE_MODE_AVERAGE : vbr_mode = vbr_abr ; break ; | |
253 | case SF_BITRATE_MODE_VARIABLE : vbr_mode = vbr_default ; break ; | |
254 | default : | |
255 | psf->error = SFE_BAD_COMMAND_PARAM ; | |
256 | return SF_FALSE ; | |
257 | } ; | |
258 | ||
259 | if (lame_set_VBR (pmpeg->lamef, vbr_mode) == LAME_OKAY) | |
260 | { /* Re-evaluate the compression setting. */ | |
261 | return mpeg_l3_encoder_set_quality (psf, pmpeg->compression) ; | |
262 | } ; | |
263 | ||
264 | psf_log_printf (psf, "Failed to set LAME vbr mode to %d.\n", vbr_mode) ; | |
265 | return SF_FALSE ; | |
266 | } /* mpeg_l3_encoder_set_bitrate_mode */ | |
267 | ||
268 | int | |
269 | mpeg_l3_encoder_get_bitrate_mode (SF_PRIVATE *psf) | |
270 | { MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; | |
271 | enum vbr_mode_e vbr_mode ; | |
272 | ||
273 | vbr_mode = lame_get_VBR (pmpeg->lamef) ; | |
274 | ||
275 | if (vbr_mode == vbr_off) | |
276 | return SF_BITRATE_MODE_CONSTANT ; | |
277 | if (vbr_mode == vbr_abr) | |
278 | return SF_BITRATE_MODE_AVERAGE ; | |
279 | if (vbr_mode == vbr_default || vbr_mode < vbr_max_indicator) | |
280 | return SF_BITRATE_MODE_VARIABLE ; | |
281 | ||
282 | /* Something is wrong. */ | |
283 | psf->error = SFE_INTERNAL ; | |
284 | return -1 ; | |
285 | } /* mpeg_l3_encoder_get_bitrate_mode */ | |
286 | ||
287 | ||
288 | /*----------------------------------------------------------------------------------------------- | |
289 | ** Private functions. | |
290 | */ | |
291 | ||
292 | static int | |
293 | mpeg_l3_encoder_close (SF_PRIVATE *psf) | |
294 | { MPEG_L3_ENC_PRIVATE* pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; | |
295 | int ret, len ; | |
296 | sf_count_t pos ; | |
297 | unsigned char *buffer ; | |
298 | ||
299 | /* Magic number 7200 comes from a comment in lame.h */ | |
300 | len = 7200 ; | |
301 | if (! (buffer = malloc (len))) | |
302 | return SFE_MALLOC_FAILED ; | |
303 | ret = lame_encode_flush (pmpeg->lamef, buffer, len) ; | |
304 | if (ret > 0) | |
305 | psf_fwrite (buffer, 1, ret, psf) ; | |
306 | ||
307 | /* | |
308 | ** Write an IDv1 trailer. The whole tag structure is always 128 bytes, so is | |
309 | ** guaranteed to fit in the buffer allocated above. | |
310 | */ | |
311 | ret = lame_get_id3v1_tag (pmpeg->lamef, buffer, len) ; | |
312 | if (ret > 0) | |
313 | { psf_log_printf (psf, " Writing ID3v1 trailer.\n") ; | |
314 | psf_fwrite (buffer, 1, ret, psf) ; | |
315 | } ; | |
316 | ||
317 | /* | |
318 | ** If possible, seek back and write the LAME/XING/Info headers. This | |
319 | ** contains information about the whole file and a seek table, and can | |
320 | ** only be written after encoding. | |
321 | ** | |
322 | ** If enabled, Lame wrote an empty header at the beginning of the data | |
323 | ** that we now fill in. | |
324 | */ | |
325 | ret = lame_get_lametag_frame (pmpeg->lamef, 0, 0) ; | |
326 | if (ret > 0) | |
327 | { if (ret > len) | |
328 | { len = ret ; | |
329 | free (buffer) ; | |
330 | if (! (buffer = malloc (len))) | |
331 | return SFE_MALLOC_FAILED ; | |
332 | } ; | |
333 | psf_log_printf (psf, " Writing LAME info header at offset %d, %d bytes.\n", | |
334 | psf->dataoffset, len) ; | |
335 | lame_get_lametag_frame (pmpeg->lamef, buffer, len) ; | |
336 | pos = psf_ftell (psf) ; | |
337 | if (psf_fseek (psf, psf->dataoffset, SEEK_SET) == psf->dataoffset) | |
338 | { psf_fwrite (buffer, 1, ret, psf) ; | |
339 | psf_fseek (psf, pos, SEEK_SET) ; | |
340 | } ; | |
341 | } ; | |
342 | free (buffer) ; | |
343 | ||
344 | free (pmpeg->block) ; | |
345 | pmpeg->block = NULL ; | |
346 | ||
347 | if (pmpeg->lamef) | |
348 | { lame_close (pmpeg->lamef) ; | |
349 | pmpeg->lamef = NULL ; | |
350 | } ; | |
351 | ||
352 | return 0 ; | |
353 | } /* mpeg_l3_encoder_close */ | |
354 | ||
355 | static void | |
356 | mpeg_l3_encoder_log_config (SF_PRIVATE *psf, lame_t lamef) | |
357 | { const char *version ; | |
358 | const char *chn_mode ; | |
359 | ||
360 | switch (lame_get_version (lamef)) | |
361 | { case 0 : version = "2" ; break ; | |
362 | case 1 : version = "1" ; break ; | |
363 | case 2 : version = "2.5" ; break ; | |
364 | default : version = "unknown!?" ; break ; | |
365 | } ; | |
366 | switch (lame_get_mode (lamef)) | |
367 | { case STEREO : chn_mode = "stereo" ; break ; | |
368 | case JOINT_STEREO : chn_mode = "joint-stereo" ; break ; | |
369 | case MONO : chn_mode = "mono" ; break ; | |
370 | default : chn_mode = "unknown!?" ; break ; | |
371 | } ; | |
372 | psf_log_printf (psf, " MPEG Version : %s\n", version) ; | |
373 | psf_log_printf (psf, " Block samples : %d\n", lame_get_framesize (lamef)) ; | |
374 | psf_log_printf (psf, " Channel mode : %s\n", chn_mode) ; | |
375 | psf_log_printf (psf, " Samplerate : %d\n", lame_get_out_samplerate (lamef)) ; | |
376 | psf_log_printf (psf, " Encoder mode : ") ; | |
377 | switch (lame_get_VBR (lamef)) | |
378 | { case vbr_off : | |
379 | psf_log_printf (psf, "CBR\n") ; | |
380 | psf_log_printf (psf, " Bitrate : %d kbps\n", lame_get_brate (lamef)) ; | |
381 | break ; | |
382 | case vbr_abr : | |
383 | psf_log_printf (psf, "ABR\n") ; | |
384 | psf_log_printf (psf, " Mean Bitrate : %d kbps\n", lame_get_VBR_mean_bitrate_kbps (lamef)) ; | |
385 | break ; | |
386 | ||
387 | case vbr_mt : | |
388 | case vbr_default : | |
389 | psf_log_printf (psf, "VBR\n") ; | |
390 | psf_log_printf (psf, " Quality : %d\n", lame_get_VBR_q (lamef)) ; | |
391 | break ; | |
392 | ||
393 | default: | |
394 | psf_log_printf (psf, "Unknown!? (%d)\n", lame_get_VBR (lamef)) ; | |
395 | break ; | |
396 | } ; | |
397 | ||
398 | psf_log_printf (psf, " Encoder delay : %d\n", lame_get_encoder_delay (lamef)) ; | |
399 | psf_log_printf (psf, " Write INFO header : %d\n", lame_get_bWriteVbrTag (lamef)) ; | |
400 | } /* mpeg_l3_encoder_log_config */ | |
401 | ||
402 | static int | |
403 | mpeg_l3_encoder_construct (SF_PRIVATE *psf) | |
404 | { MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; | |
405 | int frame_samples_per_channel ; | |
406 | ||
407 | if (pmpeg->initialized == SF_FALSE) | |
408 | { if (lame_init_params (pmpeg->lamef) < 0) | |
409 | { psf_log_printf (psf, "Failed to initialize lame encoder!\n") ; | |
410 | return SFE_INTERNAL ; | |
411 | } ; | |
412 | ||
413 | psf_log_printf (psf, "Initialized LAME encoder.\n") ; | |
414 | mpeg_l3_encoder_log_config (psf, pmpeg->lamef) ; | |
415 | ||
416 | frame_samples_per_channel = lame_get_framesize (pmpeg->lamef) ; | |
417 | ||
418 | /* | |
419 | * Suggested output buffer size in bytes from lame.h comment is | |
420 | * 1.25 * samples + 7200 | |
421 | */ | |
422 | pmpeg->block_len = (frame_samples_per_channel * 4) / 3 + 7200 ; | |
423 | pmpeg->frame_samples = frame_samples_per_channel * psf->sf.channels ; | |
424 | ||
425 | pmpeg->block = malloc (pmpeg->block_len) ; | |
426 | if (!pmpeg->block) | |
427 | return SFE_MALLOC_FAILED ; | |
428 | ||
429 | pmpeg->initialized = SF_TRUE ; | |
430 | } ; | |
431 | ||
432 | return 0 ; | |
433 | } /* mpeg_l3_encoder_construct */ | |
434 | ||
435 | static int | |
436 | mpeg_l3_encoder_byterate (SF_PRIVATE *psf) | |
437 | { MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; | |
438 | int bitrate_mode ; | |
439 | int byterate ; | |
440 | float calculated_byterate ; | |
441 | ||
442 | bitrate_mode = mpeg_l3_encoder_get_bitrate_mode (psf) ; | |
443 | byterate = (lame_get_brate (pmpeg->lamef) + 7) / 8 ; | |
444 | ||
445 | if (bitrate_mode == SF_BITRATE_MODE_VARIABLE) | |
446 | { /* | |
447 | ** For VBR, lame_get_brate returns the minimum bitrate, so calculate the | |
448 | ** average byterate so far. | |
449 | */ | |
450 | calculated_byterate = psf_ftell (psf) - psf->dataoffset ; | |
451 | calculated_byterate /= (float) psf->write_current ; | |
452 | calculated_byterate *= (float) psf->sf.samplerate ; | |
453 | ||
454 | return SF_MIN (byterate, (int) calculated_byterate) ; | |
455 | } | |
456 | ||
457 | return byterate ; | |
458 | } /* mpeg_l3_encoder_byterate */ | |
459 | ||
460 | static sf_count_t | |
461 | mpeg_l3_encode_write_short_mono (SF_PRIVATE *psf, const short *ptr, sf_count_t len) | |
462 | { MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; | |
463 | sf_count_t total = 0 ; | |
464 | int nbytes, writecount, writen ; | |
465 | ||
466 | if ((psf->error = mpeg_l3_encoder_construct (psf))) | |
467 | return 0 ; | |
468 | ||
469 | while (len) | |
470 | { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; | |
471 | ||
472 | nbytes = lame_encode_buffer (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; | |
473 | if (nbytes < 0) | |
474 | { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; | |
475 | break ; | |
476 | } ; | |
477 | ||
478 | if (nbytes) | |
479 | { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; | |
480 | if (writen != nbytes) | |
481 | { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; | |
482 | } ; | |
483 | } ; | |
484 | ||
485 | total += writecount ; | |
486 | len -= writecount ; | |
487 | } ; | |
488 | ||
489 | return total ; | |
490 | } | |
491 | ||
492 | ||
493 | static sf_count_t | |
494 | mpeg_l3_encode_write_short_stereo (SF_PRIVATE *psf, const short *ptr, sf_count_t len) | |
495 | { BUF_UNION ubuf ; | |
496 | MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; | |
497 | sf_count_t total = 0 ; | |
498 | int nbytes, writecount, writen ; | |
499 | ||
500 | if ((psf->error = mpeg_l3_encoder_construct (psf))) | |
501 | return 0 ; | |
502 | ||
503 | const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.sbuf), pmpeg->frame_samples) ; | |
504 | while (len) | |
505 | { writecount = SF_MIN (len, max_samples) ; | |
506 | /* | |
507 | * An oversight, but lame_encode_buffer_interleaved() lacks a const. | |
508 | * As such, need another memcpy to not cause a warning. | |
509 | */ | |
510 | memcpy (ubuf.sbuf, ptr + total, writecount) ; | |
511 | nbytes = lame_encode_buffer_interleaved (pmpeg->lamef, ubuf.sbuf, writecount / 2, pmpeg->block, pmpeg->block_len) ; | |
512 | if (nbytes < 0) | |
513 | { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; | |
514 | break ; | |
515 | } ; | |
516 | ||
517 | if (nbytes) | |
518 | { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; | |
519 | if (writen != nbytes) | |
520 | { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; | |
521 | } ; | |
522 | } ; | |
523 | ||
524 | total += writecount ; | |
525 | len -= writecount ; | |
526 | } ; | |
527 | ||
528 | return total ; | |
529 | } | |
530 | ||
531 | ||
532 | static sf_count_t | |
533 | mpeg_l3_encode_write_int_mono (SF_PRIVATE *psf, const int *ptr, sf_count_t len) | |
534 | { MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; | |
535 | sf_count_t total = 0 ; | |
536 | int nbytes, writecount, writen ; | |
537 | ||
538 | if ((psf->error = mpeg_l3_encoder_construct (psf))) | |
539 | return 0 ; | |
540 | ||
541 | while (len) | |
542 | { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; | |
543 | ||
544 | nbytes = lame_encode_buffer_int (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; | |
545 | if (nbytes < 0) | |
546 | { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; | |
547 | break ; | |
548 | } ; | |
549 | ||
550 | if (nbytes) | |
551 | { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; | |
552 | if (writen != nbytes) | |
553 | { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; | |
554 | } ; | |
555 | } ; | |
556 | ||
557 | total += writecount ; | |
558 | len -= writecount ; | |
559 | } ; | |
560 | ||
561 | return total ; | |
562 | } | |
563 | ||
564 | ||
565 | static sf_count_t | |
566 | mpeg_l3_encode_write_int_stereo (SF_PRIVATE *psf, const int *ptr, sf_count_t len) | |
567 | { MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; | |
568 | sf_count_t total = 0 ; | |
569 | int nbytes, writecount, writen ; | |
570 | ||
571 | if ((psf->error = mpeg_l3_encoder_construct (psf))) | |
572 | return 0 ; | |
573 | ||
574 | while (len) | |
575 | { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; | |
576 | ||
577 | nbytes = lame_encode_buffer_interleaved_int (pmpeg->lamef, ptr + total, writecount / 2, pmpeg->block, pmpeg->block_len) ; | |
578 | if (nbytes < 0) | |
579 | { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; | |
580 | break ; | |
581 | } ; | |
582 | ||
583 | if (nbytes) | |
584 | { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; | |
585 | if (writen != nbytes) | |
586 | { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; | |
587 | } ; | |
588 | } ; | |
589 | ||
590 | total += writecount ; | |
591 | len -= writecount ; | |
592 | } ; | |
593 | ||
594 | return total ; | |
595 | } | |
596 | ||
597 | ||
598 | static sf_count_t | |
599 | mpeg_l3_encode_write_float_mono (SF_PRIVATE *psf, const float *ptr, sf_count_t len) | |
600 | { MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; | |
601 | sf_count_t total = 0 ; | |
602 | int nbytes, writecount, writen ; | |
603 | ||
604 | if ((psf->error = mpeg_l3_encoder_construct (psf))) | |
605 | return 0 ; | |
606 | ||
607 | while (len) | |
608 | { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; | |
609 | ||
610 | if (psf->norm_float) | |
611 | nbytes = lame_encode_buffer_ieee_float (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; | |
612 | else | |
613 | nbytes = lame_encode_buffer_float (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; | |
614 | if (nbytes < 0) | |
615 | { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; | |
616 | break ; | |
617 | } ; | |
618 | ||
619 | if (nbytes) | |
620 | { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; | |
621 | if (writen != nbytes) | |
622 | { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; | |
623 | } ; | |
624 | } ; | |
625 | ||
626 | total += writecount ; | |
627 | len -= writecount ; | |
628 | } ; | |
629 | ||
630 | return total ; | |
631 | } | |
632 | ||
633 | ||
634 | static inline void | |
635 | normalize_float (float *dest, const float *src, sf_count_t count, float norm_fact) | |
636 | { while (--count >= 0) | |
637 | { dest [count] = src [count] * norm_fact ; | |
638 | } ; | |
639 | } | |
640 | ||
641 | ||
642 | static sf_count_t | |
643 | mpeg_l3_encode_write_float_stereo (SF_PRIVATE *psf, const float *ptr, sf_count_t len) | |
644 | { BUF_UNION ubuf ; | |
645 | MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; | |
646 | sf_count_t total = 0 ; | |
647 | int nbytes, writecount, writen ; | |
648 | ||
649 | if ((psf->error = mpeg_l3_encoder_construct (psf))) | |
650 | return 0 ; | |
651 | ||
652 | const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.fbuf), pmpeg->frame_samples) ; | |
653 | while (len) | |
654 | { writecount = SF_MIN (len, max_samples) ; | |
655 | ||
656 | if (psf->norm_float) | |
657 | nbytes = lame_encode_buffer_interleaved_ieee_float (pmpeg->lamef, ptr + total, writecount / 2, pmpeg->block, pmpeg->block_len) ; | |
658 | else | |
659 | { /* Lame lacks a non-normalized interleaved float write. Bummer. */ | |
660 | normalize_float (ubuf.fbuf, ptr + total, writecount, 1.0 / (float) 0x8000) ; | |
661 | nbytes = lame_encode_buffer_interleaved_ieee_float (pmpeg->lamef, ubuf.fbuf, writecount / 2, pmpeg->block, pmpeg->block_len) ; | |
662 | } | |
663 | ||
664 | if (nbytes < 0) | |
665 | { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; | |
666 | break ; | |
667 | } ; | |
668 | ||
669 | if (nbytes) | |
670 | { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; | |
671 | if (writen != nbytes) | |
672 | { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; | |
673 | } ; | |
674 | } ; | |
675 | ||
676 | total += writecount ; | |
677 | len -= writecount ; | |
678 | } ; | |
679 | ||
680 | return total ; | |
681 | } | |
682 | ||
683 | ||
684 | static inline void | |
685 | normalize_double (double *dest, const double *src, sf_count_t count, double norm_fact) | |
686 | { while (--count >= 0) | |
687 | { dest [count] = src [count] * norm_fact ; | |
688 | } ; | |
689 | } | |
690 | ||
691 | ||
692 | static sf_count_t | |
693 | mpeg_l3_encode_write_double_mono (SF_PRIVATE *psf, const double *ptr, sf_count_t len) | |
694 | { BUF_UNION ubuf ; | |
695 | MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; | |
696 | sf_count_t total = 0 ; | |
697 | int nbytes, writecount, writen ; | |
698 | ||
699 | if ((psf->error = mpeg_l3_encoder_construct (psf))) | |
700 | return 0 ; | |
701 | ||
702 | const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.dbuf), pmpeg->frame_samples) ; | |
703 | while (len) | |
704 | { writecount = SF_MIN (len, max_samples) ; | |
705 | ||
706 | if (psf->norm_double) | |
707 | nbytes = lame_encode_buffer_ieee_double (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; | |
708 | else | |
709 | { /* Lame lacks non-normalized double writing */ | |
710 | normalize_double (ubuf.dbuf, ptr + total, writecount, 1.0 / (double) 0x8000) ; | |
711 | nbytes = lame_encode_buffer_ieee_double (pmpeg->lamef, ubuf.dbuf, NULL, writecount, pmpeg->block, pmpeg->block_len) ; | |
712 | } | |
713 | ||
714 | if (nbytes < 0) | |
715 | { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; | |
716 | break ; | |
717 | } ; | |
718 | ||
719 | if (nbytes) | |
720 | { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; | |
721 | if (writen != nbytes) | |
722 | { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; | |
723 | } ; | |
724 | } ; | |
725 | ||
726 | total += writecount ; | |
727 | len -= writecount ; | |
728 | } ; | |
729 | ||
730 | return total ; | |
731 | } | |
732 | ||
733 | ||
734 | static sf_count_t | |
735 | mpeg_l3_encode_write_double_stereo (SF_PRIVATE *psf, const double *ptr, sf_count_t len) | |
736 | { BUF_UNION ubuf ; | |
737 | MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; | |
738 | sf_count_t total = 0 ; | |
739 | int nbytes, writecount, writen ; | |
740 | ||
741 | if ((psf->error = mpeg_l3_encoder_construct (psf))) | |
742 | return 0 ; | |
743 | ||
744 | const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.dbuf), pmpeg->frame_samples) ; | |
745 | while (len) | |
746 | { writecount = SF_MIN (len, max_samples) ; | |
747 | ||
748 | if (psf->norm_double) | |
749 | nbytes = lame_encode_buffer_interleaved_ieee_double (pmpeg->lamef, ptr + total, writecount / 2, pmpeg->block, pmpeg->block_len) ; | |
750 | else | |
751 | { /* Lame lacks interleaved non-normalized double writing */ | |
752 | normalize_double (ubuf.dbuf, ptr + total, writecount, 1.0 / (double) 0x8000) ; | |
753 | nbytes = lame_encode_buffer_interleaved_ieee_double (pmpeg->lamef, ubuf.dbuf, writecount / 2, pmpeg->block, pmpeg->block_len) ; | |
754 | } | |
755 | ||
756 | if (nbytes < 0) | |
757 | { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; | |
758 | break ; | |
759 | } ; | |
760 | ||
761 | if (nbytes) | |
762 | { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; | |
763 | if (writen != nbytes) | |
764 | { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; | |
765 | } ; | |
766 | } ; | |
767 | ||
768 | total += writecount ; | |
769 | len -= writecount ; | |
770 | } ; | |
771 | ||
772 | return total ; | |
773 | } | |
774 | ||
775 | #else /* HAVE_MPEG */ | |
776 | ||
777 | int | |
778 | mpeg_l3_encoder_init (SF_PRIVATE *psf, int UNUSED (vbr)) | |
779 | { psf_log_printf (psf, "This version of libsndfile was compiled without MPEG Layer 3 encoding support.\n") ; | |
780 | return SFE_UNIMPLEMENTED ; | |
781 | } /* mpeg_l3_encoder_init */ | |
782 | ||
783 | #endif |
127 | 127 | if (psf->file.mode == SFM_WRITE) |
128 | 128 | samplesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ; |
129 | 129 | |
130 | if (blockalign < 7 * psf->sf.channels) | |
131 | { psf_log_printf (psf, "*** Error blockalign (%d) should be > %d.\n", blockalign, 7 * psf->sf.channels) ; | |
130 | /* There's 7 samples per channel in the preamble of each block */ | |
131 | if (samplesperblock < 7 * psf->sf.channels) | |
132 | { psf_log_printf (psf, "*** Error samplesperblock (%d) should be >= %d.\n", samplesperblock, 7 * psf->sf.channels) ; | |
133 | return SFE_INTERNAL ; | |
134 | } ; | |
135 | ||
136 | if (2 * blockalign < samplesperblock * psf->sf.channels) | |
137 | { psf_log_printf (psf, "*** Error blockalign (%d) should be >= %d.\n", blockalign, samplesperblock * psf->sf.channels / 2) ; | |
132 | 138 | return SFE_INTERNAL ; |
133 | 139 | } ; |
134 | 140 | |
223 | 229 | return 1 ; |
224 | 230 | } ; |
225 | 231 | |
226 | if ((k = psf_fread (pms->block, 1, pms->blocksize, psf)) != pms->blocksize) | |
232 | if ((k = (int) psf_fread (pms->block, 1, pms->blocksize, psf)) != pms->blocksize) | |
227 | 233 | { psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pms->blocksize) ; |
228 | 234 | if (k <= 0) |
229 | 235 | return 1 ; |
348 | 354 | while (len > 0) |
349 | 355 | { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; |
350 | 356 | |
351 | if ((count = msadpcm_read_block (psf, pms, ptr, readcount)) <= 0) | |
357 | if ((count = (int) msadpcm_read_block (psf, pms, ptr, readcount)) <= 0) | |
352 | 358 | return -1 ; |
353 | 359 | |
354 | 360 | total += count ; |
375 | 381 | sptr = ubuf.sbuf ; |
376 | 382 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
377 | 383 | while (len > 0) |
378 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
379 | ||
380 | if ((count = msadpcm_read_block (psf, pms, sptr, readcount)) <= 0) | |
384 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
385 | ||
386 | if ((count = (int) msadpcm_read_block (psf, pms, sptr, readcount)) <= 0) | |
381 | 387 | return -1 ; |
382 | 388 | |
383 | 389 | for (k = 0 ; k < readcount ; k++) |
407 | 413 | sptr = ubuf.sbuf ; |
408 | 414 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
409 | 415 | while (len > 0) |
410 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
411 | ||
412 | if ((count = msadpcm_read_block (psf, pms, sptr, readcount)) <= 0) | |
416 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
417 | ||
418 | if ((count = (int) msadpcm_read_block (psf, pms, sptr, readcount)) <= 0) | |
413 | 419 | return -1 ; |
414 | 420 | |
415 | 421 | for (k = 0 ; k < readcount ; k++) |
439 | 445 | sptr = ubuf.sbuf ; |
440 | 446 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
441 | 447 | while (len > 0) |
442 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
443 | ||
444 | if ((count = msadpcm_read_block (psf, pms, sptr, readcount)) <= 0) | |
448 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
449 | ||
450 | if ((count = (int) msadpcm_read_block (psf, pms, sptr, readcount)) <= 0) | |
445 | 451 | return -1 ; |
446 | 452 | |
447 | 453 | for (k = 0 ; k < readcount ; k++) |
626 | 632 | |
627 | 633 | /* Write the block to disk. */ |
628 | 634 | |
629 | if ((k = psf_fwrite (pms->block, 1, pms->blocksize, psf)) != pms->blocksize) | |
635 | if ((k = (int) psf_fwrite (pms->block, 1, pms->blocksize, psf)) != pms->blocksize) | |
630 | 636 | psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pms->blocksize) ; |
631 | 637 | |
632 | 638 | memset (pms->samples, 0, pms->samplesperblock * sizeof (short)) ; |
672 | 678 | while (len > 0) |
673 | 679 | { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; |
674 | 680 | |
675 | count = msadpcm_write_block (psf, pms, ptr, writecount) ; | |
681 | count = (int) msadpcm_write_block (psf, pms, ptr, writecount) ; | |
676 | 682 | |
677 | 683 | total += count ; |
678 | 684 | len -= count ; |
698 | 704 | sptr = ubuf.sbuf ; |
699 | 705 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
700 | 706 | while (len > 0) |
701 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
707 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
702 | 708 | for (k = 0 ; k < writecount ; k++) |
703 | 709 | sptr [k] = ptr [total + k] >> 16 ; |
704 | count = msadpcm_write_block (psf, pms, sptr, writecount) ; | |
710 | count = (int) msadpcm_write_block (psf, pms, sptr, writecount) ; | |
705 | 711 | total += count ; |
706 | 712 | len -= writecount ; |
707 | 713 | if (count != writecount) |
728 | 734 | sptr = ubuf.sbuf ; |
729 | 735 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
730 | 736 | while (len > 0) |
731 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
737 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
732 | 738 | for (k = 0 ; k < writecount ; k++) |
733 | 739 | sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; |
734 | count = msadpcm_write_block (psf, pms, sptr, writecount) ; | |
740 | count = (int) msadpcm_write_block (psf, pms, sptr, writecount) ; | |
735 | 741 | total += count ; |
736 | 742 | len -= writecount ; |
737 | 743 | if (count != writecount) |
758 | 764 | sptr = ubuf.sbuf ; |
759 | 765 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
760 | 766 | while (len > 0) |
761 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
767 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
762 | 768 | for (k = 0 ; k < writecount ; k++) |
763 | 769 | sptr [k] = psf_lrint (normfact * ptr [total + k]) ; |
764 | count = msadpcm_write_block (psf, pms, sptr, writecount) ; | |
770 | count = (int) msadpcm_write_block (psf, pms, sptr, writecount) ; | |
765 | 771 | total += count ; |
766 | 772 | len -= writecount ; |
767 | 773 | if (count != writecount) |
701 | 701 | psf_nms_adpcm_decode_block (SF_PRIVATE *psf, NMS_ADPCM_PRIVATE *pnms) |
702 | 702 | { int k ; |
703 | 703 | |
704 | if ((k = psf_fread (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock) | |
704 | if ((k = (int) psf_fread (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock) | |
705 | 705 | { psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pnms->shortsperblock) ; |
706 | 706 | memset (pnms->block + (k * sizeof (short)), 0, (pnms->shortsperblock - k) * sizeof (short)) ; |
707 | 707 | } ; |
784 | 784 | sptr = ubuf.sbuf ; |
785 | 785 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
786 | 786 | while (len > 0) |
787 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
787 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
788 | 788 | count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ; |
789 | 789 | |
790 | 790 | for (k = 0 ; k < readcount ; k++) |
817 | 817 | sptr = ubuf.sbuf ; |
818 | 818 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
819 | 819 | while (len > 0) |
820 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
820 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
821 | 821 | count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ; |
822 | 822 | for (k = 0 ; k < readcount ; k++) |
823 | 823 | ptr [total + k] = normfact * sptr [k] ; |
849 | 849 | sptr = ubuf.sbuf ; |
850 | 850 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
851 | 851 | while (len > 0) |
852 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
852 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
853 | 853 | count = nms_adpcm_read_block (psf, pnms, sptr, readcount) ; |
854 | 854 | for (k = 0 ; k < readcount ; k++) |
855 | 855 | ptr [total + k] = normfact * (double) (sptr [k]) ; |
874 | 874 | endswap_short_array ((signed short *) pnms->block, pnms->shortsperblock) ; |
875 | 875 | |
876 | 876 | /* Write the block to disk. */ |
877 | if ((k = psf_fwrite (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock) | |
877 | if ((k = (int) psf_fwrite (pnms->block, sizeof (short), pnms->shortsperblock, psf)) != pnms->shortsperblock) | |
878 | 878 | psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pnms->shortsperblock) ; |
879 | 879 | |
880 | 880 | pnms->sample_curr = 0 ; |
944 | 944 | sptr = ubuf.sbuf ; |
945 | 945 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
946 | 946 | while (len > 0) |
947 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
947 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
948 | 948 | for (k = 0 ; k < writecount ; k++) |
949 | 949 | sptr [k] = ptr [total + k] >> 16 ; |
950 | 950 | count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ; |
975 | 975 | sptr = ubuf.sbuf ; |
976 | 976 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
977 | 977 | while (len > 0) |
978 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
978 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
979 | 979 | for (k = 0 ; k < writecount ; k++) |
980 | 980 | sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; |
981 | 981 | count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ; |
1007 | 1007 | sptr = ubuf.sbuf ; |
1008 | 1008 | bufferlen = SF_BUFFER_LEN / sizeof (short) ; |
1009 | 1009 | while (len > 0) |
1010 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
1010 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
1011 | 1011 | for (k = 0 ; k < writecount ; k++) |
1012 | 1012 | sptr [k] = psf_lrint (normfact * ptr [total + k]) ; |
1013 | 1013 | count = nms_adpcm_write_block (psf, pnms, sptr, writecount) ; |
409 | 409 | opus_print_header (SF_PRIVATE *psf, OpusHeader *h) |
410 | 410 | { psf_log_printf (psf, "Opus Header Metadata\n") ; |
411 | 411 | psf_log_printf (psf, " OggOpus version : %d\n", h->version) ; |
412 | psf_log_printf (psf, " Channels : %d\n", h->channels) ; | |
413 | psf_log_printf (psf, " Preskip : %d samples @48kHz\n", h->preskip) ; | |
412 | psf_log_printf (psf, " Channels : %d\n", h->channels) ; | |
413 | psf_log_printf (psf, " Preskip : %d samples @48kHz\n", h->preskip) ; | |
414 | 414 | psf_log_printf (psf, " Input Samplerate : %d Hz\n", h->input_samplerate) ; |
415 | psf_log_printf (psf, " Gain : %d.%d\n", arith_shift_right (h->gain & 0xF0, 8), h->gain & 0x0F) ; | |
415 | psf_log_printf (psf, " Gain : %d.%d\n", arith_shift_right (h->gain & 0xF0, 8), h->gain & 0x0F) ; | |
416 | 416 | psf_log_printf (psf, " Channel Mapping : ") ; |
417 | 417 | switch (h->channel_mapping) |
418 | 418 | { case 0 : psf_log_printf (psf, "0 (mono or stereo)\n") ; break ; |
425 | 425 | { int i ; |
426 | 426 | psf_log_printf (psf, " streams total : %d\n", h->nb_streams) ; |
427 | 427 | psf_log_printf (psf, " streams coupled : %d\n", h->nb_coupled) ; |
428 | psf_log_printf (psf, " stream mapping : [") ; | |
428 | psf_log_printf (psf, " stream mapping : [") ; | |
429 | 429 | for (i = 0 ; i < h->channels - 1 ; i++) |
430 | 430 | psf_log_printf (psf, "%d,", h->stream_map [i]) ; |
431 | 431 | psf_log_printf (psf, "%d]\n", h->stream_map [i]) ; |
0 | 0 | /* |
1 | ** Copyright (C) 2018-2021 Arthur Taylor <art@ified.ca> | |
1 | 2 | ** Copyright (C) 2002-2016 Erik de Castro Lopo <erikd@mega-nerd.com> |
2 | 3 | ** Copyright (C) 2002-2005 Michael Smith <msmith@xiph.org> |
3 | 4 | ** Copyright (C) 2007 John ffitch |
18 | 19 | */ |
19 | 20 | |
20 | 21 | /* |
21 | ** Much of this code is based on the examples in libvorbis from the | |
22 | ** Much of this code is based on the examples in libvorbis from the | |
22 | 23 | ** XIPHOPHORUS Company http://www.xiph.org/ which has a BSD-style Licence |
23 | 24 | ** Copyright (c) 2002, Xiph.org Foundation |
24 | 25 | ** |
77 | 78 | |
78 | 79 | #include "ogg.h" |
79 | 80 | |
81 | /* How many seconds in the future to not bother bisection searching for. */ | |
82 | #define VORBIS_SEEK_THRESHOLD 2 | |
83 | ||
80 | 84 | typedef int convert_func (SF_PRIVATE *psf, int, void *, int, int, float **) ; |
81 | 85 | |
82 | 86 | static int vorbis_read_header (SF_PRIVATE *psf) ; |
84 | 88 | static int vorbis_close (SF_PRIVATE *psf) ; |
85 | 89 | static int vorbis_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; |
86 | 90 | static int vorbis_byterate (SF_PRIVATE *psf) ; |
87 | static sf_count_t vorbis_calculate_page_duration (SF_PRIVATE *psf) ; | |
91 | static int vorbis_calculate_granulepos (SF_PRIVATE *psf, uint64_t *gp_out) ; | |
92 | static int vorbis_skip (SF_PRIVATE *psf, uint64_t target_gp) ; | |
93 | static int vorbis_seek_trysearch (SF_PRIVATE *psf, uint64_t target_gp) ; | |
88 | 94 | static sf_count_t vorbis_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; |
89 | 95 | static sf_count_t vorbis_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; |
90 | 96 | static sf_count_t vorbis_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; |
114 | 120 | { SF_STR_ALBUM, "Album" }, |
115 | 121 | { SF_STR_LICENSE, "License" }, |
116 | 122 | { SF_STR_TRACKNUMBER, "Tracknumber" }, |
117 | { SF_STR_GENRE, "Genre" }, | |
123 | { SF_STR_GENRE, "Genre" }, | |
118 | 124 | } ; |
119 | 125 | |
120 | 126 | typedef struct |
121 | { /* Count current location */ | |
122 | sf_count_t loc ; | |
127 | { /* Current granule position. */ | |
128 | uint64_t gp ; | |
123 | 129 | /* Struct that stores all the static vorbis bitstream settings */ |
124 | 130 | vorbis_info vinfo ; |
125 | 131 | /* Struct that stores all the bitstream user comments */ |
126 | 132 | vorbis_comment vcomment ; |
127 | /* Ventral working state for the packet->PCM decoder */ | |
133 | /* Central working state for the packet->PCM decoder */ | |
128 | 134 | vorbis_dsp_state vdsp ; |
129 | 135 | /* Local working space for packet->PCM decode */ |
130 | 136 | vorbis_block vblock ; |
131 | ||
132 | 137 | /* Encoding quality in range [0.0, 1.0]. */ |
133 | 138 | double quality ; |
134 | ||
135 | /* Current granule position. */ | |
136 | uint64_t pcm_current ; | |
137 | 139 | /* Offset of the first samples' granule position. */ |
138 | 140 | uint64_t pcm_start ; |
139 | 141 | /* Last valid samples' granule position. */ |
146 | 148 | vorbis_read_header (SF_PRIVATE *psf) |
147 | 149 | { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; |
148 | 150 | VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; |
149 | sf_count_t duration ; | |
150 | 151 | int printed_metadata_msg = 0 ; |
151 | int i, k, nn ; | |
152 | int i, nn ; | |
153 | sf_count_t last_page ; | |
154 | sf_count_t saved_offset ; | |
152 | 155 | |
153 | 156 | /* |
154 | 157 | ** The first page of the Ogg stream we are told to try and open as Vorbis |
183 | 186 | ** Vorbis decoder. |
184 | 187 | ** |
185 | 188 | ** The next two packets in order are the comment and codebook headers. |
186 | ** They're likely large and may span multiple pages. Thus we reead | |
187 | ** and submit data until we get our two pacakets, watching that no | |
189 | ** They're likely large and may span multiple pages. Thus we read | |
190 | ** and submit data until we get our two packets, watching that no | |
188 | 191 | ** pages are missing. If a page is missing, error out ; losing a |
189 | 192 | ** header page is the only place where missing data is fatal. |
190 | 193 | */ |
230 | 233 | psf->dataoffset = ogg_sync_ftell (psf) ; |
231 | 234 | |
232 | 235 | /* |
233 | ** Caculate the granule position offset. The first page with a payload | |
236 | ** Calculate the granule position offset. The first page with a payload | |
234 | 237 | ** packet shouldn't end in a continued packet. The difference between the |
235 | 238 | ** page's granule position and the sum of frames on the page tells us the |
236 | 239 | ** granule position offset. |
237 | 240 | ** See https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-132000A.2 |
238 | 241 | */ |
239 | 242 | ogg_stream_unpack_page (psf, odata) ; |
240 | vdata->pcm_start = odata->pkt [odata->pkt_len - 1].granulepos ; | |
241 | duration = vorbis_calculate_page_duration (psf) ; | |
242 | ||
243 | if (duration < (sf_count_t) vdata->pcm_start) | |
244 | vdata->pcm_start -= duration ; | |
245 | else | |
246 | vdata->pcm_start = 0 ; | |
243 | vorbis_calculate_granulepos (psf, &vdata->pcm_start) ; | |
244 | vdata->gp = vdata->pcm_start ; | |
247 | 245 | |
248 | 246 | /* |
249 | 247 | ** Find the end of the stream, save it. Only works if the file is seekable. |
250 | 248 | */ |
251 | vdata->loc = vdata->pcm_start ; | |
252 | 249 | vdata->pcm_end = (uint64_t) -1 ; |
253 | 250 | psf->datalength = psf->filelength ; |
254 | 251 | if (!psf->is_pipe) |
255 | { sf_count_t last_page ; | |
256 | sf_count_t saved_offset ; | |
257 | ||
258 | saved_offset = ogg_sync_ftell (psf) ; | |
252 | { saved_offset = ogg_sync_ftell (psf) ; | |
259 | 253 | last_page = ogg_sync_last_page_before (psf, odata, &vdata->pcm_end, psf->filelength, odata->ostream.serialno) ; |
260 | 254 | if (last_page > 0) |
261 | 255 | { if (!ogg_page_eos (&odata->opage)) |
276 | 270 | psf_log_printf (psf, "PCM end : unknown\n") ; |
277 | 271 | |
278 | 272 | /* Throw the comments plus a few lines about the bitstream we're decoding. */ |
279 | for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++) | |
273 | for (i = 0 ; i < ARRAY_LEN (vorbis_metatypes) ; i++) | |
280 | 274 | { char *dd ; |
281 | 275 | |
282 | dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [k].name, 0) ; | |
276 | dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [i].name, 0) ; | |
283 | 277 | if (dd == NULL) |
284 | 278 | continue ; |
285 | 279 | |
288 | 282 | printed_metadata_msg = 1 ; |
289 | 283 | } ; |
290 | 284 | |
291 | psf_store_string (psf, vorbis_metatypes [k].id, dd) ; | |
292 | psf_log_printf (psf, " %-10s : %s\n", vorbis_metatypes [k].name, dd) ; | |
285 | psf_store_string (psf, vorbis_metatypes [i].id, dd) ; | |
286 | psf_log_printf (psf, " %-10s : %s\n", vorbis_metatypes [i].name, dd) ; | |
293 | 287 | } ; |
294 | 288 | psf_log_printf (psf, "End\n") ; |
295 | 289 | |
305 | 299 | |
306 | 300 | /* Local state for most of the decode so multiple block decodes can |
307 | 301 | ** proceed in parallel. We could init multiple vorbis_block structures |
308 | ** for vd here. */ | |
302 | ** for vdsp here. */ | |
309 | 303 | vorbis_block_init (&vdata->vdsp, &vdata->vblock) ; |
310 | 304 | |
311 | 305 | return 0 ; |
333 | 327 | if (ret) |
334 | 328 | return SFE_BAD_OPEN_FORMAT ; |
335 | 329 | |
336 | vdata->loc = 0 ; | |
330 | vdata->gp = 0 ; | |
337 | 331 | |
338 | 332 | /* add a comment */ |
339 | 333 | vorbis_comment_init (&vdata->vcomment) ; |
347 | 341 | |
348 | 342 | switch (psf->strings.data [k].type) |
349 | 343 | { case SF_STR_TITLE : name = "TITLE" ; break ; |
350 | case SF_STR_COPYRIGHT : name = "COPYRIGHT" ; break ; | |
344 | case SF_STR_COPYRIGHT : name = "COPYRIGHT" ; break ; | |
351 | 345 | case SF_STR_SOFTWARE : name = "SOFTWARE" ; break ; |
352 | 346 | case SF_STR_ARTIST : name = "ARTIST" ; break ; |
353 | 347 | case SF_STR_COMMENT : name = "COMMENT" ; break ; |
354 | 348 | case SF_STR_DATE : name = "DATE" ; break ; |
355 | 349 | case SF_STR_ALBUM : name = "ALBUM" ; break ; |
356 | 350 | case SF_STR_LICENSE : name = "LICENSE" ; break ; |
357 | case SF_STR_TRACKNUMBER : name = "Tracknumber" ; break ; | |
358 | case SF_STR_GENRE : name = "Genre" ; break ; | |
351 | case SF_STR_TRACKNUMBER : name = "Tracknumber" ; break ; | |
352 | case SF_STR_GENRE : name = "Genre" ; break ; | |
359 | 353 | |
360 | 354 | default : continue ; |
361 | 355 | } ; |
635 | 629 | len -= samples ; |
636 | 630 | /* tell libvorbis how many samples we actually consumed */ |
637 | 631 | vorbis_synthesis_read (&vdata->vdsp, samples) ; |
638 | vdata->loc += samples ; | |
632 | vdata->gp += samples ; | |
639 | 633 | if (len == 0) |
640 | return i ; /* Is this necessary */ | |
634 | return i ; | |
641 | 635 | } ; |
642 | 636 | |
643 | 637 | /* Out of samples, load the next packet. */ |
647 | 641 | if (nn <= 0) |
648 | 642 | return i ; |
649 | 643 | if (nn == 2) |
650 | { /* Ran over a hole. loc is now out of date, need to recalculate. */ | |
651 | vdata->loc = odata->pkt [odata->pkt_len - 1].granulepos ; | |
652 | vdata->loc -= vorbis_calculate_page_duration (psf) ; | |
644 | { /* Ran over a hole. gp is now out of date, need to recalculate. */ | |
645 | vorbis_synthesis_restart (&vdata->vdsp) ; | |
646 | vorbis_calculate_granulepos (psf, &vdata->gp) ; | |
653 | 647 | } |
654 | 648 | } ; |
655 | 649 | |
721 | 715 | } ; |
722 | 716 | } ; |
723 | 717 | |
724 | vdata->loc += in_frames ; | |
718 | vdata->gp += in_frames ; | |
725 | 719 | } /* vorbis_write_data */ |
726 | 720 | |
727 | 721 | |
790 | 784 | return lens ; |
791 | 785 | } /* vorbis_write_d */ |
792 | 786 | |
787 | static int | |
788 | vorbis_skip (SF_PRIVATE *psf, uint64_t target) | |
789 | { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; | |
790 | VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; | |
791 | ogg_packet *pkt ; | |
792 | int thisblock, lastblock, nn ; | |
793 | const int blocksize = vorbis_info_blocksize (&vdata->vinfo, 1) ; | |
794 | ||
795 | /* Read out any samples that may be in the decoder from a seek without a | |
796 | ** search. */ | |
797 | thisblock = vorbis_synthesis_pcmout (&vdata->vdsp, NULL) ; | |
798 | if (thisblock > 0) | |
799 | { if ((uint64_t) thisblock + vdata->gp >= target) | |
800 | thisblock = SF_MIN (thisblock, (int) (target - vdata->gp)) ; | |
801 | ||
802 | vorbis_synthesis_read (&vdata->vdsp, thisblock) ; | |
803 | vdata->gp += thisblock ; | |
804 | if (vdata->gp == target) | |
805 | return 0 ; | |
806 | } ; | |
807 | ||
808 | /* Read through packets that are before our target */ | |
809 | lastblock = 0 ; | |
810 | for ( ; vdata->gp < target ; ) | |
811 | { /* Ensure there are unpacked packets. */ | |
812 | if (odata->pkt_indx == odata->pkt_len) | |
813 | { /* Page out of packets, load and unpack the next page. */ | |
814 | nn = ogg_stream_unpack_page (psf, odata) ; | |
815 | if (nn < 0) | |
816 | return nn ; | |
817 | if (nn == 0) | |
818 | break ; | |
819 | if (nn == 2) | |
820 | { /* Ran over a hole. gp is now out of date, need to recalculate. */ | |
821 | vorbis_synthesis_restart (&vdata->vdsp) ; | |
822 | vorbis_calculate_granulepos (psf, &vdata->gp) ; | |
823 | if (target < vdata->gp) | |
824 | { /* Our target is inside the hole :-( */ | |
825 | return 0 ; | |
826 | } ; | |
827 | } ; | |
828 | } ; | |
829 | ||
830 | pkt = &odata->pkt [odata->pkt_indx] ; | |
831 | thisblock = vorbis_packet_blocksize (&vdata->vinfo, pkt) ; | |
832 | if (thisblock < 0) | |
833 | { /* Not an audio packet */ | |
834 | odata->pkt_indx++ ; | |
835 | continue ; | |
836 | } ; | |
837 | ||
838 | if (lastblock) | |
839 | { vdata->gp += ((lastblock + thisblock) / 4) ; | |
840 | } ; | |
841 | ||
842 | /* Check to see if the block contains our target */ | |
843 | if (vdata->gp + ((thisblock + blocksize) / 4) >= target) | |
844 | break ; | |
845 | ||
846 | /* Block is before the target. Track for state, but don't decode. */ | |
847 | odata->pkt_indx++ ; | |
848 | vorbis_synthesis_trackonly (&vdata->vblock, pkt) ; | |
849 | vorbis_synthesis_blockin (&vdata->vdsp, &vdata->vblock) ; | |
850 | lastblock = thisblock ; | |
851 | } ; | |
852 | ||
853 | /* We are at the correct block, but still need to consume samples to reach | |
854 | ** our target. */ | |
855 | vorbis_read_sample (psf, (void *) NULL, (target - vdata->gp) * psf->sf.channels, vorbis_rnull) ; | |
856 | ||
857 | return 0 ; | |
858 | } /* vorbis_skip */ | |
859 | ||
860 | static int | |
861 | vorbis_seek_trysearch (SF_PRIVATE *psf, uint64_t target_gp) | |
862 | { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; | |
863 | VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; | |
864 | uint64_t best_gp, search_target_gp ; | |
865 | int ret ; | |
866 | ||
867 | /* Can't bisect a file we don't know the end of (cannot seek). */ | |
868 | if (vdata->pcm_end == (uint64_t) -1) | |
869 | return 0 ; | |
870 | ||
871 | /* If the target is for the near future, don't bother bisecting, just skip | |
872 | ** to it. */ | |
873 | if (target_gp >= vdata->gp && | |
874 | target_gp - vdata->gp < ((unsigned) (VORBIS_SEEK_THRESHOLD) * psf->sf.samplerate)) | |
875 | return 0 ; | |
876 | ||
877 | /* Search for a position a half large-block before our target. As Vorbis is | |
878 | ** lapped, every sample position come from two blocks, the "left" half of | |
879 | ** one block and the "right" half of the previous block. The granule | |
880 | ** position of an Ogg page of a Vorbis stream is the sample offset of the | |
881 | ** last finished sample in the stream that can be decoded from a page. A | |
882 | ** page also contains another half-block of samples waiting to be lapped | |
883 | ** with the first half-block of samples from the next page. | |
884 | ** | |
885 | ** Searching for a sample one half of a large block before our target | |
886 | ** guarantees we always load a page containing the previous half block | |
887 | ** required to decode the target. Downside is we can't use best_gp | |
888 | ** parameter of the page seek function. */ | |
889 | search_target_gp = vorbis_info_blocksize (&vdata->vinfo, 1) / 2 ; | |
890 | search_target_gp = search_target_gp < target_gp ? target_gp - search_target_gp : 0 ; | |
891 | ||
892 | ret = ogg_stream_seek_page_search (psf, odata, search_target_gp, vdata->pcm_start, | |
893 | vdata->pcm_end, &best_gp, psf->dataoffset, vdata->last_page) ; | |
894 | if (ret < 0) | |
895 | return ret ; | |
896 | ||
897 | ret = ogg_stream_unpack_page (psf, odata) ; | |
898 | if (ret > 0) | |
899 | { /* Reset the decoder, recalculate position */ | |
900 | vorbis_synthesis_restart (&vdata->vdsp) ; | |
901 | ret = vorbis_calculate_granulepos (psf, &vdata->gp) ; | |
902 | } ; | |
903 | ||
904 | return ret ; | |
905 | } /* vorbis_seek_trysearch */ | |
906 | ||
793 | 907 | static sf_count_t |
794 | 908 | vorbis_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset) |
795 | 909 | { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; |
796 | 910 | VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; |
797 | sf_count_t target ; | |
911 | uint64_t target_gp ; | |
798 | 912 | int ret ; |
799 | 913 | |
800 | 914 | if (odata == NULL || vdata == NULL) |
806 | 920 | } ; |
807 | 921 | |
808 | 922 | if (psf->file.mode == SFM_READ) |
809 | { target = offset + vdata->pcm_start ; | |
810 | ||
811 | /* | |
812 | ** If the end of the file is know, and the seek isn't for the near | |
813 | ** future, do a search of the file for a good place to start. | |
814 | */ | |
815 | ret = 0 ; | |
816 | if ((vdata->pcm_end != (uint64_t) -1) && | |
817 | (target < vdata->loc || target - vdata->loc > (2 * psf->sf.samplerate))) | |
818 | { uint64_t best_gp ; | |
819 | ||
820 | best_gp = vdata->pcm_start ; | |
821 | ||
822 | ret = ogg_stream_seek_page_search (psf, odata, target, vdata->pcm_start, | |
823 | vdata->pcm_end, &best_gp, psf->dataoffset, vdata->last_page) ; | |
824 | if (ret >= 0) | |
825 | { ret = ogg_stream_unpack_page (psf, odata) ; | |
826 | if (ret == 1) | |
827 | { vdata->loc = best_gp ; | |
828 | vorbis_synthesis_restart (&vdata->vdsp) ; | |
829 | } ; | |
830 | } ; | |
831 | } ; | |
832 | ||
833 | if (ret >= 0 && offset + (sf_count_t) vdata->pcm_start >= vdata->loc) | |
834 | target = offset + vdata->pcm_start - vdata->loc ; | |
835 | else | |
923 | { target_gp = (uint64_t) offset + vdata->pcm_start ; | |
924 | ||
925 | ret = vorbis_seek_trysearch (psf, target_gp) ; | |
926 | ||
927 | if (ret < 0 || vdata->gp > target_gp) | |
836 | 928 | { /* Search failed (bad data?), reset to the beginning of the stream. */ |
929 | psf_log_printf (psf, "Vorbis: Seek search failed. Reading through stream from start.\n") ; | |
837 | 930 | ogg_stream_reset_serialno (&odata->ostream, odata->ostream.serialno) ; |
838 | 931 | odata->pkt_len = 0 ; |
839 | 932 | odata->pkt_indx = 0 ; |
840 | 933 | ogg_sync_fseek (psf, psf->dataoffset, SEEK_SET) ; |
841 | vdata->loc = 0 ; | |
934 | vdata->gp = vdata->pcm_start ; | |
842 | 935 | vorbis_synthesis_restart (&vdata->vdsp) ; |
843 | target = offset ; | |
844 | } ; | |
845 | ||
846 | while (target > 0) | |
847 | { sf_count_t m = target > 4096 ? 4096 : target ; | |
848 | ||
849 | /* | |
850 | ** Need to multiply by channels here because the seek is done in | |
851 | ** terms of frames and the read function is done in terms of | |
852 | ** samples. | |
853 | */ | |
854 | vorbis_read_sample (psf, (void *) NULL, m * psf->sf.channels, vorbis_rnull) ; | |
855 | ||
856 | target -= m ; | |
857 | } ; | |
858 | ||
859 | return vdata->loc - vdata->pcm_start ; | |
860 | } ; | |
861 | ||
862 | return 0 ; | |
936 | } ; | |
937 | ||
938 | vorbis_skip (psf, target_gp) ; | |
939 | ||
940 | return vdata->gp - vdata->pcm_start ; | |
941 | } ; | |
942 | ||
943 | psf->error = SFE_BAD_SEEK ; | |
944 | return ((sf_count_t) -1) ; | |
863 | 945 | } /* vorbis_seek */ |
864 | ||
865 | 946 | |
866 | 947 | static int |
867 | 948 | vorbis_byterate (SF_PRIVATE *psf) |
872 | 953 | return -1 ; |
873 | 954 | } /* vorbis_byterate */ |
874 | 955 | |
875 | static sf_count_t | |
876 | vorbis_calculate_page_duration (SF_PRIVATE *psf) | |
956 | static int | |
957 | vorbis_calculate_granulepos (SF_PRIVATE *psf, uint64_t *gp_out) | |
877 | 958 | { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; |
878 | 959 | VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; |
879 | long thisblock, lastblock ; | |
880 | sf_count_t duration ; | |
881 | int i ; | |
882 | ||
883 | lastblock = -1 ; | |
884 | duration = 0 ; | |
885 | for (i = 0 ; i < odata->pkt_len ; i++) | |
886 | { thisblock = vorbis_packet_blocksize (&vdata->vinfo, &(odata->pkt [i])) ; | |
887 | if (thisblock >= 0) | |
888 | { if (lastblock != -1) | |
889 | duration += (lastblock + thisblock) >> 2 ; | |
890 | lastblock = thisblock ; | |
891 | } ; | |
892 | } ; | |
893 | ||
894 | return duration ; | |
895 | } | |
960 | ogg_packet *pkt ; | |
961 | uint64_t last_gp ; | |
962 | int thisblock, lastblock, i ; | |
963 | unsigned duration ; | |
964 | ||
965 | /* Calculate the granule position when dropped into the middle of a stream | |
966 | ** with an un-primed decoder. | |
967 | ** | |
968 | ** Normally the last unpacked packet contains the granule position of the | |
969 | ** last completed sample from decoding all the blocks in the page's | |
970 | ** packets. By calculating how many samples we can decode from the blocks | |
971 | ** in the page's packets and subtracting it from the final packet's granule | |
972 | ** position we get the position of the first sample to be output from the | |
973 | ** decoder after it primes. That is, the current granule position. | |
974 | ** | |
975 | ** However, there is an ambiguity if this is the last page of a stream. The | |
976 | ** last page of a stream may have a granule position of fewer samples than | |
977 | ** the page actually contains. The excess samples are padding leftovers | |
978 | ** for and exact sample length file. */ | |
979 | ||
980 | if (odata->pkt_len > 0) | |
981 | { /* Calculate how many samples can be decoded from blocks in this page, | |
982 | ** accounting for the fact that blocks are 1/2 lapped. */ | |
983 | lastblock = -1 ; | |
984 | duration = 0 ; | |
985 | pkt = odata->pkt ; | |
986 | for (i = 0 ; i < odata->pkt_len ; i++) | |
987 | { thisblock = vorbis_packet_blocksize (&vdata->vinfo, &pkt [i]) ; | |
988 | if (thisblock >= 0) | |
989 | { if (lastblock != -1) | |
990 | duration += (lastblock + thisblock) >> 2 ; | |
991 | lastblock = thisblock ; | |
992 | } ; | |
993 | } ; | |
994 | ||
995 | pkt = &odata->pkt [odata->pkt_len - 1] ; | |
996 | last_gp = pkt->granulepos ; | |
997 | if (last_gp == (uint64_t) -1) | |
998 | { psf_log_printf (psf, "Vorbis: Ogg page has no granule position, cannot calculate sample position!\n") ; | |
999 | psf->error = SFE_MALFORMED_FILE ; | |
1000 | return -1 ; | |
1001 | } ; | |
1002 | ||
1003 | if (pkt->e_o_s) | |
1004 | { if (last_gp <= duration) | |
1005 | { /* Corner case: One page stream. Ogg/Vorbis spec dictates the | |
1006 | ** granule position offset MUST be zero, hence this first (and | |
1007 | ** only) page must start at 0. */ | |
1008 | *gp_out = 0 ; | |
1009 | return 1 ; | |
1010 | } ; | |
1011 | ||
1012 | /* Otherwise, we cannot know where we are without looking at the | |
1013 | ** blocks of the previous page. (The granule position of the | |
1014 | ** previous page is not enough, we need the block sizes.) | |
1015 | ** | |
1016 | ** We avoid this case by never allowing a bisection search to seek | |
1017 | ** beyond the second-to-last page, so the last page is always | |
1018 | ** approached with a known location and never dropped into. | |
1019 | ** | |
1020 | ** The only way we should be able to end up here is if there was a | |
1021 | ** hole in stream just before the last page, in which case all bets | |
1022 | ** are off anyways. */ | |
1023 | psf_log_printf (psf, "Vorbis: Cannot calculate ambiguous last page duration. Sample count may be wrong.\n") ; | |
1024 | } ; | |
1025 | ||
1026 | if (last_gp < duration) | |
1027 | { psf_log_printf (psf, "Vorbis: Granule position is nonsensical! (Missing end-of-stream marker?)\n") ; | |
1028 | psf->error = SFE_MALFORMED_FILE ; | |
1029 | return -1 ; | |
1030 | } ; | |
1031 | ||
1032 | *gp_out = last_gp - duration ; | |
1033 | return 1 ; | |
1034 | } ; | |
1035 | ||
1036 | return 0 ; | |
1037 | } /* vorbis_calculate_granulepos */ | |
896 | 1038 | |
897 | 1039 | #else /* HAVE_EXTERNAL_XIPH_LIBS */ |
898 | 1040 |
492 | 492 | } ; |
493 | 493 | |
494 | 494 | /* Read the block. */ |
495 | if ((k = psf_fread (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize) | |
495 | if ((k = (int) psf_fread (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize) | |
496 | 496 | psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, ppaf24->blocksize) ; |
497 | 497 | |
498 | 498 | /* Do endian swapping if necessary. */ |
548 | 548 | iptr = ubuf.ibuf ; |
549 | 549 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
550 | 550 | while (len > 0) |
551 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
551 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
552 | 552 | count = paf24_read (psf, ppaf24, iptr, readcount) ; |
553 | 553 | for (k = 0 ; k < readcount ; k++) |
554 | 554 | ptr [total + k] = iptr [k] >> 16 ; |
590 | 590 | iptr = ubuf.ibuf ; |
591 | 591 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
592 | 592 | while (len > 0) |
593 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
593 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
594 | 594 | count = paf24_read (psf, ppaf24, iptr, readcount) ; |
595 | 595 | for (k = 0 ; k < readcount ; k++) |
596 | 596 | ptr [total + k] = normfact * iptr [k] ; |
618 | 618 | iptr = ubuf.ibuf ; |
619 | 619 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
620 | 620 | while (len > 0) |
621 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
621 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
622 | 622 | count = paf24_read (psf, ppaf24, iptr, readcount) ; |
623 | 623 | for (k = 0 ; k < readcount ; k++) |
624 | 624 | ptr [total + k] = normfact * iptr [k] ; |
667 | 667 | } ; |
668 | 668 | |
669 | 669 | /* Write block to disk. */ |
670 | if ((k = psf_fwrite (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize) | |
670 | if ((k = (int) psf_fwrite (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize) | |
671 | 671 | psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, ppaf24->blocksize) ; |
672 | 672 | |
673 | 673 | if (ppaf24->sample_count < ppaf24->write_block * PAF24_SAMPLES_PER_BLOCK + ppaf24->write_count) |
717 | 717 | iptr = ubuf.ibuf ; |
718 | 718 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
719 | 719 | while (len > 0) |
720 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
720 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
721 | 721 | for (k = 0 ; k < writecount ; k++) |
722 | 722 | iptr [k] = ptr [total + k] << 16 ; |
723 | 723 | count = paf24_write (psf, ppaf24, iptr, writecount) ; |
771 | 771 | iptr = ubuf.ibuf ; |
772 | 772 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
773 | 773 | while (len > 0) |
774 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
774 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
775 | 775 | for (k = 0 ; k < writecount ; k++) |
776 | 776 | iptr [k] = psf_lrintf (normfact * ptr [total + k]) ; |
777 | 777 | count = paf24_write (psf, ppaf24, iptr, writecount) ; |
802 | 802 | iptr = ubuf.ibuf ; |
803 | 803 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
804 | 804 | while (len > 0) |
805 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
805 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
806 | 806 | for (k = 0 ; k < writecount ; k++) |
807 | 807 | iptr [k] = psf_lrint (normfact * ptr [total+k]) ; |
808 | 808 | count = paf24_write (psf, ppaf24, iptr, writecount) ; |
133 | 133 | else if ((SF_CODEC (psf->sf.format)) == SF_FORMAT_PCM_U8) |
134 | 134 | chars = SF_CHARS_UNSIGNED ; |
135 | 135 | |
136 | if (CPU_IS_BIG_ENDIAN) | |
137 | psf->data_endswap = (psf->endian == SF_ENDIAN_BIG) ? SF_FALSE : SF_TRUE ; | |
138 | else | |
139 | psf->data_endswap = (psf->endian == SF_ENDIAN_LITTLE) ? SF_FALSE : SF_TRUE ; | |
136 | #if CPU_IS_BIG_ENDIAN | |
137 | psf->data_endswap = (psf->endian == SF_ENDIAN_BIG) ? SF_FALSE : SF_TRUE ; | |
138 | #else | |
139 | psf->data_endswap = (psf->endian == SF_ENDIAN_LITTLE) ? SF_FALSE : SF_TRUE ; | |
140 | #endif | |
140 | 141 | |
141 | 142 | if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR) |
142 | 143 | { switch (psf->bytewidth * 0x10000 + psf->endian + chars) |
282 | 283 | |
283 | 284 | static inline void |
284 | 285 | sc2s_array (const signed char *src, int count, short *dest) |
285 | { while (--count >= 0) | |
286 | { dest [count] = ((uint16_t) src [count]) << 8 ; | |
286 | { for (int i = 0 ; i < count ; i++) | |
287 | { dest [i] = ((uint16_t) src [i]) << 8 ; | |
287 | 288 | } ; |
288 | 289 | } /* sc2s_array */ |
289 | 290 | |
290 | 291 | static inline void |
291 | 292 | uc2s_array (const unsigned char *src, int count, short *dest) |
292 | { while (--count >= 0) | |
293 | { dest [count] = (((uint32_t) src [count]) - 0x80) << 8 ; | |
293 | { for (int i = 0 ; i < count ; i++) | |
294 | { dest [i] = (((uint32_t) src [i]) - 0x80) << 8 ; | |
294 | 295 | } ; |
295 | 296 | } /* uc2s_array */ |
296 | 297 | |
297 | 298 | static inline void |
298 | 299 | let2s_array (const tribyte *src, int count, short *dest) |
299 | { while (--count >= 0) | |
300 | dest [count] = LET2H_16_PTR (src [count].bytes) ; | |
300 | { for (int i = 0 ; i < count ; i++) | |
301 | dest [i] = LET2H_16_PTR (src [i].bytes) ; | |
301 | 302 | } /* let2s_array */ |
302 | 303 | |
303 | 304 | static inline void |
304 | 305 | bet2s_array (const tribyte *src, int count, short *dest) |
305 | { while (--count >= 0) | |
306 | dest [count] = BET2H_16_PTR (src [count].bytes) ; | |
306 | { for (int i = 0 ; i < count ; i++) | |
307 | dest [i] = BET2H_16_PTR (src [i].bytes) ; | |
307 | 308 | } /* bet2s_array */ |
308 | 309 | |
309 | 310 | static inline void |
310 | 311 | lei2s_array (const int *src, int count, short *dest) |
311 | 312 | { int value ; |
312 | 313 | |
313 | while (--count >= 0) | |
314 | { value = LE2H_32 (src [count]) ; | |
315 | dest [count] = value >> 16 ; | |
314 | for (int i = 0 ; i < count ; i++) | |
315 | { value = LE2H_32 (src [i]) ; | |
316 | dest [i] = value >> 16 ; | |
316 | 317 | } ; |
317 | 318 | } /* lei2s_array */ |
318 | 319 | |
320 | 321 | bei2s_array (const int *src, int count, short *dest) |
321 | 322 | { int value ; |
322 | 323 | |
323 | while (--count >= 0) | |
324 | { value = BE2H_32 (src [count]) ; | |
325 | dest [count] = value >> 16 ; | |
324 | for (int i = 0 ; i < count ; i++) | |
325 | { value = BE2H_32 (src [i]) ; | |
326 | dest [i] = value >> 16 ; | |
326 | 327 | } ; |
327 | 328 | } /* bei2s_array */ |
328 | 329 | |
331 | 332 | |
332 | 333 | static inline void |
333 | 334 | sc2i_array (const signed char *src, int count, int *dest) |
334 | { while (--count >= 0) | |
335 | { dest [count] = arith_shift_left ((int) src [count], 24) ; | |
335 | { for (int i = 0 ; i < count ; i++) | |
336 | { dest [i] = arith_shift_left ((int) src [i], 24) ; | |
336 | 337 | } ; |
337 | 338 | } /* sc2i_array */ |
338 | 339 | |
339 | 340 | static inline void |
340 | 341 | uc2i_array (const unsigned char *src, int count, int *dest) |
341 | { while (--count >= 0) | |
342 | { dest [count] = arith_shift_left (((int) src [count]) - 128, 24) ; | |
342 | { for (int i = 0 ; i < count ; i++) | |
343 | { dest [i] = arith_shift_left (((int) src [i]) - 128, 24) ; | |
343 | 344 | } ; |
344 | 345 | } /* uc2i_array */ |
345 | 346 | |
347 | 348 | bes2i_array (const short *src, int count, int *dest) |
348 | 349 | { short value ; |
349 | 350 | |
350 | while (--count >= 0) | |
351 | { value = BE2H_16 (src [count]) ; | |
352 | dest [count] = arith_shift_left (value, 16) ; | |
351 | for (int i = 0 ; i < count ; i++) | |
352 | { value = BE2H_16 (src [i]) ; | |
353 | dest [i] = arith_shift_left (value, 16) ; | |
353 | 354 | } ; |
354 | 355 | } /* bes2i_array */ |
355 | 356 | |
357 | 358 | les2i_array (const short *src, int count, int *dest) |
358 | 359 | { short value ; |
359 | 360 | |
360 | while (--count >= 0) | |
361 | { value = LE2H_16 (src [count]) ; | |
362 | dest [count] = arith_shift_left (value, 16) ; | |
361 | for (int i = 0 ; i < count ; i++) | |
362 | { value = LE2H_16 (src [i]) ; | |
363 | dest [i] = arith_shift_left (value, 16) ; | |
363 | 364 | } ; |
364 | 365 | } /* les2i_array */ |
365 | 366 | |
366 | 367 | static inline void |
367 | 368 | bet2i_array (const tribyte *src, int count, int *dest) |
368 | { while (--count >= 0) | |
369 | dest [count] = psf_get_be24 (src [count].bytes, 0) ; | |
369 | { for (int i = 0 ; i < count ; i++) | |
370 | dest [i] = psf_get_be24 (src [i].bytes, 0) ; | |
370 | 371 | } /* bet2i_array */ |
371 | 372 | |
372 | 373 | static inline void |
373 | 374 | let2i_array (const tribyte *src, int count, int *dest) |
374 | { while (--count >= 0) | |
375 | dest [count] = psf_get_le24 (src [count].bytes, 0) ; | |
375 | { for (int i = 0 ; i < count ; i++) | |
376 | dest [i] = psf_get_le24 (src [i].bytes, 0) ; | |
376 | 377 | } /* let2i_array */ |
377 | 378 | |
378 | 379 | /*-------------------------------------------------------------------------- |
380 | 381 | |
381 | 382 | static inline void |
382 | 383 | sc2f_array (const signed char *src, int count, float *dest, float normfact) |
383 | { while (--count >= 0) | |
384 | dest [count] = ((float) src [count]) * normfact ; | |
384 | { for (int i = 0 ; i < count ; i++) | |
385 | dest [i] = ((float) src [i]) * normfact ; | |
385 | 386 | } /* sc2f_array */ |
386 | 387 | |
387 | 388 | static inline void |
388 | 389 | uc2f_array (const unsigned char *src, int count, float *dest, float normfact) |
389 | { while (--count >= 0) | |
390 | dest [count] = (((int) src [count]) - 128) * normfact ; | |
390 | { for (int i = 0 ; i < count ; i++) | |
391 | dest [i] = (((int) src [i]) - 128) * normfact ; | |
391 | 392 | } /* uc2f_array */ |
392 | 393 | |
393 | 394 | static inline void |
394 | 395 | les2f_array (const short *src, int count, float *dest, float normfact) |
395 | 396 | { short value ; |
396 | 397 | |
397 | while (--count >= 0) | |
398 | { value = src [count] ; | |
398 | for (int i = 0 ; i < count ; i++) | |
399 | { value = src [i] ; | |
399 | 400 | value = LE2H_16 (value) ; |
400 | dest [count] = ((float) value) * normfact ; | |
401 | dest [i] = ((float) value) * normfact ; | |
401 | 402 | } ; |
402 | 403 | } /* les2f_array */ |
403 | 404 | |
405 | 406 | bes2f_array (const short *src, int count, float *dest, float normfact) |
406 | 407 | { short value ; |
407 | 408 | |
408 | while (--count >= 0) | |
409 | { value = src [count] ; | |
409 | for (int i = 0 ; i < count ; i++) | |
410 | { value = src [i] ; | |
410 | 411 | value = BE2H_16 (value) ; |
411 | dest [count] = ((float) value) * normfact ; | |
412 | dest [i] = ((float) value) * normfact ; | |
412 | 413 | } ; |
413 | 414 | } /* bes2f_array */ |
414 | 415 | |
416 | 417 | let2f_array (const tribyte *src, int count, float *dest, float normfact) |
417 | 418 | { int value ; |
418 | 419 | |
419 | while (--count >= 0) | |
420 | { value = psf_get_le24 (src [count].bytes, 0) ; | |
421 | dest [count] = ((float) value) * normfact ; | |
420 | for (int i = 0 ; i < count ; i++) | |
421 | { value = psf_get_le24 (src [i].bytes, 0) ; | |
422 | dest [i] = ((float) value) * normfact ; | |
422 | 423 | } ; |
423 | 424 | } /* let2f_array */ |
424 | 425 | |
426 | 427 | bet2f_array (const tribyte *src, int count, float *dest, float normfact) |
427 | 428 | { int value ; |
428 | 429 | |
429 | while (--count >= 0) | |
430 | { value = psf_get_be24 (src [count].bytes, 0) ; | |
431 | dest [count] = ((float) value) * normfact ; | |
430 | for (int i = 0 ; i < count ; i++) | |
431 | { value = psf_get_be24 (src [i].bytes, 0) ; | |
432 | dest [i] = ((float) value) * normfact ; | |
432 | 433 | } ; |
433 | 434 | } /* bet2f_array */ |
434 | 435 | |
436 | 437 | lei2f_array (const int *src, int count, float *dest, float normfact) |
437 | 438 | { int value ; |
438 | 439 | |
439 | while (--count >= 0) | |
440 | { value = src [count] ; | |
440 | for (int i = 0 ; i < count ; i++) | |
441 | { value = src [i] ; | |
441 | 442 | value = LE2H_32 (value) ; |
442 | dest [count] = ((float) value) * normfact ; | |
443 | dest [i] = ((float) value) * normfact ; | |
443 | 444 | } ; |
444 | 445 | } /* lei2f_array */ |
445 | 446 | |
447 | 448 | bei2f_array (const int *src, int count, float *dest, float normfact) |
448 | 449 | { int value ; |
449 | 450 | |
450 | while (--count >= 0) | |
451 | { value = src [count] ; | |
451 | for (int i = 0 ; i < count ; i++) | |
452 | { value = src [i] ; | |
452 | 453 | value = BE2H_32 (value) ; |
453 | dest [count] = ((float) value) * normfact ; | |
454 | dest [i] = ((float) value) * normfact ; | |
454 | 455 | } ; |
455 | 456 | } /* bei2f_array */ |
456 | 457 | |
459 | 460 | |
460 | 461 | static inline void |
461 | 462 | sc2d_array (const signed char *src, int count, double *dest, double normfact) |
462 | { while (--count >= 0) | |
463 | dest [count] = ((double) src [count]) * normfact ; | |
463 | { for (int i = 0 ; i < count ; i++) | |
464 | dest [i] = ((double) src [i]) * normfact ; | |
464 | 465 | } /* sc2d_array */ |
465 | 466 | |
466 | 467 | static inline void |
467 | 468 | uc2d_array (const unsigned char *src, int count, double *dest, double normfact) |
468 | { while (--count >= 0) | |
469 | dest [count] = (((int) src [count]) - 128) * normfact ; | |
469 | { for (int i = 0 ; i < count ; i++) | |
470 | dest [i] = (((int) src [i]) - 128) * normfact ; | |
470 | 471 | } /* uc2d_array */ |
471 | 472 | |
472 | 473 | static inline void |
473 | 474 | les2d_array (const short *src, int count, double *dest, double normfact) |
474 | 475 | { short value ; |
475 | 476 | |
476 | while (--count >= 0) | |
477 | { value = src [count] ; | |
477 | for (int i = 0 ; i < count ; i++) | |
478 | { value = src [i] ; | |
478 | 479 | value = LE2H_16 (value) ; |
479 | dest [count] = ((double) value) * normfact ; | |
480 | dest [i] = ((double) value) * normfact ; | |
480 | 481 | } ; |
481 | 482 | } /* les2d_array */ |
482 | 483 | |
484 | 485 | bes2d_array (const short *src, int count, double *dest, double normfact) |
485 | 486 | { short value ; |
486 | 487 | |
487 | while (--count >= 0) | |
488 | { value = src [count] ; | |
488 | for (int i = 0 ; i < count ; i++) | |
489 | { value = src [i] ; | |
489 | 490 | value = BE2H_16 (value) ; |
490 | dest [count] = ((double) value) * normfact ; | |
491 | dest [i] = ((double) value) * normfact ; | |
491 | 492 | } ; |
492 | 493 | } /* bes2d_array */ |
493 | 494 | |
495 | 496 | let2d_array (const tribyte *src, int count, double *dest, double normfact) |
496 | 497 | { int value ; |
497 | 498 | |
498 | while (--count >= 0) | |
499 | { value = psf_get_le24 (src [count].bytes, 0) ; | |
500 | dest [count] = ((double) value) * normfact ; | |
499 | for (int i = 0 ; i < count ; i++) | |
500 | { value = psf_get_le24 (src [i].bytes, 0) ; | |
501 | dest [i] = ((double) value) * normfact ; | |
501 | 502 | } ; |
502 | 503 | } /* let2d_array */ |
503 | 504 | |
505 | 506 | bet2d_array (const tribyte *src, int count, double *dest, double normfact) |
506 | 507 | { int value ; |
507 | 508 | |
508 | while (--count >= 0) | |
509 | { value = psf_get_be24 (src [count].bytes, 0) ; | |
510 | dest [count] = ((double) value) * normfact ; | |
509 | for (int i = 0 ; i < count ; i++) | |
510 | { value = psf_get_be24 (src [i].bytes, 0) ; | |
511 | dest [i] = ((double) value) * normfact ; | |
511 | 512 | } ; |
512 | 513 | } /* bet2d_array */ |
513 | 514 | |
515 | 516 | lei2d_array (const int *src, int count, double *dest, double normfact) |
516 | 517 | { int value ; |
517 | 518 | |
518 | while (--count >= 0) | |
519 | { value = src [count] ; | |
519 | for (int i = 0 ; i < count ; i++) | |
520 | { value = src [i] ; | |
520 | 521 | value = LE2H_32 (value) ; |
521 | dest [count] = ((double) value) * normfact ; | |
522 | dest [i] = ((double) value) * normfact ; | |
522 | 523 | } ; |
523 | 524 | } /* lei2d_array */ |
524 | 525 | |
526 | 527 | bei2d_array (const int *src, int count, double *dest, double normfact) |
527 | 528 | { int value ; |
528 | 529 | |
529 | while (--count >= 0) | |
530 | { value = src [count] ; | |
530 | for (int i = 0 ; i < count ; i++) | |
531 | { value = src [i] ; | |
531 | 532 | value = BE2H_32 (value) ; |
532 | dest [count] = ((double) value) * normfact ; | |
533 | dest [i] = ((double) value) * normfact ; | |
533 | 534 | } ; |
534 | 535 | } /* bei2d_array */ |
535 | 536 | |
538 | 539 | |
539 | 540 | static inline void |
540 | 541 | s2sc_array (const short *src, signed char *dest, int count) |
541 | { while (--count >= 0) | |
542 | dest [count] = src [count] >> 8 ; | |
542 | { for (int i = 0 ; i < count ; i++) | |
543 | dest [i] = src [i] >> 8 ; | |
543 | 544 | } /* s2sc_array */ |
544 | 545 | |
545 | 546 | static inline void |
546 | 547 | s2uc_array (const short *src, unsigned char *dest, int count) |
547 | { while (--count >= 0) | |
548 | dest [count] = (src [count] >> 8) + 0x80 ; | |
548 | { for (int i = 0 ; i < count ; i++) | |
549 | dest [i] = (src [i] >> 8) + 0x80 ; | |
549 | 550 | } /* s2uc_array */ |
550 | 551 | |
551 | 552 | static inline void |
552 | 553 | s2let_array (const short *src, tribyte *dest, int count) |
553 | { while (--count >= 0) | |
554 | { dest [count].bytes [0] = 0 ; | |
555 | dest [count].bytes [1] = src [count] ; | |
556 | dest [count].bytes [2] = src [count] >> 8 ; | |
554 | { for (int i = 0 ; i < count ; i++) | |
555 | { dest [i].bytes [0] = 0 ; | |
556 | dest [i].bytes [1] = src [i] ; | |
557 | dest [i].bytes [2] = src [i] >> 8 ; | |
557 | 558 | } ; |
558 | 559 | } /* s2let_array */ |
559 | 560 | |
560 | 561 | static inline void |
561 | 562 | s2bet_array (const short *src, tribyte *dest, int count) |
562 | { while (--count >= 0) | |
563 | { dest [count].bytes [2] = 0 ; | |
564 | dest [count].bytes [1] = src [count] ; | |
565 | dest [count].bytes [0] = src [count] >> 8 ; | |
563 | { for (int i = 0 ; i < count ; i++) | |
564 | { dest [i].bytes [2] = 0 ; | |
565 | dest [i].bytes [1] = src [i] ; | |
566 | dest [i].bytes [0] = src [i] >> 8 ; | |
566 | 567 | } ; |
567 | 568 | } /* s2bet_array */ |
568 | 569 | |
570 | 571 | s2lei_array (const short *src, int *dest, int count) |
571 | 572 | { unsigned char *ucptr ; |
572 | 573 | |
573 | ucptr = ((unsigned char*) dest) + 4 * count ; | |
574 | while (--count >= 0) | |
575 | { ucptr -= 4 ; | |
574 | for (int i = 0 ; i < count ; i++) | |
575 | { ucptr = (unsigned char*) &dest [i] ; | |
576 | 576 | ucptr [0] = 0 ; |
577 | 577 | ucptr [1] = 0 ; |
578 | ucptr [2] = src [count] ; | |
579 | ucptr [3] = src [count] >> 8 ; | |
578 | ucptr [2] = src [i] ; | |
579 | ucptr [3] = src [i] >> 8 ; | |
580 | 580 | } ; |
581 | 581 | } /* s2lei_array */ |
582 | 582 | |
584 | 584 | s2bei_array (const short *src, int *dest, int count) |
585 | 585 | { unsigned char *ucptr ; |
586 | 586 | |
587 | ucptr = ((unsigned char*) dest) + 4 * count ; | |
588 | while (--count >= 0) | |
589 | { ucptr -= 4 ; | |
590 | ucptr [0] = src [count] >> 8 ; | |
591 | ucptr [1] = src [count] ; | |
587 | for (int i = 0 ; i < count ; i++) | |
588 | { ucptr = (unsigned char*) &dest [i] ; | |
589 | ucptr [0] = src [i] >> 8 ; | |
590 | ucptr [1] = src [i] ; | |
592 | 591 | ucptr [2] = 0 ; |
593 | 592 | ucptr [3] = 0 ; |
594 | 593 | } ; |
599 | 598 | |
600 | 599 | static inline void |
601 | 600 | i2sc_array (const int *src, signed char *dest, int count) |
602 | { while (--count >= 0) | |
603 | dest [count] = (src [count] >> 24) ; | |
601 | { for (int i = 0 ; i < count ; i++) | |
602 | dest [i] = (src [i] >> 24) ; | |
604 | 603 | } /* i2sc_array */ |
605 | 604 | |
606 | 605 | static inline void |
607 | 606 | i2uc_array (const int *src, unsigned char *dest, int count) |
608 | { while (--count >= 0) | |
609 | dest [count] = ((src [count] >> 24) + 128) ; | |
607 | { for (int i = 0 ; i < count ; i++) | |
608 | dest [i] = ((src [i] >> 24) + 128) ; | |
610 | 609 | } /* i2uc_array */ |
611 | 610 | |
612 | 611 | static inline void |
613 | 612 | i2bes_array (const int *src, short *dest, int count) |
614 | 613 | { unsigned char *ucptr ; |
615 | 614 | |
616 | ucptr = ((unsigned char*) dest) + 2 * count ; | |
617 | while (--count >= 0) | |
618 | { ucptr -= 2 ; | |
619 | ucptr [0] = src [count] >> 24 ; | |
620 | ucptr [1] = src [count] >> 16 ; | |
615 | for (int i = 0 ; i < count ; i++) | |
616 | { ucptr = (unsigned char*) &dest [i] ; | |
617 | ucptr [0] = src [i] >> 24 ; | |
618 | ucptr [1] = src [i] >> 16 ; | |
621 | 619 | } ; |
622 | 620 | } /* i2bes_array */ |
623 | 621 | |
625 | 623 | i2les_array (const int *src, short *dest, int count) |
626 | 624 | { unsigned char *ucptr ; |
627 | 625 | |
628 | ucptr = ((unsigned char*) dest) + 2 * count ; | |
629 | while (--count >= 0) | |
630 | { ucptr -= 2 ; | |
631 | ucptr [0] = src [count] >> 16 ; | |
632 | ucptr [1] = src [count] >> 24 ; | |
626 | for (int i = 0 ; i < count ; i++) | |
627 | { ucptr = (unsigned char*) &dest [i] ; | |
628 | ucptr [0] = src [i] >> 16 ; | |
629 | ucptr [1] = src [i] >> 24 ; | |
633 | 630 | } ; |
634 | 631 | } /* i2les_array */ |
635 | 632 | |
637 | 634 | i2let_array (const int *src, tribyte *dest, int count) |
638 | 635 | { int value ; |
639 | 636 | |
640 | while (--count >= 0) | |
641 | { value = src [count] >> 8 ; | |
642 | dest [count].bytes [0] = value ; | |
643 | dest [count].bytes [1] = value >> 8 ; | |
644 | dest [count].bytes [2] = value >> 16 ; | |
637 | for (int i = 0 ; i < count ; i++) | |
638 | { value = src [i] >> 8 ; | |
639 | dest [i].bytes [0] = value ; | |
640 | dest [i].bytes [1] = value >> 8 ; | |
641 | dest [i].bytes [2] = value >> 16 ; | |
645 | 642 | } ; |
646 | 643 | } /* i2let_array */ |
647 | 644 | |
649 | 646 | i2bet_array (const int *src, tribyte *dest, int count) |
650 | 647 | { int value ; |
651 | 648 | |
652 | while (--count >= 0) | |
653 | { value = src [count] >> 8 ; | |
654 | dest [count].bytes [2] = value ; | |
655 | dest [count].bytes [1] = value >> 8 ; | |
656 | dest [count].bytes [0] = value >> 16 ; | |
649 | for (int i = 0 ; i < count ; i++) | |
650 | { value = src [i] >> 8 ; | |
651 | dest [i].bytes [2] = value ; | |
652 | dest [i].bytes [1] = value >> 8 ; | |
653 | dest [i].bytes [0] = value >> 16 ; | |
657 | 654 | } ; |
658 | 655 | } /* i2bet_array */ |
659 | 656 | |
671 | 668 | while (len > 0) |
672 | 669 | { if (len < bufferlen) |
673 | 670 | bufferlen = (int) len ; |
674 | readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
671 | readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
675 | 672 | sc2s_array (ubuf.scbuf, readcount, ptr + total) ; |
676 | 673 | total += readcount ; |
677 | 674 | if (readcount < bufferlen) |
693 | 690 | while (len > 0) |
694 | 691 | { if (len < bufferlen) |
695 | 692 | bufferlen = (int) len ; |
696 | readcount = psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
693 | readcount = (int) psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
697 | 694 | uc2s_array (ubuf.ucbuf, readcount, ptr + total) ; |
698 | 695 | total += readcount ; |
699 | 696 | if (readcount < bufferlen) |
708 | 705 | pcm_read_bes2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) |
709 | 706 | { int total ; |
710 | 707 | |
711 | total = psf_fread (ptr, sizeof (short), len, psf) ; | |
712 | if (CPU_IS_LITTLE_ENDIAN) | |
713 | endswap_short_array (ptr, len) ; | |
708 | total = (int) psf_fread (ptr, sizeof (short), len, psf) ; | |
709 | #if CPU_IS_LITTLE_ENDIAN | |
710 | endswap_short_array (ptr, len) ; | |
711 | #endif | |
714 | 712 | |
715 | 713 | return total ; |
716 | 714 | } /* pcm_read_bes2s */ |
720 | 718 | { int total ; |
721 | 719 | |
722 | 720 | total = psf_fread (ptr, sizeof (short), len, psf) ; |
723 | if (CPU_IS_BIG_ENDIAN) | |
724 | endswap_short_array (ptr, len) ; | |
721 | #if CPU_IS_BIG_ENDIAN | |
722 | endswap_short_array (ptr, len) ; | |
723 | #endif | |
725 | 724 | |
726 | 725 | return total ; |
727 | 726 | } /* pcm_read_les2s */ |
737 | 736 | while (len > 0) |
738 | 737 | { if (len < bufferlen) |
739 | 738 | bufferlen = (int) len ; |
740 | readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
739 | readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
741 | 740 | bet2s_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total) ; |
742 | 741 | total += readcount ; |
743 | 742 | if (readcount < bufferlen) |
759 | 758 | while (len > 0) |
760 | 759 | { if (len < bufferlen) |
761 | 760 | bufferlen = (int) len ; |
762 | readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
761 | readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
763 | 762 | let2s_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total) ; |
764 | 763 | total += readcount ; |
765 | 764 | if (readcount < bufferlen) |
781 | 780 | while (len > 0) |
782 | 781 | { if (len < bufferlen) |
783 | 782 | bufferlen = (int) len ; |
784 | readcount = psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
783 | readcount = (int) psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
785 | 784 | bei2s_array (ubuf.ibuf, readcount, ptr + total) ; |
786 | 785 | total += readcount ; |
787 | 786 | if (readcount < bufferlen) |
803 | 802 | while (len > 0) |
804 | 803 | { if (len < bufferlen) |
805 | 804 | bufferlen = (int) len ; |
806 | readcount = psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
805 | readcount = (int) psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
807 | 806 | lei2s_array (ubuf.ibuf, readcount, ptr + total) ; |
808 | 807 | total += readcount ; |
809 | 808 | if (readcount < bufferlen) |
828 | 827 | while (len > 0) |
829 | 828 | { if (len < bufferlen) |
830 | 829 | bufferlen = (int) len ; |
831 | readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
830 | readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
832 | 831 | sc2i_array (ubuf.scbuf, readcount, ptr + total) ; |
833 | 832 | total += readcount ; |
834 | 833 | if (readcount < bufferlen) |
850 | 849 | while (len > 0) |
851 | 850 | { if (len < bufferlen) |
852 | 851 | bufferlen = (int) len ; |
853 | readcount = psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
852 | readcount = (int) psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
854 | 853 | uc2i_array (ubuf.ucbuf, readcount, ptr + total) ; |
855 | 854 | total += readcount ; |
856 | 855 | if (readcount < bufferlen) |
872 | 871 | while (len > 0) |
873 | 872 | { if (len < bufferlen) |
874 | 873 | bufferlen = (int) len ; |
875 | readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
874 | readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
876 | 875 | bes2i_array (ubuf.sbuf, readcount, ptr + total) ; |
877 | 876 | total += readcount ; |
878 | 877 | if (readcount < bufferlen) |
894 | 893 | while (len > 0) |
895 | 894 | { if (len < bufferlen) |
896 | 895 | bufferlen = (int) len ; |
897 | readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
896 | readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
898 | 897 | les2i_array (ubuf.sbuf, readcount, ptr + total) ; |
899 | 898 | total += readcount ; |
900 | 899 | if (readcount < bufferlen) |
916 | 915 | while (len > 0) |
917 | 916 | { if (len < bufferlen) |
918 | 917 | bufferlen = (int) len ; |
919 | readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
918 | readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
920 | 919 | bet2i_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total) ; |
921 | 920 | total += readcount ; |
922 | 921 | if (readcount < bufferlen) |
938 | 937 | while (len > 0) |
939 | 938 | { if (len < bufferlen) |
940 | 939 | bufferlen = (int) len ; |
941 | readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
940 | readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
942 | 941 | let2i_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total) ; |
943 | 942 | total += readcount ; |
944 | 943 | if (readcount < bufferlen) |
954 | 953 | { int total ; |
955 | 954 | |
956 | 955 | total = psf_fread (ptr, sizeof (int), len, psf) ; |
957 | if (CPU_IS_LITTLE_ENDIAN) | |
958 | endswap_int_array (ptr, len) ; | |
956 | #if CPU_IS_LITTLE_ENDIAN | |
957 | endswap_int_array (ptr, len) ; | |
958 | #endif | |
959 | 959 | |
960 | 960 | return total ; |
961 | 961 | } /* pcm_read_bei2i */ |
965 | 965 | { int total ; |
966 | 966 | |
967 | 967 | total = psf_fread (ptr, sizeof (int), len, psf) ; |
968 | if (CPU_IS_BIG_ENDIAN) | |
969 | endswap_int_array (ptr, len) ; | |
968 | #if CPU_IS_BIG_ENDIAN | |
969 | endswap_int_array (ptr, len) ; | |
970 | #endif | |
970 | 971 | |
971 | 972 | return total ; |
972 | 973 | } /* pcm_read_lei2i */ |
988 | 989 | while (len > 0) |
989 | 990 | { if (len < bufferlen) |
990 | 991 | bufferlen = (int) len ; |
991 | readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
992 | readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
992 | 993 | sc2f_array (ubuf.scbuf, readcount, ptr + total, normfact) ; |
993 | 994 | total += readcount ; |
994 | 995 | if (readcount < bufferlen) |
1013 | 1014 | while (len > 0) |
1014 | 1015 | { if (len < bufferlen) |
1015 | 1016 | bufferlen = (int) len ; |
1016 | readcount = psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
1017 | readcount = (int) psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
1017 | 1018 | uc2f_array (ubuf.ucbuf, readcount, ptr + total, normfact) ; |
1018 | 1019 | total += readcount ; |
1019 | 1020 | if (readcount < bufferlen) |
1038 | 1039 | while (len > 0) |
1039 | 1040 | { if (len < bufferlen) |
1040 | 1041 | bufferlen = (int) len ; |
1041 | readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1042 | readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1042 | 1043 | bes2f_array (ubuf.sbuf, readcount, ptr + total, normfact) ; |
1043 | 1044 | total += readcount ; |
1044 | 1045 | if (readcount < bufferlen) |
1063 | 1064 | while (len > 0) |
1064 | 1065 | { if (len < bufferlen) |
1065 | 1066 | bufferlen = (int) len ; |
1066 | readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1067 | readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1067 | 1068 | les2f_array (ubuf.sbuf, readcount, ptr + total, normfact) ; |
1068 | 1069 | total += readcount ; |
1069 | 1070 | if (readcount < bufferlen) |
1089 | 1090 | while (len > 0) |
1090 | 1091 | { if (len < bufferlen) |
1091 | 1092 | bufferlen = (int) len ; |
1092 | readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1093 | readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1093 | 1094 | bet2f_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total, normfact) ; |
1094 | 1095 | total += readcount ; |
1095 | 1096 | if (readcount < bufferlen) |
1115 | 1116 | while (len > 0) |
1116 | 1117 | { if (len < bufferlen) |
1117 | 1118 | bufferlen = (int) len ; |
1118 | readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1119 | readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1119 | 1120 | let2f_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total, normfact) ; |
1120 | 1121 | total += readcount ; |
1121 | 1122 | if (readcount < bufferlen) |
1140 | 1141 | while (len > 0) |
1141 | 1142 | { if (len < bufferlen) |
1142 | 1143 | bufferlen = (int) len ; |
1143 | readcount = psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1144 | readcount = (int) psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1144 | 1145 | bei2f_array (ubuf.ibuf, readcount, ptr + total, normfact) ; |
1145 | 1146 | total += readcount ; |
1146 | 1147 | if (readcount < bufferlen) |
1165 | 1166 | while (len > 0) |
1166 | 1167 | { if (len < bufferlen) |
1167 | 1168 | bufferlen = (int) len ; |
1168 | readcount = psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1169 | readcount = (int) psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1169 | 1170 | lei2f_array (ubuf.ibuf, readcount, ptr + total, normfact) ; |
1170 | 1171 | total += readcount ; |
1171 | 1172 | if (readcount < bufferlen) |
1193 | 1194 | while (len > 0) |
1194 | 1195 | { if (len < bufferlen) |
1195 | 1196 | bufferlen = (int) len ; |
1196 | readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
1197 | readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
1197 | 1198 | sc2d_array (ubuf.scbuf, readcount, ptr + total, normfact) ; |
1198 | 1199 | total += readcount ; |
1199 | 1200 | if (readcount < bufferlen) |
1218 | 1219 | while (len > 0) |
1219 | 1220 | { if (len < bufferlen) |
1220 | 1221 | bufferlen = (int) len ; |
1221 | readcount = psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
1222 | readcount = (int) psf_fread (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
1222 | 1223 | uc2d_array (ubuf.ucbuf, readcount, ptr + total, normfact) ; |
1223 | 1224 | total += readcount ; |
1224 | 1225 | if (readcount < bufferlen) |
1243 | 1244 | while (len > 0) |
1244 | 1245 | { if (len < bufferlen) |
1245 | 1246 | bufferlen = (int) len ; |
1246 | readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1247 | readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1247 | 1248 | bes2d_array (ubuf.sbuf, readcount, ptr + total, normfact) ; |
1248 | 1249 | total += readcount ; |
1249 | 1250 | if (readcount < bufferlen) |
1268 | 1269 | while (len > 0) |
1269 | 1270 | { if (len < bufferlen) |
1270 | 1271 | bufferlen = (int) len ; |
1271 | readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1272 | readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1272 | 1273 | les2d_array (ubuf.sbuf, readcount, ptr + total, normfact) ; |
1273 | 1274 | total += readcount ; |
1274 | 1275 | if (readcount < bufferlen) |
1293 | 1294 | while (len > 0) |
1294 | 1295 | { if (len < bufferlen) |
1295 | 1296 | bufferlen = (int) len ; |
1296 | readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1297 | readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1297 | 1298 | bet2d_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total, normfact) ; |
1298 | 1299 | total += readcount ; |
1299 | 1300 | if (readcount < bufferlen) |
1319 | 1320 | while (len > 0) |
1320 | 1321 | { if (len < bufferlen) |
1321 | 1322 | bufferlen = (int) len ; |
1322 | readcount = psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1323 | readcount = (int) psf_fread (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1323 | 1324 | let2d_array ((tribyte*) (ubuf.ucbuf), readcount, ptr + total, normfact) ; |
1324 | 1325 | total += readcount ; |
1325 | 1326 | if (readcount < bufferlen) |
1344 | 1345 | while (len > 0) |
1345 | 1346 | { if (len < bufferlen) |
1346 | 1347 | bufferlen = (int) len ; |
1347 | readcount = psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1348 | readcount = (int) psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1348 | 1349 | bei2d_array (ubuf.ibuf, readcount, ptr + total, normfact) ; |
1349 | 1350 | total += readcount ; |
1350 | 1351 | if (readcount < bufferlen) |
1369 | 1370 | while (len > 0) |
1370 | 1371 | { if (len < bufferlen) |
1371 | 1372 | bufferlen = (int) len ; |
1372 | readcount = psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1373 | readcount = (int) psf_fread (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1373 | 1374 | lei2d_array (ubuf.ibuf, readcount, ptr + total, normfact) ; |
1374 | 1375 | total += readcount ; |
1375 | 1376 | if (readcount < bufferlen) |
1397 | 1398 | { if (len < bufferlen) |
1398 | 1399 | bufferlen = (int) len ; |
1399 | 1400 | s2sc_array (ptr + total, ubuf.scbuf, bufferlen) ; |
1400 | writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
1401 | writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
1401 | 1402 | total += writecount ; |
1402 | 1403 | if (writecount < bufferlen) |
1403 | 1404 | break ; |
1419 | 1420 | { if (len < bufferlen) |
1420 | 1421 | bufferlen = (int) len ; |
1421 | 1422 | s2uc_array (ptr + total, ubuf.ucbuf, bufferlen) ; |
1422 | writecount = psf_fwrite (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
1423 | writecount = (int) psf_fwrite (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
1423 | 1424 | total += writecount ; |
1424 | 1425 | if (writecount < bufferlen) |
1425 | 1426 | break ; |
1431 | 1432 | |
1432 | 1433 | static sf_count_t |
1433 | 1434 | pcm_write_s2bes (SF_PRIVATE *psf, const short *ptr, sf_count_t len) |
1434 | { BUF_UNION ubuf ; | |
1435 | int bufferlen, writecount ; | |
1436 | sf_count_t total = 0 ; | |
1437 | ||
1438 | if (CPU_IS_BIG_ENDIAN) | |
1439 | return psf_fwrite (ptr, sizeof (short), len, psf) ; | |
1440 | else | |
1435 | { | |
1436 | #if CPU_IS_BIG_ENDIAN | |
1437 | return psf_fwrite (ptr, sizeof (short), len, psf) ; | |
1438 | #else | |
1439 | BUF_UNION ubuf ; | |
1440 | int bufferlen, writecount ; | |
1441 | sf_count_t total = 0 ; | |
1441 | 1442 | |
1442 | 1443 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
1443 | 1444 | |
1445 | 1446 | { if (len < bufferlen) |
1446 | 1447 | bufferlen = (int) len ; |
1447 | 1448 | endswap_short_copy (ubuf.sbuf, ptr + total, bufferlen) ; |
1448 | writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1449 | total += writecount ; | |
1450 | if (writecount < bufferlen) | |
1451 | break ; | |
1452 | len -= writecount ; | |
1453 | } ; | |
1454 | ||
1455 | return total ; | |
1449 | writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1450 | total += writecount ; | |
1451 | if (writecount < bufferlen) | |
1452 | break ; | |
1453 | len -= writecount ; | |
1454 | } ; | |
1455 | ||
1456 | return total ; | |
1457 | #endif | |
1456 | 1458 | } /* pcm_write_s2bes */ |
1457 | 1459 | |
1458 | 1460 | static sf_count_t |
1459 | 1461 | pcm_write_s2les (SF_PRIVATE *psf, const short *ptr, sf_count_t len) |
1460 | { BUF_UNION ubuf ; | |
1461 | int bufferlen, writecount ; | |
1462 | sf_count_t total = 0 ; | |
1463 | ||
1464 | if (CPU_IS_LITTLE_ENDIAN) | |
1465 | return psf_fwrite (ptr, sizeof (short), len, psf) ; | |
1462 | { | |
1463 | #if CPU_IS_LITTLE_ENDIAN | |
1464 | return psf_fwrite (ptr, sizeof (short), len, psf) ; | |
1465 | #else | |
1466 | BUF_UNION ubuf ; | |
1467 | int bufferlen, writecount ; | |
1468 | sf_count_t total = 0 ; | |
1466 | 1469 | |
1467 | 1470 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
1468 | 1471 | |
1470 | 1473 | { if (len < bufferlen) |
1471 | 1474 | bufferlen = (int) len ; |
1472 | 1475 | endswap_short_copy (ubuf.sbuf, ptr + total, bufferlen) ; |
1473 | writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1474 | total += writecount ; | |
1475 | if (writecount < bufferlen) | |
1476 | break ; | |
1477 | len -= writecount ; | |
1478 | } ; | |
1479 | ||
1480 | return total ; | |
1476 | writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1477 | total += writecount ; | |
1478 | if (writecount < bufferlen) | |
1479 | break ; | |
1480 | len -= writecount ; | |
1481 | } ; | |
1482 | ||
1483 | return total ; | |
1484 | #endif | |
1481 | 1485 | } /* pcm_write_s2les */ |
1482 | 1486 | |
1483 | 1487 | static sf_count_t |
1492 | 1496 | { if (len < bufferlen) |
1493 | 1497 | bufferlen = (int) len ; |
1494 | 1498 | s2bet_array (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen) ; |
1495 | writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1499 | writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1496 | 1500 | total += writecount ; |
1497 | 1501 | if (writecount < bufferlen) |
1498 | 1502 | break ; |
1514 | 1518 | { if (len < bufferlen) |
1515 | 1519 | bufferlen = (int) len ; |
1516 | 1520 | s2let_array (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen) ; |
1517 | writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1521 | writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1518 | 1522 | total += writecount ; |
1519 | 1523 | if (writecount < bufferlen) |
1520 | 1524 | break ; |
1536 | 1540 | { if (len < bufferlen) |
1537 | 1541 | bufferlen = (int) len ; |
1538 | 1542 | s2bei_array (ptr + total, ubuf.ibuf, bufferlen) ; |
1539 | writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1543 | writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1540 | 1544 | total += writecount ; |
1541 | 1545 | if (writecount < bufferlen) |
1542 | 1546 | break ; |
1558 | 1562 | { if (len < bufferlen) |
1559 | 1563 | bufferlen = (int) len ; |
1560 | 1564 | s2lei_array (ptr + total, ubuf.ibuf, bufferlen) ; |
1561 | writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1565 | writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1562 | 1566 | total += writecount ; |
1563 | 1567 | if (writecount < bufferlen) |
1564 | 1568 | break ; |
1583 | 1587 | { if (len < bufferlen) |
1584 | 1588 | bufferlen = (int) len ; |
1585 | 1589 | i2sc_array (ptr + total, ubuf.scbuf, bufferlen) ; |
1586 | writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
1590 | writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
1587 | 1591 | total += writecount ; |
1588 | 1592 | if (writecount < bufferlen) |
1589 | 1593 | break ; |
1605 | 1609 | { if (len < bufferlen) |
1606 | 1610 | bufferlen = (int) len ; |
1607 | 1611 | i2uc_array (ptr + total, ubuf.ucbuf, bufferlen) ; |
1608 | writecount = psf_fwrite (ubuf.ucbuf, sizeof (signed char), bufferlen, psf) ; | |
1612 | writecount = (int) psf_fwrite (ubuf.ucbuf, sizeof (signed char), bufferlen, psf) ; | |
1609 | 1613 | total += writecount ; |
1610 | 1614 | if (writecount < bufferlen) |
1611 | 1615 | break ; |
1627 | 1631 | { if (len < bufferlen) |
1628 | 1632 | bufferlen = (int) len ; |
1629 | 1633 | i2bes_array (ptr + total, ubuf.sbuf, bufferlen) ; |
1630 | writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1634 | writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1631 | 1635 | total += writecount ; |
1632 | 1636 | if (writecount < bufferlen) |
1633 | 1637 | break ; |
1649 | 1653 | { if (len < bufferlen) |
1650 | 1654 | bufferlen = (int) len ; |
1651 | 1655 | i2les_array (ptr + total, ubuf.sbuf, bufferlen) ; |
1652 | writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1656 | writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1653 | 1657 | total += writecount ; |
1654 | 1658 | if (writecount < bufferlen) |
1655 | 1659 | break ; |
1671 | 1675 | { if (len < bufferlen) |
1672 | 1676 | bufferlen = (int) len ; |
1673 | 1677 | i2bet_array (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen) ; |
1674 | writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1678 | writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1675 | 1679 | total += writecount ; |
1676 | 1680 | if (writecount < bufferlen) |
1677 | 1681 | break ; |
1693 | 1697 | { if (len < bufferlen) |
1694 | 1698 | bufferlen = (int) len ; |
1695 | 1699 | i2let_array (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen) ; |
1696 | writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1700 | writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
1697 | 1701 | total += writecount ; |
1698 | 1702 | if (writecount < bufferlen) |
1699 | 1703 | break ; |
1705 | 1709 | |
1706 | 1710 | static sf_count_t |
1707 | 1711 | pcm_write_i2bei (SF_PRIVATE *psf, const int *ptr, sf_count_t len) |
1708 | { BUF_UNION ubuf ; | |
1709 | int bufferlen, writecount ; | |
1710 | sf_count_t total = 0 ; | |
1711 | ||
1712 | if (CPU_IS_BIG_ENDIAN) | |
1713 | return psf_fwrite (ptr, sizeof (int), len, psf) ; | |
1712 | { | |
1713 | #if CPU_IS_BIG_ENDIAN | |
1714 | return psf_fwrite (ptr, sizeof (int), len, psf) ; | |
1715 | #else | |
1716 | BUF_UNION ubuf ; | |
1717 | int bufferlen, writecount ; | |
1718 | sf_count_t total = 0 ; | |
1714 | 1719 | |
1715 | 1720 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
1716 | 1721 | |
1718 | 1723 | { if (len < bufferlen) |
1719 | 1724 | bufferlen = (int) len ; |
1720 | 1725 | endswap_int_copy (ubuf.ibuf, ptr + total, bufferlen) ; |
1721 | writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1722 | total += writecount ; | |
1723 | if (writecount < bufferlen) | |
1724 | break ; | |
1725 | len -= writecount ; | |
1726 | } ; | |
1727 | ||
1728 | return total ; | |
1726 | writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1727 | total += writecount ; | |
1728 | if (writecount < bufferlen) | |
1729 | break ; | |
1730 | len -= writecount ; | |
1731 | } ; | |
1732 | ||
1733 | return total ; | |
1734 | #endif | |
1729 | 1735 | } /* pcm_write_i2bei */ |
1730 | 1736 | |
1731 | 1737 | static sf_count_t |
1732 | 1738 | pcm_write_i2lei (SF_PRIVATE *psf, const int *ptr, sf_count_t len) |
1733 | { BUF_UNION ubuf ; | |
1734 | int bufferlen, writecount ; | |
1735 | sf_count_t total = 0 ; | |
1736 | ||
1737 | if (CPU_IS_LITTLE_ENDIAN) | |
1738 | return psf_fwrite (ptr, sizeof (int), len, psf) ; | |
1739 | { | |
1740 | #if CPU_IS_LITTLE_ENDIAN | |
1741 | return psf_fwrite (ptr, sizeof (int), len, psf) ; | |
1742 | #else | |
1743 | BUF_UNION ubuf ; | |
1744 | int bufferlen, writecount ; | |
1745 | sf_count_t total = 0 ; | |
1739 | 1746 | |
1740 | 1747 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
1741 | 1748 | |
1743 | 1750 | { if (len < bufferlen) |
1744 | 1751 | bufferlen = (int) len ; |
1745 | 1752 | endswap_int_copy (ubuf.ibuf, ptr + total, bufferlen) ; |
1746 | writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1747 | total += writecount ; | |
1748 | if (writecount < bufferlen) | |
1749 | break ; | |
1750 | len -= writecount ; | |
1751 | } ; | |
1752 | ||
1753 | return total ; | |
1753 | writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
1754 | total += writecount ; | |
1755 | if (writecount < bufferlen) | |
1756 | break ; | |
1757 | len -= writecount ; | |
1758 | } ; | |
1759 | ||
1760 | return total ; | |
1761 | #endif | |
1754 | 1762 | } /* pcm_write_i2lei */ |
1755 | 1763 | |
1756 | 1764 | /*------------------------------------------------------------------------------ |
1764 | 1772 | |
1765 | 1773 | normfact = normalize ? (1.0 * 0x7F) : 1.0 ; |
1766 | 1774 | |
1767 | while (--count >= 0) | |
1768 | { dest [count] = psf_lrintf (src [count] * normfact) ; | |
1775 | for (int i = 0 ; i < count ; i++) | |
1776 | { dest [i] = psf_lrintf (src [i] * normfact) ; | |
1769 | 1777 | } ; |
1770 | 1778 | } /* f2sc_array */ |
1771 | 1779 | |
1775 | 1783 | |
1776 | 1784 | normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; |
1777 | 1785 | |
1778 | while (--count >= 0) | |
1779 | { scaled_value = src [count] * normfact ; | |
1780 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
1781 | { dest [count] = 127 ; | |
1782 | continue ; | |
1783 | } ; | |
1784 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
1785 | { dest [count] = -128 ; | |
1786 | continue ; | |
1787 | } ; | |
1788 | ||
1789 | dest [count] = psf_lrintf (scaled_value) >> 24 ; | |
1786 | for (int i = 0 ; i < count ; i++) | |
1787 | { scaled_value = src [i] * normfact ; | |
1788 | #if CPU_CLIPS_POSITIVE == 0 | |
1789 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
1790 | { dest [i] = 127 ; | |
1791 | continue ; | |
1792 | } ; | |
1793 | #endif | |
1794 | #if CPU_CLIPS_NEGATIVE == 0 | |
1795 | if (scaled_value <= (-8.0 * 0x10000000)) | |
1796 | { dest [i] = -128 ; | |
1797 | continue ; | |
1798 | } ; | |
1799 | #endif | |
1800 | ||
1801 | dest [i] = psf_lrintf (scaled_value) >> 24 ; | |
1790 | 1802 | } ; |
1791 | 1803 | } /* f2sc_clip_array */ |
1792 | 1804 | |
1804 | 1816 | { if (len < bufferlen) |
1805 | 1817 | bufferlen = (int) len ; |
1806 | 1818 | convert (ptr + total, ubuf.scbuf, bufferlen, psf->norm_float) ; |
1807 | writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
1819 | writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
1808 | 1820 | total += writecount ; |
1809 | 1821 | if (writecount < bufferlen) |
1810 | 1822 | break ; |
1823 | 1835 | |
1824 | 1836 | normfact = normalize ? (1.0 * 0x7F) : 1.0 ; |
1825 | 1837 | |
1826 | while (--count >= 0) | |
1827 | { dest [count] = psf_lrintf (src [count] * normfact) + 128 ; | |
1838 | for (int i = 0 ; i < count ; i++) | |
1839 | { dest [i] = psf_lrintf (src [i] * normfact) + 128 ; | |
1828 | 1840 | } ; |
1829 | 1841 | } /* f2uc_array */ |
1830 | 1842 | |
1834 | 1846 | |
1835 | 1847 | normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; |
1836 | 1848 | |
1837 | while (--count >= 0) | |
1838 | { scaled_value = src [count] * normfact ; | |
1839 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
1840 | { dest [count] = 0xFF ; | |
1841 | continue ; | |
1842 | } ; | |
1843 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
1844 | { dest [count] = 0 ; | |
1845 | continue ; | |
1846 | } ; | |
1847 | ||
1848 | dest [count] = (psf_lrintf (scaled_value) >> 24) + 128 ; | |
1849 | for (int i = 0 ; i < count ; i++) | |
1850 | { scaled_value = src [i] * normfact ; | |
1851 | #if CPU_CLIPS_POSITIVE == 0 | |
1852 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
1853 | { dest [i] = 0xFF ; | |
1854 | continue ; | |
1855 | } ; | |
1856 | #endif | |
1857 | #if CPU_CLIPS_NEGATIVE == 0 | |
1858 | if (scaled_value <= (-8.0 * 0x10000000)) | |
1859 | { dest [i] = 0 ; | |
1860 | continue ; | |
1861 | } ; | |
1862 | #endif | |
1863 | ||
1864 | dest [i] = (psf_lrintf (scaled_value) >> 24) + 128 ; | |
1849 | 1865 | } ; |
1850 | 1866 | } /* f2uc_clip_array */ |
1851 | 1867 | |
1863 | 1879 | { if (len < bufferlen) |
1864 | 1880 | bufferlen = (int) len ; |
1865 | 1881 | convert (ptr + total, ubuf.ucbuf, bufferlen, psf->norm_float) ; |
1866 | writecount = psf_fwrite (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
1882 | writecount = (int) psf_fwrite (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
1867 | 1883 | total += writecount ; |
1868 | 1884 | if (writecount < bufferlen) |
1869 | 1885 | break ; |
1883 | 1899 | short value ; |
1884 | 1900 | |
1885 | 1901 | normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; |
1886 | ucptr = ((unsigned char*) dest) + 2 * count ; | |
1887 | ||
1888 | while (--count >= 0) | |
1889 | { ucptr -= 2 ; | |
1890 | value = psf_lrintf (src [count] * normfact) ; | |
1902 | ||
1903 | for (int i = 0 ; i < count ; i++) | |
1904 | { ucptr = (unsigned char*) &dest [i] ; | |
1905 | value = psf_lrintf (src [i] * normfact) ; | |
1891 | 1906 | ucptr [1] = value ; |
1892 | 1907 | ucptr [0] = value >> 8 ; |
1893 | 1908 | } ; |
1900 | 1915 | int value ; |
1901 | 1916 | |
1902 | 1917 | normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; |
1903 | ucptr = ((unsigned char*) dest) + 2 * count ; | |
1904 | ||
1905 | while (--count >= 0) | |
1906 | { ucptr -= 2 ; | |
1907 | scaled_value = src [count] * normfact ; | |
1908 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
1918 | ||
1919 | for (int i = 0 ; i < count ; i++) | |
1920 | { ucptr = (unsigned char*) &dest [i] ; | |
1921 | scaled_value = src [i] * normfact ; | |
1922 | #if CPU_CLIPS_POSITIVE == 0 | |
1923 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
1909 | 1924 | { ucptr [1] = 0xFF ; |
1910 | 1925 | ucptr [0] = 0x7F ; |
1911 | 1926 | continue ; |
1912 | 1927 | } ; |
1913 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
1928 | #endif | |
1929 | #if CPU_CLIPS_NEGATIVE == 0 | |
1930 | if (scaled_value <= (-8.0 * 0x10000000)) | |
1914 | 1931 | { ucptr [1] = 0x00 ; |
1915 | 1932 | ucptr [0] = 0x80 ; |
1916 | 1933 | continue ; |
1917 | 1934 | } ; |
1935 | #endif | |
1918 | 1936 | |
1919 | 1937 | value = psf_lrintf (scaled_value) ; |
1920 | 1938 | ucptr [1] = value >> 16 ; |
1936 | 1954 | { if (len < bufferlen) |
1937 | 1955 | bufferlen = (int) len ; |
1938 | 1956 | convert (ptr + total, ubuf.sbuf, bufferlen, psf->norm_float) ; |
1939 | writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1957 | writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
1940 | 1958 | total += writecount ; |
1941 | 1959 | if (writecount < bufferlen) |
1942 | 1960 | break ; |
1956 | 1974 | int value ; |
1957 | 1975 | |
1958 | 1976 | normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; |
1959 | ucptr = ((unsigned char*) dest) + 2 * count ; | |
1960 | ||
1961 | while (--count >= 0) | |
1962 | { ucptr -= 2 ; | |
1963 | value = psf_lrintf (src [count] * normfact) ; | |
1977 | ||
1978 | for (int i = 0 ; i < count ; i++) | |
1979 | { ucptr = (unsigned char*) &dest [i] ; | |
1980 | value = psf_lrintf (src [i] * normfact) ; | |
1964 | 1981 | ucptr [0] = value ; |
1965 | 1982 | ucptr [1] = value >> 8 ; |
1966 | 1983 | } ; |
1973 | 1990 | int value ; |
1974 | 1991 | |
1975 | 1992 | normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; |
1976 | ucptr = ((unsigned char*) dest) + 2 * count ; | |
1977 | ||
1978 | while (--count >= 0) | |
1979 | { ucptr -= 2 ; | |
1980 | scaled_value = src [count] * normfact ; | |
1981 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
1993 | ||
1994 | for (int i = 0 ; i < count ; i++) | |
1995 | { ucptr = (unsigned char*) &dest [i] ; | |
1996 | scaled_value = src [i] * normfact ; | |
1997 | #if CPU_CLIPS_POSITIVE == 0 | |
1998 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
1982 | 1999 | { ucptr [0] = 0xFF ; |
1983 | 2000 | ucptr [1] = 0x7F ; |
1984 | 2001 | continue ; |
1985 | 2002 | } ; |
1986 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2003 | #endif | |
2004 | #if CPU_CLIPS_NEGATIVE == 0 | |
2005 | if (scaled_value <= (-8.0 * 0x10000000)) | |
1987 | 2006 | { ucptr [0] = 0x00 ; |
1988 | 2007 | ucptr [1] = 0x80 ; |
1989 | 2008 | continue ; |
1990 | 2009 | } ; |
2010 | #endif | |
1991 | 2011 | |
1992 | 2012 | value = psf_lrintf (scaled_value) ; |
1993 | 2013 | ucptr [0] = value >> 16 ; |
2009 | 2029 | { if (len < bufferlen) |
2010 | 2030 | bufferlen = (int) len ; |
2011 | 2031 | convert (ptr + total, ubuf.sbuf, bufferlen, psf->norm_float) ; |
2012 | writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
2032 | writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
2013 | 2033 | total += writecount ; |
2014 | 2034 | if (writecount < bufferlen) |
2015 | 2035 | break ; |
2029 | 2049 | |
2030 | 2050 | normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; |
2031 | 2051 | |
2032 | while (--count >= 0) | |
2033 | { value = psf_lrintf (src [count] * normfact) ; | |
2034 | dest [count].bytes [0] = value ; | |
2035 | dest [count].bytes [1] = value >> 8 ; | |
2036 | dest [count].bytes [2] = value >> 16 ; | |
2052 | for (int i = 0 ; i < count ; i++) | |
2053 | { value = psf_lrintf (src [i] * normfact) ; | |
2054 | dest [i].bytes [0] = value ; | |
2055 | dest [i].bytes [1] = value >> 8 ; | |
2056 | dest [i].bytes [2] = value >> 16 ; | |
2037 | 2057 | } ; |
2038 | 2058 | } /* f2let_array */ |
2039 | 2059 | |
2044 | 2064 | |
2045 | 2065 | normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; |
2046 | 2066 | |
2047 | while (--count >= 0) | |
2048 | { scaled_value = src [count] * normfact ; | |
2049 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2050 | { dest [count].bytes [0] = 0xFF ; | |
2051 | dest [count].bytes [1] = 0xFF ; | |
2052 | dest [count].bytes [2] = 0x7F ; | |
2053 | continue ; | |
2054 | } ; | |
2055 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2056 | { dest [count].bytes [0] = 0x00 ; | |
2057 | dest [count].bytes [1] = 0x00 ; | |
2058 | dest [count].bytes [2] = 0x80 ; | |
2059 | continue ; | |
2060 | } ; | |
2067 | for (int i = 0 ; i < count ; i++) | |
2068 | { scaled_value = src [i] * normfact ; | |
2069 | #if CPU_CLIPS_POSITIVE == 0 | |
2070 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2071 | { dest [i].bytes [0] = 0xFF ; | |
2072 | dest [i].bytes [1] = 0xFF ; | |
2073 | dest [i].bytes [2] = 0x7F ; | |
2074 | continue ; | |
2075 | } ; | |
2076 | #endif | |
2077 | #if CPU_CLIPS_NEGATIVE == 0 | |
2078 | if (scaled_value <= (-8.0 * 0x10000000)) | |
2079 | { dest [i].bytes [0] = 0x00 ; | |
2080 | dest [i].bytes [1] = 0x00 ; | |
2081 | dest [i].bytes [2] = 0x80 ; | |
2082 | continue ; | |
2083 | } ; | |
2084 | #endif | |
2061 | 2085 | |
2062 | 2086 | value = psf_lrintf (scaled_value) ; |
2063 | dest [count].bytes [0] = value >> 8 ; | |
2064 | dest [count].bytes [1] = value >> 16 ; | |
2065 | dest [count].bytes [2] = value >> 24 ; | |
2087 | dest [i].bytes [0] = value >> 8 ; | |
2088 | dest [i].bytes [1] = value >> 16 ; | |
2089 | dest [i].bytes [2] = value >> 24 ; | |
2066 | 2090 | } ; |
2067 | 2091 | } /* f2let_clip_array */ |
2068 | 2092 | |
2080 | 2104 | { if (len < bufferlen) |
2081 | 2105 | bufferlen = (int) len ; |
2082 | 2106 | convert (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen, psf->norm_float) ; |
2083 | writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
2107 | writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
2084 | 2108 | total += writecount ; |
2085 | 2109 | if (writecount < bufferlen) |
2086 | 2110 | break ; |
2100 | 2124 | |
2101 | 2125 | normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; |
2102 | 2126 | |
2103 | while (--count >= 0) | |
2104 | { value = psf_lrintf (src [count] * normfact) ; | |
2105 | dest [count].bytes [0] = value >> 16 ; | |
2106 | dest [count].bytes [1] = value >> 8 ; | |
2107 | dest [count].bytes [2] = value ; | |
2127 | for (int i = 0 ; i < count ; i++) | |
2128 | { value = psf_lrintf (src [i] * normfact) ; | |
2129 | dest [i].bytes [0] = value >> 16 ; | |
2130 | dest [i].bytes [1] = value >> 8 ; | |
2131 | dest [i].bytes [2] = value ; | |
2108 | 2132 | } ; |
2109 | 2133 | } /* f2bet_array */ |
2110 | 2134 | |
2115 | 2139 | |
2116 | 2140 | normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; |
2117 | 2141 | |
2118 | while (--count >= 0) | |
2119 | { scaled_value = src [count] * normfact ; | |
2120 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2121 | { dest [count].bytes [0] = 0x7F ; | |
2122 | dest [count].bytes [1] = 0xFF ; | |
2123 | dest [count].bytes [2] = 0xFF ; | |
2124 | continue ; | |
2125 | } ; | |
2126 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2127 | { dest [count].bytes [0] = 0x80 ; | |
2128 | dest [count].bytes [1] = 0x00 ; | |
2129 | dest [count].bytes [2] = 0x00 ; | |
2130 | continue ; | |
2131 | } ; | |
2142 | for (int i = 0 ; i < count ; i++) | |
2143 | { scaled_value = src [i] * normfact ; | |
2144 | #if CPU_CLIPS_POSITIVE == 0 | |
2145 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2146 | { dest [i].bytes [0] = 0x7F ; | |
2147 | dest [i].bytes [1] = 0xFF ; | |
2148 | dest [i].bytes [2] = 0xFF ; | |
2149 | continue ; | |
2150 | } ; | |
2151 | #endif | |
2152 | #if CPU_CLIPS_NEGATIVE == 0 | |
2153 | if (scaled_value <= (-8.0 * 0x10000000)) | |
2154 | { dest [i].bytes [0] = 0x80 ; | |
2155 | dest [i].bytes [1] = 0x00 ; | |
2156 | dest [i].bytes [2] = 0x00 ; | |
2157 | continue ; | |
2158 | } ; | |
2159 | #endif | |
2132 | 2160 | |
2133 | 2161 | value = psf_lrint (scaled_value) ; |
2134 | dest [count].bytes [0] = value >> 24 ; | |
2135 | dest [count].bytes [1] = value >> 16 ; | |
2136 | dest [count].bytes [2] = value >> 8 ; | |
2162 | dest [i].bytes [0] = value >> 24 ; | |
2163 | dest [i].bytes [1] = value >> 16 ; | |
2164 | dest [i].bytes [2] = value >> 8 ; | |
2137 | 2165 | } ; |
2138 | 2166 | } /* f2bet_clip_array */ |
2139 | 2167 | |
2151 | 2179 | { if (len < bufferlen) |
2152 | 2180 | bufferlen = (int) len ; |
2153 | 2181 | convert (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen, psf->norm_float) ; |
2154 | writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
2182 | writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
2155 | 2183 | total += writecount ; |
2156 | 2184 | if (writecount < bufferlen) |
2157 | 2185 | break ; |
2171 | 2199 | int value ; |
2172 | 2200 | |
2173 | 2201 | normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; |
2174 | ucptr = ((unsigned char*) dest) + 4 * count ; | |
2175 | while (--count >= 0) | |
2176 | { ucptr -= 4 ; | |
2177 | value = psf_lrintf (src [count] * normfact) ; | |
2202 | ||
2203 | for (int i = 0 ; i < count ; i++) | |
2204 | { ucptr = (unsigned char*) &dest [i] ; | |
2205 | value = psf_lrintf (src [i] * normfact) ; | |
2178 | 2206 | ucptr [0] = value >> 24 ; |
2179 | 2207 | ucptr [1] = value >> 16 ; |
2180 | 2208 | ucptr [2] = value >> 8 ; |
2189 | 2217 | int value ; |
2190 | 2218 | |
2191 | 2219 | normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; |
2192 | ucptr = ((unsigned char*) dest) + 4 * count ; | |
2193 | ||
2194 | while (--count >= 0) | |
2195 | { ucptr -= 4 ; | |
2196 | scaled_value = src [count] * normfact ; | |
2197 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= 1.0 * 0x7FFFFFFF) | |
2220 | ||
2221 | for (int i = 0 ; i < count ; i++) | |
2222 | { ucptr = (unsigned char*) &dest [i] ; | |
2223 | scaled_value = src [i] * normfact ; | |
2224 | #if CPU_CLIPS_POSITIVE == 0 | |
2225 | if (scaled_value >= 1.0 * 0x7FFFFFFF) | |
2198 | 2226 | { ucptr [0] = 0x7F ; |
2199 | 2227 | ucptr [1] = 0xFF ; |
2200 | 2228 | ucptr [2] = 0xFF ; |
2201 | 2229 | ucptr [3] = 0xFF ; |
2202 | 2230 | continue ; |
2203 | 2231 | } ; |
2204 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2232 | #endif | |
2233 | #if CPU_CLIPS_NEGATIVE == 0 | |
2234 | if (scaled_value <= (-8.0 * 0x10000000)) | |
2205 | 2235 | { ucptr [0] = 0x80 ; |
2206 | 2236 | ucptr [1] = 0x00 ; |
2207 | 2237 | ucptr [2] = 0x00 ; |
2208 | 2238 | ucptr [3] = 0x00 ; |
2209 | 2239 | continue ; |
2210 | 2240 | } ; |
2241 | #endif | |
2211 | 2242 | |
2212 | 2243 | value = psf_lrintf (scaled_value) ; |
2213 | 2244 | ucptr [0] = value >> 24 ; |
2231 | 2262 | { if (len < bufferlen) |
2232 | 2263 | bufferlen = (int) len ; |
2233 | 2264 | convert (ptr + total, ubuf.ibuf, bufferlen, psf->norm_float) ; |
2234 | writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
2265 | writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
2235 | 2266 | total += writecount ; |
2236 | 2267 | if (writecount < bufferlen) |
2237 | 2268 | break ; |
2251 | 2282 | int value ; |
2252 | 2283 | |
2253 | 2284 | normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; |
2254 | ucptr = ((unsigned char*) dest) + 4 * count ; | |
2255 | ||
2256 | while (--count >= 0) | |
2257 | { ucptr -= 4 ; | |
2258 | value = psf_lrintf (src [count] * normfact) ; | |
2285 | ||
2286 | for (int i = 0 ; i < count ; i++) | |
2287 | { ucptr = (unsigned char*) &dest [i] ; | |
2288 | value = psf_lrintf (src [i] * normfact) ; | |
2259 | 2289 | ucptr [0] = value ; |
2260 | 2290 | ucptr [1] = value >> 8 ; |
2261 | 2291 | ucptr [2] = value >> 16 ; |
2270 | 2300 | int value ; |
2271 | 2301 | |
2272 | 2302 | normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; |
2273 | ucptr = ((unsigned char*) dest) + 4 * count ; | |
2274 | ||
2275 | while (--count >= 0) | |
2276 | { ucptr -= 4 ; | |
2277 | scaled_value = src [count] * normfact ; | |
2278 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2303 | ||
2304 | for (int i = 0 ; i < count ; i++) | |
2305 | { ucptr = (unsigned char*) &dest [i] ; | |
2306 | scaled_value = src [i] * normfact ; | |
2307 | #if CPU_CLIPS_POSITIVE == 0 | |
2308 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2279 | 2309 | { ucptr [0] = 0xFF ; |
2280 | 2310 | ucptr [1] = 0xFF ; |
2281 | 2311 | ucptr [2] = 0xFF ; |
2282 | 2312 | ucptr [3] = 0x7F ; |
2283 | 2313 | continue ; |
2284 | 2314 | } ; |
2285 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2315 | #endif | |
2316 | #if CPU_CLIPS_NEGATIVE == 0 | |
2317 | if (scaled_value <= (-8.0 * 0x10000000)) | |
2286 | 2318 | { ucptr [0] = 0x00 ; |
2287 | 2319 | ucptr [1] = 0x00 ; |
2288 | 2320 | ucptr [2] = 0x00 ; |
2289 | 2321 | ucptr [3] = 0x80 ; |
2290 | 2322 | continue ; |
2291 | 2323 | } ; |
2324 | #endif | |
2292 | 2325 | |
2293 | 2326 | value = psf_lrintf (scaled_value) ; |
2294 | 2327 | ucptr [0] = value ; |
2312 | 2345 | { if (len < bufferlen) |
2313 | 2346 | bufferlen = (int) len ; |
2314 | 2347 | convert (ptr + total, ubuf.ibuf, bufferlen, psf->norm_float) ; |
2315 | writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
2348 | writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
2316 | 2349 | total += writecount ; |
2317 | 2350 | if (writecount < bufferlen) |
2318 | 2351 | break ; |
2331 | 2364 | |
2332 | 2365 | normfact = normalize ? (1.0 * 0x7F) : 1.0 ; |
2333 | 2366 | |
2334 | while (--count >= 0) | |
2335 | { dest [count] = psf_lrint (src [count] * normfact) ; | |
2367 | for (int i = 0 ; i < count ; i++) | |
2368 | { dest [i] = psf_lrint (src [i] * normfact) ; | |
2336 | 2369 | } ; |
2337 | 2370 | } /* d2sc_array */ |
2338 | 2371 | |
2342 | 2375 | |
2343 | 2376 | normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; |
2344 | 2377 | |
2345 | while (--count >= 0) | |
2346 | { scaled_value = src [count] * normfact ; | |
2347 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2348 | { dest [count] = 127 ; | |
2349 | continue ; | |
2350 | } ; | |
2351 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2352 | { dest [count] = -128 ; | |
2353 | continue ; | |
2354 | } ; | |
2355 | ||
2356 | dest [count] = psf_lrintf (scaled_value) >> 24 ; | |
2378 | for (int i = 0 ; i < count ; i++) | |
2379 | { scaled_value = src [i] * normfact ; | |
2380 | #if CPU_CLIPS_POSITIVE == 0 | |
2381 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2382 | { dest [i] = 127 ; | |
2383 | continue ; | |
2384 | } ; | |
2385 | #endif | |
2386 | #if CPU_CLIPS_NEGATIVE == 0 | |
2387 | if (scaled_value <= (-8.0 * 0x10000000)) | |
2388 | { dest [i] = -128 ; | |
2389 | continue ; | |
2390 | } ; | |
2391 | #endif | |
2392 | ||
2393 | dest [i] = psf_lrintf (scaled_value) >> 24 ; | |
2357 | 2394 | } ; |
2358 | 2395 | } /* d2sc_clip_array */ |
2359 | 2396 | |
2371 | 2408 | { if (len < bufferlen) |
2372 | 2409 | bufferlen = (int) len ; |
2373 | 2410 | convert (ptr + total, ubuf.scbuf, bufferlen, psf->norm_double) ; |
2374 | writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
2411 | writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
2375 | 2412 | total += writecount ; |
2376 | 2413 | if (writecount < bufferlen) |
2377 | 2414 | break ; |
2390 | 2427 | |
2391 | 2428 | normfact = normalize ? (1.0 * 0x7F) : 1.0 ; |
2392 | 2429 | |
2393 | while (--count >= 0) | |
2394 | { dest [count] = psf_lrint (src [count] * normfact) + 128 ; | |
2430 | for (int i = 0 ; i < count ; i++) | |
2431 | { dest [i] = psf_lrint (src [i] * normfact) + 128 ; | |
2395 | 2432 | } ; |
2396 | 2433 | } /* d2uc_array */ |
2397 | 2434 | |
2401 | 2438 | |
2402 | 2439 | normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; |
2403 | 2440 | |
2404 | while (--count >= 0) | |
2405 | { scaled_value = src [count] * normfact ; | |
2406 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2407 | { dest [count] = 255 ; | |
2408 | continue ; | |
2409 | } ; | |
2410 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2411 | { dest [count] = 0 ; | |
2412 | continue ; | |
2413 | } ; | |
2414 | ||
2415 | dest [count] = (psf_lrint (src [count] * normfact) >> 24) + 128 ; | |
2441 | for (int i = 0 ; i < count ; i++) | |
2442 | { scaled_value = src [i] * normfact ; | |
2443 | #if CPU_CLIPS_POSITIVE == 0 | |
2444 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2445 | { dest [i] = 255 ; | |
2446 | continue ; | |
2447 | } ; | |
2448 | #endif | |
2449 | #if CPU_CLIPS_NEGATIVE == 0 | |
2450 | if (scaled_value <= (-8.0 * 0x10000000)) | |
2451 | { dest [i] = 0 ; | |
2452 | continue ; | |
2453 | } ; | |
2454 | #endif | |
2455 | ||
2456 | dest [i] = (psf_lrint (src [i] * normfact) >> 24) + 128 ; | |
2416 | 2457 | } ; |
2417 | 2458 | } /* d2uc_clip_array */ |
2418 | 2459 | |
2430 | 2471 | { if (len < bufferlen) |
2431 | 2472 | bufferlen = (int) len ; |
2432 | 2473 | convert (ptr + total, ubuf.ucbuf, bufferlen, psf->norm_double) ; |
2433 | writecount = psf_fwrite (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
2474 | writecount = (int) psf_fwrite (ubuf.ucbuf, sizeof (unsigned char), bufferlen, psf) ; | |
2434 | 2475 | total += writecount ; |
2435 | 2476 | if (writecount < bufferlen) |
2436 | 2477 | break ; |
2450 | 2491 | double normfact ; |
2451 | 2492 | |
2452 | 2493 | normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; |
2453 | ucptr = ((unsigned char*) dest) + 2 * count ; | |
2454 | ||
2455 | while (--count >= 0) | |
2456 | { ucptr -= 2 ; | |
2457 | value = psf_lrint (src [count] * normfact) ; | |
2494 | ||
2495 | for (int i = 0 ; i < count ; i++) | |
2496 | { ucptr = (unsigned char*) &dest [i] ; | |
2497 | value = psf_lrint (src [i] * normfact) ; | |
2458 | 2498 | ucptr [1] = value ; |
2459 | 2499 | ucptr [0] = value >> 8 ; |
2460 | 2500 | } ; |
2467 | 2507 | int value ; |
2468 | 2508 | |
2469 | 2509 | normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; |
2470 | ucptr = ((unsigned char*) dest) + 2 * count ; | |
2471 | ||
2472 | while (--count >= 0) | |
2473 | { ucptr -= 2 ; | |
2474 | scaled_value = src [count] * normfact ; | |
2475 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2510 | ||
2511 | for (int i = 0 ; i < count ; i++) | |
2512 | { ucptr = (unsigned char*) &dest [i] ; | |
2513 | scaled_value = src [i] * normfact ; | |
2514 | #if CPU_CLIPS_POSITIVE == 0 | |
2515 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2476 | 2516 | { ucptr [1] = 0xFF ; |
2477 | 2517 | ucptr [0] = 0x7F ; |
2478 | 2518 | continue ; |
2479 | 2519 | } ; |
2480 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2520 | #endif | |
2521 | #if CPU_CLIPS_NEGATIVE == 0 | |
2522 | if (scaled_value <= (-8.0 * 0x10000000)) | |
2481 | 2523 | { ucptr [1] = 0x00 ; |
2482 | 2524 | ucptr [0] = 0x80 ; |
2483 | 2525 | continue ; |
2484 | 2526 | } ; |
2527 | #endif | |
2485 | 2528 | |
2486 | 2529 | value = psf_lrint (scaled_value) ; |
2487 | 2530 | ucptr [1] = value >> 16 ; |
2503 | 2546 | { if (len < bufferlen) |
2504 | 2547 | bufferlen = (int) len ; |
2505 | 2548 | convert (ptr + total, ubuf.sbuf, bufferlen, psf->norm_double) ; |
2506 | writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
2549 | writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
2507 | 2550 | total += writecount ; |
2508 | 2551 | if (writecount < bufferlen) |
2509 | 2552 | break ; |
2523 | 2566 | double normfact ; |
2524 | 2567 | |
2525 | 2568 | normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; |
2526 | ucptr = ((unsigned char*) dest) + 2 * count ; | |
2527 | ||
2528 | while (--count >= 0) | |
2529 | { ucptr -= 2 ; | |
2530 | value = psf_lrint (src [count] * normfact) ; | |
2569 | ||
2570 | for (int i = 0 ; i < count ; i++) | |
2571 | { ucptr = (unsigned char*) &dest [i] ; | |
2572 | value = psf_lrint (src [i] * normfact) ; | |
2531 | 2573 | ucptr [0] = value ; |
2532 | 2574 | ucptr [1] = value >> 8 ; |
2533 | 2575 | } ; |
2540 | 2582 | double normfact, scaled_value ; |
2541 | 2583 | |
2542 | 2584 | normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; |
2543 | ucptr = ((unsigned char*) dest) + 2 * count ; | |
2544 | ||
2545 | while (--count >= 0) | |
2546 | { ucptr -= 2 ; | |
2547 | scaled_value = src [count] * normfact ; | |
2548 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2585 | ||
2586 | for (int i = 0 ; i < count ; i++) | |
2587 | { ucptr = (unsigned char*) &dest [i] ; | |
2588 | scaled_value = src [i] * normfact ; | |
2589 | #if CPU_CLIPS_POSITIVE == 0 | |
2590 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2549 | 2591 | { ucptr [0] = 0xFF ; |
2550 | 2592 | ucptr [1] = 0x7F ; |
2551 | 2593 | continue ; |
2552 | 2594 | } ; |
2553 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2595 | #endif | |
2596 | #if CPU_CLIPS_NEGATIVE == 0 | |
2597 | if (scaled_value <= (-8.0 * 0x10000000)) | |
2554 | 2598 | { ucptr [0] = 0x00 ; |
2555 | 2599 | ucptr [1] = 0x80 ; |
2556 | 2600 | continue ; |
2557 | 2601 | } ; |
2602 | #endif | |
2558 | 2603 | |
2559 | 2604 | value = psf_lrint (scaled_value) ; |
2560 | 2605 | ucptr [0] = value >> 16 ; |
2576 | 2621 | { if (len < bufferlen) |
2577 | 2622 | bufferlen = (int) len ; |
2578 | 2623 | convert (ptr + total, ubuf.sbuf, bufferlen, psf->norm_double) ; |
2579 | writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
2624 | writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
2580 | 2625 | total += writecount ; |
2581 | 2626 | if (writecount < bufferlen) |
2582 | 2627 | break ; |
2596 | 2641 | |
2597 | 2642 | normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; |
2598 | 2643 | |
2599 | while (--count >= 0) | |
2600 | { value = psf_lrint (src [count] * normfact) ; | |
2601 | dest [count].bytes [0] = value ; | |
2602 | dest [count].bytes [1] = value >> 8 ; | |
2603 | dest [count].bytes [2] = value >> 16 ; | |
2644 | for (int i = 0 ; i < count ; i++) | |
2645 | { value = psf_lrint (src [i] * normfact) ; | |
2646 | dest [i].bytes [0] = value ; | |
2647 | dest [i].bytes [1] = value >> 8 ; | |
2648 | dest [i].bytes [2] = value >> 16 ; | |
2604 | 2649 | } ; |
2605 | 2650 | } /* d2let_array */ |
2606 | 2651 | |
2611 | 2656 | |
2612 | 2657 | normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; |
2613 | 2658 | |
2614 | while (--count >= 0) | |
2615 | { scaled_value = src [count] * normfact ; | |
2616 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2617 | { dest [count].bytes [0] = 0xFF ; | |
2618 | dest [count].bytes [1] = 0xFF ; | |
2619 | dest [count].bytes [2] = 0x7F ; | |
2620 | continue ; | |
2621 | } ; | |
2622 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2623 | { dest [count].bytes [0] = 0x00 ; | |
2624 | dest [count].bytes [1] = 0x00 ; | |
2625 | dest [count].bytes [2] = 0x80 ; | |
2626 | continue ; | |
2627 | } ; | |
2659 | for (int i = 0 ; i < count ; i++) | |
2660 | { scaled_value = src [i] * normfact ; | |
2661 | #if CPU_CLIPS_POSITIVE == 0 | |
2662 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2663 | { dest [i].bytes [0] = 0xFF ; | |
2664 | dest [i].bytes [1] = 0xFF ; | |
2665 | dest [i].bytes [2] = 0x7F ; | |
2666 | continue ; | |
2667 | } ; | |
2668 | #endif | |
2669 | #if CPU_CLIPS_NEGATIVE == 0 | |
2670 | if (scaled_value <= (-8.0 * 0x10000000)) | |
2671 | { dest [i].bytes [0] = 0x00 ; | |
2672 | dest [i].bytes [1] = 0x00 ; | |
2673 | dest [i].bytes [2] = 0x80 ; | |
2674 | continue ; | |
2675 | } ; | |
2676 | #endif | |
2628 | 2677 | |
2629 | 2678 | value = psf_lrint (scaled_value) ; |
2630 | dest [count].bytes [0] = value >> 8 ; | |
2631 | dest [count].bytes [1] = value >> 16 ; | |
2632 | dest [count].bytes [2] = value >> 24 ; | |
2679 | dest [i].bytes [0] = value >> 8 ; | |
2680 | dest [i].bytes [1] = value >> 16 ; | |
2681 | dest [i].bytes [2] = value >> 24 ; | |
2633 | 2682 | } ; |
2634 | 2683 | } /* d2let_clip_array */ |
2635 | 2684 | |
2647 | 2696 | { if (len < bufferlen) |
2648 | 2697 | bufferlen = (int) len ; |
2649 | 2698 | convert (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen, psf->norm_double) ; |
2650 | writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
2699 | writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
2651 | 2700 | total += writecount ; |
2652 | 2701 | if (writecount < bufferlen) |
2653 | 2702 | break ; |
2667 | 2716 | |
2668 | 2717 | normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; |
2669 | 2718 | |
2670 | while (--count >= 0) | |
2671 | { value = psf_lrint (src [count] * normfact) ; | |
2672 | dest [count].bytes [2] = value ; | |
2673 | dest [count].bytes [1] = value >> 8 ; | |
2674 | dest [count].bytes [0] = value >> 16 ; | |
2719 | for (int i = 0 ; i < count ; i++) | |
2720 | { value = psf_lrint (src [i] * normfact) ; | |
2721 | dest [i].bytes [2] = value ; | |
2722 | dest [i].bytes [1] = value >> 8 ; | |
2723 | dest [i].bytes [0] = value >> 16 ; | |
2675 | 2724 | } ; |
2676 | 2725 | } /* d2bet_array */ |
2677 | 2726 | |
2682 | 2731 | |
2683 | 2732 | normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; |
2684 | 2733 | |
2685 | while (--count >= 0) | |
2686 | { scaled_value = src [count] * normfact ; | |
2687 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2688 | { dest [count].bytes [2] = 0xFF ; | |
2689 | dest [count].bytes [1] = 0xFF ; | |
2690 | dest [count].bytes [0] = 0x7F ; | |
2691 | continue ; | |
2692 | } ; | |
2693 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2694 | { dest [count].bytes [2] = 0x00 ; | |
2695 | dest [count].bytes [1] = 0x00 ; | |
2696 | dest [count].bytes [0] = 0x80 ; | |
2697 | continue ; | |
2698 | } ; | |
2734 | for (int i = 0 ; i < count ; i++) | |
2735 | { scaled_value = src [i] * normfact ; | |
2736 | #if CPU_CLIPS_POSITIVE == 0 | |
2737 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2738 | { dest [i].bytes [2] = 0xFF ; | |
2739 | dest [i].bytes [1] = 0xFF ; | |
2740 | dest [i].bytes [0] = 0x7F ; | |
2741 | continue ; | |
2742 | } ; | |
2743 | #endif | |
2744 | #if CPU_CLIPS_NEGATIVE == 0 | |
2745 | if (scaled_value <= (-8.0 * 0x10000000)) | |
2746 | { dest [i].bytes [2] = 0x00 ; | |
2747 | dest [i].bytes [1] = 0x00 ; | |
2748 | dest [i].bytes [0] = 0x80 ; | |
2749 | continue ; | |
2750 | } ; | |
2751 | #endif | |
2699 | 2752 | |
2700 | 2753 | value = psf_lrint (scaled_value) ; |
2701 | dest [count].bytes [2] = value >> 8 ; | |
2702 | dest [count].bytes [1] = value >> 16 ; | |
2703 | dest [count].bytes [0] = value >> 24 ; | |
2754 | dest [i].bytes [2] = value >> 8 ; | |
2755 | dest [i].bytes [1] = value >> 16 ; | |
2756 | dest [i].bytes [0] = value >> 24 ; | |
2704 | 2757 | } ; |
2705 | 2758 | } /* d2bet_clip_array */ |
2706 | 2759 | |
2718 | 2771 | { if (len < bufferlen) |
2719 | 2772 | bufferlen = (int) len ; |
2720 | 2773 | convert (ptr + total, (tribyte*) (ubuf.ucbuf), bufferlen, psf->norm_double) ; |
2721 | writecount = psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
2774 | writecount = (int) psf_fwrite (ubuf.ucbuf, SIZEOF_TRIBYTE, bufferlen, psf) ; | |
2722 | 2775 | total += writecount ; |
2723 | 2776 | if (writecount < bufferlen) |
2724 | 2777 | break ; |
2738 | 2791 | double normfact ; |
2739 | 2792 | |
2740 | 2793 | normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; |
2741 | ucptr = ((unsigned char*) dest) + 4 * count ; | |
2742 | ||
2743 | while (--count >= 0) | |
2744 | { ucptr -= 4 ; | |
2745 | value = psf_lrint (src [count] * normfact) ; | |
2794 | ||
2795 | for (int i = 0 ; i < count ; i++) | |
2796 | { ucptr = (unsigned char*) &dest [i] ; | |
2797 | value = psf_lrint (src [i] * normfact) ; | |
2746 | 2798 | ucptr [0] = value >> 24 ; |
2747 | 2799 | ucptr [1] = value >> 16 ; |
2748 | 2800 | ucptr [2] = value >> 8 ; |
2757 | 2809 | double normfact, scaled_value ; |
2758 | 2810 | |
2759 | 2811 | normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; |
2760 | ucptr = ((unsigned char*) dest) + 4 * count ; | |
2761 | ||
2762 | while (--count >= 0) | |
2763 | { ucptr -= 4 ; | |
2764 | scaled_value = src [count] * normfact ; | |
2765 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2812 | ||
2813 | for (int i = 0 ; i < count ; i++) | |
2814 | { ucptr = (unsigned char*) &dest [i] ; | |
2815 | scaled_value = src [i] * normfact ; | |
2816 | #if CPU_CLIPS_POSITIVE == 0 | |
2817 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2766 | 2818 | { ucptr [3] = 0xFF ; |
2767 | 2819 | ucptr [2] = 0xFF ; |
2768 | 2820 | ucptr [1] = 0xFF ; |
2769 | 2821 | ucptr [0] = 0x7F ; |
2770 | 2822 | continue ; |
2771 | 2823 | } ; |
2772 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2824 | #endif | |
2825 | #if CPU_CLIPS_NEGATIVE == 0 | |
2826 | if (scaled_value <= (-8.0 * 0x10000000)) | |
2773 | 2827 | { ucptr [3] = 0x00 ; |
2774 | 2828 | ucptr [2] = 0x00 ; |
2775 | 2829 | ucptr [1] = 0x00 ; |
2776 | 2830 | ucptr [0] = 0x80 ; |
2777 | 2831 | continue ; |
2778 | 2832 | } ; |
2833 | #endif | |
2779 | 2834 | |
2780 | 2835 | value = psf_lrint (scaled_value) ; |
2781 | 2836 | ucptr [0] = value >> 24 ; |
2799 | 2854 | { if (len < bufferlen) |
2800 | 2855 | bufferlen = (int) len ; |
2801 | 2856 | convert (ptr + total, ubuf.ibuf, bufferlen, psf->norm_double) ; |
2802 | writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
2857 | writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
2803 | 2858 | total += writecount ; |
2804 | 2859 | if (writecount < bufferlen) |
2805 | 2860 | break ; |
2819 | 2874 | double normfact ; |
2820 | 2875 | |
2821 | 2876 | normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; |
2822 | ucptr = ((unsigned char*) dest) + 4 * count ; | |
2823 | ||
2824 | while (--count >= 0) | |
2825 | { ucptr -= 4 ; | |
2826 | value = psf_lrint (src [count] * normfact) ; | |
2877 | ||
2878 | for (int i = 0 ; i < count ; i++) | |
2879 | { ucptr = (unsigned char*) &dest [i] ; | |
2880 | value = psf_lrint (src [i] * normfact) ; | |
2827 | 2881 | ucptr [0] = value ; |
2828 | 2882 | ucptr [1] = value >> 8 ; |
2829 | 2883 | ucptr [2] = value >> 16 ; |
2838 | 2892 | double normfact, scaled_value ; |
2839 | 2893 | |
2840 | 2894 | normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; |
2841 | ucptr = ((unsigned char*) dest) + 4 * count ; | |
2842 | ||
2843 | while (--count >= 0) | |
2844 | { ucptr -= 4 ; | |
2845 | scaled_value = src [count] * normfact ; | |
2846 | if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2895 | ||
2896 | for (int i = 0 ; i < count ; i++) | |
2897 | { ucptr = (unsigned char*) &dest [i] ; | |
2898 | scaled_value = src [i] * normfact ; | |
2899 | #if CPU_CLIPS_POSITIVE == 0 | |
2900 | if (scaled_value >= (1.0 * 0x7FFFFFFF)) | |
2847 | 2901 | { ucptr [0] = 0xFF ; |
2848 | 2902 | ucptr [1] = 0xFF ; |
2849 | 2903 | ucptr [2] = 0xFF ; |
2850 | 2904 | ucptr [3] = 0x7F ; |
2851 | 2905 | continue ; |
2852 | 2906 | } ; |
2853 | if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) | |
2907 | #endif | |
2908 | #if CPU_CLIPS_NEGATIVE == 0 | |
2909 | if (scaled_value <= (-8.0 * 0x10000000)) | |
2854 | 2910 | { ucptr [0] = 0x00 ; |
2855 | 2911 | ucptr [1] = 0x00 ; |
2856 | 2912 | ucptr [2] = 0x00 ; |
2857 | 2913 | ucptr [3] = 0x80 ; |
2858 | 2914 | continue ; |
2859 | 2915 | } ; |
2916 | #endif | |
2860 | 2917 | |
2861 | 2918 | value = psf_lrint (scaled_value) ; |
2862 | 2919 | ucptr [0] = value ; |
2880 | 2937 | { if (len < bufferlen) |
2881 | 2938 | bufferlen = (int) len ; |
2882 | 2939 | convert (ptr + total, ubuf.ibuf, bufferlen, psf->norm_double) ; |
2883 | writecount = psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
2940 | writecount = (int) psf_fwrite (ubuf.ibuf, sizeof (int), bufferlen, psf) ; | |
2884 | 2941 | total += writecount ; |
2885 | 2942 | if (writecount < bufferlen) |
2886 | 2943 | break ; |
196 | 196 | else |
197 | 197 | psf_log_printf (psf, "%M : 0x%x (should be 0xFFFFFFFF)\n %M\n", RF64_MARKER, WAVE_MARKER) ; |
198 | 198 | |
199 | while (NOT (done)) | |
199 | while (!done) | |
200 | 200 | { |
201 | 201 | marker = chunk_size = 0 ; |
202 | 202 | psf_binheader_readf (psf, "em4", &marker, &chunk_size) ; |
327 | 327 | if (psf->datalength + psf->dataoffset < psf->filelength) |
328 | 328 | psf->dataend = psf->datalength + psf->dataoffset ; |
329 | 329 | |
330 | if (NOT (psf->sf.seekable) || psf->dataoffset < 0) | |
330 | if (!psf->sf.seekable || psf->dataoffset < 0) | |
331 | 331 | break ; |
332 | 332 | |
333 | 333 | /* Seek past data and continue reading header. */ |
761 | 761 | |
762 | 762 | psf->dataoffset = psf->header.indx ; |
763 | 763 | |
764 | if (NOT (has_data)) | |
764 | if (!has_data) | |
765 | 765 | psf_fseek (psf, psf->dataoffset, SEEK_SET) ; |
766 | 766 | else if (current > 0) |
767 | 767 | psf_fseek (psf, current, SEEK_SET) ; |
239 | 239 | /* Very start of resource fork. */ |
240 | 240 | psf_binheader_writef (psf, "E444", BHW4 (rsrc.data_offset), BHW4 (rsrc.map_offset), BHW4 (rsrc.data_length)) ; |
241 | 241 | |
242 | psf_binheader_writef (psf, "Eop", BHWo (0x30), BHWp (psf->file.name.c)) ; | |
242 | psf_binheader_writef (psf, "Eop", BHWo (0x30), BHWp (psf->file.name)) ; | |
243 | 243 | psf_binheader_writef (psf, "Eo2mm", BHWo (0x50), BHW2 (0), BHWm (Sd2f_MARKER), BHWm (lsf1_MARKER)) ; |
244 | 244 | |
245 | 245 | /* Very start of resource map. */ |
280 | 280 | |
281 | 281 | for (blockcount = 0 ; bytesread < psf->filelength ; blockcount++) |
282 | 282 | { |
283 | bytesread += psf_fread (&marker, 1, 2, psf) ; | |
283 | bytesread += (int) psf_fread (&marker, 1, 2, psf) ; | |
284 | 284 | |
285 | 285 | if (marker == 0) |
286 | 286 | break ; |
430 | 430 | return 1 ; |
431 | 431 | } ; |
432 | 432 | |
433 | if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) | |
433 | if ((k = (int) psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) | |
434 | 434 | psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ; |
435 | 435 | |
436 | 436 | if (psds->read_data [0] != 0xF0) |
474 | 474 | return 1 ; |
475 | 475 | } ; |
476 | 476 | |
477 | if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) | |
477 | if ((k = (int) psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) | |
478 | 478 | psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ; |
479 | 479 | |
480 | 480 | if (psds->read_data [0] != 0xF0) |
518 | 518 | return 1 ; |
519 | 519 | } ; |
520 | 520 | |
521 | if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) | |
521 | if ((k = (int) psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) | |
522 | 522 | psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ; |
523 | 523 | |
524 | 524 | if (psds->read_data [0] != 0xF0) |
564 | 564 | iptr = ubuf.ibuf ; |
565 | 565 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
566 | 566 | while (len > 0) |
567 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
567 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
568 | 568 | count = sds_read (psf, psds, iptr, readcount) ; |
569 | 569 | for (k = 0 ; k < readcount ; k++) |
570 | 570 | ptr [total + k] = iptr [k] >> 16 ; |
610 | 610 | iptr = ubuf.ibuf ; |
611 | 611 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
612 | 612 | while (len > 0) |
613 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
613 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
614 | 614 | count = sds_read (psf, psds, iptr, readcount) ; |
615 | 615 | for (k = 0 ; k < readcount ; k++) |
616 | 616 | ptr [total + k] = normfact * iptr [k] ; |
642 | 642 | iptr = ubuf.ibuf ; |
643 | 643 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
644 | 644 | while (len > 0) |
645 | { readcount = (len >= bufferlen) ? bufferlen : len ; | |
645 | { readcount = (len >= bufferlen) ? bufferlen : (int) len ; | |
646 | 646 | count = sds_read (psf, psds, iptr, readcount) ; |
647 | 647 | for (k = 0 ; k < readcount ; k++) |
648 | 648 | ptr [total + k] = normfact * iptr [k] ; |
793 | 793 | psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ; |
794 | 794 | psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ; |
795 | 795 | |
796 | if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) | |
796 | if ((k = (int) psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) | |
797 | 797 | psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ; |
798 | 798 | |
799 | 799 | psds->write_block ++ ; |
835 | 835 | psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ; |
836 | 836 | psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ; |
837 | 837 | |
838 | if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) | |
838 | if ((k = (int) psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) | |
839 | 839 | psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ; |
840 | 840 | |
841 | 841 | psds->write_block ++ ; |
878 | 878 | psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ; |
879 | 879 | psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ; |
880 | 880 | |
881 | if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) | |
881 | if ((k = (int) psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) | |
882 | 882 | psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ; |
883 | 883 | |
884 | 884 | psds->write_block ++ ; |
907 | 907 | iptr = ubuf.ibuf ; |
908 | 908 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
909 | 909 | while (len > 0) |
910 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
910 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
911 | 911 | for (k = 0 ; k < writecount ; k++) |
912 | 912 | iptr [k] = arith_shift_left (ptr [total + k], 16) ; |
913 | 913 | count = sds_write (psf, psds, iptr, writecount) ; |
955 | 955 | iptr = ubuf.ibuf ; |
956 | 956 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
957 | 957 | while (len > 0) |
958 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
958 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
959 | 959 | for (k = 0 ; k < writecount ; k++) |
960 | 960 | iptr [k] = normfact * ptr [total + k] ; |
961 | 961 | count = sds_write (psf, psds, iptr, writecount) ; |
988 | 988 | iptr = ubuf.ibuf ; |
989 | 989 | bufferlen = ARRAY_LEN (ubuf.ibuf) ; |
990 | 990 | while (len > 0) |
991 | { writecount = (len >= bufferlen) ? bufferlen : len ; | |
991 | { writecount = (len >= bufferlen) ? bufferlen : (int) len ; | |
992 | 992 | for (k = 0 ; k < writecount ; k++) |
993 | 993 | iptr [k] = normfact * ptr [total + k] ; |
994 | 994 | count = sds_write (psf, psds, iptr, writecount) ; |
23 | 23 | #include <stdint.h> |
24 | 24 | #include <inttypes.h> |
25 | 25 | |
26 | #ifndef __has_builtin | |
27 | #define __has_builtin(x) 0 | |
28 | #endif | |
29 | ||
26 | 30 | #if HAVE_BYTESWAP_H /* Linux, any CPU */ |
27 | 31 | #include <byteswap.h> |
28 | 32 | |
30 | 34 | #define ENDSWAP_32(x) (bswap_32 (x)) |
31 | 35 | #define ENDSWAP_64(x) (bswap_64 (x)) |
32 | 36 | |
33 | #elif defined __has_builtin | |
34 | ||
35 | #if __has_builtin (__builtin_bswap16) | |
37 | #elif __has_builtin(__builtin_bswap16) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64) | |
38 | ||
36 | 39 | #define ENDSWAP_16(x) ((int16_t) __builtin_bswap16 ((uint16_t) x)) |
37 | #endif | |
38 | ||
39 | #if __has_builtin (__builtin_bswap32) | |
40 | 40 | #define ENDSWAP_32(x) ((int32_t) __builtin_bswap32 ((uint32_t) x)) |
41 | #endif | |
42 | ||
43 | #if __has_builtin (__builtin_bswap64) | |
44 | 41 | #define ENDSWAP_64(x) ((int64_t) __builtin_bswap64 ((uint64_t) x)) |
45 | #endif | |
46 | 42 | |
47 | 43 | #elif COMPILER_IS_GCC |
48 | 44 | |
209 | 205 | psf_get_be64 (const uint8_t *ptr, int offset) |
210 | 206 | { int64_t value ; |
211 | 207 | |
212 | value = ((uint32_t) ptr [offset]) << 24 ; | |
208 | value = (int64_t) ((uint64_t) ptr [offset] << 24) ; | |
209 | value += (int64_t) ((uint64_t) ptr [offset + 1] << 16) ; | |
210 | value += (int64_t) ((uint64_t) ptr [offset + 2] << 8) ; | |
211 | value += ptr [offset + 3] ; | |
212 | ||
213 | value = (int64_t) (((uint64_t) value) << 32) ; | |
214 | ||
215 | value += (int64_t) ((uint64_t) ptr [offset + 4] << 24) ; | |
216 | value += (int64_t) ((uint64_t) ptr [offset + 5] << 16) ; | |
217 | value += (int64_t) ((uint64_t) ptr [offset + 6] << 8) ; | |
218 | value += ptr [offset + 7] ; | |
219 | return value ; | |
220 | } /* psf_get_be64 */ | |
221 | ||
222 | static inline int64_t | |
223 | psf_get_le64 (const uint8_t *ptr, int offset) | |
224 | { int64_t value = (int64_t) ((uint64_t) ptr [offset + 7] << 24) ; | |
225 | value += (int64_t) ((uint64_t) ptr [offset + 6] << 16) ; | |
226 | value += (int64_t) ((uint64_t) ptr [offset + 5] << 8) ; | |
227 | value += ptr [offset + 4] ; | |
228 | ||
229 | value = (int64_t) (((uint64_t) value) << 32) ; | |
230 | ||
231 | value += (int64_t) ((uint64_t) ptr [offset + 3] << 24) ; | |
232 | value += (int64_t) ((uint64_t) ptr [offset + 2] << 16) ; | |
233 | value += (int64_t) ((uint64_t) ptr [offset + 1] << 8) ; | |
234 | value += ptr [offset] ; | |
235 | return value ; | |
236 | } /* psf_get_le64 */ | |
237 | ||
238 | static inline int32_t | |
239 | psf_get_be32 (const uint8_t *ptr, int offset) | |
240 | { int32_t value = ((uint32_t) ptr [offset]) << 24 ; | |
213 | 241 | value += ptr [offset + 1] << 16 ; |
214 | 242 | value += ptr [offset + 2] << 8 ; |
215 | 243 | value += ptr [offset + 3] ; |
216 | ||
217 | value = (int64_t) (((uint64_t) value) << 32) ; | |
218 | ||
219 | value += ((uint32_t) ptr [offset + 4]) << 24 ; | |
220 | value += ptr [offset + 5] << 16 ; | |
221 | value += ptr [offset + 6] << 8 ; | |
222 | value += ptr [offset + 7] ; | |
223 | return value ; | |
224 | } /* psf_get_be64 */ | |
225 | ||
226 | static inline int64_t | |
227 | psf_get_le64 (const uint8_t *ptr, int offset) | |
228 | { int64_t value ; | |
229 | ||
230 | value = ((uint32_t) ptr [offset + 7]) << 24 ; | |
231 | value += ptr [offset + 6] << 16 ; | |
232 | value += ptr [offset + 5] << 8 ; | |
233 | value += ptr [offset + 4] ; | |
234 | ||
235 | value = (int64_t) (((uint64_t) value) << 32) ; | |
236 | ||
237 | value += ((uint32_t) ptr [offset + 3]) << 24 ; | |
244 | return value ; | |
245 | } /* psf_get_be32 */ | |
246 | ||
247 | static inline int32_t | |
248 | psf_get_le32 (const uint8_t *ptr, int offset) | |
249 | { int32_t value = ((uint32_t) ptr [offset + 3]) << 24 ; | |
238 | 250 | value += ptr [offset + 2] << 16 ; |
239 | 251 | value += ptr [offset + 1] << 8 ; |
240 | 252 | value += ptr [offset] ; |
241 | 253 | return value ; |
242 | } /* psf_get_le64 */ | |
243 | ||
244 | static inline int32_t | |
245 | psf_get_be32 (const uint8_t *ptr, int offset) | |
246 | { int32_t value ; | |
247 | ||
248 | value = ((uint32_t) ptr [offset]) << 24 ; | |
254 | } /* psf_get_le32 */ | |
255 | ||
256 | static inline int32_t | |
257 | psf_get_be24 (const uint8_t *ptr, int offset) | |
258 | { int32_t value = ((uint32_t) ptr [offset]) << 24 ; | |
249 | 259 | value += ptr [offset + 1] << 16 ; |
250 | 260 | value += ptr [offset + 2] << 8 ; |
251 | value += ptr [offset + 3] ; | |
252 | return value ; | |
253 | } /* psf_get_be32 */ | |
254 | ||
255 | static inline int32_t | |
256 | psf_get_le32 (const uint8_t *ptr, int offset) | |
257 | { int32_t value ; | |
258 | ||
259 | value = ((uint32_t) ptr [offset + 3]) << 24 ; | |
260 | value += ptr [offset + 2] << 16 ; | |
261 | value += ptr [offset + 1] << 8 ; | |
262 | value += ptr [offset] ; | |
263 | return value ; | |
264 | } /* psf_get_le32 */ | |
265 | ||
266 | static inline int32_t | |
267 | psf_get_be24 (const uint8_t *ptr, int offset) | |
268 | { int32_t value ; | |
269 | ||
270 | value = ((uint32_t) ptr [offset]) << 24 ; | |
271 | value += ptr [offset + 1] << 16 ; | |
272 | value += ptr [offset + 2] << 8 ; | |
273 | 261 | return value ; |
274 | 262 | } /* psf_get_be24 */ |
275 | 263 | |
276 | 264 | static inline int32_t |
277 | 265 | psf_get_le24 (const uint8_t *ptr, int offset) |
278 | { int32_t value ; | |
279 | ||
280 | value = ((uint32_t) ptr [offset + 2]) << 24 ; | |
266 | { int32_t value = ((uint32_t) ptr [offset + 2]) << 24 ; | |
281 | 267 | value += ptr [offset + 1] << 16 ; |
282 | 268 | value += ptr [offset] << 8 ; |
283 | 269 | return value ; |
294 | 280 | |
295 | 281 | static inline void |
296 | 282 | endswap_short_array (short *ptr, int len) |
297 | { short temp ; | |
298 | ||
299 | while (--len >= 0) | |
300 | { temp = ptr [len] ; | |
301 | ptr [len] = ENDSWAP_16 (temp) ; | |
283 | { | |
284 | for (int i = 0 ; i < len ; i++) | |
285 | { short temp = ptr [i] ; | |
286 | ptr [i] = ENDSWAP_16 (temp) ; | |
302 | 287 | } ; |
303 | 288 | } /* endswap_short_array */ |
304 | 289 | |
305 | 290 | static inline void |
306 | 291 | endswap_short_copy (short *dest, const short *src, int len) |
307 | 292 | { |
308 | while (--len >= 0) | |
309 | { dest [len] = ENDSWAP_16 (src [len]) ; | |
293 | for (int i = 0 ; i < len ; i++) | |
294 | { dest [i] = ENDSWAP_16 (src [i]) ; | |
310 | 295 | } ; |
311 | 296 | } /* endswap_short_copy */ |
312 | 297 | |
313 | 298 | static inline void |
314 | 299 | endswap_int_array (int *ptr, int len) |
315 | { int temp ; | |
316 | ||
317 | while (--len >= 0) | |
318 | { temp = ptr [len] ; | |
319 | ptr [len] = ENDSWAP_32 (temp) ; | |
300 | { | |
301 | for (int i = 0 ; i < len ; i++) | |
302 | { int temp = ptr [i] ; | |
303 | ptr [i] = ENDSWAP_32 (temp) ; | |
320 | 304 | } ; |
321 | 305 | } /* endswap_int_array */ |
322 | 306 | |
323 | 307 | static inline void |
324 | 308 | endswap_int_copy (int *dest, const int *src, int len) |
325 | 309 | { |
326 | while (--len >= 0) | |
327 | { dest [len] = ENDSWAP_32 (src [len]) ; | |
310 | for (int i = 0 ; i < len ; i++) | |
311 | { dest [i] = ENDSWAP_32 (src [i]) ; | |
328 | 312 | } ; |
329 | 313 | } /* endswap_int_copy */ |
330 | 314 | |
333 | 317 | |
334 | 318 | static inline void |
335 | 319 | endswap_int64_t_array (int64_t *ptr, int len) |
336 | { int64_t value ; | |
337 | ||
338 | while (--len >= 0) | |
339 | { value = ptr [len] ; | |
340 | ptr [len] = ENDSWAP_64 (value) ; | |
320 | { | |
321 | for (int i = 0 ; i < len ; i++) | |
322 | { int64_t value = ptr [i] ; | |
323 | ptr [i] = ENDSWAP_64 (value) ; | |
341 | 324 | } ; |
342 | 325 | } /* endswap_int64_t_array */ |
343 | 326 | |
344 | 327 | static inline void |
345 | 328 | endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len) |
346 | { int64_t value ; | |
347 | ||
348 | while (--len >= 0) | |
349 | { value = src [len] ; | |
350 | dest [len] = ENDSWAP_64 (value) ; | |
329 | { | |
330 | for (int i = 0 ; i < len ; i++) | |
331 | { int64_t value = src [i] ; | |
332 | dest [i] = ENDSWAP_64 (value) ; | |
351 | 333 | } ; |
352 | 334 | } /* endswap_int64_t_copy */ |
353 | 335 |
30 | 30 | #include <unistd.h> |
31 | 31 | #elif defined _WIN32 |
32 | 32 | #include <io.h> |
33 | #endif | |
34 | ||
35 | #ifdef _WIN32 | |
36 | #define WIN32_LEAN_AND_MEAN | |
37 | #include <windows.h> | |
33 | 38 | #endif |
34 | 39 | |
35 | 40 | #define SNDFILE_MAGICK 0x1234C0DE |
276 | 281 | { SFE_FILENAME_TOO_LONG , "Error : Supplied filename too long." }, |
277 | 282 | { SFE_NEGATIVE_RW_LEN , "Error : Length parameter passed to read/write is negative." }, |
278 | 283 | |
279 | { SFE_OPUS_BAD_SAMPLERATE , "Error : Opus only supports sample rates of 8000, 12000, 16000, 24000 and 48000." }, | |
284 | { SFE_OPUS_BAD_SAMPLERATE , "Error : Opus only supports sample rates of 8000, 12000, 16000, 24000, and 48000." }, | |
285 | ||
286 | { SFE_MPEG_BAD_SAMPLERATE , "Error : MPEG-1/2/2.5 only supports sample rates of 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, and 48000." }, | |
287 | ||
288 | { SFE_CAF_NOT_CAF , "Error : Not a CAF file." }, | |
289 | { SFE_CAF_NO_DESC , "Error : No 'desc' marker in CAF file." }, | |
290 | { SFE_CAF_BAD_PEAK , "Error : Bad 'PEAK' chunk in CAF file." }, | |
291 | ||
292 | { SFE_AVR_NOT_AVR , "Error : Not an AVR file." }, | |
293 | { SFE_AVR_BAD_REZ_SIGN , "Error : Bad rez/sign combination." }, | |
294 | ||
295 | { SFE_MPC_NO_MARKER , "Error : No marker in MPC2K file." }, | |
280 | 296 | |
281 | 297 | { SFE_MAX_ERROR , "Maximum error number." }, |
282 | 298 | { SFE_MAX_ERROR + 1 , NULL } |
290 | 306 | static int validate_sfinfo (SF_INFO *sfinfo) ; |
291 | 307 | static int validate_psf (SF_PRIVATE *psf) ; |
292 | 308 | static void save_header_info (SF_PRIVATE *psf) ; |
293 | static int copy_filename (SF_PRIVATE *psf, const char *path) ; | |
294 | 309 | static int psf_close (SF_PRIVATE *psf) ; |
295 | 310 | |
296 | 311 | static int try_resource_fork (SF_PRIVATE * psf) ; |
331 | 346 | SNDFILE* |
332 | 347 | sf_open (const char *path, int mode, SF_INFO *sfinfo) |
333 | 348 | { SF_PRIVATE *psf ; |
349 | const char *utf8path_ptr ; | |
350 | #ifdef _WIN32 | |
351 | LPWSTR wpath ; | |
352 | int nResult ; | |
353 | int wpath_len ; | |
354 | char utf8path [SF_FILENAME_LEN] ; | |
355 | DWORD dwError ; | |
356 | #endif | |
334 | 357 | |
335 | 358 | /* Ultimate sanity check. */ |
336 | 359 | assert (sizeof (sf_count_t) == 8) ; |
344 | 367 | |
345 | 368 | psf_log_printf (psf, "File : %s\n", path) ; |
346 | 369 | |
347 | if (copy_filename (psf, path) != 0) | |
370 | #ifdef _WIN32 | |
371 | nResult = MultiByteToWideChar (CP_ACP, 0, path, -1, NULL, 0) ; | |
372 | if (nResult == 0) | |
373 | { sf_errno = SF_ERR_UNSUPPORTED_ENCODING ; | |
374 | psf_close (psf) ; | |
375 | return NULL ; | |
376 | } ; | |
377 | ||
378 | wpath_len = nResult ; | |
379 | wpath = malloc (wpath_len * sizeof (WCHAR)) ; | |
380 | if (!wpath) | |
381 | { sf_errno = SFE_MALLOC_FAILED ; | |
382 | psf_close (psf) ; | |
383 | return NULL ; | |
384 | } ; | |
385 | ||
386 | nResult = MultiByteToWideChar (CP_ACP, 0, path, -1, wpath, wpath_len) ; | |
387 | if (nResult == 0) | |
388 | { sf_errno = SF_ERR_UNSUPPORTED_ENCODING ; | |
389 | free (wpath) ; | |
390 | psf_close (psf) ; | |
391 | return NULL ; | |
392 | } ; | |
393 | ||
394 | nResult = WideCharToMultiByte (CP_UTF8, 0, wpath, wpath_len, NULL, 0, NULL, | |
395 | NULL) ; | |
396 | if (nResult == 0) | |
397 | { sf_errno = SF_ERR_UNSUPPORTED_ENCODING ; | |
398 | free (wpath) ; | |
399 | psf_close (psf) ; | |
400 | return NULL ; | |
401 | } ; | |
402 | ||
403 | nResult = WideCharToMultiByte (CP_UTF8, 0, wpath, wpath_len, utf8path, | |
404 | SF_FILENAME_LEN, NULL, NULL) ; | |
405 | ||
406 | free (wpath) ; | |
407 | ||
408 | if (nResult == 0) | |
409 | { dwError = GetLastError () ; | |
410 | if (dwError == ERROR_INSUFFICIENT_BUFFER) | |
411 | sf_errno = SFE_FILENAME_TOO_LONG ; | |
412 | else | |
413 | sf_errno = SF_ERR_UNSUPPORTED_ENCODING ; | |
414 | psf_close (psf) ; | |
415 | return NULL ; | |
416 | } ; | |
417 | ||
418 | utf8path_ptr = utf8path ; | |
419 | #else | |
420 | utf8path_ptr = path ; | |
421 | #endif | |
422 | ||
423 | if (psf_copy_filename (psf, utf8path_ptr) != 0) | |
348 | 424 | { sf_errno = psf->error ; |
425 | psf_close (psf) ; | |
349 | 426 | return NULL ; |
350 | 427 | } ; |
351 | 428 | |
380 | 457 | } ; |
381 | 458 | |
382 | 459 | psf_init_files (psf) ; |
383 | copy_filename (psf, "") ; | |
460 | psf_copy_filename (psf, "") ; | |
384 | 461 | |
385 | 462 | psf->file.mode = mode ; |
386 | 463 | psf_set_file (psf, fd) ; |
613 | 690 | if ((subformat == SF_FORMAT_NMS_ADPCM_16 || subformat == SF_FORMAT_NMS_ADPCM_24 || |
614 | 691 | subformat == SF_FORMAT_NMS_ADPCM_32) && info->channels == 1) |
615 | 692 | return 1 ; |
693 | if (subformat == SF_FORMAT_MPEG_LAYER_III && info->channels <= 2) | |
694 | return 1 ; | |
616 | 695 | break ; |
617 | 696 | |
618 | 697 | case SF_FORMAT_WAVEX : |
881 | 960 | if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) |
882 | 961 | return 1 ; |
883 | 962 | if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) |
963 | return 1 ; | |
964 | break ; | |
965 | ||
966 | case SF_FORMAT_MPEG : | |
967 | if (info->channels > 2) | |
968 | return 0 ; | |
969 | if (endian != SF_ENDIAN_FILE) | |
970 | return 0 ; | |
971 | if (subformat == SF_FORMAT_MPEG_LAYER_I || subformat == SF_FORMAT_MPEG_LAYER_II || subformat == SF_FORMAT_MPEG_LAYER_III) | |
884 | 972 | return 1 ; |
885 | 973 | break ; |
886 | 974 | default : break ; |
1225 | 1313 | return SF_FALSE ; |
1226 | 1314 | } ; |
1227 | 1315 | |
1228 | if (NOT (broadcast_var_set (psf, data, datasize))) | |
1316 | if (!broadcast_var_set (psf, data, datasize)) | |
1229 | 1317 | return SF_FALSE ; |
1230 | 1318 | |
1231 | 1319 | if (psf->write_header) |
1254 | 1342 | { psf->error = SFE_CMD_HAS_DATA ; |
1255 | 1343 | return SF_FALSE ; |
1256 | 1344 | } ; |
1257 | if (NOT (cart_var_set (psf, data, datasize))) | |
1345 | if (!cart_var_set (psf, data, datasize)) | |
1258 | 1346 | return SF_FALSE ; |
1259 | 1347 | if (psf->write_header) |
1260 | 1348 | psf->write_header (psf, SF_TRUE) ; |
2611 | 2699 | } ; |
2612 | 2700 | |
2613 | 2701 | /* More checking here. */ |
2614 | psf_log_printf (psf, "Resource fork : %s\n", psf->rsrc.path.c) ; | |
2702 | psf_log_printf (psf, "Resource fork : %s\n", psf->rsrc.path) ; | |
2615 | 2703 | |
2616 | 2704 | return SF_FORMAT_SD2 ; |
2617 | 2705 | } /* try_resource_fork */ |
2622 | 2710 | char buffer [16] ; |
2623 | 2711 | int format = 0 ; |
2624 | 2712 | |
2625 | if ((cptr = strrchr (psf->file.name.c, '.')) == NULL) | |
2713 | if ((cptr = strrchr (psf->file.name, '.')) == NULL) | |
2626 | 2714 | return 0 ; |
2627 | 2715 | |
2628 | 2716 | cptr ++ ; |
2667 | 2755 | psf->sf.samplerate = 8000 ; |
2668 | 2756 | format = SF_FORMAT_RAW | SF_FORMAT_GSM610 ; |
2669 | 2757 | } |
2758 | else if (strcmp (cptr, "mp3") == 0) | |
2759 | { /* | |
2760 | * MPEG streams are quite tollerate of crap. If we couldn't identify a | |
2761 | * MP3 stream, but it has a .mp3 extension, let libmpg123 have a try. | |
2762 | */ | |
2763 | format = SF_FORMAT_MPEG ; | |
2764 | } | |
2670 | 2765 | |
2671 | 2766 | /* For RAW files, make sure the dataoffset if set correctly. */ |
2672 | 2767 | if ((SF_CONTAINER (format)) == SF_FORMAT_RAW) |
2679 | 2774 | guess_file_type (SF_PRIVATE *psf) |
2680 | 2775 | { uint32_t buffer [3], format ; |
2681 | 2776 | |
2777 | retry: | |
2682 | 2778 | if (psf_binheader_readf (psf, "b", &buffer, SIGNED_SIZEOF (buffer)) != SIGNED_SIZEOF (buffer)) |
2683 | 2779 | { psf->error = SFE_BAD_FILE_READ ; |
2684 | 2780 | return 0 ; |
2775 | 2871 | if (buffer [0] == MAKE_MARKER ('R', 'F', '6', '4') && buffer [2] == MAKE_MARKER ('W', 'A', 'V', 'E')) |
2776 | 2872 | return SF_FORMAT_RF64 ; |
2777 | 2873 | |
2874 | if ((buffer [0] & MAKE_MARKER (0xFF, 0xE0, 0, 0)) == MAKE_MARKER (0xFF, 0xE0, 0, 0) && /* Frame sync */ | |
2875 | (buffer [0] & MAKE_MARKER (0, 0x18, 0, 0)) != MAKE_MARKER (0, 0x08, 0, 0) && /* Valid MPEG version */ | |
2876 | (buffer [0] & MAKE_MARKER (0, 0x06, 0, 0)) != MAKE_MARKER (0, 0, 0, 0) && /* Valid layer description */ | |
2877 | (buffer [0] & MAKE_MARKER (0, 0, 0xF0, 0)) != MAKE_MARKER (0, 0, 0xF0, 0) && /* Valid bitrate */ | |
2878 | (buffer [0] & MAKE_MARKER (0, 0, 0x0C, 0)) != MAKE_MARKER (0, 0, 0x0C, 0)) /* Valid samplerate */ | |
2879 | return SF_FORMAT_MPEG ; | |
2880 | ||
2778 | 2881 | if (buffer [0] == MAKE_MARKER ('I', 'D', '3', 2) || buffer [0] == MAKE_MARKER ('I', 'D', '3', 3) |
2779 | 2882 | || buffer [0] == MAKE_MARKER ('I', 'D', '3', 4)) |
2780 | 2883 | { psf_log_printf (psf, "Found 'ID3' marker.\n") ; |
2781 | 2884 | if (id3_skip (psf)) |
2782 | return guess_file_type (psf) ; | |
2885 | goto retry ; | |
2783 | 2886 | return 0 ; |
2784 | 2887 | } ; |
2785 | 2888 | |
2804 | 2907 | |
2805 | 2908 | static int |
2806 | 2909 | validate_sfinfo (SF_INFO *sfinfo) |
2807 | { if (sfinfo->samplerate < 1) | |
2910 | { if ((sfinfo->samplerate < 1) || (sfinfo->samplerate > SF_MAX_SAMPLERATE)) | |
2808 | 2911 | return 0 ; |
2809 | 2912 | if (sfinfo->frames < 0) |
2810 | 2913 | return 0 ; |
2811 | if (sfinfo->channels < 1) | |
2914 | if ((sfinfo->channels < 1) || (sfinfo->channels > SF_MAX_CHANNELS)) | |
2812 | 2915 | return 0 ; |
2813 | 2916 | if ((SF_CONTAINER (sfinfo->format)) == 0) |
2814 | 2917 | return 0 ; |
2842 | 2945 | save_header_info (SF_PRIVATE *psf) |
2843 | 2946 | { snprintf (sf_parselog, sizeof (sf_parselog), "%s", psf->parselog.buf) ; |
2844 | 2947 | } /* save_header_info */ |
2845 | ||
2846 | static int | |
2847 | copy_filename (SF_PRIVATE *psf, const char *path) | |
2848 | { const char *ccptr ; | |
2849 | char *cptr ; | |
2850 | ||
2851 | if (strlen (path) > 1 && strlen (path) - 1 >= sizeof (psf->file.path.c)) | |
2852 | { psf->error = SFE_FILENAME_TOO_LONG ; | |
2853 | return psf->error ; | |
2854 | } ; | |
2855 | ||
2856 | snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", path) ; | |
2857 | if ((ccptr = strrchr (path, '/')) || (ccptr = strrchr (path, '\\'))) | |
2858 | ccptr ++ ; | |
2859 | else | |
2860 | ccptr = path ; | |
2861 | ||
2862 | snprintf (psf->file.name.c, sizeof (psf->file.name.c), "%s", ccptr) ; | |
2863 | ||
2864 | /* Now grab the directory. */ | |
2865 | snprintf (psf->file.dir.c, sizeof (psf->file.dir.c), "%s", path) ; | |
2866 | if ((cptr = strrchr (psf->file.dir.c, '/')) || (cptr = strrchr (psf->file.dir.c, '\\'))) | |
2867 | cptr [1] = 0 ; | |
2868 | else | |
2869 | psf->file.dir.c [0] = 0 ; | |
2870 | ||
2871 | return 0 ; | |
2872 | } /* copy_filename */ | |
2873 | 2948 | |
2874 | 2949 | /*============================================================================== |
2875 | 2950 | */ |
3184 | 3259 | error = mpc2k_open (psf) ; |
3185 | 3260 | break ; |
3186 | 3261 | |
3262 | case SF_FORMAT_MPEG : | |
3263 | error = mpeg_open (psf) ; | |
3264 | break ; | |
3265 | ||
3187 | 3266 | /* Lite remove end */ |
3188 | 3267 | |
3189 | 3268 | default : |
3204 | 3283 | /* Actual embedded files. */ |
3205 | 3284 | break ; |
3206 | 3285 | |
3286 | case SF_FORMAT_MPEG : | |
3207 | 3287 | case SF_FORMAT_FLAC : |
3208 | 3288 | /* Flac with an ID3v2 header? */ |
3209 | 3289 | break ; |
239 | 239 | |
240 | 240 | psf_log_printf (psf, " %M : %u\n", marker, chunk_size) ; |
241 | 241 | |
242 | if (strlen (psf->file.name.c) != chunk_size) | |
243 | { if (chunk_size > sizeof (psf->file.name.c) - 1) | |
242 | if (strlen (psf->file.name) != chunk_size) | |
243 | { if (chunk_size > sizeof (psf->file.name) - 1) | |
244 | 244 | return SFE_SVX_BAD_NAME_LENGTH ; |
245 | 245 | |
246 | psf_binheader_readf (psf, "b", psf->file.name.c, chunk_size) ; | |
247 | psf->file.name.c [chunk_size] = 0 ; | |
246 | psf_binheader_readf (psf, "b", psf->file.name, chunk_size) ; | |
247 | psf->file.name [chunk_size] = 0 ; | |
248 | 248 | } |
249 | 249 | else |
250 | 250 | psf_binheader_readf (psf, "j", chunk_size) ; |
306 | 306 | if ((chunk_size = psf_ftell (psf)) & 0x03) |
307 | 307 | { psf_log_printf (psf, " Unknown chunk marker at position %d. Resynching.\n", chunk_size - 4) ; |
308 | 308 | |
309 | psf_binheader_readf (psf, "j", -3) ; | |
309 | chunk_size = chunk_size & 3 ; | |
310 | psf_binheader_readf (psf, "j", 4 - chunk_size) ; | |
310 | 311 | break ; |
311 | 312 | } ; |
312 | 313 | psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D. Exiting parser.\n", marker, psf_ftell (psf) - 8) ; |
379 | 380 | psf_binheader_writef (psf, "Em44", BHWm (CHAN_MARKER), BHW4 (4), BHW4 (6)) ; |
380 | 381 | |
381 | 382 | /* Filename and annotation strings. */ |
382 | psf_binheader_writef (psf, "Emsms", BHWm (NAME_MARKER), BHWs (psf->file.name.c), BHWm (ANNO_MARKER), BHWs (annotation)) ; | |
383 | psf_binheader_writef (psf, "Emsms", BHWm (NAME_MARKER), BHWs (psf->file.name), BHWm (ANNO_MARKER), BHWs (annotation)) ; | |
383 | 384 | |
384 | 385 | /* BODY marker and size. */ |
385 | 386 | psf_binheader_writef (psf, "Etm8", BHWm (BODY_MARKER), BHW8 ((psf->datalength < 0) ? |
88 | 88 | static void |
89 | 89 | test_broadcast_var_zero (void) |
90 | 90 | { SF_PRIVATE sf_private, *psf ; |
91 | #ifdef _MSC_VER | |
91 | 92 | SF_BROADCAST_INFO_VAR (0) bi ; |
93 | #else | |
94 | SF_BROADCAST_INFO_VAR () bi ; | |
95 | #endif | |
92 | 96 | |
93 | 97 | psf = &sf_private ; |
94 | 98 | memset (psf, 0, sizeof (sf_private)) ; |
61 | 61 | memset (psf, 0, sizeof (sf_private)) ; |
62 | 62 | |
63 | 63 | psf->file.mode = SFM_WRITE ; |
64 | snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ; | |
64 | snprintf (psf->file.path, sizeof (psf->file.path), "%s", filename) ; | |
65 | 65 | |
66 | 66 | if (psf_fopen (psf) != 0) |
67 | 67 | { printf ("\n\nError : failed to open file '%s' for write.\n\n", filename) ; |
76 | 76 | memset (psf, 0, sizeof (sf_private)) ; |
77 | 77 | |
78 | 78 | psf->file.mode = SFM_READ ; |
79 | snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ; | |
79 | snprintf (psf->file.path, sizeof (psf->file.path), "%s", filename) ; | |
80 | 80 | |
81 | 81 | if (psf_fopen (psf) != 0) |
82 | 82 | { printf ("\n\nError : failed to open file '%s' for read.\n\n", filename) ; |
72 | 72 | } ; |
73 | 73 | |
74 | 74 | psf->file.mode = SFM_READ ; |
75 | snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ; | |
75 | snprintf (psf->file.path, sizeof (psf->file.path), "%s", filename) ; | |
76 | 76 | |
77 | 77 | /* Test that open for read fails if the file doesn't exist. */ |
78 | 78 | error = psf_fopen (psf) ; |
90 | 90 | |
91 | 91 | test_close_or_die (psf, __LINE__) ; |
92 | 92 | |
93 | unlink (psf->file.path.c) ; | |
93 | unlink (psf->file.path) ; | |
94 | 94 | |
95 | 95 | /* Test file open in read/write mode for a non-existant file. */ |
96 | 96 | psf->file.mode = SFM_RDWR ; |
104 | 104 | |
105 | 105 | test_close_or_die (psf, __LINE__) ; |
106 | 106 | |
107 | unlink (psf->file.path.c) ; | |
107 | unlink (psf->file.path) ; | |
108 | 108 | puts ("ok") ; |
109 | 109 | } /* file_open_test */ |
110 | 110 | |
125 | 125 | |
126 | 126 | memset (&sf_data, 0, sizeof (sf_data)) ; |
127 | 127 | psf = &sf_data ; |
128 | snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ; | |
128 | snprintf (psf->file.path, sizeof (psf->file.path), "%s", filename) ; | |
129 | 129 | |
130 | 130 | /* Test file open in write mode. */ |
131 | 131 | psf->file.mode = SFM_WRITE ; |
281 | 281 | memset (buffer, 0xEE, sizeof (buffer)) ; |
282 | 282 | |
283 | 283 | psf = &sf_data ; |
284 | snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ; | |
284 | snprintf (psf->file.path, sizeof (psf->file.path), "%s", filename) ; | |
285 | 285 | |
286 | 286 | /* |
287 | 287 | ** Open the file write mode, write 0xEE data and then extend the file |
301 | 301 | |
302 | 302 | for (k = 0 ; k < SIGNED_SIZEOF (buffer) / 2 ; k++) |
303 | 303 | if (buffer [k] != 0xEE) |
304 | { printf ("\n\nLine %d : buffer [%d] = %d (should be 0xEE)\n\n", __LINE__, k, buffer [k]) ; | |
304 | { printf ("\n\nLine %d : buffer [%d] = %hhu (should be 0xEE)\n\n", __LINE__, k, buffer [k]) ; | |
305 | 305 | exit (1) ; |
306 | 306 | } ; |
307 | 307 | |
308 | 308 | for (k = SIGNED_SIZEOF (buffer) / 2 ; k < SIGNED_SIZEOF (buffer) ; k++) |
309 | 309 | if (buffer [k] != 0) |
310 | { printf ("\n\nLine %d : buffer [%d] = %d (should be 0)\n\n", __LINE__, k, buffer [k]) ; | |
310 | { printf ("\n\nLine %d : buffer [%d] = %hhu (should be 0)\n\n", __LINE__, k, buffer [k]) ; | |
311 | 311 | exit (1) ; |
312 | 312 | } ; |
313 | 313 | |
338 | 338 | memset (&sf_data, 0, sizeof (sf_data)) ; |
339 | 339 | psf = &sf_data ; |
340 | 340 | psf->file.mode = SFM_READ ; |
341 | snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ; | |
341 | snprintf (psf->file.path, sizeof (psf->file.path), "%s", filename) ; | |
342 | 342 | test_open_or_die (psf, __LINE__) ; |
343 | 343 | |
344 | 344 | /* Gather basic info before setting offset. */ |
112 | 112 | /* Test printing of strings. */ |
113 | 113 | CMP_4_ARGS (__LINE__, errors, "B %s, %3s, %8s, %-8s", "str") ; |
114 | 114 | |
115 | CMP_4_ARGS (__LINE__, errors, "B %.2s, %.8s, %-8.8s, %-4.2s", "str") ; | |
116 | ||
115 | 117 | if (errors) |
116 | 118 | { puts ("\nExiting due to errors.\n") ; |
117 | 119 | exit (1) ; |
792 | 792 | |
793 | 793 | static inline void |
794 | 794 | ulaw2s_array (unsigned char *buffer, int count, short *ptr) |
795 | { while (--count >= 0) | |
796 | ptr [count] = ulaw_decode [(int) buffer [count]] ; | |
795 | { for (int i = 0 ; i < count ; i++) | |
796 | ptr [i] = ulaw_decode [(int) buffer [i]] ; | |
797 | 797 | } /* ulaw2s_array */ |
798 | 798 | |
799 | 799 | static inline void |
800 | 800 | ulaw2i_array (unsigned char *buffer, int count, int *ptr) |
801 | { while (--count >= 0) | |
802 | ptr [count] = ((uint32_t) ulaw_decode [buffer [count]]) << 16 ; | |
801 | { for (int i = 0 ; i < count ; i++) | |
802 | ptr [i] = ((uint32_t) ulaw_decode [buffer [i]]) << 16 ; | |
803 | 803 | } /* ulaw2i_array */ |
804 | 804 | |
805 | 805 | static inline void |
806 | 806 | ulaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact) |
807 | { while (--count >= 0) | |
808 | ptr [count] = normfact * ulaw_decode [(int) buffer [count]] ; | |
807 | { for (int i = 0 ; i < count ; i++) | |
808 | ptr [i] = normfact * ulaw_decode [(int) buffer [i]] ; | |
809 | 809 | } /* ulaw2f_array */ |
810 | 810 | |
811 | 811 | static inline void |
812 | 812 | ulaw2d_array (const unsigned char *buffer, int count, double *ptr, double normfact) |
813 | { while (--count >= 0) | |
814 | ptr [count] = normfact * ulaw_decode [(int) buffer [count]] ; | |
813 | { for (int i = 0 ; i < count ; i++) | |
814 | ptr [i] = normfact * ulaw_decode [(int) buffer [i]] ; | |
815 | 815 | } /* ulaw2d_array */ |
816 | 816 | |
817 | 817 | static inline void |
818 | 818 | s2ulaw_array (const short *ptr, int count, unsigned char *buffer) |
819 | { while (--count >= 0) | |
820 | { if (ptr [count] >= 0) | |
821 | buffer [count] = ulaw_encode [ptr [count] / 4] ; | |
819 | { for (int i = 0 ; i < count ; i++) | |
820 | { if (ptr [i] >= 0) | |
821 | buffer [i] = ulaw_encode [ptr [i] / 4] ; | |
822 | 822 | else |
823 | buffer [count] = 0x7F & ulaw_encode [ptr [count] / -4] ; | |
823 | buffer [i] = 0x7F & ulaw_encode [ptr [i] / -4] ; | |
824 | 824 | } ; |
825 | 825 | } /* s2ulaw_array */ |
826 | 826 | |
827 | 827 | static inline void |
828 | 828 | i2ulaw_array (const int *ptr, int count, unsigned char *buffer) |
829 | { while (--count >= 0) | |
830 | { if (ptr [count] == INT_MIN) | |
831 | buffer [count] = ulaw_encode [INT_MAX >> (16 + 2)] ; | |
832 | else if (ptr [count] >= 0) | |
833 | buffer [count] = ulaw_encode [ptr [count] >> (16 + 2)] ; | |
829 | { for (int i = 0 ; i < count ; i++) | |
830 | { if (ptr [i] == INT_MIN) | |
831 | buffer [i] = ulaw_encode [INT_MAX >> (16 + 2)] ; | |
832 | else if (ptr [i] >= 0) | |
833 | buffer [i] = ulaw_encode [ptr [i] >> (16 + 2)] ; | |
834 | 834 | else |
835 | buffer [count] = 0x7F & ulaw_encode [-ptr [count] >> (16 + 2)] ; | |
835 | buffer [i] = 0x7F & ulaw_encode [-ptr [i] >> (16 + 2)] ; | |
836 | 836 | } ; |
837 | 837 | } /* i2ulaw_array */ |
838 | 838 | |
839 | 839 | static inline void |
840 | 840 | f2ulaw_array (const float *ptr, int count, unsigned char *buffer, float normfact) |
841 | { while (--count >= 0) | |
842 | { if (ptr [count] >= 0) | |
843 | buffer [count] = ulaw_encode [psf_lrintf (normfact * ptr [count])] ; | |
841 | { for (int i = 0 ; i < count ; i++) | |
842 | { if (ptr [i] >= 0) | |
843 | buffer [i] = ulaw_encode [psf_lrintf (normfact * ptr [i])] ; | |
844 | 844 | else |
845 | buffer [count] = 0x7F & ulaw_encode [- psf_lrintf (normfact * ptr [count])] ; | |
845 | buffer [i] = 0x7F & ulaw_encode [- psf_lrintf (normfact * ptr [i])] ; | |
846 | 846 | } ; |
847 | 847 | } /* f2ulaw_array */ |
848 | 848 | |
849 | 849 | static inline void |
850 | 850 | d2ulaw_array (const double *ptr, int count, unsigned char *buffer, double normfact) |
851 | { while (--count >= 0) | |
852 | { if (!isfinite (ptr [count])) | |
853 | buffer [count] = 0 ; | |
854 | else if (ptr [count] >= 0) | |
855 | buffer [count] = ulaw_encode [psf_lrint (normfact * ptr [count])] ; | |
851 | { for (int i = 0 ; i < count ; i++) | |
852 | { if (!isfinite (ptr [i])) | |
853 | buffer [i] = 0 ; | |
854 | else if (ptr [i] >= 0) | |
855 | buffer [i] = ulaw_encode [psf_lrint (normfact * ptr [i])] ; | |
856 | 856 | else |
857 | buffer [count] = 0x7F & ulaw_encode [- psf_lrint (normfact * ptr [count])] ; | |
857 | buffer [i] = 0x7F & ulaw_encode [- psf_lrint (normfact * ptr [i])] ; | |
858 | 858 | } ; |
859 | 859 | } /* d2ulaw_array */ |
860 | 860 | |
872 | 872 | while (len > 0) |
873 | 873 | { if (len < bufferlen) |
874 | 874 | bufferlen = (int) len ; |
875 | readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
875 | readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
876 | 876 | ulaw2s_array (ubuf.ucbuf, readcount, ptr + total) ; |
877 | 877 | total += readcount ; |
878 | 878 | if (readcount < bufferlen) |
894 | 894 | while (len > 0) |
895 | 895 | { if (len < bufferlen) |
896 | 896 | bufferlen = (int) len ; |
897 | readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
897 | readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
898 | 898 | ulaw2i_array (ubuf.ucbuf, readcount, ptr + total) ; |
899 | 899 | total += readcount ; |
900 | 900 | if (readcount < bufferlen) |
919 | 919 | while (len > 0) |
920 | 920 | { if (len < bufferlen) |
921 | 921 | bufferlen = (int) len ; |
922 | readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
922 | readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
923 | 923 | ulaw2f_array (ubuf.ucbuf, readcount, ptr + total, normfact) ; |
924 | 924 | total += readcount ; |
925 | 925 | if (readcount < bufferlen) |
943 | 943 | while (len > 0) |
944 | 944 | { if (len < bufferlen) |
945 | 945 | bufferlen = (int) len ; |
946 | readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
946 | readcount = (int) psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ; | |
947 | 947 | ulaw2d_array (ubuf.ucbuf, readcount, ptr + total, normfact) ; |
948 | 948 | total += readcount ; |
949 | 949 | if (readcount < bufferlen) |
969 | 969 | { if (len < bufferlen) |
970 | 970 | bufferlen = (int) len ; |
971 | 971 | s2ulaw_array (ptr + total, bufferlen, ubuf.ucbuf) ; |
972 | writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
972 | writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
973 | 973 | total += writecount ; |
974 | 974 | if (writecount < bufferlen) |
975 | 975 | break ; |
991 | 991 | { if (len < bufferlen) |
992 | 992 | bufferlen = (int) len ; |
993 | 993 | i2ulaw_array (ptr + total, bufferlen, ubuf.ucbuf) ; |
994 | writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
994 | writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
995 | 995 | total += writecount ; |
996 | 996 | if (writecount < bufferlen) |
997 | 997 | break ; |
1017 | 1017 | { if (len < bufferlen) |
1018 | 1018 | bufferlen = (int) len ; |
1019 | 1019 | f2ulaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ; |
1020 | writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
1020 | writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
1021 | 1021 | total += writecount ; |
1022 | 1022 | if (writecount < bufferlen) |
1023 | 1023 | break ; |
1043 | 1043 | { if (len < bufferlen) |
1044 | 1044 | bufferlen = (int) len ; |
1045 | 1045 | d2ulaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ; |
1046 | writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
1046 | writecount = (int) psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ; | |
1047 | 1047 | total += writecount ; |
1048 | 1048 | if (writecount < bufferlen) |
1049 | 1049 | break ; |
127 | 127 | while (indx < len) |
128 | 128 | { pvox->code_count = (len - indx > IMA_OKI_ADPCM_PCM_LEN) ? IMA_OKI_ADPCM_CODE_LEN : (len - indx + 1) / 2 ; |
129 | 129 | |
130 | if ((k = psf_fread (pvox->codes, 1, pvox->code_count, psf)) != pvox->code_count) | |
130 | if ((k = (int) psf_fread (pvox->codes, 1, pvox->code_count, psf)) != pvox->code_count) | |
131 | 131 | { if (psf_ftell (psf) != psf->filelength) |
132 | 132 | psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pvox->code_count) ; |
133 | 133 | if (k == 0) |
274 | 274 | |
275 | 275 | ima_oki_adpcm_encode_block (pvox) ; |
276 | 276 | |
277 | if ((k = psf_fwrite (pvox->codes, 1, pvox->code_count, psf)) != pvox->code_count) | |
277 | if ((k = (int) psf_fwrite (pvox->codes, 1, pvox->code_count, psf)) != pvox->code_count) | |
278 | 278 | psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pvox->code_count) ; |
279 | 279 | |
280 | 280 | indx += pvox->pcm_count ; |
240 | 240 | psf_binheader_readf (psf, "j", 8 - (psf->header.indx & 0x7)) ; |
241 | 241 | |
242 | 242 | /* Generate hash of 16 byte marker. */ |
243 | marker = chunk_size = 0 ; | |
243 | marker = 0 ; | |
244 | chunk_size = 0 ; | |
245 | ||
244 | 246 | bytesread = psf_binheader_readf (psf, "eh8", &marker, &chunk_size) ; |
245 | 247 | if (bytesread == 0) |
246 | 248 | break ; |
72 | 72 | #define wvpk_MARKER (MAKE_MARKER ('w', 'v', 'p', 'k')) |
73 | 73 | #define OggS_MARKER (MAKE_MARKER ('O', 'g', 'g', 'S')) |
74 | 74 | |
75 | /* ID3v1 trailer which can show up at the end and erronerously look like a chunk. */ | |
76 | #define TAG__MARKER (MAKE_MARKER ('T', 'A', 'G', 0)) | |
77 | #define TAG__MARKER_MASK (MAKE_MARKER (0xff, 0xff, 0xff, 0)) | |
78 | ||
75 | 79 | #define WAVLIKE_PEAK_CHUNK_SIZE(ch) (2 * sizeof (int) + ch * (sizeof (float) + sizeof (int))) |
76 | 80 | |
77 | 81 | |
78 | 82 | enum |
79 | { HAVE_RIFF = 0x01, | |
80 | HAVE_WAVE = 0x02, | |
81 | HAVE_fmt = 0x04, | |
82 | HAVE_fact = 0x08, | |
83 | HAVE_PEAK = 0x10, | |
84 | HAVE_data = 0x20, | |
85 | HAVE_other = 0x80000000 | |
83 | { HAVE_RIFF = 1 << 0, | |
84 | HAVE_WAVE = 1 << 1, | |
85 | HAVE_fmt = 1 << 2, | |
86 | HAVE_fact = 1 << 3, | |
87 | HAVE_PEAK = 1 << 4, | |
88 | HAVE_data = 1 << 5, | |
89 | HAVE_other = 1 << 6 | |
86 | 90 | } ; |
87 | ||
88 | 91 | |
89 | 92 | |
90 | 93 | /* known WAVEFORMATEXTENSIBLE GUIDS */ |
202 | 205 | psf->dataoffset = 0 ; |
203 | 206 | psf->sf.frames = 0 ; |
204 | 207 | } ; |
208 | ||
209 | #if (ENABLE_EXPERIMENTAL_CODE == 0) | |
210 | /* For now, don't support writing MPEGLAYER3 WAVs, as we can't guarentee that | |
211 | ** such a file written by libsndfile would have the same length when opened again. | |
212 | */ | |
213 | if (subformat == SF_FORMAT_MPEG_LAYER_III) | |
214 | return SFE_UNSUPPORTED_ENCODING ; | |
215 | #endif | |
205 | 216 | |
206 | 217 | if (subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM) |
207 | 218 | { blockalign = wavlike_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; |
271 | 282 | |
272 | 283 | case SF_FORMAT_GSM610 : |
273 | 284 | error = gsm610_init (psf) ; |
285 | break ; | |
286 | ||
287 | case SF_FORMAT_MPEG_LAYER_III : | |
288 | error = mpeg_init (psf, SF_BITRATE_MODE_CONSTANT, SF_FALSE) ; | |
274 | 289 | break ; |
275 | 290 | |
276 | 291 | default : return SFE_UNIMPLEMENTED ; |
604 | 619 | break ; |
605 | 620 | } ; |
606 | 621 | |
622 | if ((marker & TAG__MARKER_MASK) == TAG__MARKER && | |
623 | psf_ftell (psf) - 8 + 128 == psf->filelength) | |
624 | { psf_log_printf (psf, "*** Hit ID3v1 trailer. Exiting parser.\n") ; | |
625 | chunk_size = 128 ; | |
626 | done = SF_TRUE ; | |
627 | parsestage |= HAVE_other ; | |
628 | break ; | |
629 | } ; | |
630 | ||
607 | 631 | if (psf_isprint ((marker >> 24) & 0xFF) && psf_isprint ((marker >> 16) & 0xFF) |
608 | 632 | && psf_isprint ((marker >> 8) & 0xFF) && psf_isprint (marker & 0xFF)) |
609 | 633 | { psf_log_printf (psf, "*** %M : %u (unknown marker)\n", marker, chunk_size) ; |
682 | 706 | break ; |
683 | 707 | |
684 | 708 | case WAVE_FORMAT_NMS_VBXADPCM : |
685 | *blockalign = wav_fmt->min.blockalign ; | |
686 | *framesperblock = 160 ; | |
687 | 709 | switch (wav_fmt->min.bitwidth) |
688 | 710 | { case 2 : |
689 | 711 | psf->sf.format = SF_FORMAT_WAV | SF_FORMAT_NMS_ADPCM_16 ; |
737 | 759 | |
738 | 760 | case WAVE_FORMAT_G721_ADPCM : |
739 | 761 | psf->sf.format = SF_FORMAT_WAV | SF_FORMAT_G721_32 ; |
762 | break ; | |
763 | ||
764 | case WAVE_FORMAT_MPEGLAYER3 : | |
765 | psf->sf.format = SF_FORMAT_WAV | SF_FORMAT_MPEG_LAYER_III ; | |
766 | if (parsestage & HAVE_fact) | |
767 | psf->sf.frames = fact_chunk.frames ; | |
740 | 768 | break ; |
741 | 769 | |
742 | 770 | default : return SFE_UNIMPLEMENTED ; |
922 | 950 | |
923 | 951 | add_fact_chunk = SF_TRUE ; |
924 | 952 | break ; |
953 | ||
954 | #if (ENABLE_EXPERIMENTAL_CODE == 0) | |
955 | case SF_FORMAT_MPEG_LAYER_III : | |
956 | { int bytespersec, blockalign, flags, blocksize, samplesperblock, codecdelay ; | |
957 | ||
958 | /* Intended to be set as the average sample rate. | |
959 | ** TODO: Maybe re-write this on close with final average | |
960 | ** byterate? */ | |
961 | bytespersec = psf->byterate (psf) ; | |
962 | ||
963 | /* Average block size. Info only I think. */ | |
964 | blocksize = (1152 * bytespersec) / psf->sf.samplerate ; | |
965 | ||
966 | /* Can be set to block size IFF the block size is | |
967 | ** constant, set to 1 otherwise. Constant sized | |
968 | ** MPEG block streams are uncommon (CBR @ 32kHz and | |
969 | ** 48kHz only. Meh. */ | |
970 | blockalign = 1 ; | |
971 | ||
972 | /* TODO: Only flags defined are padding-type. I /think/ | |
973 | ** Lame does ISO style padding by default, which has a | |
974 | ** flag value of 0. | |
975 | */ | |
976 | flags = 0 ; | |
977 | ||
978 | /* Should only vary per MPEG 1.0/2.0 vs '2.5'. | |
979 | ** TODO: Move this out to MPEG specific place? */ | |
980 | samplesperblock = psf->sf.samplerate >= 32000 ? 1152 : 576 ; | |
981 | ||
982 | /* Set as 0 if unknown. | |
983 | ** TODO: Plumb this cleanly from Lame. | |
984 | */ | |
985 | codecdelay = 0 ; | |
986 | ||
987 | /* fmt chunk. */ | |
988 | fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 + 4 + 2 + 2 + 2 ; | |
989 | ||
990 | /* fmt : size, WAV format type, channels. */ | |
991 | psf_binheader_writef (psf, "422", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_MPEGLAYER3), BHW2 (psf->sf.channels)) ; | |
992 | ||
993 | /* fmt : samplerate, bytespersec. */ | |
994 | psf_binheader_writef (psf, "44", BHW4 (psf->sf.samplerate), BHW4 (bytespersec)) ; | |
995 | ||
996 | /* fmt : blockalign, bitwidth, extrabytes, id. */ | |
997 | psf_binheader_writef (psf, "2222", BHW2 (blockalign), BHW2 (0), BHW2 (12), BHW2 (1)) ; | |
998 | ||
999 | /* fmt : flags, blocksize, samplesperblock, codecdelay */ | |
1000 | psf_binheader_writef (psf, "4222", BHW4 (flags), BHW2 (blocksize), BHW2 (samplesperblock), BHW2 (codecdelay)) ; | |
1001 | } ; | |
1002 | ||
1003 | add_fact_chunk = SF_TRUE ; | |
1004 | break ; | |
1005 | #endif | |
925 | 1006 | |
926 | 1007 | default : return SFE_UNIMPLEMENTED ; |
927 | 1008 | } ; |
1324 | 1405 | psf_log_printf (psf, " SMPTE Format : %u\n", dword) ; |
1325 | 1406 | |
1326 | 1407 | bytesread += psf_binheader_readf (psf, "4", &dword) ; |
1327 | snprintf (buffer, sizeof (buffer), "%02d:%02d:%02d %02d", | |
1328 | (dword >> 24) & 0x7F, (dword >> 16) & 0x7F, (dword >> 8) & 0x7F, dword & 0x7F) ; | |
1408 | snprintf (buffer, sizeof (buffer), "%02"PRIu32 ":%02"PRIu32 ":%02"PRIu32 | |
1409 | " %02"PRIu32 "", (dword >> 24) & 0x7F, (dword >> 16) & 0x7F, | |
1410 | (dword >> 8) & 0x7F, dword & 0x7F) ; | |
1329 | 1411 | psf_log_printf (psf, " SMPTE Offset : %s\n", buffer) ; |
1330 | 1412 | |
1331 | 1413 | bytesread += psf_binheader_readf (psf, "4", &loop_count) ; |
172 | 172 | { switch (wav_fmt->format) |
173 | 173 | { case WAVE_FORMAT_GSM610 : |
174 | 174 | case WAVE_FORMAT_IPP_ITU_G_723_1 : |
175 | case WAVE_FORMAT_MPEGLAYER3 : | |
175 | 176 | psf_log_printf (psf, " Bit Width : %d\n", wav_fmt->min.bitwidth) ; |
176 | 177 | break ; |
177 | 178 | default : |
182 | 183 | { switch (wav_fmt->format) |
183 | 184 | { case WAVE_FORMAT_GSM610 : |
184 | 185 | case WAVE_FORMAT_IPP_ITU_G_723_1 : |
185 | psf_log_printf (psf, " Bit Width : %d (should be 0)\n", wav_fmt->min.bitwidth) ; | |
186 | case WAVE_FORMAT_MPEGLAYER3 : | |
187 | psf_log_printf (psf, " Bit Width : %d (should be 0)\n", wav_fmt->min.bitwidth) ; | |
186 | 188 | break ; |
187 | 189 | default : |
188 | 190 | psf_log_printf (psf, " Bit Width : %d\n", wav_fmt->min.bitwidth) ; |
303 | 305 | |
304 | 306 | psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->gsm610.extrabytes) ; |
305 | 307 | psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->gsm610.samplesperblock) ; |
308 | break ; | |
309 | ||
310 | case WAVE_FORMAT_MPEGLAYER3 : | |
311 | bytesread += psf_binheader_readf (psf, "24222", &(wav_fmt->mpeg3.extrabytes), | |
312 | &(wav_fmt->mpeg3.id), &(wav_fmt->mpeg3.flags), &(wav_fmt->mpeg3.blocksize), | |
313 | &(wav_fmt->mpeg3.samplesperblock), &(wav_fmt->mpeg3.codecdelay)) ; | |
314 | ||
315 | psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->mpeg3.bytespersec) ; | |
316 | psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->mpeg3.extrabytes) ; | |
317 | if (wav_fmt->mpeg3.id != 1) | |
318 | psf_log_printf (psf, " ID : %d (unknown, should be 1)\n", wav_fmt->mpeg3.id) ; | |
319 | else | |
320 | psf_log_printf (psf, " ID : MPEGLAYER3_ID_MPEG\n") ; | |
321 | psf_log_printf (psf, " Flags : 0x%08x\n", wav_fmt->mpeg3.flags) ; | |
322 | psf_log_printf (psf, " Block Size : %d\n", wav_fmt->mpeg3.blocksize) ; | |
323 | psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->mpeg3.samplesperblock) ; | |
324 | psf_log_printf (psf, " Codec Delay : %d samples\n", wav_fmt->mpeg3.codecdelay) ; | |
306 | 325 | break ; |
307 | 326 | |
308 | 327 | case WAVE_FORMAT_EXTENSIBLE : |
829 | 848 | return 0 ; |
830 | 849 | } ; |
831 | 850 | |
832 | if (chunksize >= sizeof (SF_CART_INFO_16K)) | |
851 | /* | |
852 | ** SF_CART_INFO_16K has an extra field 'tag_text_size' that isn't part | |
853 | ** of the chunk, so don't include it in the size check. | |
854 | */ | |
855 | if (chunksize >= sizeof (SF_CART_INFO_16K) - 4) | |
833 | 856 | { psf_log_printf (psf, "cart : %u too big to be handled\n", chunksize) ; |
834 | 857 | psf_binheader_readf (psf, "j", chunksize) ; |
835 | 858 | return 0 ; |
263 | 263 | } GSM610_WAV_FMT ; |
264 | 264 | |
265 | 265 | typedef struct |
266 | { unsigned short format ; | |
267 | unsigned short channels ; | |
268 | unsigned int samplerate ; | |
269 | unsigned int bytespersec ; | |
270 | unsigned short blockalign ; | |
271 | unsigned short bitwidth ; | |
272 | unsigned short extrabytes ; | |
273 | unsigned short id ; | |
274 | unsigned int flags ; | |
275 | unsigned short blocksize ; | |
276 | unsigned short samplesperblock ; | |
277 | unsigned short codecdelay ; | |
278 | } MPEGLAYER3_WAV_FMT ; | |
279 | ||
280 | typedef struct | |
266 | 281 | { unsigned int esf_field1 ; |
267 | 282 | unsigned short esf_field2 ; |
268 | 283 | unsigned short esf_field3 ; |
290 | 305 | G72x_ADPCM_WAV_FMT g72x ; |
291 | 306 | EXTENSIBLE_WAV_FMT ext ; |
292 | 307 | GSM610_WAV_FMT gsm610 ; |
308 | MPEGLAYER3_WAV_FMT mpeg3 ; | |
293 | 309 | WAV_FMT_SIZE20 size20 ; |
294 | 310 | char padding [512] ; |
295 | 311 | } WAV_FMT ; |
26 | 26 | #if OS_IS_WIN32 |
27 | 27 | #include <windows.h> |
28 | 28 | |
29 | #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1 | |
30 | 29 | #include "sndfile.h" |
31 | 30 | #include "common.h" |
32 | 31 | |
33 | 32 | extern int sf_errno ; |
34 | 33 | |
35 | static void copy_filename (SF_PRIVATE * psf, LPCWSTR wpath) ; | |
36 | ||
37 | 34 | SNDFILE* |
38 | 35 | sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) |
39 | 36 | { SF_PRIVATE *psf ; |
40 | char utf8name [512] ; | |
37 | char utf8name [SF_BUFFER_LEN] ; | |
38 | DWORD dwError ; | |
41 | 39 | |
42 | 40 | if ((psf = psf_allocate ()) == NULL) |
43 | 41 | { sf_errno = SFE_MALLOC_FAILED ; |
47 | 45 | psf_init_files (psf) ; |
48 | 46 | |
49 | 47 | if (WideCharToMultiByte (CP_UTF8, 0, wpath, -1, utf8name, sizeof (utf8name), NULL, NULL) == 0) |
50 | psf->file.path.wc [0] = 0 ; | |
48 | { dwError = GetLastError () ; | |
49 | if (dwError == ERROR_INSUFFICIENT_BUFFER) | |
50 | sf_errno = SFE_FILENAME_TOO_LONG ; | |
51 | else | |
52 | sf_errno = SF_ERR_UNSUPPORTED_ENCODING ; | |
53 | ||
54 | sf_close (psf) ; | |
55 | ||
56 | return NULL ; | |
57 | } ; | |
51 | 58 | |
52 | 59 | psf_log_printf (psf, "File : '%s' (utf-8 converted from ucs-2)\n", utf8name) ; |
53 | 60 | |
54 | copy_filename (psf, wpath) ; | |
55 | psf->file.use_wchar = SF_TRUE ; | |
61 | psf_copy_filename (psf, utf8name) ; | |
56 | 62 | psf->file.mode = mode ; |
57 | 63 | |
58 | 64 | psf->error = psf_fopen (psf) ; |
60 | 66 | return psf_open_file (psf, sfinfo) ; |
61 | 67 | } /* sf_wchar_open */ |
62 | 68 | |
63 | ||
64 | static void | |
65 | copy_filename (SF_PRIVATE *psf, LPCWSTR wpath) | |
66 | { const wchar_t *cwcptr ; | |
67 | wchar_t *wcptr ; | |
68 | ||
69 | wcsncpy (psf->file.path.wc, wpath, ARRAY_LEN (psf->file.path.wc)) ; | |
70 | psf->file.path.wc [ARRAY_LEN (psf->file.path.wc) - 1] = 0 ; | |
71 | if ((cwcptr = wcsrchr (wpath, '/')) || (cwcptr = wcsrchr (wpath, '\\'))) | |
72 | cwcptr ++ ; | |
73 | else | |
74 | cwcptr = wpath ; | |
75 | ||
76 | wcsncpy (psf->file.name.wc, cwcptr, ARRAY_LEN (psf->file.name.wc)) ; | |
77 | psf->file.name.wc [ARRAY_LEN (psf->file.name.wc) - 1] = 0 ; | |
78 | ||
79 | /* Now grab the directory. */ | |
80 | wcsncpy (psf->file.dir.wc, wpath, ARRAY_LEN (psf->file.dir.wc)) ; | |
81 | psf->file.dir.wc [ARRAY_LEN (psf->file.dir.wc) - 1] = 0 ; | |
82 | ||
83 | if ((wcptr = wcsrchr (psf->file.dir.wc, '/')) || (wcptr = wcsrchr (psf->file.dir.wc, '\\'))) | |
84 | wcptr [1] = 0 ; | |
85 | else | |
86 | psf->file.dir.wc [0] = 0 ; | |
87 | ||
88 | return ; | |
89 | } /* copy_filename */ | |
90 | ||
91 | 69 | #endif |
251 | 251 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
252 | 252 | while (total > 0) |
253 | 253 | { len = (total > bufferlen) ? bufferlen : total ; |
254 | total -= dpcm_read_dles2s (psf, ubuf.sbuf, len) ; | |
254 | total -= (int) dpcm_read_dles2s (psf, ubuf.sbuf, len) ; | |
255 | 255 | } ; |
256 | 256 | } |
257 | 257 | else |
259 | 259 | bufferlen = ARRAY_LEN (ubuf.sbuf) ; |
260 | 260 | while (total > 0) |
261 | 261 | { len = (total > bufferlen) ? bufferlen : total ; |
262 | total -= dpcm_read_dsc2s (psf, ubuf.sbuf, len) ; | |
262 | total -= (int) dpcm_read_dsc2s (psf, ubuf.sbuf, len) ; | |
263 | 263 | } ; |
264 | 264 | } ; |
265 | 265 | |
310 | 310 | psf_binheader_writef (psf, "111111", BHW1 (128), BHW1 (0), BHW1 (pxi->sample_flags), BHW1 (128), BHW1 (0), BHW1 (strlen (pxi->sample_name))) ; |
311 | 311 | |
312 | 312 | psf_binheader_writef (psf, "b", BHWv (pxi->sample_name), BHWz (sizeof (pxi->sample_name))) ; |
313 | ||
314 | ||
315 | ||
316 | ||
317 | 313 | |
318 | 314 | /* Header construction complete so write it out. */ |
319 | 315 | psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ; |
407 | 403 | psf_log_printf (psf, "Sample #%d\n name : %s\n", k + 1, name) ; |
408 | 404 | |
409 | 405 | psf_log_printf (psf, " size : %d\n", sample_sizes [k]) ; |
410 | ||
411 | ||
412 | 406 | |
413 | 407 | psf_log_printf (psf, " loop\n begin : %d\n end : %d\n", loop_begin, loop_end) ; |
414 | 408 | |
521 | 515 | while (len > 0) |
522 | 516 | { if (len < bufferlen) |
523 | 517 | bufferlen = (int) len ; |
524 | readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
518 | readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
525 | 519 | dsc2s_array (pxi, ubuf.scbuf, readcount, ptr + total) ; |
526 | 520 | total += readcount ; |
527 | 521 | if (readcount < bufferlen) |
547 | 541 | while (len > 0) |
548 | 542 | { if (len < bufferlen) |
549 | 543 | bufferlen = (int) len ; |
550 | readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
544 | readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
551 | 545 | dsc2i_array (pxi, ubuf.scbuf, readcount, ptr + total) ; |
552 | 546 | total += readcount ; |
553 | 547 | if (readcount < bufferlen) |
576 | 570 | while (len > 0) |
577 | 571 | { if (len < bufferlen) |
578 | 572 | bufferlen = (int) len ; |
579 | readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
573 | readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
580 | 574 | dsc2f_array (pxi, ubuf.scbuf, readcount, ptr + total, normfact) ; |
581 | 575 | total += readcount ; |
582 | 576 | if (readcount < bufferlen) |
605 | 599 | while (len > 0) |
606 | 600 | { if (len < bufferlen) |
607 | 601 | bufferlen = (int) len ; |
608 | readcount = psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
602 | readcount = (int) psf_fread (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
609 | 603 | dsc2d_array (pxi, ubuf.scbuf, readcount, ptr + total, normfact) ; |
610 | 604 | total += readcount ; |
611 | 605 | if (readcount < bufferlen) |
634 | 628 | while (len > 0) |
635 | 629 | { if (len < bufferlen) |
636 | 630 | bufferlen = (int) len ; |
637 | readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
631 | readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
638 | 632 | dles2s_array (pxi, ubuf.sbuf, readcount, ptr + total) ; |
639 | 633 | total += readcount ; |
640 | 634 | if (readcount < bufferlen) |
660 | 654 | while (len > 0) |
661 | 655 | { if (len < bufferlen) |
662 | 656 | bufferlen = (int) len ; |
663 | readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
657 | readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
664 | 658 | dles2i_array (pxi, ubuf.sbuf, readcount, ptr + total) ; |
665 | 659 | total += readcount ; |
666 | 660 | if (readcount < bufferlen) |
689 | 683 | while (len > 0) |
690 | 684 | { if (len < bufferlen) |
691 | 685 | bufferlen = (int) len ; |
692 | readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
686 | readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
693 | 687 | dles2f_array (pxi, ubuf.sbuf, readcount, ptr + total, normfact) ; |
694 | 688 | total += readcount ; |
695 | 689 | if (readcount < bufferlen) |
718 | 712 | while (len > 0) |
719 | 713 | { if (len < bufferlen) |
720 | 714 | bufferlen = (int) len ; |
721 | readcount = psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
715 | readcount = (int) psf_fread (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
722 | 716 | dles2d_array (pxi, ubuf.sbuf, readcount, ptr + total, normfact) ; |
723 | 717 | total += readcount ; |
724 | 718 | if (readcount < bufferlen) |
759 | 753 | { if (len < bufferlen) |
760 | 754 | bufferlen = (int) len ; |
761 | 755 | s2dsc_array (pxi, ptr + total, ubuf.scbuf, bufferlen) ; |
762 | writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
756 | writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
763 | 757 | total += writecount ; |
764 | 758 | if (writecount < bufferlen) |
765 | 759 | break ; |
785 | 779 | { if (len < bufferlen) |
786 | 780 | bufferlen = (int) len ; |
787 | 781 | i2dsc_array (pxi, ptr + total, ubuf.scbuf, bufferlen) ; |
788 | writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
782 | writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
789 | 783 | total += writecount ; |
790 | 784 | if (writecount < bufferlen) |
791 | 785 | break ; |
814 | 808 | { if (len < bufferlen) |
815 | 809 | bufferlen = (int) len ; |
816 | 810 | f2dsc_array (pxi, ptr + total, ubuf.scbuf, bufferlen, normfact) ; |
817 | writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
811 | writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
818 | 812 | total += writecount ; |
819 | 813 | if (writecount < bufferlen) |
820 | 814 | break ; |
843 | 837 | { if (len < bufferlen) |
844 | 838 | bufferlen = (int) len ; |
845 | 839 | d2dsc_array (pxi, ptr + total, ubuf.scbuf, bufferlen, normfact) ; |
846 | writecount = psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
840 | writecount = (int) psf_fwrite (ubuf.scbuf, sizeof (signed char), bufferlen, psf) ; | |
847 | 841 | total += writecount ; |
848 | 842 | if (writecount < bufferlen) |
849 | 843 | break ; |
870 | 864 | { if (len < bufferlen) |
871 | 865 | bufferlen = (int) len ; |
872 | 866 | s2dles_array (pxi, ptr + total, ubuf.sbuf, bufferlen) ; |
873 | writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
867 | writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
874 | 868 | total += writecount ; |
875 | 869 | if (writecount < bufferlen) |
876 | 870 | break ; |
896 | 890 | { if (len < bufferlen) |
897 | 891 | bufferlen = (int) len ; |
898 | 892 | i2dles_array (pxi, ptr + total, ubuf.sbuf, bufferlen) ; |
899 | writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
893 | writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
900 | 894 | total += writecount ; |
901 | 895 | if (writecount < bufferlen) |
902 | 896 | break ; |
925 | 919 | { if (len < bufferlen) |
926 | 920 | bufferlen = (int) len ; |
927 | 921 | f2dles_array (pxi, ptr + total, ubuf.sbuf, bufferlen, normfact) ; |
928 | writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
922 | writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
929 | 923 | total += writecount ; |
930 | 924 | if (writecount < bufferlen) |
931 | 925 | break ; |
954 | 948 | { if (len < bufferlen) |
955 | 949 | bufferlen = (int) len ; |
956 | 950 | d2dles_array (pxi, ptr + total, ubuf.sbuf, bufferlen, normfact) ; |
957 | writecount = psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
951 | writecount = (int) psf_fwrite (ubuf.sbuf, sizeof (short), bufferlen, psf) ; | |
958 | 952 | total += writecount ; |
959 | 953 | if (writecount < bufferlen) |
960 | 954 | break ; |
1226 | 1220 | |
1227 | 1221 | pxi->last_16 = last_val ; |
1228 | 1222 | } /* d2dles_array */ |
1229 |
48 | 48 | |
49 | 49 | print_test_name ("alaw_test", "encoder") ; |
50 | 50 | |
51 | filename = "test.raw" ; | |
51 | filename = "alaw_test.raw" ; | |
52 | 52 | |
53 | 53 | sf_info_setup (&sfinfo, SF_FORMAT_RAW | SF_FORMAT_ALAW, 44100, 1) ; |
54 | 54 |
37 | 37 | #define LOG_BUFFER_SIZE 1024 |
38 | 38 | |
39 | 39 | static void chunk_test (const char *filename, int format) ; |
40 | static void wav_subchunk_test (size_t chunk_size) ; | |
41 | static void large_free_test (const char *filename, int format, size_t chunk_size) ; | |
40 | static void wav_subchunk_test (unsigned int chunk_size) ; | |
41 | static void large_free_test (const char *filename, int format, unsigned int chunk_size) ; | |
42 | 42 | |
43 | 43 | int |
44 | 44 | main (int argc, char *argv []) |
132 | 132 | snprintf (chunk_info.id, sizeof (chunk_info.id), "Test") ; |
133 | 133 | chunk_info.id_size = 4 ; |
134 | 134 | chunk_info.data = strdup (testdata) ; |
135 | chunk_info.datalen = strlen (chunk_info.data) ; | |
135 | chunk_info.datalen = (unsigned int) strlen (chunk_info.data) ; | |
136 | 136 | |
137 | 137 | length_before = chunk_info.datalen ; |
138 | 138 | |
223 | 223 | chunk_info.id_size = 4 ; |
224 | 224 | |
225 | 225 | chunk_info.data = strdup (testdata [i]) ; |
226 | chunk_info.datalen = strlen (chunk_info.data) ; | |
226 | chunk_info.datalen = (unsigned int) strlen (chunk_info.data) ; | |
227 | 227 | |
228 | 228 | length_before [i] = chunk_info.datalen ; |
229 | 229 | |
315 | 315 | |
316 | 316 | |
317 | 317 | static void |
318 | wav_subchunk_test (size_t chunk_size) | |
318 | wav_subchunk_test (unsigned int chunk_size) | |
319 | 319 | { SNDFILE * file ; |
320 | 320 | SF_INFO sfinfo ; |
321 | 321 | SF_CHUNK_INFO chunk_info ; |
324 | 324 | short audio [16] ; |
325 | 325 | int err, value ; |
326 | 326 | |
327 | snprintf (filename, sizeof (filename), "subchunk_%04d.wav", (int) chunk_size) ; | |
327 | snprintf (filename, sizeof (filename), "subchunk_%04u.wav", chunk_size) ; | |
328 | 328 | print_test_name (__func__, filename) ; |
329 | 329 | |
330 | 330 | exit_if_true (sizeof (chunk_data) < chunk_size, "\n\nLine %d : sizeof (data) < chunk_size\n\n", __LINE__) ; |
352 | 352 | snprintf (chunk_info.id, sizeof (chunk_info.id), "LIST") ; |
353 | 353 | chunk_info.id_size = 4 ; |
354 | 354 | chunk_info.data = chunk_data ; |
355 | chunk_info.datalen = chunk_size ; | |
355 | chunk_info.datalen = (unsigned int) chunk_size ; | |
356 | 356 | |
357 | 357 | err = sf_set_chunk (file, &chunk_info) ; |
358 | 358 | exit_if_true ( |
385 | 385 | } /* wav_subchunk_test */ |
386 | 386 | |
387 | 387 | static void |
388 | large_free_test (const char *filename, int format, size_t chunk_size) | |
388 | large_free_test (const char *filename, int format, unsigned int chunk_size) | |
389 | 389 | { SNDFILE * file ; |
390 | 390 | SF_INFO sfinfo ; |
391 | 391 | SF_CHUNK_INFO chunk_info ; |
114 | 114 | { /* Preliminary float/double normalisation tests. More testing |
115 | 115 | ** is done in the program 'floating_point_test'. |
116 | 116 | */ |
117 | float_norm_test ("float.wav") ; | |
118 | double_norm_test ("double.wav") ; | |
117 | float_norm_test ("cmd_float.wav") ; | |
118 | double_norm_test ("cmd_double.wav") ; | |
119 | 119 | test_count ++ ; |
120 | 120 | } ; |
121 | 121 | |
238 | 238 | |
239 | 239 | /* Create float_data with all values being less than 1.0. */ |
240 | 240 | for (k = 0 ; k < BUFFER_LEN / 2 ; k++) |
241 | float_data [k] = (k + 5) / (2.0 * BUFFER_LEN) ; | |
241 | float_data [k] = (k + 5) / (2.0f * BUFFER_LEN) ; | |
242 | 242 | for (k = BUFFER_LEN / 2 ; k < BUFFER_LEN ; k++) |
243 | float_data [k] = (k + 5) ; | |
243 | float_data [k] = (float) (k + 5) ; | |
244 | 244 | |
245 | 245 | if (! (file = sf_open (filename, SFM_WRITE, &sfinfo))) |
246 | 246 | { printf ("Line %d: sf_open_write failed with error : ", __LINE__) ; |
251 | 251 | |
252 | 252 | /* Normalisation is on by default so no need to do anything here. */ |
253 | 253 | |
254 | if ((k = sf_write_float (file, float_data, BUFFER_LEN / 2)) != BUFFER_LEN / 2) | |
254 | if ((k = (unsigned int) sf_write_float (file, float_data, BUFFER_LEN / 2)) != BUFFER_LEN / 2) | |
255 | 255 | { printf ("Line %d: sf_write_float failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; |
256 | 256 | exit (1) ; |
257 | 257 | } ; |
259 | 259 | /* Turn normalisation off. */ |
260 | 260 | sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ; |
261 | 261 | |
262 | if ((k = sf_write_float (file, float_data + BUFFER_LEN / 2, BUFFER_LEN / 2)) != BUFFER_LEN / 2) | |
262 | if ((k = (unsigned int) sf_write_float (file, float_data + BUFFER_LEN / 2, BUFFER_LEN / 2)) != BUFFER_LEN / 2) | |
263 | 263 | { printf ("Line %d: sf_write_float failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; |
264 | 264 | exit (1) ; |
265 | 265 | } ; |
290 | 290 | } ; |
291 | 291 | |
292 | 292 | /* Read float_data and check that it is normalised (ie default). */ |
293 | if ((k = sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN) | |
293 | if ((k = (unsigned int) sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN) | |
294 | 294 | { printf ("\n\nLine %d: sf_read_float failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; |
295 | 295 | exit (1) ; |
296 | 296 | } ; |
305 | 305 | sf_seek (file, 0, SEEK_SET) ; |
306 | 306 | sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ; |
307 | 307 | |
308 | if ((k = sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN) | |
308 | if ((k = (unsigned int) sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN) | |
309 | 309 | { printf ("\n\nLine %d: sf_read_float failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; |
310 | 310 | exit (1) ; |
311 | 311 | } ; |
320 | 320 | sf_seek (file, 0, SEEK_SET) ; |
321 | 321 | sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_TRUE) ; |
322 | 322 | |
323 | if ((k = sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN) | |
323 | if ((k = (unsigned int) sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN) | |
324 | 324 | { printf ("\n\nLine %d: sf_read_float failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; |
325 | 325 | exit (1) ; |
326 | 326 | } ; |
368 | 368 | /* Normailsation is on by default so no need to do anything here. */ |
369 | 369 | /*-sf_command (file, "set-norm-double", "true", 0) ;-*/ |
370 | 370 | |
371 | if ((k = sf_write_double (file, double_data, BUFFER_LEN / 2)) != BUFFER_LEN / 2) | |
371 | if ((k = (unsigned int) sf_write_double (file, double_data, BUFFER_LEN / 2)) != BUFFER_LEN / 2) | |
372 | 372 | { printf ("Line %d: sf_write_double failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; |
373 | 373 | exit (1) ; |
374 | 374 | } ; |
376 | 376 | /* Turn normalisation off. */ |
377 | 377 | sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ; |
378 | 378 | |
379 | if ((k = sf_write_double (file, double_data + BUFFER_LEN / 2, BUFFER_LEN / 2)) != BUFFER_LEN / 2) | |
379 | if ((k = (unsigned int) sf_write_double (file, double_data + BUFFER_LEN / 2, BUFFER_LEN / 2)) != BUFFER_LEN / 2) | |
380 | 380 | { printf ("Line %d: sf_write_double failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; |
381 | 381 | exit (1) ; |
382 | 382 | } ; |
406 | 406 | } ; |
407 | 407 | |
408 | 408 | /* Read double_data and check that it is normalised (ie default). */ |
409 | if ((k = sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN) | |
409 | if ((k = (unsigned int) sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN) | |
410 | 410 | { printf ("\n\nLine %d: sf_read_double failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; |
411 | 411 | exit (1) ; |
412 | 412 | } ; |
421 | 421 | sf_seek (file, 0, SEEK_SET) ; |
422 | 422 | sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ; |
423 | 423 | |
424 | if ((k = sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN) | |
424 | if ((k = (unsigned int) sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN) | |
425 | 425 | { printf ("\n\nLine %d: sf_read_double failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; |
426 | 426 | exit (1) ; |
427 | 427 | } ; |
436 | 436 | sf_seek (file, 0, SEEK_SET) ; |
437 | 437 | sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_TRUE) ; |
438 | 438 | |
439 | if ((k = sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN) | |
439 | if ((k = (unsigned int) sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN) | |
440 | 440 | { printf ("\n\nLine %d: sf_read_double failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ; |
441 | 441 | exit (1) ; |
442 | 442 | } ; |
531 | 531 | /* Now test subtype formats. */ |
532 | 532 | sf_command (NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &count, sizeof (int)) ; |
533 | 533 | |
534 | if (count < 0 || count > 30) | |
534 | if (count < 0 || count > 33) | |
535 | 535 | { printf ("Line %d: Weird count.\n", __LINE__) ; |
536 | 536 | exit (1) ; |
537 | 537 | } ; |
1020 | 1020 | sfinfo.channels = 1 ; |
1021 | 1021 | |
1022 | 1022 | file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; |
1023 | if (sf_command (file, SFC_SET_CUE, write_cue, cues_size) == SF_FALSE) | |
1023 | if (sf_command (file, SFC_SET_CUE, write_cue, (int) cues_size) == SF_FALSE) | |
1024 | 1024 | { printf ("\n\nLine %d : sf_command (SFC_SET_CUE) failed with %d cues, datasize %zu --> error: %s\n\n", __LINE__, count, cues_size, sf_strerror (file)) ; |
1025 | 1025 | exit (1) ; |
1026 | 1026 | } ; |
1031 | 1031 | |
1032 | 1032 | file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; |
1033 | 1033 | |
1034 | if (sf_command (file, SFC_GET_CUE, read_cue, cues_size) == SF_FALSE) | |
1034 | if (sf_command (file, SFC_GET_CUE, read_cue, (int) cues_size) == SF_FALSE) | |
1035 | 1035 | { printf ("\n\nLine %d : sf_command (SFC_GET_CUE) failed with %d cues, datasize %zu --> error: %s\n\n", __LINE__, count, cues_size, sf_strerror (file)) ; |
1036 | 1036 | exit (1) ; |
1037 | 1037 | } ; |
1350 | 1350 | exit (1) ; |
1351 | 1351 | } ; |
1352 | 1352 | |
1353 | bc_write.coding_history_size = strlen (supplied_history) ; | |
1353 | bc_write.coding_history_size = (uint32_t) strlen (supplied_history) ; | |
1354 | 1354 | bc_write.coding_history_size = snprintf (bc_write.coding_history, sizeof (bc_write.coding_history), "%s", supplied_history) ; |
1355 | 1355 | |
1356 | 1356 | file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; |
1422 | 1422 | for (k = 0 ; bc_write.coding_history_size < 512 ; k++) |
1423 | 1423 | { snprintf (bc_write.coding_history + bc_write.coding_history_size, |
1424 | 1424 | sizeof (bc_write.coding_history) - bc_write.coding_history_size, "line %4d\n", k) ; |
1425 | bc_write.coding_history_size = strlen (bc_write.coding_history) ; | |
1425 | bc_write.coding_history_size = (uint32_t) strlen (bc_write.coding_history) ; | |
1426 | 1426 | } ; |
1427 | 1427 | |
1428 | 1428 | exit_if_true (bc_write.coding_history_size < 512, |
1492 | 1492 | ca_write.level_reference = 42 ; |
1493 | 1493 | snprintf (ca_write.url, sizeof (ca_write.url), "http://www.test.com/test_url") ; |
1494 | 1494 | snprintf (ca_write.tag_text, sizeof (ca_write.tag_text), "tag text test! \r\n") ; // must be terminated \r\n to be valid |
1495 | ca_write.tag_text_size = strlen (ca_write.tag_text) ; | |
1495 | ca_write.tag_text_size = (uint32_t) strlen (ca_write.tag_text) ; | |
1496 | 1496 | |
1497 | 1497 | file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; |
1498 | 1498 | if (sf_command (file, SFC_SET_CART_INFO, &ca_write, sizeof (ca_write)) == SF_FALSE) |
1651 | 1651 | cinfo.level_reference = 42 ; |
1652 | 1652 | snprintf (cinfo.url, sizeof (cinfo.url), "http://www.test.com/test_url") ; |
1653 | 1653 | snprintf (cinfo.tag_text, sizeof (cinfo.tag_text), "tag text test!\r\n") ; |
1654 | cinfo.tag_text_size = strlen (cinfo.tag_text) ; | |
1654 | cinfo.tag_text_size = (uint32_t) strlen (cinfo.tag_text) ; | |
1655 | 1655 | |
1656 | 1656 | file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ; |
1657 | 1657 | frames = sfinfo.frames ; |
36 | 36 | #define SAMPLE_RATE 16000 |
37 | 37 | #define DATA_LENGTH (SAMPLE_RATE) |
38 | 38 | |
39 | static const char CMP_TEST_PREFIX[] = "cmp" ; | |
40 | ||
39 | 41 | static float data_out [DATA_LENGTH] ; |
40 | 42 | |
41 | 43 | static inline float |
52 | 54 | float max_abs = 0.0 ; |
53 | 55 | unsigned k ; |
54 | 56 | |
57 | get_unique_test_name (&filename, CMP_TEST_PREFIX) ; | |
58 | ||
55 | 59 | print_test_name ("vorbis_test", filename) ; |
56 | 60 | |
57 | 61 | /* Generate float data. */ |
97 | 101 | sf_close (file) ; |
98 | 102 | |
99 | 103 | for (k = 0 ; k < ARRAY_LEN (float_data) ; k ++) |
100 | max_abs = max_float (max_abs, fabs (float_data [k])) ; | |
104 | max_abs = max_float (max_abs, fabsf (float_data [k])) ; | |
101 | 105 | |
102 | 106 | exit_if_true (max_abs > 1.023, |
103 | 107 | "\n\nLine %d : max_abs %f should be < 1.023.\n\n", __LINE__, max_abs) ; |
122 | 126 | double quality ; |
123 | 127 | int k ; |
124 | 128 | |
129 | get_unique_test_name (&filename, CMP_TEST_PREFIX) ; | |
130 | ||
125 | 131 | snprintf (q3_fname, sizeof (q3_fname), "q3_%s", filename) ; |
126 | 132 | snprintf (q6_fname, sizeof (q6_fname), "q6_%s", filename) ; |
127 | 133 | |
153 | 159 | sf_close (q3_file) ; |
154 | 160 | sf_close (q6_file) ; |
155 | 161 | |
156 | q3_size = file_length (q3_fname) ; | |
157 | q6_size = file_length (q6_fname) ; | |
162 | q3_size = (int) file_length (q3_fname) ; | |
163 | q6_size = (int) file_length (q6_fname) ; | |
158 | 164 | |
159 | 165 | exit_if_true (q3_size >= q6_size, |
160 | 166 | "\n\nLine %d : q3 size (%d) >= q6 size (%d)\n\n", __LINE__, q3_size, q6_size) ; |
177 | 183 | " vorbis - test Ogg/Vorbis\n" |
178 | 184 | " flac - test FLAC\n" |
179 | 185 | " opus - test Opus\n" |
186 | " mpeg - test mpeg\n" | |
180 | 187 | " all - perform all tests\n", |
181 | 188 | argv [0]) ; |
182 | 189 | exit (0) ; |
183 | 190 | } ; |
184 | 191 | |
185 | if (! HAVE_EXTERNAL_XIPH_LIBS) | |
186 | { puts (" No Ogg/Vorbis tests because Ogg/Vorbis support was not compiled in.") ; | |
187 | return 0 ; | |
188 | } ; | |
189 | ||
190 | 192 | if (strcmp (argv [1], "all") == 0) |
191 | 193 | all_tests = 1 ; |
192 | 194 | |
193 | 195 | if (all_tests || strcmp (argv [1], "vorbis") == 0) |
194 | { vorbis_test () ; | |
195 | compression_size_test (SF_FORMAT_OGG | SF_FORMAT_VORBIS, "vorbis.oga") ; | |
196 | tests ++ ; | |
196 | { if (HAVE_EXTERNAL_XIPH_LIBS) | |
197 | { vorbis_test () ; | |
198 | compression_size_test (SF_FORMAT_OGG | SF_FORMAT_VORBIS, "vorbis.oga") ; | |
199 | tests ++ ; | |
200 | } | |
201 | else | |
202 | puts (" No Ogg Vorbis tests because support was not compiled in.") ; | |
197 | 203 | } ; |
198 | 204 | |
199 | 205 | if (all_tests || strcmp (argv [1], "flac") == 0) |
200 | { compression_size_test (SF_FORMAT_FLAC | SF_FORMAT_PCM_16, "pcm16.flac") ; | |
201 | tests ++ ; | |
206 | { if (HAVE_EXTERNAL_XIPH_LIBS) | |
207 | { compression_size_test (SF_FORMAT_FLAC | SF_FORMAT_PCM_16, "pcm16.flac") ; | |
208 | tests ++ ; | |
209 | } | |
210 | else | |
211 | puts (" No FLAC tests because support was not compiled in.") ; | |
202 | 212 | } ; |
203 | 213 | |
204 | 214 | if (all_tests || strcmp (argv [1], "opus") == 0) |
205 | { compression_size_test (SF_FORMAT_OGG | SF_FORMAT_OPUS, "opus.opus") ; | |
206 | tests ++ ; | |
215 | { if (HAVE_EXTERNAL_XIPH_LIBS) | |
216 | { compression_size_test (SF_FORMAT_OGG | SF_FORMAT_OPUS, "opus.opus") ; | |
217 | tests ++ ; | |
218 | } | |
219 | else | |
220 | puts (" No Opus tests because support was not compiled in.") ; | |
221 | } ; | |
222 | ||
223 | if (all_tests || strcmp (argv [1], "mpeg") == 0) | |
224 | { if (HAVE_MPEG) | |
225 | { compression_size_test (SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III, "mpeg.mp3") ; | |
226 | tests ++ ; | |
227 | } | |
228 | else | |
229 | puts (" No MPEG tests because support was not compiled in.") ; | |
207 | 230 | } ; |
208 | 231 | |
209 | 232 | return 0 ; |
85 | 85 | |
86 | 86 | file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; |
87 | 87 | |
88 | if ((k = sf_read_int (file, read_buf, BUFFER_SIZE)) != BUFFER_SIZE) | |
88 | if ((k = (int) sf_read_int (file, read_buf, BUFFER_SIZE)) != BUFFER_SIZE) | |
89 | 89 | { printf ("Error (line %d) : Only read %d/%d.frames.\n", __LINE__, k, BUFFER_SIZE) ; |
90 | 90 | exit (1) ; |
91 | 91 | } |
28 | 28 | #include "sf_unistd.h" |
29 | 29 | #endif |
30 | 30 | |
31 | #if OS_IS_WIN32 | |
32 | #include <windows.h> | |
33 | #endif | |
34 | ||
35 | 31 | #include <sndfile.h> |
36 | 32 | |
37 | 33 | #include "utils.h" |
212 | 208 | |
213 | 209 | if (sf_close (sndfile) == 0) |
214 | 210 | { |
211 | printf ("\n\nLine %d : sf_close should not have returned zero.\n", __LINE__) ; | |
215 | 212 | #if OS_IS_WIN32 |
216 | OSVERSIONINFOEX osvi ; | |
217 | ||
218 | memset (&osvi, 0, sizeof (OSVERSIONINFOEX)) ; | |
219 | osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX) ; | |
220 | ||
221 | if (GetVersionEx ((OSVERSIONINFO *) &osvi)) | |
222 | { printf ("\n\nLine %d : sf_close should not have returned zero.\n", __LINE__) ; | |
223 | printf ("\nHowever, this is a known bug in version %d.%d of windows so we'll ignore it.\n\n", | |
224 | (int) osvi.dwMajorVersion, (int) osvi.dwMinorVersion) ; | |
225 | } ; | |
213 | printf ("\nHowever, this is a known bug on windows platform so we'll ignore it.\n\n") ; | |
226 | 214 | #else |
227 | printf ("\n\nLine %d : sf_close should not have returned zero.\n", __LINE__) ; | |
228 | 215 | exit (1) ; |
229 | 216 | #endif |
230 | 217 | } ; |
254 | 241 | sndfile = sf_open (filename, SFM_READ, &sfinfo) ; |
255 | 242 | |
256 | 243 | exit_if_true (sndfile != NULL, |
257 | "\n\nLine %d : SNDFILE* pointer (%p) should ne NULL.\n", __LINE__, sndfile | |
244 | "\n\nLine %d : SNDFILE* pointer (%p) should be NULL.\n", __LINE__, (void *) sndfile | |
258 | 245 | ) ; |
259 | 246 | |
260 | 247 | k = sf_error (sndfile) ; |
37 | 37 | |
38 | 38 | #define SAMPLE_RATE 16000 |
39 | 39 | |
40 | static const char FPT_TEST_PREFIX[] = "fpt" ; | |
41 | ||
40 | 42 | static void float_scaled_test (const char *filename, int allow_exit, int replace_float, int filetype, double target_snr) ; |
41 | 43 | static void double_scaled_test (const char *filename, int allow_exit, int replace_float, int filetype, double target_snr) ; |
42 | 44 | |
43 | 45 | [+ FOR float_type +][+ FOR int_type +][+ FOR endian_type |
44 | +]static void [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test (const char * filename) ; | |
46 | +]static void [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test (const char * filename, int replace_float) ; | |
45 | 47 | [+ ENDFOR endian_type +][+ ENDFOR int_type +][+ ENDFOR float_type |
46 | 48 | +] |
47 | 49 | |
124 | 126 | float_scaled_test ("opus.opus", allow_exit, SF_FALSE, SF_FORMAT_OGG | SF_FORMAT_OPUS, -32.0) ; |
125 | 127 | #endif |
126 | 128 | |
129 | #if HAVE_MPEG | |
130 | float_scaled_test ("mpeg.mp3", allow_exit, SF_FALSE, SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III, -52.0) ; | |
131 | #endif | |
132 | ||
127 | 133 | float_scaled_test ("replace_float.raw", allow_exit, SF_TRUE, SF_ENDIAN_LITTLE | SF_FORMAT_RAW | SF_FORMAT_FLOAT, -163.0) ; |
128 | 134 | |
129 | 135 | /*============================================================================== |
182 | 188 | double_scaled_test ("opus.opus", allow_exit, SF_FALSE, SF_FORMAT_OGG | SF_FORMAT_OPUS, -32.0) ; |
183 | 189 | #endif |
184 | 190 | |
191 | #if HAVE_MPEG | |
192 | double_scaled_test ("mpeg.mp3", allow_exit, SF_FALSE, SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III, -52.0) ; | |
193 | #endif | |
194 | ||
185 | 195 | double_scaled_test ("replace_double.raw", allow_exit, SF_TRUE, SF_FORMAT_RAW | SF_FORMAT_DOUBLE, -201.0) ; |
186 | 196 | |
187 | 197 | putchar ('\n') ; |
188 | 198 | /* Float int tests. */ |
189 | [+ FOR float_type +][+ FOR int_type +][+ FOR endian_type | |
190 | +] [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test ("[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +].au") ; | |
191 | [+ ENDFOR endian_type +][+ ENDFOR int_type +][+ ENDFOR float_type | |
192 | +] | |
199 | [+ FOR float_type +][+ FOR int_type +][+ FOR endian_type +] | |
200 | [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test ("[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +].au", SF_FALSE) ; | |
201 | [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test ("[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_replace.au", SF_TRUE) ; | |
202 | [+ ENDFOR endian_type +][+ ENDFOR int_type +][+ ENDFOR float_type +] | |
193 | 203 | |
194 | 204 | return 0 ; |
195 | 205 | } /* main */ |
205 | 215 | double snr ; |
206 | 216 | int byterate ; |
207 | 217 | |
218 | get_unique_test_name (&filename, FPT_TEST_PREFIX) ; | |
208 | 219 | print_test_name ("float_scaled_test", filename) ; |
209 | 220 | |
210 | 221 | gen_windowed_sine_float (float_data, DFT_DATA_LENGTH, 0.9999) ; |
258 | 269 | double snr ; |
259 | 270 | int byterate ; |
260 | 271 | |
272 | get_unique_test_name (&filename, FPT_TEST_PREFIX) ; | |
261 | 273 | print_test_name ("double_scaled_test", filename) ; |
262 | 274 | |
263 | 275 | gen_windowed_sine_double (double_data, DFT_DATA_LENGTH, 0.9999) ; |
310 | 322 | [+ FOR float_type +][+ FOR int_type +][+ FOR endian_type |
311 | 323 | +] |
312 | 324 | static void |
313 | [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test (const char * filename) | |
325 | [+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test (const char * filename, int replace_float) | |
314 | 326 | { SNDFILE *file ; |
315 | 327 | SF_INFO sfinfo ; |
316 | 328 | int max ; |
317 | 329 | unsigned k ; |
318 | 330 | |
331 | get_unique_test_name (&filename, FPT_TEST_PREFIX) ; | |
319 | 332 | print_test_name ("[+ (get "float_name") +]_[+ (get "int_name") +]_[+ (get "end_name") +]_test", filename) ; |
320 | 333 | |
321 | 334 | gen_windowed_sine_[+ (get "float_name") +] ([+ (get "float_name") +]_data, ARRAY_LEN ([+ (get "float_name") +]_data), 0.9999) ; |
327 | 340 | sfinfo.format = [+ (get "end_type") +] | SF_FORMAT_AU | [+ (get "minor_type") +] ; |
328 | 341 | |
329 | 342 | file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; |
343 | sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ; | |
330 | 344 | test_write_[+ (get "float_name") +]_or_die (file, 0, [+ (get "float_name") +]_data, ARRAY_LEN ([+ (get "float_name") +]_data), __LINE__) ; |
331 | 345 | sf_close (file) ; |
332 | 346 | |
333 | 347 | file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; |
348 | sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ; | |
334 | 349 | |
335 | 350 | if (sfinfo.frames != ARRAY_LEN ([+ (get "float_name") +]_data)) |
336 | 351 | { printf ("\n\nLine %d: Incorrect number of frames in file (too short). (%" PRId64 " should be %d)\n", __LINE__, sfinfo.frames, DFT_DATA_LENGTH) ; |
120 | 120 | __LINE__ |
121 | 121 | ) ; |
122 | 122 | |
123 | /* Only have decode, not encode support for MPEG Layer I and II */ | |
124 | if (subtype_fmt_info.format == SF_FORMAT_MPEG_LAYER_I || | |
125 | subtype_fmt_info.format == SF_FORMAT_MPEG_LAYER_II) | |
126 | continue ; | |
127 | ||
128 | /* MPEG Layer III in WAV is decode only currently */ | |
129 | if (subtype_fmt_info.format == SF_FORMAT_MPEG_LAYER_III && | |
130 | major_fmt_info.format == SF_FORMAT_WAV) | |
131 | continue ; | |
132 | ||
123 | 133 | snprintf (filename, sizeof (filename), "format-check.%s", major_fmt_info.extension) ; |
124 | 134 | |
125 | 135 | sndfile = sf_open (filename, SFM_WRITE, &info) ; |
38 | 38 | |
39 | 39 | output = calloc (len, sizeof (float)) ; |
40 | 40 | |
41 | maxabs = crappy_snare (output, len, 0, 0.95, maxabs) ; | |
42 | maxabs = crappy_snare (output, len, len / 4, 0.85, maxabs) ; | |
43 | maxabs = crappy_snare (output, len, 2 * len / 4, 0.85, maxabs) ; | |
44 | crappy_snare (output, len, 3 * len / 4, 0.85, maxabs) ; | |
41 | maxabs = crappy_snare (output, len, 0, 0.95f, maxabs) ; | |
42 | maxabs = crappy_snare (output, len, len / 4, 0.85f, maxabs) ; | |
43 | maxabs = crappy_snare (output, len, 2 * len / 4, 0.85f, maxabs) ; | |
44 | crappy_snare (output, len, 3 * len / 4, 0.85f, maxabs) ; | |
45 | 45 | |
46 | 46 | write_mono_file (filename, format, 44100, output, len) ; |
47 | 47 | |
50 | 50 | |
51 | 51 | static inline float |
52 | 52 | rand_float (void) |
53 | { return rand () / (0.5 * RAND_MAX) - 1.0 ; | |
53 | { return rand () / (0.5f * (float) RAND_MAX) - 1.0f ; | |
54 | 54 | } /* rand_float */ |
55 | 55 | |
56 | 56 | static float |
57 | 57 | crappy_snare (float *output, int len, int offset, float gain, float maxabs) |
58 | 58 | { int k ; |
59 | float env = 0.0 ; | |
59 | float env = 0.0f ; | |
60 | 60 | |
61 | 61 | for (k = offset ; k < len && env < gain ; k++) |
62 | { env += 0.03 ; | |
62 | { env += 0.03f ; | |
63 | 63 | output [k] += env * rand_float () ; |
64 | maxabs = SF_MAX (maxabs, fabs (output [k])) ; | |
64 | maxabs = SF_MAX (maxabs, fabsf (output [k])) ; | |
65 | 65 | } ; |
66 | 66 | |
67 | 67 | for ( ; k < len && env > 1e-8 ; k++) |
68 | { env *= 0.995 ; | |
68 | { env *= 0.995f ; | |
69 | 69 | output [k] += env * rand_float () ; |
70 | maxabs = SF_MAX (maxabs, fabs (output [k])) ; | |
70 | maxabs = SF_MAX (maxabs, fabsf (output [k])) ; | |
71 | 71 | } ; |
72 | 72 | |
73 | 73 | return maxabs ; |
105 | 105 | update_seek_int_test ("header_int.aiff", SF_FORMAT_AIFF) ; |
106 | 106 | update_seek_float_test ("header_float.aiff", SF_FORMAT_AIFF) ; |
107 | 107 | update_seek_double_test ("header_double.aiff", SF_FORMAT_AIFF) ; |
108 | header_shrink_test ("header_shrink.wav", SF_FORMAT_AIFF) ; | |
108 | header_shrink_test ("header_shrink.aiff", SF_FORMAT_AIFF) ; | |
109 | 109 | extra_header_test ("extra.aiff", SF_FORMAT_AIFF) ; |
110 | 110 | test_count++ ; |
111 | 111 | } ; |
43 | 43 | { |
44 | 44 | old_test () ; |
45 | 45 | |
46 | headerless_test ("raw.vox", SF_FORMAT_VOX_ADPCM, SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM) ; | |
47 | headerless_test ("raw.gsm", SF_FORMAT_GSM610, SF_FORMAT_RAW | SF_FORMAT_GSM610) ; | |
46 | headerless_test ("headerless.vox", SF_FORMAT_VOX_ADPCM, SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM) ; | |
47 | headerless_test ("headerless.gsm", SF_FORMAT_GSM610, SF_FORMAT_RAW | SF_FORMAT_GSM610) ; | |
48 | 48 | |
49 | headerless_test ("raw.snd", SF_FORMAT_ULAW, SF_FORMAT_RAW | SF_FORMAT_ULAW) ; | |
50 | headerless_test ("raw.au" , SF_FORMAT_ULAW, SF_FORMAT_RAW | SF_FORMAT_ULAW) ; | |
49 | headerless_test ("headerless.snd", SF_FORMAT_ULAW, SF_FORMAT_RAW | SF_FORMAT_ULAW) ; | |
50 | headerless_test ("headerless.au" , SF_FORMAT_ULAW, SF_FORMAT_RAW | SF_FORMAT_ULAW) ; | |
51 | 51 | |
52 | 52 | return 0 ; |
53 | 53 | } /* main */ |
73 | 73 | |
74 | 74 | file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; |
75 | 75 | |
76 | if ((k = sf_write_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE) | |
76 | if ((k = (int) sf_write_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE) | |
77 | 77 | { printf ("Line %d: sf_write_short failed with short write (%d => %d).\n", __LINE__, BUFFER_SIZE, k) ; |
78 | 78 | fflush (stdout) ; |
79 | 79 | puts (sf_strerror (file)) ; |
134 | 134 | |
135 | 135 | file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; |
136 | 136 | |
137 | if ((k = sf_write_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE) | |
137 | if ((k = (int) sf_write_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE) | |
138 | 138 | { printf ("Line %d: sf_write_short failed with short write (%d => %d).\n", __LINE__, BUFFER_SIZE, k) ; |
139 | 139 | fflush (stdout) ; |
140 | 140 | puts (sf_strerror (file)) ; |
167 | 167 | |
168 | 168 | check_log_buffer_or_die (file, __LINE__) ; |
169 | 169 | |
170 | if ((k = sf_read_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE) | |
170 | if ((k = (int) sf_read_short (file, buffer, BUFFER_SIZE)) != BUFFER_SIZE) | |
171 | 171 | { printf ("Line %d: short read (%d).\n", __LINE__, k) ; |
172 | 172 | exit (1) ; |
173 | 173 | } ; |
33 | 33 | |
34 | 34 | #if OS_IS_WIN32 |
35 | 35 | #include <windows.h> |
36 | #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1 | |
37 | 36 | #endif |
38 | 37 | |
39 | 38 | #include "sndfile.h" |
65 | 65 | { int value = k / 32 ; |
66 | 66 | int_data [k] = (value & 1 ? -1 : 1) * value ; |
67 | 67 | short_data [k] = int_data [k] ; |
68 | float_data [k] = int_data [k] / 32000.0 ; | |
68 | float_data [k] = int_data [k] / 32000.0f ; | |
69 | 69 | double_data [k] = int_data [k] / 32000.0 ; |
70 | 70 | } |
71 | 71 |
43 | 43 | |
44 | 44 | #define LCT_MAX(x, y) ((x) > (y) ? (x) : (y)) |
45 | 45 | |
46 | static const char LCT_TEST_PREFIX[] = "lct" ; | |
47 | ||
46 | 48 | static void lcomp_test_short (const char *filename, int filetype, int chan, double margin) ; |
47 | 49 | static void lcomp_test_int (const char *filename, int filetype, int chan, double margin) ; |
48 | 50 | static void lcomp_test_float (const char *filename, int filetype, int chan, double margin) ; |
650 | 652 | sf_count_t datalen ; |
651 | 653 | short *orig, *data ; |
652 | 654 | |
655 | get_unique_test_name (&filename, LCT_TEST_PREFIX) ; | |
653 | 656 | print_test_name ("lcomp_test_short", filename) ; |
654 | 657 | |
655 | 658 | datalen = BUFFER_SIZE / channels ; |
657 | 660 | data = data_buffer.s ; |
658 | 661 | orig = orig_buffer.s ; |
659 | 662 | |
660 | gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ; | |
663 | gen_signal_double (orig_buffer.d, 32000.0, channels, (int) datalen) ; | |
661 | 664 | for (k = 0 ; k < channels * datalen ; k++) |
662 | 665 | orig [k] = (short) (orig_buffer.d [k]) ; |
663 | 666 | |
708 | 711 | for (k = 0 ; k < datalen ; k++) |
709 | 712 | { if (error_function (data [k], orig [k], margin)) |
710 | 713 | { printf ("\n\nLine %d: Incorrect sample A (#%d : %d should be %d).\n", __LINE__, k, data [k], orig [k]) ; |
711 | oct_save_short (orig, data, datalen) ; | |
714 | oct_save_short (orig, data, (int) datalen) ; | |
712 | 715 | exit (1) ; |
713 | 716 | } ; |
714 | 717 | half_max_abs = LCT_MAX (half_max_abs, abs (data [k] / 2)) ; |
719 | 722 | exit (1) ; |
720 | 723 | } ; |
721 | 724 | |
722 | if ((k = sf_readf_short (file, data, datalen)) != sfinfo.frames - datalen) | |
725 | if ((k = (int) sf_readf_short (file, data, datalen)) != sfinfo.frames - datalen) | |
723 | 726 | { printf ("\n\nLine %d: Incorrect read length (%" PRId64 " should be %d).\n", __LINE__, |
724 | 727 | channels * sfinfo.frames - datalen, k) ; |
725 | 728 | exit (1) ; |
743 | 746 | |
744 | 747 | /* Now test sf_seek function. */ |
745 | 748 | |
746 | if ((k = sf_seek (file, 0, SEEK_SET)) != 0) | |
749 | if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) | |
747 | 750 | { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; |
748 | 751 | exit (1) ; |
749 | 752 | } ; |
764 | 767 | seekpos = BUFFER_SIZE / 10 ; |
765 | 768 | |
766 | 769 | /* Check seek from start of file. */ |
767 | if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
770 | if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
768 | 771 | { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; |
769 | 772 | exit (1) ; |
770 | 773 | } ; |
776 | 779 | exit (1) ; |
777 | 780 | } ; |
778 | 781 | |
779 | if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
782 | if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
780 | 783 | { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; |
781 | 784 | exit (1) ; |
782 | 785 | } ; |
783 | 786 | |
784 | seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
785 | k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
787 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
788 | k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
786 | 789 | test_readf_short_or_die (file, 0, data, 1, __LINE__) ; |
787 | 790 | if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) |
788 | 791 | { printf ("\n\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ; |
789 | oct_save_short (orig, data, datalen) ; | |
790 | exit (1) ; | |
791 | } ; | |
792 | ||
793 | seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; | |
792 | oct_save_short (orig, data, (int) datalen) ; | |
793 | exit (1) ; | |
794 | } ; | |
795 | ||
796 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; | |
794 | 797 | /* Check seek backward from current position. */ |
795 | k = sf_seek (file, -20, SEEK_CUR) ; | |
798 | k = (int) sf_seek (file, -20, SEEK_CUR) ; | |
796 | 799 | test_readf_short_or_die (file, 0, data, 1, __LINE__) ; |
797 | 800 | if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) |
798 | 801 | { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ; |
802 | 805 | /* Check that read past end of file returns number of items. */ |
803 | 806 | sf_seek (file, sfinfo.frames, SEEK_SET) ; |
804 | 807 | |
805 | if ((k = sf_readf_short (file, data, datalen)) != 0) | |
808 | if ((k = (int) sf_readf_short (file, data, datalen)) != 0) | |
806 | 809 | { printf ("\n\nLine %d: Return value from sf_readf_short past end of file incorrect (%d).\n", __LINE__, k) ; |
807 | 810 | exit (1) ; |
808 | 811 | } ; |
809 | 812 | |
810 | 813 | /* Check seek backward from end. */ |
811 | if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
814 | if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
812 | 815 | { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; |
813 | 816 | exit (1) ; |
814 | 817 | } ; |
837 | 840 | double scale, max_val ; |
838 | 841 | int *orig, *data ; |
839 | 842 | |
843 | get_unique_test_name (&filename, LCT_TEST_PREFIX) ; | |
840 | 844 | print_test_name ("lcomp_test_int", filename) ; |
841 | 845 | |
842 | 846 | datalen = BUFFER_SIZE / channels ; |
853 | 857 | data = data_buffer.i ; |
854 | 858 | orig = orig_buffer.i ; |
855 | 859 | |
856 | gen_signal_double (orig_buffer.d, max_val, channels, datalen) ; | |
860 | gen_signal_double (orig_buffer.d, max_val, channels, (int) datalen) ; | |
857 | 861 | |
858 | 862 | for (k = 0 ; k < channels * datalen ; k++) |
859 | 863 | orig [k] = lrint (orig_buffer.d [k]) ; |
905 | 909 | for (k = 0 ; k < datalen ; k++) |
906 | 910 | { if (error_function (data [k] / scale, orig [k] / scale, margin)) |
907 | 911 | { printf ("\nLine %d: Incorrect sample (#%d : %f should be %f).\n", __LINE__, k, data [k] / scale, orig [k] / scale) ; |
908 | oct_save_int (orig, data, datalen) ; | |
912 | oct_save_int (orig, data, (int) datalen) ; | |
909 | 913 | exit (1) ; |
910 | 914 | } ; |
911 | 915 | half_max_abs = LCT_MAX (half_max_abs, abs (data [k] / 2)) ; |
916 | 920 | exit (1) ; |
917 | 921 | } ; |
918 | 922 | |
919 | if ((k = sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen) | |
923 | if ((k = (int) sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen) | |
920 | 924 | { printf ("\n\nLine %d: Incorrect read length (%" PRId64 " should be %d).\n", __LINE__, |
921 | 925 | channels * sfinfo.frames - datalen, k) ; |
922 | 926 | exit (1) ; |
941 | 945 | |
942 | 946 | /* Now test sf_seek function. */ |
943 | 947 | |
944 | if ((k = sf_seek (file, 0, SEEK_SET)) != 0) | |
948 | if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) | |
945 | 949 | { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; |
946 | 950 | exit (1) ; |
947 | 951 | } ; |
962 | 966 | seekpos = BUFFER_SIZE / 10 ; |
963 | 967 | |
964 | 968 | /* Check seek from start of file. */ |
965 | if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
969 | if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
966 | 970 | { printf ("Seek to start of file + %" PRId64 " failed (%d).\n", seekpos, k) ; |
967 | 971 | exit (1) ; |
968 | 972 | } ; |
974 | 978 | exit (1) ; |
975 | 979 | } ; |
976 | 980 | |
977 | if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
981 | if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
978 | 982 | { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %" PRId64 ")\n", __LINE__, k, seekpos + 1) ; |
979 | 983 | exit (1) ; |
980 | 984 | } ; |
981 | 985 | |
982 | 986 | seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; |
983 | k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
987 | k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
984 | 988 | test_readf_int_or_die (file, 0, data, 1, __LINE__) ; |
985 | 989 | if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) |
986 | 990 | { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %" PRId64 ").\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ; |
989 | 993 | |
990 | 994 | seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; |
991 | 995 | /* Check seek backward from current position. */ |
992 | k = sf_seek (file, -20, SEEK_CUR) ; | |
996 | k = (int) sf_seek (file, -20, SEEK_CUR) ; | |
993 | 997 | test_readf_int_or_die (file, 0, data, 1, __LINE__) ; |
994 | 998 | if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) |
995 | 999 | { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %" PRId64 ").\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ; |
999 | 1003 | /* Check that read past end of file returns number of items. */ |
1000 | 1004 | sf_seek (file, sfinfo.frames, SEEK_SET) ; |
1001 | 1005 | |
1002 | if ((k = sf_readf_int (file, data, datalen)) != 0) | |
1006 | if ((k = (int) sf_readf_int (file, data, datalen)) != 0) | |
1003 | 1007 | { printf ("\n\nLine %d: Return value from sf_readf_int past end of file incorrect (%d).\n", __LINE__, k) ; |
1004 | 1008 | exit (1) ; |
1005 | 1009 | } ; |
1006 | 1010 | |
1007 | 1011 | /* Check seek backward from end. */ |
1008 | if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
1012 | if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
1009 | 1013 | { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; |
1010 | 1014 | exit (1) ; |
1011 | 1015 | } ; |
1034 | 1038 | float *orig, *data ; |
1035 | 1039 | double half_max_abs ; |
1036 | 1040 | |
1041 | get_unique_test_name (&filename, LCT_TEST_PREFIX) ; | |
1037 | 1042 | print_test_name ("lcomp_test_float", filename) ; |
1038 | 1043 | |
1039 | 1044 | datalen = BUFFER_SIZE / channels ; |
1041 | 1046 | data = data_buffer.f ; |
1042 | 1047 | orig = orig_buffer.f ; |
1043 | 1048 | |
1044 | gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ; | |
1049 | gen_signal_double (orig_buffer.d, 32000.0, channels, (int) datalen) ; | |
1045 | 1050 | for (k = 0 ; k < channels * datalen ; k++) |
1046 | orig [k] = orig_buffer.d [k] ; | |
1051 | orig [k] = (float) orig_buffer.d [k] ; | |
1047 | 1052 | |
1048 | 1053 | sfinfo.samplerate = SAMPLE_RATE ; |
1049 | 1054 | sfinfo.frames = 123456789 ; /* Ridiculous value. */ |
1099 | 1104 | for (k = 0 ; k < datalen ; k++) |
1100 | 1105 | { if (error_function (data [k], orig [k], margin)) |
1101 | 1106 | { printf ("\nLine %d: Incorrect sample A (#%d : %f should be %f).\n", __LINE__, k, data [k], orig [k]) ; |
1102 | oct_save_float (orig, data, datalen) ; | |
1107 | oct_save_float (orig, data, (int) datalen) ; | |
1103 | 1108 | exit (1) ; |
1104 | 1109 | } ; |
1105 | 1110 | half_max_abs = LCT_MAX (half_max_abs, fabs (0.5 * data [k])) ; |
1110 | 1115 | exit (1) ; |
1111 | 1116 | } ; |
1112 | 1117 | |
1113 | if ((k = sf_readf_float (file, data, datalen)) != sfinfo.frames - datalen) | |
1118 | if ((k = (int) sf_readf_float (file, data, datalen)) != sfinfo.frames - datalen) | |
1114 | 1119 | { printf ("\n\nLine %d: Incorrect read length (%" PRId64 " should be %d).\n", __LINE__, |
1115 | 1120 | channels * sfinfo.frames - datalen, k) ; |
1116 | 1121 | exit (1) ; |
1135 | 1140 | |
1136 | 1141 | /* Now test sf_seek function. */ |
1137 | 1142 | |
1138 | if ((k = sf_seek (file, 0, SEEK_SET)) != 0) | |
1143 | if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) | |
1139 | 1144 | { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; |
1140 | 1145 | exit (1) ; |
1141 | 1146 | } ; |
1156 | 1161 | seekpos = BUFFER_SIZE / 10 ; |
1157 | 1162 | |
1158 | 1163 | /* Check seek from start of file. */ |
1159 | if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
1164 | if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
1160 | 1165 | { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; |
1161 | 1166 | exit (1) ; |
1162 | 1167 | } ; |
1168 | 1173 | exit (1) ; |
1169 | 1174 | } ; |
1170 | 1175 | |
1171 | if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
1176 | if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
1172 | 1177 | { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; |
1173 | 1178 | exit (1) ; |
1174 | 1179 | } ; |
1175 | 1180 | |
1176 | seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
1177 | k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
1181 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
1182 | k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
1178 | 1183 | test_readf_float_or_die (file, 0, data, 1, __LINE__) ; |
1179 | 1184 | if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos) |
1180 | 1185 | { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_float failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ; |
1181 | 1186 | exit (1) ; |
1182 | 1187 | } ; |
1183 | 1188 | |
1184 | seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; | |
1189 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; | |
1185 | 1190 | /* Check seek backward from current position. */ |
1186 | k = sf_seek (file, -20, SEEK_CUR) ; | |
1191 | k = (int) sf_seek (file, -20, SEEK_CUR) ; | |
1187 | 1192 | test_readf_float_or_die (file, 0, data, 1, __LINE__) ; |
1188 | 1193 | if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos) |
1189 | 1194 | { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_float failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ; |
1193 | 1198 | /* Check that read past end of file returns number of items. */ |
1194 | 1199 | sf_seek (file, sfinfo.frames, SEEK_SET) ; |
1195 | 1200 | |
1196 | if ((k = sf_readf_float (file, data, datalen)) != 0) | |
1201 | if ((k = (int) sf_readf_float (file, data, datalen)) != 0) | |
1197 | 1202 | { printf ("\n\nLine %d: Return value from sf_readf_float past end of file incorrect (%d).\n", __LINE__, k) ; |
1198 | 1203 | exit (1) ; |
1199 | 1204 | } ; |
1200 | 1205 | |
1201 | 1206 | /* Check seek backward from end. */ |
1202 | if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
1207 | if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
1203 | 1208 | { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; |
1204 | 1209 | exit (1) ; |
1205 | 1210 | } ; |
1228 | 1233 | double *orig, *data ; |
1229 | 1234 | double half_max_abs ; |
1230 | 1235 | |
1236 | get_unique_test_name (&filename, LCT_TEST_PREFIX) ; | |
1231 | 1237 | print_test_name ("lcomp_test_double", filename) ; |
1232 | 1238 | |
1233 | 1239 | datalen = BUFFER_SIZE / channels ; |
1235 | 1241 | data = data_buffer.d ; |
1236 | 1242 | orig = orig_buffer.d ; |
1237 | 1243 | |
1238 | gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ; | |
1244 | gen_signal_double (orig_buffer.d, 32000.0, channels, (int) datalen) ; | |
1239 | 1245 | for (k = 0 ; k < channels * datalen ; k++) |
1240 | 1246 | orig [k] = orig_buffer.d [k] ; |
1241 | 1247 | |
1293 | 1299 | for (k = 0 ; k < datalen ; k++) |
1294 | 1300 | { if (error_function (data [k], orig [k], margin)) |
1295 | 1301 | { printf ("\nLine %d: Incorrect sample A (#%d : %f should be %f).\n", __LINE__, k, data [k], orig [k]) ; |
1296 | oct_save_double (orig, data, datalen) ; | |
1302 | oct_save_double (orig, data, (int) datalen) ; | |
1297 | 1303 | exit (1) ; |
1298 | 1304 | } ; |
1299 | 1305 | half_max_abs = LCT_MAX (half_max_abs, ABS (0.5 * data [k])) ; |
1304 | 1310 | exit (1) ; |
1305 | 1311 | } ; |
1306 | 1312 | |
1307 | if ((k = sf_readf_double (file, data, datalen)) != sfinfo.frames - datalen) | |
1313 | if ((k = (int) sf_readf_double (file, data, datalen)) != sfinfo.frames - datalen) | |
1308 | 1314 | { printf ("\n\nLine %d: Incorrect read length (%" PRId64 " should be %d).\n", __LINE__, |
1309 | 1315 | channels * sfinfo.frames - datalen, k) ; |
1310 | 1316 | exit (1) ; |
1329 | 1335 | |
1330 | 1336 | /* Now test sf_seek function. */ |
1331 | 1337 | |
1332 | if ((k = sf_seek (file, 0, SEEK_SET)) != 0) | |
1338 | if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) | |
1333 | 1339 | { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; |
1334 | 1340 | exit (1) ; |
1335 | 1341 | } ; |
1350 | 1356 | seekpos = BUFFER_SIZE / 10 ; |
1351 | 1357 | |
1352 | 1358 | /* Check seek from start of file. */ |
1353 | if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
1359 | if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
1354 | 1360 | { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; |
1355 | 1361 | exit (1) ; |
1356 | 1362 | } ; |
1362 | 1368 | exit (1) ; |
1363 | 1369 | } ; |
1364 | 1370 | |
1365 | if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
1371 | if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
1366 | 1372 | { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; |
1367 | 1373 | exit (1) ; |
1368 | 1374 | } ; |
1369 | 1375 | |
1370 | seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
1371 | k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
1376 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
1377 | k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
1372 | 1378 | test_readf_double_or_die (file, 0, data, 1, __LINE__) ; |
1373 | 1379 | if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos) |
1374 | 1380 | { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_double failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ; |
1375 | 1381 | exit (1) ; |
1376 | 1382 | } ; |
1377 | 1383 | |
1378 | seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; | |
1384 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; | |
1379 | 1385 | /* Check seek backward from current position. */ |
1380 | k = sf_seek (file, -20, SEEK_CUR) ; | |
1386 | k = (int) sf_seek (file, -20, SEEK_CUR) ; | |
1381 | 1387 | test_readf_double_or_die (file, 0, data, 1, __LINE__) ; |
1382 | 1388 | if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos) |
1383 | 1389 | { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_double failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ; |
1387 | 1393 | /* Check that read past end of file returns number of items. */ |
1388 | 1394 | sf_seek (file, sfinfo.frames, SEEK_SET) ; |
1389 | 1395 | |
1390 | if ((k = sf_readf_double (file, data, datalen)) != 0) | |
1396 | if ((k = (int) sf_readf_double (file, data, datalen)) != 0) | |
1391 | 1397 | { printf ("\n\nLine %d: Return value from sf_readf_double past end of file incorrect (%d).\n", __LINE__, k) ; |
1392 | 1398 | exit (1) ; |
1393 | 1399 | } ; |
1394 | 1400 | |
1395 | 1401 | /* Check seek backward from end. */ |
1396 | if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
1402 | if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
1397 | 1403 | { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; |
1398 | 1404 | exit (1) ; |
1399 | 1405 | } ; |
1423 | 1429 | short *orig, *data, *smooth ; |
1424 | 1430 | |
1425 | 1431 | channels = 1 ; |
1432 | ||
1433 | get_unique_test_name (&filename, LCT_TEST_PREFIX) ; | |
1426 | 1434 | print_test_name ("sdlcomp_test_short", filename) ; |
1427 | 1435 | |
1428 | 1436 | datalen = BUFFER_SIZE ; |
1431 | 1439 | data = data_buffer.s ; |
1432 | 1440 | smooth = smooth_buffer.s ; |
1433 | 1441 | |
1434 | gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ; | |
1442 | gen_signal_double (orig_buffer.d, 32000.0, channels, (int) datalen) ; | |
1435 | 1443 | for (k = 0 ; k < datalen ; k++) |
1436 | orig [k] = lrint (orig_buffer.d [k]) ; | |
1444 | orig [k] = (short) lrint (orig_buffer.d [k]) ; | |
1437 | 1445 | |
1438 | 1446 | sfinfo.samplerate = SAMPLE_RATE ; |
1439 | 1447 | sfinfo.frames = 123456789 ; /* Ridiculous value. */ |
1469 | 1477 | |
1470 | 1478 | if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_OPUS && !check_opus_version (file)) |
1471 | 1479 | { sf_close (file) ; |
1480 | unlink (filename) ; | |
1472 | 1481 | return ; |
1473 | 1482 | } ; |
1474 | 1483 | |
1512 | 1521 | test_readf_short_or_die (file, 0, data, datalen, __LINE__) ; |
1513 | 1522 | |
1514 | 1523 | memcpy (smooth, orig, datalen * sizeof (short)) ; |
1515 | smoothed_diff_short (data, datalen) ; | |
1516 | smoothed_diff_short (smooth, datalen) ; | |
1517 | ||
1518 | half_max_abs = 0.0 ; | |
1524 | smoothed_diff_short (data, (unsigned int) datalen) ; | |
1525 | smoothed_diff_short (smooth, (unsigned int) datalen) ; | |
1526 | ||
1527 | half_max_abs = 0 ; | |
1519 | 1528 | for (k = 0 ; k < datalen ; k++) |
1520 | 1529 | { if (error_function (1.0 * data [k], 1.0 * smooth [k], margin)) |
1521 | 1530 | { printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, data [k], smooth [k]) ; |
1522 | oct_save_short (orig, smooth, datalen) ; | |
1523 | exit (1) ; | |
1524 | } ; | |
1525 | half_max_abs = LCT_MAX (half_max_abs, ABS (0.5 * data [k])) ; | |
1531 | oct_save_short (orig, smooth, (int) datalen) ; | |
1532 | exit (1) ; | |
1533 | } ; | |
1534 | half_max_abs = (int) (LCT_MAX (half_max_abs, ABS (0.5 * data [k]))) ; | |
1526 | 1535 | } ; |
1527 | 1536 | |
1528 | 1537 | if (half_max_abs < 1) |
1530 | 1539 | exit (1) ; |
1531 | 1540 | } ; |
1532 | 1541 | |
1533 | if ((k = sf_read_short (file, data, datalen)) != sfinfo.frames - datalen) | |
1542 | if ((k = (int) sf_read_short (file, data, datalen)) != sfinfo.frames - datalen) | |
1534 | 1543 | { printf ("\n\nLine %d: Incorrect read length (%d should be %" PRId64 ").\n", __LINE__, k, sfinfo.frames - datalen) ; |
1535 | 1544 | exit (1) ; |
1536 | 1545 | } ; |
1545 | 1554 | |
1546 | 1555 | /* Now test sf_seek function. */ |
1547 | 1556 | if (sfinfo.seekable) |
1548 | { if ((k = sf_seek (file, 0, SEEK_SET)) != 0) | |
1557 | { if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) | |
1549 | 1558 | { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; |
1550 | 1559 | exit (1) ; |
1551 | 1560 | } ; |
1553 | 1562 | for (m = 0 ; m < 3 ; m++) |
1554 | 1563 | { test_readf_short_or_die (file, m, data, datalen / 7, __LINE__) ; |
1555 | 1564 | |
1556 | smoothed_diff_short (data, datalen / 7) ; | |
1565 | smoothed_diff_short (data, (unsigned int) (datalen / 7)) ; | |
1557 | 1566 | memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (short)) ; |
1558 | smoothed_diff_short (smooth, datalen / 7) ; | |
1567 | smoothed_diff_short (smooth, (unsigned int) (datalen / 7)) ; | |
1559 | 1568 | |
1560 | 1569 | for (k = 0 ; k < datalen / 7 ; k++) |
1561 | 1570 | if (error_function (1.0 * data [k], 1.0 * smooth [k], margin)) |
1570 | 1579 | seekpos = BUFFER_SIZE / 10 ; |
1571 | 1580 | |
1572 | 1581 | /* Check seek from start of file. */ |
1573 | if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
1582 | if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
1574 | 1583 | { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; |
1575 | 1584 | exit (1) ; |
1576 | 1585 | } ; |
1581 | 1590 | exit (1) ; |
1582 | 1591 | } ; |
1583 | 1592 | |
1584 | if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
1593 | if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
1585 | 1594 | { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; |
1586 | 1595 | exit (1) ; |
1587 | 1596 | } ; |
1588 | 1597 | |
1589 | seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
1590 | k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
1598 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
1599 | k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
1591 | 1600 | test_readf_short_or_die (file, 0, data, 1, __LINE__) ; |
1592 | 1601 | if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) |
1593 | 1602 | { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_read_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ; |
1594 | 1603 | exit (1) ; |
1595 | 1604 | } ; |
1596 | 1605 | |
1597 | seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; | |
1606 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; | |
1598 | 1607 | /* Check seek backward from current position. */ |
1599 | k = sf_seek (file, -20, SEEK_CUR) ; | |
1608 | k = (int) sf_seek (file, -20, SEEK_CUR) ; | |
1600 | 1609 | test_readf_short_or_die (file, 0, data, 1, __LINE__) ; |
1601 | 1610 | if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) |
1602 | 1611 | { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_read_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ; |
1606 | 1615 | /* Check that read past end of file returns number of items. */ |
1607 | 1616 | sf_seek (file, sfinfo.frames, SEEK_SET) ; |
1608 | 1617 | |
1609 | if ((k = sf_read_short (file, data, datalen)) != 0) | |
1618 | if ((k = (int) sf_read_short (file, data, datalen)) != 0) | |
1610 | 1619 | { printf ("\n\nLine %d: Return value from sf_read_short past end of file incorrect (%d).\n", __LINE__, k) ; |
1611 | 1620 | exit (1) ; |
1612 | 1621 | } ; |
1613 | 1622 | |
1614 | 1623 | /* Check seek backward from end. */ |
1615 | 1624 | |
1616 | if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
1625 | if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
1617 | 1626 | { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; |
1618 | 1627 | exit (1) ; |
1619 | 1628 | } ; |
1642 | 1651 | |
1643 | 1652 | channels = 1 ; |
1644 | 1653 | |
1654 | get_unique_test_name (&filename, LCT_TEST_PREFIX) ; | |
1645 | 1655 | print_test_name ("sdlcomp_test_int", filename) ; |
1646 | 1656 | |
1647 | 1657 | datalen = BUFFER_SIZE ; |
1651 | 1661 | data = data_buffer.i ; |
1652 | 1662 | smooth = smooth_buffer.i ; |
1653 | 1663 | |
1654 | gen_signal_double (orig_buffer.d, 32000.0 * scale, channels, datalen) ; | |
1664 | gen_signal_double (orig_buffer.d, 32000.0 * scale, channels, (int) datalen) ; | |
1655 | 1665 | for (k = 0 ; k < datalen ; k++) |
1656 | 1666 | orig [k] = lrint (orig_buffer.d [k]) ; |
1657 | 1667 | |
1689 | 1699 | |
1690 | 1700 | if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_OPUS && !check_opus_version (file)) |
1691 | 1701 | { sf_close (file) ; |
1702 | unlink (filename) ; | |
1692 | 1703 | return ; |
1693 | 1704 | } ; |
1694 | 1705 | |
1728 | 1739 | test_readf_int_or_die (file, 0, data, datalen, __LINE__) ; |
1729 | 1740 | |
1730 | 1741 | memcpy (smooth, orig, datalen * sizeof (int)) ; |
1731 | smoothed_diff_int (data, datalen) ; | |
1732 | smoothed_diff_int (smooth, datalen) ; | |
1742 | smoothed_diff_int (data, (unsigned int) datalen) ; | |
1743 | smoothed_diff_int (smooth, (unsigned int) datalen) ; | |
1733 | 1744 | |
1734 | 1745 | half_max_abs = abs (data [0] >> 16) ; |
1735 | 1746 | for (k = 1 ; k < datalen ; k++) |
1736 | 1747 | { if (error_function (data [k] / scale, smooth [k] / scale, margin)) |
1737 | 1748 | { printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, data [k], smooth [k]) ; |
1738 | oct_save_int (orig, smooth, datalen) ; | |
1749 | oct_save_int (orig, smooth, (int) datalen) ; | |
1739 | 1750 | exit (1) ; |
1740 | 1751 | } ; |
1741 | 1752 | half_max_abs = LCT_MAX (half_max_abs, abs (data [k] / 2)) ; |
1746 | 1757 | exit (1) ; |
1747 | 1758 | } ; |
1748 | 1759 | |
1749 | if ((k = sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen) | |
1760 | if ((k = (int) sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen) | |
1750 | 1761 | { printf ("\n\nLine %d: Incorrect read length (%d should be %" PRId64 ").\n", __LINE__, k, sfinfo.frames - datalen) ; |
1751 | 1762 | exit (1) ; |
1752 | 1763 | } ; |
1767 | 1778 | |
1768 | 1779 | /* Now test sf_seek function. */ |
1769 | 1780 | if (sfinfo.seekable) |
1770 | { if ((k = sf_seek (file, 0, SEEK_SET)) != 0) | |
1781 | { if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) | |
1771 | 1782 | { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; |
1772 | 1783 | exit (1) ; |
1773 | 1784 | } ; |
1775 | 1786 | for (m = 0 ; m < 3 ; m++) |
1776 | 1787 | { test_readf_int_or_die (file, m, data, datalen / 7, __LINE__) ; |
1777 | 1788 | |
1778 | smoothed_diff_int (data, datalen / 7) ; | |
1789 | smoothed_diff_int (data, (unsigned int) (datalen / 7)) ; | |
1779 | 1790 | memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (int)) ; |
1780 | smoothed_diff_int (smooth, datalen / 7) ; | |
1791 | smoothed_diff_int (smooth, (unsigned int) (datalen / 7)) ; | |
1781 | 1792 | |
1782 | 1793 | for (k = 0 ; k < datalen / 7 ; k++) |
1783 | 1794 | if (error_function (data [k] / scale, smooth [k] / scale, margin)) |
1792 | 1803 | seekpos = BUFFER_SIZE / 10 ; |
1793 | 1804 | |
1794 | 1805 | /* Check seek from start of file. */ |
1795 | if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
1806 | if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
1796 | 1807 | { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; |
1797 | 1808 | exit (1) ; |
1798 | 1809 | } ; |
1803 | 1814 | exit (1) ; |
1804 | 1815 | } ; |
1805 | 1816 | |
1806 | if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
1817 | if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
1807 | 1818 | { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; |
1808 | 1819 | exit (1) ; |
1809 | 1820 | } ; |
1810 | 1821 | |
1811 | seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
1812 | k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
1822 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
1823 | k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
1813 | 1824 | test_readf_int_or_die (file, 0, data, 1, __LINE__) ; |
1814 | 1825 | if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) |
1815 | 1826 | { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ; |
1816 | 1827 | exit (1) ; |
1817 | 1828 | } ; |
1818 | 1829 | |
1819 | seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; | |
1830 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; | |
1820 | 1831 | /* Check seek backward from current position. */ |
1821 | k = sf_seek (file, -20, SEEK_CUR) ; | |
1832 | k = (int) sf_seek (file, -20, SEEK_CUR) ; | |
1822 | 1833 | test_readf_int_or_die (file, 0, data, 1, __LINE__) ; |
1823 | 1834 | if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos) |
1824 | 1835 | { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ; |
1828 | 1839 | /* Check that read past end of file returns number of items. */ |
1829 | 1840 | sf_seek (file, sfinfo.frames, SEEK_SET) ; |
1830 | 1841 | |
1831 | if ((k = sf_readf_int (file, data, datalen)) != 0) | |
1842 | if ((k = (int) sf_readf_int (file, data, datalen)) != 0) | |
1832 | 1843 | { printf ("\n\nLine %d: Return value from sf_readf_int past end of file incorrect (%d).\n", __LINE__, k) ; |
1833 | 1844 | exit (1) ; |
1834 | 1845 | } ; |
1835 | 1846 | |
1836 | 1847 | /* Check seek backward from end. */ |
1837 | 1848 | |
1838 | if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
1849 | if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
1839 | 1850 | { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; |
1840 | 1851 | exit (1) ; |
1841 | 1852 | } ; |
1864 | 1875 | |
1865 | 1876 | channels = 1 ; |
1866 | 1877 | |
1878 | get_unique_test_name (&filename, LCT_TEST_PREFIX) ; | |
1867 | 1879 | print_test_name ("sdlcomp_test_float", filename) ; |
1868 | 1880 | |
1869 | 1881 | switch ((filetype & SF_FORMAT_SUBMASK)) |
1895 | 1907 | data = data_buffer.f ; |
1896 | 1908 | smooth = smooth_buffer.f ; |
1897 | 1909 | |
1898 | gen_signal_double (orig_buffer.d, 32000.0 / scale, channels, datalen) ; | |
1910 | gen_signal_double (orig_buffer.d, 32000.0 / scale, channels, (int) datalen) ; | |
1899 | 1911 | for (k = 0 ; k < datalen ; k++) |
1900 | orig [k] = orig_buffer.d [k] ; | |
1912 | orig [k] = (float) orig_buffer.d [k] ; | |
1901 | 1913 | |
1902 | 1914 | sfinfo.samplerate = SAMPLE_RATE ; |
1903 | 1915 | sfinfo.frames = 123456789 ; /* Ridiculous value. */ |
1934 | 1946 | |
1935 | 1947 | if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_OPUS && !check_opus_version (file)) |
1936 | 1948 | { sf_close (file) ; |
1949 | unlink (filename) ; | |
1937 | 1950 | return ; |
1938 | 1951 | } ; |
1939 | 1952 | |
1978 | 1991 | test_read_float_or_die (file, 0, data, datalen, __LINE__) ; |
1979 | 1992 | |
1980 | 1993 | memcpy (smooth, orig, datalen * sizeof (float)) ; |
1981 | smoothed_diff_float (data, datalen) ; | |
1982 | smoothed_diff_float (smooth, datalen) ; | |
1994 | smoothed_diff_float (data, (unsigned int) datalen) ; | |
1995 | smoothed_diff_float (smooth, (unsigned int) datalen) ; | |
1983 | 1996 | |
1984 | 1997 | half_max_abs = fabs (data [0]) ; |
1985 | 1998 | for (k = 1 ; k < datalen ; k++) |
1986 | 1999 | { if (error_function (data [k] * scale, smooth [k] * scale, margin)) |
1987 | 2000 | { printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, (int) (data [k] * scale), (int) (smooth [k] * scale)) ; |
1988 | oct_save_float (orig, smooth, datalen) ; | |
2001 | oct_save_float (orig, smooth, (int) datalen) ; | |
1989 | 2002 | exit (1) ; |
1990 | 2003 | } ; |
1991 | 2004 | half_max_abs = LCT_MAX (half_max_abs, ABS (0.5 * data [k] * scale)) ; |
1997 | 2010 | exit (1) ; |
1998 | 2011 | } ; |
1999 | 2012 | |
2000 | if ((k = sf_read_float (file, data, datalen)) != sfinfo.frames - datalen) | |
2013 | if ((k = (int) sf_read_float (file, data, datalen)) != sfinfo.frames - datalen) | |
2001 | 2014 | { printf ("\n\nLine %d: Incorrect read length (%d should be %" PRId64 ").\n", __LINE__, k, sfinfo.frames - datalen) ; |
2002 | 2015 | exit (1) ; |
2003 | 2016 | } ; |
2012 | 2025 | |
2013 | 2026 | /* Now test sf_seek function. */ |
2014 | 2027 | if (sfinfo.seekable) |
2015 | { if ((k = sf_seek (file, 0, SEEK_SET)) != 0) | |
2028 | { if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) | |
2016 | 2029 | { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; |
2017 | 2030 | exit (1) ; |
2018 | 2031 | } ; |
2020 | 2033 | for (m = 0 ; m < 3 ; m++) |
2021 | 2034 | { test_read_float_or_die (file, 0, data, datalen / 7, __LINE__) ; |
2022 | 2035 | |
2023 | smoothed_diff_float (data, datalen / 7) ; | |
2036 | smoothed_diff_float (data, (unsigned int) (datalen / 7)) ; | |
2024 | 2037 | memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (float)) ; |
2025 | smoothed_diff_float (smooth, datalen / 7) ; | |
2038 | smoothed_diff_float (smooth, (unsigned int) (datalen / 7)) ; | |
2026 | 2039 | |
2027 | 2040 | for (k = 0 ; k < datalen / 7 ; k++) |
2028 | 2041 | if (error_function (data [k] * scale, smooth [k] * scale, margin)) |
2037 | 2050 | seekpos = BUFFER_SIZE / 10 ; |
2038 | 2051 | |
2039 | 2052 | /* Check seek from start of file. */ |
2040 | if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
2053 | if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
2041 | 2054 | { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; |
2042 | 2055 | exit (1) ; |
2043 | 2056 | } ; |
2048 | 2061 | exit (1) ; |
2049 | 2062 | } ; |
2050 | 2063 | |
2051 | if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
2064 | if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
2052 | 2065 | { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; |
2053 | 2066 | exit (1) ; |
2054 | 2067 | } ; |
2055 | 2068 | |
2056 | seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
2057 | k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
2069 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
2070 | k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
2058 | 2071 | test_read_float_or_die (file, 0, data, channels, __LINE__) ; |
2059 | 2072 | if (error_function (data [0] * scale, orig [seekpos * channels] * scale, margin) || k != seekpos) |
2060 | 2073 | { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_read_float failed (%d, %d) (%d, %d).\n", __LINE__, (int) (data [0] * scale), (int) (orig [seekpos * channels] * scale), k, seekpos + 1) ; |
2061 | 2074 | exit (1) ; |
2062 | 2075 | } ; |
2063 | 2076 | |
2064 | seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; | |
2077 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; | |
2065 | 2078 | /* Check seek backward from current position. */ |
2066 | k = sf_seek (file, -20, SEEK_CUR) ; | |
2079 | k = (int) sf_seek (file, -20, SEEK_CUR) ; | |
2067 | 2080 | test_read_float_or_die (file, 0, data, channels, __LINE__) ; |
2068 | 2081 | if (error_function (data [0] * scale, orig [seekpos * channels] * scale, margin) || k != seekpos) |
2069 | 2082 | { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_read_float failed (%d, %d) (%d, %d).\n", __LINE__, (int) (data [0] * scale), (int) (orig [seekpos * channels] * scale), k, seekpos) ; |
2073 | 2086 | /* Check that read past end of file returns number of items. */ |
2074 | 2087 | sf_seek (file, sfinfo.frames, SEEK_SET) ; |
2075 | 2088 | |
2076 | if ((k = sf_read_float (file, data, datalen)) != 0) | |
2089 | if ((k = (int) sf_read_float (file, data, datalen)) != 0) | |
2077 | 2090 | { printf ("\n\nLine %d: Return value from sf_read_float past end of file incorrect (%d).\n", __LINE__, k) ; |
2078 | 2091 | exit (1) ; |
2079 | 2092 | } ; |
2080 | 2093 | |
2081 | 2094 | /* Check seek backward from end. */ |
2082 | 2095 | |
2083 | if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
2096 | if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
2084 | 2097 | { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; |
2085 | 2098 | exit (1) ; |
2086 | 2099 | } ; |
2107 | 2120 | double *orig, *data, *smooth, half_max_abs, scale ; |
2108 | 2121 | |
2109 | 2122 | channels = 1 ; |
2123 | ||
2124 | get_unique_test_name (&filename, LCT_TEST_PREFIX) ; | |
2110 | 2125 | print_test_name ("sdlcomp_test_double", filename) ; |
2111 | 2126 | |
2112 | 2127 | switch ((filetype & SF_FORMAT_SUBMASK)) |
2138 | 2153 | data = data_buffer.d ; |
2139 | 2154 | smooth = smooth_buffer.d ; |
2140 | 2155 | |
2141 | gen_signal_double (orig_buffer.d, 32000.0 / scale, channels, datalen) ; | |
2156 | gen_signal_double (orig_buffer.d, 32000.0 / scale, channels, (int) datalen) ; | |
2142 | 2157 | |
2143 | 2158 | sfinfo.samplerate = SAMPLE_RATE ; |
2144 | 2159 | sfinfo.frames = 123456789 ; /* Ridiculous value. */ |
2174 | 2189 | |
2175 | 2190 | if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_OPUS && !check_opus_version (file)) |
2176 | 2191 | { sf_close (file) ; |
2192 | unlink (filename) ; | |
2177 | 2193 | return ; |
2178 | 2194 | } ; |
2179 | 2195 | |
2220 | 2236 | test_read_double_or_die (file, 0, data, datalen, __LINE__) ; |
2221 | 2237 | |
2222 | 2238 | memcpy (smooth, orig, datalen * sizeof (double)) ; |
2223 | smoothed_diff_double (data, datalen) ; | |
2224 | smoothed_diff_double (smooth, datalen) ; | |
2239 | smoothed_diff_double (data, (unsigned int) datalen) ; | |
2240 | smoothed_diff_double (smooth, (unsigned int) datalen) ; | |
2225 | 2241 | |
2226 | 2242 | half_max_abs = 0.0 ; |
2227 | 2243 | for (k = 0 ; k < datalen ; k++) |
2228 | 2244 | { if (error_function (data [k] * scale, smooth [k] * scale, margin)) |
2229 | 2245 | { printf ("\n\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, (int) (data [k] * scale), (int) (smooth [k] * scale)) ; |
2230 | oct_save_double (orig, smooth, datalen) ; | |
2246 | oct_save_double (orig, smooth, (int) datalen) ; | |
2231 | 2247 | exit (1) ; |
2232 | 2248 | } ; |
2233 | 2249 | half_max_abs = LCT_MAX (half_max_abs, 0.5 * fabs (data [k] * scale)) ; |
2238 | 2254 | exit (1) ; |
2239 | 2255 | } ; |
2240 | 2256 | |
2241 | if ((k = sf_read_double (file, data, datalen)) != sfinfo.frames - datalen) | |
2257 | if ((k = (int) sf_read_double (file, data, datalen)) != sfinfo.frames - datalen) | |
2242 | 2258 | { printf ("\n\nLine %d: Incorrect read length (%d should be %" PRId64 ").\n", __LINE__, k, sfinfo.frames - datalen) ; |
2243 | 2259 | exit (1) ; |
2244 | 2260 | } ; |
2253 | 2269 | |
2254 | 2270 | /* Now test sf_seek function. */ |
2255 | 2271 | if (sfinfo.seekable) |
2256 | { if ((k = sf_seek (file, 0, SEEK_SET)) != 0) | |
2272 | { if ((k = (int) sf_seek (file, 0, SEEK_SET)) != 0) | |
2257 | 2273 | { printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ; |
2258 | 2274 | exit (1) ; |
2259 | 2275 | } ; |
2261 | 2277 | for (m = 0 ; m < 3 ; m++) |
2262 | 2278 | { test_read_double_or_die (file, m, data, datalen / 7, __LINE__) ; |
2263 | 2279 | |
2264 | smoothed_diff_double (data, datalen / 7) ; | |
2280 | smoothed_diff_double (data, (unsigned int) (datalen / 7)) ; | |
2265 | 2281 | memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (double)) ; |
2266 | smoothed_diff_double (smooth, datalen / 7) ; | |
2282 | smoothed_diff_double (smooth, (unsigned int) (datalen / 7)) ; | |
2267 | 2283 | |
2268 | 2284 | for (k = 0 ; k < datalen / 7 ; k++) |
2269 | 2285 | if (error_function (data [k] * scale, smooth [k] * scale, margin)) |
2278 | 2294 | seekpos = BUFFER_SIZE / 10 ; |
2279 | 2295 | |
2280 | 2296 | /* Check seek from start of file. */ |
2281 | if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
2297 | if ((k = (int) sf_seek (file, seekpos, SEEK_SET)) != seekpos) | |
2282 | 2298 | { printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ; |
2283 | 2299 | exit (1) ; |
2284 | 2300 | } ; |
2289 | 2305 | exit (1) ; |
2290 | 2306 | } ; |
2291 | 2307 | |
2292 | if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
2308 | if ((k = (int) sf_seek (file, 0, SEEK_CUR)) != seekpos + 1) | |
2293 | 2309 | { printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ; |
2294 | 2310 | exit (1) ; |
2295 | 2311 | } ; |
2296 | 2312 | |
2297 | seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
2298 | k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
2313 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ; | |
2314 | k = (int) sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ; | |
2299 | 2315 | test_read_double_or_die (file, 0, data, channels, __LINE__) ; |
2300 | 2316 | if (error_function (data [0] * scale, orig [seekpos * channels] * scale, margin) || k != seekpos) |
2301 | 2317 | { printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_read_double failed (%d, %d) (%d, %d).\n", __LINE__, (int) (data [0] * scale), (int) (orig [seekpos * channels] * scale), k, seekpos + 1) ; |
2302 | 2318 | exit (1) ; |
2303 | 2319 | } ; |
2304 | 2320 | |
2305 | seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ; | |
2321 | seekpos = (int) sf_seek (file, 0, SEEK_CUR) - 20 ; | |
2306 | 2322 | /* Check seek backward from current position. */ |
2307 | k = sf_seek (file, -20, SEEK_CUR) ; | |
2323 | k = (int) sf_seek (file, -20, SEEK_CUR) ; | |
2308 | 2324 | test_read_double_or_die (file, 0, data, channels, __LINE__) ; |
2309 | 2325 | if (error_function (data [0] * scale, orig [seekpos * channels] * scale, margin) || k != seekpos) |
2310 | 2326 | { printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_read_double failed (%d, %d) (%d, %d).\n", __LINE__, (int) (data [0] * scale), (int) (orig [seekpos * channels] * scale), k, seekpos) ; |
2314 | 2330 | /* Check that read past end of file returns number of items. */ |
2315 | 2331 | sf_seek (file, sfinfo.frames, SEEK_SET) ; |
2316 | 2332 | |
2317 | if ((k = sf_read_double (file, data, datalen)) != 0) | |
2333 | if ((k = (int) sf_read_double (file, data, datalen)) != 0) | |
2318 | 2334 | { printf ("\n\nLine %d: Return value from sf_read_double past end of file incorrect (%d).\n", __LINE__, k) ; |
2319 | 2335 | exit (1) ; |
2320 | 2336 | } ; |
2321 | 2337 | |
2322 | 2338 | /* Check seek backward from end. */ |
2323 | 2339 | |
2324 | if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
2340 | if ((k = (int) sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5) | |
2325 | 2341 | { printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ; |
2326 | 2342 | exit (1) ; |
2327 | 2343 | } ; |
2347 | 2363 | short *orig, *data ; |
2348 | 2364 | int k ; |
2349 | 2365 | |
2366 | get_unique_test_name (&filename, LCT_TEST_PREFIX) ; | |
2350 | 2367 | print_test_name ("read_raw_test", filename) ; |
2351 | 2368 | |
2352 | 2369 | datalen = ARRAY_LEN (orig_buffer.s) / 2 ; |
2354 | 2371 | orig = orig_buffer.s ; |
2355 | 2372 | data = data_buffer.s ; |
2356 | 2373 | |
2357 | gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ; | |
2374 | gen_signal_double (orig_buffer.d, 32000.0, channels, (int) datalen) ; | |
2358 | 2375 | for (k = 0 ; k < datalen ; k++) |
2359 | orig [k] = lrint (orig_buffer.d [k]) ; | |
2376 | orig [k] = (short) lrint (orig_buffer.d [k]) ; | |
2360 | 2377 | |
2361 | 2378 | sfinfo.samplerate = SAMPLE_RATE ; |
2362 | 2379 | sfinfo.frames = 123456789 ; /* Ridiculous value. */ |
2515 | 2532 | |
2516 | 2533 | /* Calculate the smoothed sample-to-sample difference. */ |
2517 | 2534 | for (k = 0 ; k < datalen - 1 ; k++) |
2518 | { memory = 0.7 * memory + (1 - 0.7) * (data [k+1] - data [k]) ; | |
2535 | { memory = (float) (0.7 * memory + (1 - 0.7) * (data [k+1] - data [k])) ; | |
2519 | 2536 | data [k] = memory ; |
2520 | 2537 | } ; |
2521 | 2538 | data [datalen-1] = data [datalen-2] ; |
0 | /* | |
1 | ** Copyright (C) 2007-2019 Erik de Castro Lopo <erikd@mega-nerd.com> | |
2 | ** Copyright (C) 2019 John ffitch <jpff@codemist.co.uk> | |
3 | ** | |
4 | ** This program is free software; you can redistribute it and/or modify | |
5 | ** it under the terms of the GNU General Public License as published by | |
6 | ** the Free Software Foundation; either version 2 of the License, or | |
7 | ** (at your option) any later version. | |
8 | ** | |
9 | ** This program is distributed in the hope that it will be useful, | |
10 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | ** GNU General Public License for more details. | |
13 | ** | |
14 | ** You should have received a copy of the GNU General Public License | |
15 | ** along with this program; if not, write to the Free Software | |
16 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
17 | */ | |
18 | ||
19 | #include "sfconfig.h" | |
20 | ||
21 | #include <stdio.h> | |
22 | #include <stdlib.h> | |
23 | #include <string.h> | |
24 | #if HAVE_UNISTD_H | |
25 | #include <unistd.h> | |
26 | #else | |
27 | #include "sf_unistd.h" | |
28 | #endif | |
29 | ||
30 | #include <math.h> | |
31 | ||
32 | #include <sndfile.h> | |
33 | ||
34 | #include "utils.h" | |
35 | ||
36 | #define SAMPLE_RATE 44100 | |
37 | #define DATA_LENGTH (SAMPLE_RATE / 8) | |
38 | ||
39 | typedef union | |
40 | { double d [DATA_LENGTH] ; | |
41 | float f [DATA_LENGTH] ; | |
42 | int i [DATA_LENGTH] ; | |
43 | short s [DATA_LENGTH] ; | |
44 | } BUFFER ; | |
45 | ||
46 | static BUFFER data_out ; | |
47 | static BUFFER data_in ; | |
48 | ||
49 | static void | |
50 | mpeg_short_test (void) | |
51 | { const char * filename = "mpeg_short.mp3" ; | |
52 | ||
53 | SNDFILE * file ; | |
54 | SF_INFO sfinfo ; | |
55 | short seek_data [10] ; | |
56 | unsigned k ; | |
57 | ||
58 | print_test_name ("mpeg_short_test", filename) ; | |
59 | ||
60 | /* Generate float data. */ | |
61 | gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 1.0 * 0x7F00) ; | |
62 | ||
63 | /* Convert to shorteger. */ | |
64 | for (k = 0 ; k < ARRAY_LEN (data_out.s) ; k++) | |
65 | data_out.s [k] = lrintf (data_out.f [k]) ; | |
66 | ||
67 | memset (&sfinfo, 0, sizeof (sfinfo)) ; | |
68 | ||
69 | /* Set up output file type. */ | |
70 | sfinfo.format = SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III ; | |
71 | sfinfo.channels = 1 ; | |
72 | sfinfo.samplerate = SAMPLE_RATE ; | |
73 | ||
74 | /* Write the output file. */ | |
75 | file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; | |
76 | test_write_short_or_die (file, 0, data_out.s, ARRAY_LEN (data_out.s), __LINE__) ; | |
77 | sf_close (file) ; | |
78 | ||
79 | /* Read the file in again. */ | |
80 | memset (&sfinfo, 0, sizeof (sfinfo)) ; | |
81 | ||
82 | file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; | |
83 | test_read_short_or_die (file, 0, data_in.s, ARRAY_LEN (data_in.s), __LINE__) ; | |
84 | sf_close (file) ; | |
85 | ||
86 | puts ("ok") ; | |
87 | ||
88 | /* Test seeking. */ | |
89 | print_test_name ("mpeg_seek_test", filename) ; | |
90 | ||
91 | file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; | |
92 | ||
93 | test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ; | |
94 | test_read_short_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ; | |
95 | compare_short_or_die (seek_data, data_in.s + 10, ARRAY_LEN (seek_data), __LINE__) ; | |
96 | ||
97 | /* Test seek to end of file. */ | |
98 | test_seek_or_die (file, 0, SEEK_END, sfinfo.frames, sfinfo.channels, __LINE__) ; | |
99 | ||
100 | sf_close (file) ; | |
101 | ||
102 | puts ("ok") ; | |
103 | ||
104 | unlink (filename) ; | |
105 | } /* mpeg_short_test */ | |
106 | ||
107 | static void | |
108 | mpeg_int_test (void) | |
109 | { const char * filename = "mpeg_int.mp3" ; | |
110 | ||
111 | SNDFILE * file ; | |
112 | SF_INFO sfinfo ; | |
113 | int seek_data [10] ; | |
114 | unsigned k ; | |
115 | ||
116 | print_test_name ("mpeg_int_test", filename) ; | |
117 | ||
118 | /* Generate float data. */ | |
119 | gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 1.0 * 0x7FFF0000) ; | |
120 | ||
121 | /* Convert to integer. */ | |
122 | for (k = 0 ; k < ARRAY_LEN (data_out.i) ; k++) | |
123 | data_out.i [k] = lrintf (data_out.f [k]) ; | |
124 | ||
125 | memset (&sfinfo, 0, sizeof (sfinfo)) ; | |
126 | ||
127 | /* Set up output file type. */ | |
128 | sfinfo.format = SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III ; | |
129 | sfinfo.channels = 1 ; | |
130 | sfinfo.samplerate = SAMPLE_RATE ; | |
131 | ||
132 | /* Write the output file. */ | |
133 | file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; | |
134 | test_write_int_or_die (file, 0, data_out.i, ARRAY_LEN (data_out.i), __LINE__) ; | |
135 | sf_close (file) ; | |
136 | ||
137 | /* Read the file in again. */ | |
138 | memset (&sfinfo, 0, sizeof (sfinfo)) ; | |
139 | ||
140 | file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; | |
141 | test_read_int_or_die (file, 0, data_in.i, ARRAY_LEN (data_in.i), __LINE__) ; | |
142 | sf_close (file) ; | |
143 | ||
144 | puts ("ok") ; | |
145 | ||
146 | /* Test seeking. */ | |
147 | print_test_name ("mpeg_seek_test", filename) ; | |
148 | ||
149 | file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; | |
150 | ||
151 | test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ; | |
152 | test_read_int_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ; | |
153 | compare_int_or_die (seek_data, data_in.i + 10, ARRAY_LEN (seek_data), __LINE__) ; | |
154 | ||
155 | sf_close (file) ; | |
156 | ||
157 | puts ("ok") ; | |
158 | ||
159 | unlink (filename) ; | |
160 | } /* mpeg_int_test */ | |
161 | ||
162 | static void | |
163 | mpeg_float_test (void) | |
164 | { const char * filename = "mpeg_float.mp3" ; | |
165 | ||
166 | SNDFILE * file ; | |
167 | SF_INFO sfinfo ; | |
168 | float seek_data [10] ; | |
169 | ||
170 | print_test_name ("mpeg_float_test", filename) ; | |
171 | ||
172 | gen_windowed_sine_float (data_out.f, ARRAY_LEN (data_out.f), 0.95) ; | |
173 | ||
174 | memset (&sfinfo, 0, sizeof (sfinfo)) ; | |
175 | ||
176 | /* Set up output file type. */ | |
177 | sfinfo.format = SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III ; | |
178 | sfinfo.channels = 1 ; | |
179 | sfinfo.samplerate = SAMPLE_RATE ; | |
180 | ||
181 | /* Write the output file. */ | |
182 | file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; | |
183 | test_write_float_or_die (file, 0, data_out.f, ARRAY_LEN (data_out.f), __LINE__) ; | |
184 | sf_close (file) ; | |
185 | ||
186 | /* Read the file in again. */ | |
187 | memset (&sfinfo, 0, sizeof (sfinfo)) ; | |
188 | ||
189 | file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; | |
190 | test_read_float_or_die (file, 0, data_in.f, ARRAY_LEN (data_in.f), __LINE__) ; | |
191 | sf_close (file) ; | |
192 | ||
193 | puts ("ok") ; | |
194 | ||
195 | /* Test seeking. */ | |
196 | print_test_name ("mpeg_seek_test", filename) ; | |
197 | ||
198 | file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; | |
199 | ||
200 | test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ; | |
201 | test_read_float_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ; | |
202 | compare_float_or_die (seek_data, data_in.f + 10, ARRAY_LEN (seek_data), __LINE__) ; | |
203 | ||
204 | sf_close (file) ; | |
205 | ||
206 | puts ("ok") ; | |
207 | ||
208 | unlink (filename) ; | |
209 | } /* mpeg_float_test */ | |
210 | ||
211 | static void | |
212 | mpeg_double_test (void) | |
213 | { const char * filename = "mpeg_double.mp3" ; | |
214 | ||
215 | SNDFILE * file ; | |
216 | SF_INFO sfinfo ; | |
217 | double seek_data [10] ; | |
218 | ||
219 | print_test_name ("mpeg_double_test", filename) ; | |
220 | ||
221 | gen_windowed_sine_double (data_out.d, ARRAY_LEN (data_out.d), 0.95) ; | |
222 | ||
223 | memset (&sfinfo, 0, sizeof (sfinfo)) ; | |
224 | ||
225 | /* Set up output file type. */ | |
226 | sfinfo.format = SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III ; | |
227 | sfinfo.channels = 1 ; | |
228 | sfinfo.samplerate = SAMPLE_RATE ; | |
229 | ||
230 | /* Write the output file. */ | |
231 | file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; | |
232 | test_write_double_or_die (file, 0, data_out.d, ARRAY_LEN (data_out.d), __LINE__) ; | |
233 | sf_close (file) ; | |
234 | ||
235 | /* Read the file in again. */ | |
236 | memset (&sfinfo, 0, sizeof (sfinfo)) ; | |
237 | ||
238 | file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; | |
239 | test_read_double_or_die (file, 0, data_in.d, ARRAY_LEN (data_in.d), __LINE__) ; | |
240 | sf_close (file) ; | |
241 | ||
242 | puts ("ok") ; | |
243 | ||
244 | /* Test seeking. */ | |
245 | print_test_name ("mpeg_seek_test", filename) ; | |
246 | ||
247 | file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; | |
248 | ||
249 | test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ; | |
250 | test_read_double_or_die (file, 0, seek_data, ARRAY_LEN (seek_data), __LINE__) ; | |
251 | compare_double_or_die (seek_data, data_in.d + 10, ARRAY_LEN (seek_data), __LINE__) ; | |
252 | ||
253 | sf_close (file) ; | |
254 | ||
255 | puts ("ok") ; | |
256 | ||
257 | unlink (filename) ; | |
258 | } /* mpeg_double_test */ | |
259 | ||
260 | ||
261 | static void | |
262 | mpeg_stereo_seek_test (const char * filename, int format) | |
263 | { static float data [SAMPLE_RATE] ; | |
264 | static float stereo_out [SAMPLE_RATE * 2] ; | |
265 | ||
266 | SNDFILE * file ; | |
267 | SF_INFO sfinfo ; | |
268 | sf_count_t pos ; | |
269 | unsigned k ; | |
270 | ||
271 | print_test_name (__func__, filename) ; | |
272 | ||
273 | gen_windowed_sine_float (data, ARRAY_LEN (data), 0.95) ; | |
274 | for (k = 0 ; k < ARRAY_LEN (data) ; k++) | |
275 | { stereo_out [2 * k] = data [k] ; | |
276 | stereo_out [2 * k + 1] = data [ARRAY_LEN (data) - k - 1] ; | |
277 | } ; | |
278 | ||
279 | memset (&sfinfo, 0, sizeof (sfinfo)) ; | |
280 | ||
281 | /* Set up output file type. */ | |
282 | sfinfo.format = format ; | |
283 | sfinfo.channels = 2 ; | |
284 | sfinfo.samplerate = SAMPLE_RATE ; | |
285 | ||
286 | /* Write the output file. */ | |
287 | file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; | |
288 | test_write_float_or_die (file, 0, stereo_out, ARRAY_LEN (stereo_out), __LINE__) ; | |
289 | sf_close (file) ; | |
290 | ||
291 | /* Open file in again for reading. */ | |
292 | memset (&sfinfo, 0, sizeof (sfinfo)) ; | |
293 | file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; | |
294 | ||
295 | /* Read in the whole file. */ | |
296 | test_read_float_or_die (file, 0, stereo_out, ARRAY_LEN (stereo_out), __LINE__) ; | |
297 | ||
298 | /* Now hammer seeking code. */ | |
299 | test_seek_or_die (file, 234, SEEK_SET, 234, sfinfo.channels, __LINE__) ; | |
300 | test_readf_float_or_die (file, 0, data, 10, __LINE__) ; | |
301 | compare_float_or_die (data, stereo_out + (234 * sfinfo.channels), 10, __LINE__) ; | |
302 | ||
303 | test_seek_or_die (file, 442, SEEK_SET, 442, sfinfo.channels, __LINE__) ; | |
304 | test_readf_float_or_die (file, 0, data, 10, __LINE__) ; | |
305 | compare_float_or_die (data, stereo_out + (442 * sfinfo.channels), 10, __LINE__) ; | |
306 | ||
307 | test_seek_or_die (file, 12, SEEK_CUR, 442 + 10 + 12, sfinfo.channels, __LINE__) ; | |
308 | test_readf_float_or_die (file, 0, data, 10, __LINE__) ; | |
309 | compare_float_or_die (data, stereo_out + ((442 + 10 + 12) * sfinfo.channels), 10, __LINE__) ; | |
310 | ||
311 | test_seek_or_die (file, 12, SEEK_CUR, 442 + 20 + 24, sfinfo.channels, __LINE__) ; | |
312 | test_readf_float_or_die (file, 0, data, 10, __LINE__) ; | |
313 | compare_float_or_die (data, stereo_out + ((442 + 20 + 24) * sfinfo.channels), 10, __LINE__) ; | |
314 | ||
315 | pos = 500 - sfinfo.frames ; | |
316 | test_seek_or_die (file, pos, SEEK_END, 500, sfinfo.channels, __LINE__) ; | |
317 | test_readf_float_or_die (file, 0, data, 10, __LINE__) ; | |
318 | compare_float_or_die (data, stereo_out + (500 * sfinfo.channels), 10, __LINE__) ; | |
319 | ||
320 | pos = 10 - sfinfo.frames ; | |
321 | test_seek_or_die (file, pos, SEEK_END, 10, sfinfo.channels, __LINE__) ; | |
322 | test_readf_float_or_die (file, 0, data, 10, __LINE__) ; | |
323 | compare_float_or_die (data, stereo_out + (10 * sfinfo.channels), 10, __LINE__) ; | |
324 | ||
325 | sf_close (file) ; | |
326 | ||
327 | puts ("ok") ; | |
328 | unlink (filename) ; | |
329 | } /* mpeg_stereo_seek_test */ | |
330 | ||
331 | ||
332 | int | |
333 | main (void) | |
334 | { | |
335 | if (HAVE_MPEG) | |
336 | { mpeg_short_test () ; | |
337 | mpeg_int_test () ; | |
338 | mpeg_float_test () ; | |
339 | mpeg_double_test () ; | |
340 | ||
341 | mpeg_stereo_seek_test ("mpeg_seek.mp3", SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III) ; | |
342 | } | |
343 | else | |
344 | puts (" No MPEG tests because mpg123/lame support was not compiled in.") ; | |
345 | return 0 ; | |
346 | } /* main */ | |
347 |
160 | 160 | printf ("This offset : %" PRId64 "\n", embed_info.offset + embed_info.length) ; |
161 | 161 | } ; |
162 | 162 | |
163 | if (lseek (fd, embed_info.offset + embed_info.length, SEEK_SET) < 0) | |
163 | if (lseek (fd, (long) (embed_info.offset + embed_info.length), SEEK_SET) < 0) | |
164 | 164 | { printf ("\n\nLine %d: lseek failed : %s\n", __LINE__, strerror (errno)) ; |
165 | 165 | exit (1) ; |
166 | 166 | } ; |
61 | 61 | |
62 | 62 | /* Convert to short. */ |
63 | 63 | for (k = 0 ; k < ARRAY_LEN (data_out.s) ; k++) |
64 | data_out.s [k] = lrintf (data_out.f [k]) ; | |
64 | data_out.s [k] = (short) lrintf (data_out.f [k]) ; | |
65 | 65 | |
66 | 66 | memset (&sfinfo, 0, sizeof (sfinfo)) ; |
67 | 67 |
61 | 61 | |
62 | 62 | /* Convert to shorteger. */ |
63 | 63 | for (k = 0 ; k < ARRAY_LEN (data_out.s) ; k++) |
64 | data_out.s [k] = lrintf (data_out.f [k]) ; | |
64 | data_out.s [k] = (short) lrintf (data_out.f [k]) ; | |
65 | 65 | |
66 | 66 | memset (&sfinfo, 0, sizeof (sfinfo)) ; |
67 | 67 |
184 | 184 | } ; |
185 | 185 | |
186 | 186 | total = 0 ; |
187 | while ((k = sf_read_short (file, data + total, BUFFER_LEN - total)) > 0) | |
187 | while ((k = (int) sf_read_short (file, data + total, BUFFER_LEN - total)) > 0) | |
188 | 188 | total += k ; |
189 | 189 | |
190 | 190 | if (total != count) |
154 | 154 | |
155 | 155 | while (total < count) |
156 | 156 | { this_write = (count - total > 1024) ? 1024 : count - total ; |
157 | if ((k = sf_write_short (file, data + total, this_write)) != this_write) | |
157 | if ((k = (int) sf_write_short (file, data + total, this_write)) != this_write) | |
158 | 158 | { fprintf (stderr, "sf_write_short # %d failed with short write (%d -> %d)\n", count, this_write, k) ; |
159 | 159 | exit (1) ; |
160 | 160 | } ; |
36 | 36 | #define BUFFER_LEN (1 << 10) |
37 | 37 | #define LOG_BUFFER_SIZE 1024 |
38 | 38 | |
39 | static const char STR_TEST_PREFIX[] = "str" ; | |
40 | ||
39 | 41 | static void string_start_test (const char *filename, int typemajor) ; |
40 | 42 | static void string_start_end_test (const char *filename, int typemajor) ; |
41 | 43 | static void string_multi_set_test (const char *filename, int typemajor) ; |
109 | 111 | string_start_test ("strings.flac", SF_FORMAT_FLAC) ; |
110 | 112 | else |
111 | 113 | puts (" No FLAC tests because FLAC support was not compiled in.") ; |
114 | test_count++ ; | |
115 | } ; | |
116 | ||
117 | if (do_all || ! strcmp (argv [1], "mpeg")) | |
118 | { if (HAVE_MPEG) | |
119 | string_start_test ("mpeg.mp3", SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III) ; | |
120 | else | |
121 | puts (" No MP3 tests because MPEG support was not compiled in.") ; | |
112 | 122 | test_count++ ; |
113 | 123 | } ; |
114 | 124 | |
194 | 204 | long_title [] = "This is a very long and very boring title for this file", |
195 | 205 | long_artist [] = "The artist who kept on changing its name", |
196 | 206 | genre [] = "The genre", |
197 | trackno [] = "Track three" ; | |
207 | trackno [] = "Track three", | |
208 | id3v1_genre [] = "Rock", | |
209 | year [] = "2001" ; | |
198 | 210 | |
199 | 211 | |
200 | 212 | static short data_out [BUFFER_LEN] ; |
206 | 218 | SF_INFO sfinfo ; |
207 | 219 | int errors = 0 ; |
208 | 220 | |
221 | get_unique_test_name (&filename, STR_TEST_PREFIX) ; | |
209 | 222 | print_test_name ("string_start_end_test", filename) ; |
210 | 223 | |
211 | 224 | memset (&sfinfo, 0, sizeof (sfinfo)) ; |
355 | 368 | int errors = 0 ; |
356 | 369 | int typemajor = SF_FORMAT_TYPEMASK & formattype ; |
357 | 370 | |
371 | get_unique_test_name (&filename, STR_TEST_PREFIX) ; | |
358 | 372 | print_test_name ("string_start_test", filename) ; |
359 | 373 | |
360 | 374 | memset (&sfinfo, 0, sizeof (sfinfo)) ; |
369 | 383 | break ; |
370 | 384 | |
371 | 385 | case SF_FORMAT_OGG | SF_FORMAT_VORBIS : |
386 | case SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III : | |
372 | 387 | break ; |
373 | 388 | |
374 | 389 | default : |
385 | 400 | sf_set_string (file, SF_STR_ARTIST, artist) ; |
386 | 401 | sf_set_string (file, SF_STR_COPYRIGHT, copyright) ; |
387 | 402 | sf_set_string (file, SF_STR_COMMENT, comment) ; |
388 | sf_set_string (file, SF_STR_DATE, date) ; | |
389 | 403 | sf_set_string (file, SF_STR_ALBUM, album) ; |
390 | 404 | sf_set_string (file, SF_STR_LICENSE, license) ; |
405 | if (typemajor == SF_FORMAT_MPEG) | |
406 | { sf_set_string (file, SF_STR_GENRE, id3v1_genre) ; | |
407 | sf_set_string (file, SF_STR_DATE, year) ; | |
408 | } | |
409 | else | |
410 | { sf_set_string (file, SF_STR_DATE, date) ; | |
411 | } ; | |
391 | 412 | |
392 | 413 | /* Write data to file. */ |
393 | 414 | test_write_short_or_die (file, 0, data_out, BUFFER_LEN, __LINE__) ; |
410 | 431 | printf (" Bad filename : %s\n", cptr) ; |
411 | 432 | } ; |
412 | 433 | |
413 | cptr = sf_get_string (file, SF_STR_COPYRIGHT) ; | |
414 | if (cptr == NULL || strcmp (copyright, cptr) != 0) | |
415 | { if (errors++ == 0) | |
416 | puts ("\n") ; | |
417 | printf (" Bad copyright : %s\n", cptr) ; | |
418 | } ; | |
419 | ||
420 | cptr = sf_get_string (file, SF_STR_SOFTWARE) ; | |
421 | if (cptr == NULL || strstr (cptr, software) != cptr) | |
422 | { if (errors++ == 0) | |
423 | puts ("\n") ; | |
424 | printf (" Bad software : %s\n", cptr) ; | |
425 | } ; | |
426 | ||
427 | if (cptr && str_count (cptr, "libsndfile") != 1) | |
428 | { if (errors++ == 0) | |
429 | puts ("\n") ; | |
430 | printf (" Bad software : %s\n", cptr) ; | |
434 | if (typemajor != SF_FORMAT_MPEG) | |
435 | { cptr = sf_get_string (file, SF_STR_COPYRIGHT) ; | |
436 | if (cptr == NULL || strcmp (copyright, cptr) != 0) | |
437 | { if (errors++ == 0) | |
438 | puts ("\n") ; | |
439 | printf (" Bad copyright : %s\n", cptr) ; | |
440 | } ; | |
441 | ||
442 | cptr = sf_get_string (file, SF_STR_SOFTWARE) ; | |
443 | if (cptr == NULL || strstr (cptr, software) != cptr) | |
444 | { if (errors++ == 0) | |
445 | puts ("\n") ; | |
446 | printf (" Bad software : %s\n", cptr) ; | |
447 | } ; | |
448 | ||
449 | if (cptr && str_count (cptr, "libsndfile") != 1) | |
450 | { if (errors++ == 0) | |
451 | puts ("\n") ; | |
452 | printf (" Bad software : %s\n", cptr) ; | |
453 | } ; | |
454 | } ; | |
455 | ||
456 | if (typemajor == SF_FORMAT_MPEG) | |
457 | { cptr = sf_get_string (file, SF_STR_GENRE) ; | |
458 | if (cptr == NULL || strcmp (id3v1_genre, cptr) != 0) | |
459 | { if (errors++ == 0) | |
460 | puts ("\n") ; | |
461 | printf (" Bad genre : %s\n", cptr) ; | |
462 | } ; | |
431 | 463 | } ; |
432 | 464 | |
433 | 465 | cptr = sf_get_string (file, SF_STR_ARTIST) ; |
444 | 476 | printf (" Bad comment : %s\n", cptr) ; |
445 | 477 | } ; |
446 | 478 | |
447 | if (typemajor != SF_FORMAT_AIFF) | |
448 | { cptr = sf_get_string (file, SF_STR_DATE) ; | |
449 | if (cptr == NULL || strcmp (date, cptr) != 0) | |
450 | { if (errors++ == 0) | |
451 | puts ("\n") ; | |
452 | printf (" Bad date : %s\n", cptr) ; | |
453 | } ; | |
479 | switch (typemajor) | |
480 | { case SF_FORMAT_AIFF : | |
481 | /* not supported */ | |
482 | break ; | |
483 | ||
484 | case SF_FORMAT_MPEG : | |
485 | /* id3 only supports years */ | |
486 | cptr = sf_get_string (file, SF_STR_DATE) ; | |
487 | if (cptr == NULL || strcmp (year, cptr) != 0) | |
488 | { if (errors++ == 0) | |
489 | puts ("\n") ; | |
490 | printf (" Bad date : %s\n", cptr) ; | |
491 | } ; | |
492 | break ; | |
493 | ||
494 | default : | |
495 | cptr = sf_get_string (file, SF_STR_DATE) ; | |
496 | if (cptr == NULL || strcmp (date, cptr) != 0) | |
497 | { if (errors++ == 0) | |
498 | puts ("\n") ; | |
499 | printf (" Bad date : %s\n", cptr) ; | |
500 | } ; | |
501 | break ; | |
454 | 502 | } ; |
455 | 503 | |
456 | 504 | if (typemajor != SF_FORMAT_WAV && typemajor != SF_FORMAT_AIFF) |
462 | 510 | } ; |
463 | 511 | } ; |
464 | 512 | |
465 | if (typemajor != SF_FORMAT_WAV && typemajor != SF_FORMAT_AIFF && typemajor != SF_FORMAT_RF64) | |
466 | { cptr = sf_get_string (file, SF_STR_LICENSE) ; | |
467 | if (cptr == NULL || strcmp (license, cptr) != 0) | |
468 | { if (errors++ == 0) | |
469 | puts ("\n") ; | |
470 | printf (" Bad license : %s\n", cptr) ; | |
471 | } ; | |
513 | switch (typemajor) | |
514 | { case SF_FORMAT_WAV : | |
515 | case SF_FORMAT_AIFF : | |
516 | case SF_FORMAT_RF64 : | |
517 | case SF_FORMAT_MPEG : | |
518 | /* not supported */ | |
519 | break ; | |
520 | ||
521 | default: | |
522 | cptr = sf_get_string (file, SF_STR_LICENSE) ; | |
523 | if (cptr == NULL || strcmp (license, cptr) != 0) | |
524 | { if (errors++ == 0) | |
525 | puts ("\n") ; | |
526 | printf (" Bad license : %s\n", cptr) ; | |
527 | } ; | |
472 | 528 | } ; |
473 | 529 | |
474 | 530 | if (errors > 0) |
496 | 552 | SF_INFO sfinfo ; |
497 | 553 | int count ; |
498 | 554 | |
555 | get_unique_test_name (&filename, STR_TEST_PREFIX) ; | |
499 | 556 | print_test_name (__func__, filename) ; |
500 | 557 | |
501 | 558 | memset (&sfinfo, 0, sizeof (sfinfo)) ; |
565 | 622 | sf_count_t frames ; |
566 | 623 | const char * str ; |
567 | 624 | |
625 | get_unique_test_name (&filename, STR_TEST_PREFIX) ; | |
568 | 626 | print_test_name (__func__, filename) ; |
569 | 627 | create_short_sndfile (filename, typemajor | SF_FORMAT_PCM_16, 2) ; |
570 | 628 | |
617 | 675 | sf_count_t frames = BUFFER_LEN ; |
618 | 676 | const char * str ; |
619 | 677 | |
678 | get_unique_test_name (&filename, STR_TEST_PREFIX) ; | |
620 | 679 | print_test_name (__func__, filename) ; |
621 | 680 | |
622 | 681 | memset (&sfinfo, 0, sizeof (sfinfo)) ; |
686 | 745 | software_string_test (const char *filename) |
687 | 746 | { size_t k ; |
688 | 747 | |
748 | get_unique_test_name (&filename, STR_TEST_PREFIX) ; | |
689 | 749 | print_test_name (__func__, filename) ; |
690 | 750 | |
691 | 751 | for (k = 0 ; k < 50 ; k++) |
726 | 786 | sf_count_t frames ; |
727 | 787 | const char * str ; |
728 | 788 | |
789 | get_unique_test_name (&filename, STR_TEST_PREFIX) ; | |
729 | 790 | print_test_name (__func__, filename) ; |
730 | 791 | |
731 | 792 | /* Create a file that contains some strings. Then open the file in RDWR mode and |
784 | 845 | const char * str ; |
785 | 846 | const int GROW_BUFFER_AMOUNT = 4 ; /* this should be less than half the size of the string header */ |
786 | 847 | |
848 | get_unique_test_name (&filename, STR_TEST_PREFIX) ; | |
787 | 849 | print_test_name (__func__, filename) ; |
788 | 850 | |
789 | 851 | /* Create a short file. */ |
351 | 351 | echo " $sfversion passed tests on OPUS files." |
352 | 352 | echo "----------------------------------------------------------------------" |
353 | 353 | |
354 | # mpeg-tests | |
355 | ./tests/mpeg_test@EXEEXT@ | |
356 | ./tests/compression_size_test@EXEEXT@ mpeg | |
357 | ./tests/string_test@EXEEXT@ mpeg | |
358 | ||
359 | echo "----------------------------------------------------------------------" | |
360 | echo " $sfversion passed tests on MPEG files." | |
361 | echo "----------------------------------------------------------------------" | |
362 | ||
354 | 363 | # io-tests |
355 | 364 | ./tests/stdio_test@EXEEXT@ |
356 | 365 | ./tests/pipe_test@EXEEXT@ |
48 | 48 | |
49 | 49 | print_test_name ("ulaw_test", "encoder") ; |
50 | 50 | |
51 | filename = "test.raw" ; | |
51 | filename = "ulaw_test.raw" ; | |
52 | 52 | |
53 | 53 | sf_info_setup (&sfinfo, SF_FORMAT_RAW | SF_FORMAT_ULAW, 44100, 1) ; |
54 | 54 |
103 | 103 | void increment_open_file_count (void) ; |
104 | 104 | void check_open_file_count_or_die (int lineno) ; |
105 | 105 | |
106 | void get_unique_test_name (const char ** filename, const char * test) ; | |
107 | ||
106 | 108 | #ifdef SNDFILE_H |
107 | 109 | |
108 | 110 | static inline void |
851 | 853 | } /* check_open_file_count_or_die */ |
852 | 854 | |
853 | 855 | void |
856 | get_unique_test_name (const char ** filename, const char * test) | |
857 | { static char buffer [1024] ; | |
858 | ||
859 | snprintf (buffer, sizeof (buffer), "%s_%s", test, *filename) ; | |
860 | ||
861 | *filename = buffer ; | |
862 | } /* get_unique_test_name */ | |
863 | ||
864 | void | |
854 | 865 | write_mono_file (const char * filename, int format, int srate, float * output, int len) |
855 | 866 | { SNDFILE * file ; |
856 | 867 | SF_INFO sfinfo ; |
215 | 215 | fflush (stdout) ; |
216 | 216 | puts (sf_strerror (NULL)) ; |
217 | 217 | |
218 | dump_data_to_file (fname, vio_data.data, vio_data.length) ; | |
218 | dump_data_to_file (fname, vio_data.data, (unsigned int) vio_data.length) ; | |
219 | 219 | exit (1) ; |
220 | 220 | } ; |
221 | 221 |
40 | 40 | #define DATA_LENGTH (1 << 12) |
41 | 41 | |
42 | 42 | #define SILLY_WRITE_COUNT (234) |
43 | ||
44 | static const char WRT_TEST_PREFIX[] = "wrt" ; | |
43 | 45 | |
44 | 46 | [+ FOR data_type |
45 | 47 | +]static void pcm_test_[+ (get "type_name") +] (const char *str, int format, int long_file_ok) ; |
445 | 447 | /* Sd2 files cannot be opened from an existing file descriptor. */ |
446 | 448 | allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ; |
447 | 449 | |
450 | get_unique_test_name (&filename, WRT_TEST_PREFIX) ; | |
448 | 451 | print_test_name ("pcm_test_[+ (get "type_name") +]", filename) ; |
449 | 452 | |
450 | 453 | sfinfo.samplerate = 44100 ; |
1007 | 1010 | /* Sd2 files cannot be opened from an existing file descriptor. */ |
1008 | 1011 | allow_fd = ((format & SF_FORMAT_TYPEMASK) == SF_FORMAT_SD2) ? SF_FALSE : SF_TRUE ; |
1009 | 1012 | |
1013 | get_unique_test_name (&filename, WRT_TEST_PREFIX) ; | |
1010 | 1014 | print_test_name ("empty_file_test", filename) ; |
1011 | 1015 | |
1012 | 1016 | unlink (filename) ; |
0 | { | |
1 | "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", | |
2 | "name": "libsndfile", | |
3 | "description": "A library for reading and writing audio files", | |
4 | "version-semver": "1.1.0", | |
5 | "default-features": [ | |
6 | "external-libs", | |
7 | "mpeg" | |
8 | ], | |
9 | "features": { | |
10 | "external-libs": { | |
11 | "description": "Enable FLAC, Vorbis, and Opus codecs", | |
12 | "dependencies": [ | |
13 | "libvorbis", | |
14 | "libflac", | |
15 | "opus" | |
16 | ] | |
17 | }, | |
18 | "mpeg": { | |
19 | "description": "Enable MPEG codecs", | |
20 | "dependencies": [ | |
21 | "mpg123", | |
22 | "mp3lame" | |
23 | ] | |
24 | }, | |
25 | "regtest": { | |
26 | "description": "Build regtest", | |
27 | "dependencies": [ | |
28 | "sqlite3" | |
29 | ] | |
30 | }, | |
31 | "experimental": { | |
32 | "description": "Enable experimental code", | |
33 | "dependencies": [ | |
34 | "speex" | |
35 | ] | |
36 | } | |
37 | } | |
38 | } |