diff options
author | Sigrid Solveig Haflínudóttir <sigrid@ftrv.se> | 2022-09-09 16:15:52 +0000 |
---|---|---|
committer | Sigrid Solveig Haflínudóttir <sigrid@ftrv.se> | 2022-09-09 16:15:52 +0000 |
commit | a5d6746e4d2dc7961910ce7d1729f5500a4dc0f3 (patch) | |
tree | 9150b44ca1ad9dc88d42826899e8bade019e3397 /sys/src/cmd/audio | |
parent | 341502a0fd20bd3188b8d4e100b2d975f2d94007 (diff) |
libFLAC: update 1.3.4 → 1.4.0
Diffstat (limited to 'sys/src/cmd/audio')
58 files changed, 2531 insertions, 934 deletions
diff --git a/sys/src/cmd/audio/libFLAC/FLAC/all.h b/sys/src/cmd/audio/libFLAC/FLAC/all.h index b37a68fc8..8c6cdc3c5 100644 --- a/sys/src/cmd/audio/libFLAC/FLAC/all.h +++ b/sys/src/cmd/audio/libFLAC/FLAC/all.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -147,7 +147,7 @@ * library. * * Also, there are several places in the libFLAC code with comments marked - * with "OPT:" where a #define can be changed to enable code that might be + * with "OPT:" where a \#define can be changed to enable code that might be * faster on a specific platform. Experimenting with these can yield faster * binaries. */ @@ -159,9 +159,9 @@ * the libraries to newer versions of FLAC. * * One simple facility for making porting easier that has been added - * in FLAC 1.1.3 is a set of \c #defines in \c export.h of each + * in FLAC 1.1.3 is a set of \#defines in \c export.h of each * library's includes (e.g. \c include/FLAC/export.h). The - * \c #defines mirror the libraries' + * \#defines mirror the libraries' * <A HREF="http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning">libtool version numbers</A>, * e.g. in libFLAC there are \c FLAC_API_VERSION_CURRENT, * \c FLAC_API_VERSION_REVISION, and \c FLAC_API_VERSION_AGE. @@ -357,6 +357,85 @@ * \c FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN */ +/** \defgroup porting_1_3_4_to_1_4_0 Porting from FLAC 1.3.4 to 1.4.0 + * \ingroup porting + * + * \brief + * This module describes porting from FLAC 1.3.4 to FLAC 1.4.0. + * + * \section porting_1_3_4_to_1_4_0_summary Summary + * + * Between FLAC 1.3.4 and FLAC 1.4.0, there have four breaking changes + * - the function get_client_data_from_decoder has been renamed to + * FLAC__get_decoder_client_data + * - some data types in the FLAC__Frame struct have changed + * - all functions resizing metadata blocks now return the object + * untouched if memory allocation fails, whereas previously the + * handling varied and was more or less undefined + * - all functions accepting a filename now take UTF-8 encoded filenames + * on Windows instead of filenames in the current codepage + * + * Furthermore, there have been the following additions + * - the functions FLAC__stream_encoder_set_limit_min_bitrate, + * FLAC__stream_encoder_get_limit_min_bitrate, + * FLAC::encoder::file::set_limit_min_bitrate() and + * FLAC::encoder::file::get_limit_min_bitrate() have been added + * - Added FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA to the + * FLAC__StreamDecoderErrorStatus enum + * + * \section porting_1_3_4_to_1_4_0_breaking Breaking changes + * + * The function \b get_client_data_from_decoder was added in FLAC 1.3.3 + * but did not follow the API naming convention and was not properly + * exported. The function is now renamed and properly integrated as + * FLAC__stream_decoder_get_client_data + * + * To accomodate encoding and decoding 32-bit int PCM, some data types + * in the \b FLAC__frame struct were changed. Specifically, warmup + * in both the FLAC__Subframe_Fixed struc and the FLAC__Subframe_LPC + * struct is changed from FLAC__int32 to FLAC__int64. Also, value + * in the FLAC__Subframe_Constant is changed from FLAC__int32 to + * FLAC__int64. Finally, in FLAC__Subframe_Verbatim struct data is + * changes from a FLAC__int32 array to a union containing a FLAC__int32 + * array and a FLAC__int64 array. Also, a new member is added, + * data_type, which clarifies whether the FLAC__int32 or FLAC__int64 + * array is in use. + * + * Furthermore, the following functions now return the object untouched + * if memory allocation fails, whereas previously the handling varied + * and was more or less undefined + * + * - FLAC__metadata_object_seektable_resize_points + * - FLAC__metadata_object_vorbiscomment_resize_comments + * - FLAC__metadata_object_cuesheet_track_resize_indices + * - FLAC__metadata_object_cuesheet_resize_tracks + * + * The last breaking change is that all API functions taking a filename + * as an argument now, on Windows, must be supplied with that filename + * in the UTF-8 character encoding instead of using the current code + * page. libFLAC internally translates these UTF-8 encoded filenames to + * an appropriate representation to use with _wfopen. On all other + * systems, filename is passed to fopen without any translation, as it + * in libFLAC 1.3.4 and earlier. + * + * \section porting_1_3_4_to_1_4_0_additions Additions + * + * To aid in creating properly streamable FLAC files, a set of functions + * was added to make it possible to enfore a minimum bitrate to files + * created through libFLAC's stream_encoder.h interface. With this + * function enabled the resulting FLAC files have a minimum bitrate of + * 1bit/sample independent of the number of channels, i.e. 48kbit/s for + * 48kHz. This can be beneficial for streaming, as very low bitrates for + * silent sections compressed with 'constant' subframes can result in a + * bitrate of 1kbit/s, creating problems with clients that aren't aware + * of this possibility and buffer too much data. + * + * Finally, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA was added to + * the FLAC__StreamDecoderErrorStatus enum to signal that the decoder + * encountered unreadable metadata. + * + */ + /** \defgroup flac FLAC C API * * The FLAC C API is the interface to libFLAC, a set of structures diff --git a/sys/src/cmd/audio/libFLAC/FLAC/assert.h b/sys/src/cmd/audio/libFLAC/FLAC/assert.h index 55b34777b..aee23c8c0 100644 --- a/sys/src/cmd/audio/libFLAC/FLAC/assert.h +++ b/sys/src/cmd/audio/libFLAC/FLAC/assert.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/FLAC/callback.h b/sys/src/cmd/audio/libFLAC/FLAC/callback.h index 38e23002b..59d2ee0c7 100644 --- a/sys/src/cmd/audio/libFLAC/FLAC/callback.h +++ b/sys/src/cmd/audio/libFLAC/FLAC/callback.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2004-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/FLAC/export.h b/sys/src/cmd/audio/libFLAC/FLAC/export.h index d52f0bbb5..cde72b73b 100644 --- a/sys/src/cmd/audio/libFLAC/FLAC/export.h +++ b/sys/src/cmd/audio/libFLAC/FLAC/export.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,7 +36,7 @@ /** \file include/FLAC/export.h * * \brief - * This module contains #defines and symbols for exporting function + * This module contains \#defines and symbols for exporting function * calls, and providing version information and compiled-in features. * * See the \link flac_export export \endlink module. @@ -46,7 +46,7 @@ * \ingroup flac * * \brief - * This module contains #defines and symbols for exporting function + * This module contains \#defines and symbols for exporting function * calls, and providing version information and compiled-in features. * * If you are compiling with MSVC and will link to the static library @@ -56,15 +56,22 @@ * \{ */ -#if defined(FLAC__NO_DLL) -#define FLAC_API +/* This has grown quite complicated. FLAC__NO_DLL is used by MSVC sln + * files and CMake, which build either static or shared. autotools can + * build static, shared or **both**. Therefore, DLL_EXPORT, which is set + * by libtool, must override FLAC__NO_DLL on building shared components + */ +#if defined(_WIN32) -#elif defined(_MSC_VER) +#if defined(FLAC__NO_DLL) && !(defined(DLL_EXPORT)) +#define FLAC_API +#else #ifdef FLAC_API_EXPORTS #define FLAC_API __declspec(dllexport) #else #define FLAC_API __declspec(dllimport) #endif +#endif #elif defined(FLAC__USE_VISIBILITY_ATTR) #define FLAC_API __attribute__ ((visibility ("default"))) @@ -74,12 +81,12 @@ #endif -/** These #defines will mirror the libtool-based library version number, see +/** These \#defines will mirror the libtool-based library version number, see * http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning */ -#define FLAC_API_VERSION_CURRENT 11 +#define FLAC_API_VERSION_CURRENT 12 #define FLAC_API_VERSION_REVISION 0 /**< see above */ -#define FLAC_API_VERSION_AGE 3 /**< see above */ +#define FLAC_API_VERSION_AGE 0 /**< see above */ #ifdef __cplusplus extern "C" { diff --git a/sys/src/cmd/audio/libFLAC/FLAC/format.h b/sys/src/cmd/audio/libFLAC/FLAC/format.h index 769ab8afc..7835f8392 100644 --- a/sys/src/cmd/audio/libFLAC/FLAC/format.h +++ b/sys/src/cmd/audio/libFLAC/FLAC/format.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -113,19 +113,17 @@ extern "C" { /** The maximum sample resolution permitted by libFLAC. * - * \warning * FLAC__MAX_BITS_PER_SAMPLE is the limit of the FLAC format. However, - * the reference encoder/decoder is currently limited to 24 bits because - * of prevalent 32-bit math, so make sure and use this value when - * appropriate. + * the reference encoder/decoder used to be limited to 24 bits. This + * value was used to signal that limit. */ -#define FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE (24u) +#define FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE (32u) /** The maximum sample rate permitted by the format. The value is * ((2 ^ 16) - 1) * 10; see <A HREF="../format.html">FLAC format</A> * as to why. */ -#define FLAC__MAX_SAMPLE_RATE (655350u) +#define FLAC__MAX_SAMPLE_RATE (1048575u) /** The maximum LPC order permitted by the format. */ #define FLAC__MAX_LPC_ORDER (32u) @@ -282,14 +280,24 @@ extern FLAC_API const char * const FLAC__SubframeTypeString[]; /** CONSTANT subframe. (c.f. <A HREF="../format.html#subframe_constant">format specification</A>) */ typedef struct { - FLAC__int32 value; /**< The constant signal value. */ + FLAC__int64 value; /**< The constant signal value. */ } FLAC__Subframe_Constant; +/** An enumeration of the possible verbatim subframe data types. */ +typedef enum { + FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT32, /**< verbatim subframe has 32-bit int */ + FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT64 /**< verbatim subframe has 64-bit int */ +} FLAC__VerbatimSubframeDataType; + /** VERBATIM subframe. (c.f. <A HREF="../format.html#subframe_verbatim">format specification</A>) */ typedef struct { - const FLAC__int32 *data; /**< A pointer to verbatim signal. */ + union { + const FLAC__int32 *int32; /**< A FLAC__int32 pointer to verbatim signal. */ + const FLAC__int64 *int64; /**< A FLAC__int64 pointer to verbatim signal. */ + } data; + FLAC__VerbatimSubframeDataType data_type; } FLAC__Subframe_Verbatim; @@ -302,7 +310,7 @@ typedef struct { uint32_t order; /**< The polynomial order. */ - FLAC__int32 warmup[FLAC__MAX_FIXED_ORDER]; + FLAC__int64 warmup[FLAC__MAX_FIXED_ORDER]; /**< Warmup samples to prime the predictor, length == order. */ const FLAC__int32 *residual; @@ -328,7 +336,7 @@ typedef struct { FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER]; /**< FIR filter coefficients. */ - FLAC__int32 warmup[FLAC__MAX_LPC_ORDER]; + FLAC__int64 warmup[FLAC__MAX_LPC_ORDER]; /**< Warmup samples to prime the predictor, length == order. */ const FLAC__int32 *residual; @@ -831,7 +839,7 @@ typedef struct { /** FLAC metadata block structure. (c.f. <A HREF="../format.html#metadata_block">format specification</A>) */ -typedef struct { +typedef struct FLAC__StreamMetadata { FLAC__MetadataType type; /**< The type of the metadata block; used determine which member of the * \a data union to dereference. If type >= FLAC__METADATA_TYPE_UNDEFINED diff --git a/sys/src/cmd/audio/libFLAC/FLAC/metadata.h b/sys/src/cmd/audio/libFLAC/FLAC/metadata.h index 4c67b87f6..bf1bffe4f 100644 --- a/sys/src/cmd/audio/libFLAC/FLAC/metadata.h +++ b/sys/src/cmd/audio/libFLAC/FLAC/metadata.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -134,6 +134,11 @@ extern "C" { * STREAMINFO, VORBIS_COMMENT, CUESHEET, and PICTURE blocks, requiring * only a filename. * + * On Windows, filename must be a UTF-8 encoded filename, which libFLAC + * internally translates to an appropriate representation to use with + * _wfopen. On all other systems, filename is passed to fopen without + * any translation. + * * They try to skip any ID3v2 tag at the head of the file. * * \{ @@ -387,6 +392,11 @@ FLAC_API FLAC__Metadata_SimpleIteratorStatus FLAC__metadata_simple_iterator_stat /** Initialize the iterator to point to the first metadata block in the * given FLAC file. * + * On Windows, filename must be a UTF-8 encoded filename, which libFLAC + * internally translates to an appropriate representation to use with + * _wfopen. On all other systems, filename is passed to fopen without + * any translation. + * * \param iterator A pointer to an existing iterator. * \param filename The path to the FLAC file. * \param read_only If \c true, the FLAC file will be opened @@ -820,6 +830,11 @@ FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_C /** Read all metadata from a FLAC file into the chain. * + * On Windows, filename must be a UTF-8 encoded filename, which libFLAC + * internally translates to an appropriate representation to use with + * _wfopen. On all other systems, filename is passed to fopen without + * any translation. + * * \param chain A pointer to an existing chain. * \param filename The path to the FLAC file to read. * \assert @@ -834,6 +849,11 @@ FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const /** Read all metadata from an Ogg FLAC file into the chain. * + * On Windows, filename must be a UTF-8 encoded filename, which libFLAC + * internally translates to an appropriate representation to use with + * _wfopen. On all other systems, filename is passed to fopen without + * any translation. + * * \note Ogg FLAC metadata data writing is not supported yet and * FLAC__metadata_chain_write() will fail. * @@ -1378,7 +1398,8 @@ FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetad /** Resize the seekpoint array. * * If the size shrinks, elements will truncated; if it grows, new placeholder - * points will be added to the end. + * points will be added to the end. If this function returns false, the + * object is left untouched. * * \param object A pointer to an existing SEEKTABLE object. * \param new_num_points The desired length of the array; may be \c 0. @@ -1591,7 +1612,8 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__ /** Resize the comment array. * * If the size shrinks, elements will truncated; if it grows, new empty - * fields will be added to the end. + * fields will be added to the end. If this function returns false, the + * object is left untouched. * * \param object A pointer to an existing VORBIS_COMMENT object. * \param new_num_comments The desired length of the array; may be \c 0. @@ -1871,7 +1893,8 @@ FLAC_API void FLAC__metadata_object_cuesheet_track_delete(FLAC__StreamMetadata_C /** Resize a track's index point array. * * If the size shrinks, elements will truncated; if it grows, new blank - * indices will be added to the end. + * indices will be added to the end. If this function returns false, the + * track object is left untouched. * * \param object A pointer to an existing CUESHEET object. * \param track_num The index of the track to modify. NOTE: this is not @@ -1957,7 +1980,8 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__Stre /** Resize the track array. * * If the size shrinks, elements will truncated; if it grows, new blank - * tracks will be added to the end. + * tracks will be added to the end. If this function returns false, the + * object is left untouched. * * \param object A pointer to an existing CUESHEET object. * \param new_num_tracks The desired length of the array; may be \c 0. diff --git a/sys/src/cmd/audio/libFLAC/FLAC/ordinals.h b/sys/src/cmd/audio/libFLAC/FLAC/ordinals.h index 75b830d65..77757d660 100644 --- a/sys/src/cmd/audio/libFLAC/FLAC/ordinals.h +++ b/sys/src/cmd/audio/libFLAC/FLAC/ordinals.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/FLAC/stream_decoder.h b/sys/src/cmd/audio/libFLAC/FLAC/stream_decoder.h index 57215c5ed..2d285aecd 100644 --- a/sys/src/cmd/audio/libFLAC/FLAC/stream_decoder.h +++ b/sys/src/cmd/audio/libFLAC/FLAC/stream_decoder.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -422,7 +422,11 @@ extern FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[]; * could be because the decoder encountered a valid frame made by a future * version of the encoder which it cannot parse, or because of a false * sync making it appear as though an encountered frame was generated by - * a future encoder. + * a future encoder. \c FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA is + * caused by finding data that doesn't fit a metadata block (too large + * or too small) or finding inconsistencies in the metadata, for example + * a PICTURE block with an image that exceeds the size of the metadata + * block. */ typedef enum { @@ -435,9 +439,12 @@ typedef enum { FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH, /**< The frame's data did not match the CRC in the footer. */ - FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM + FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM, /**< The decoder encountered reserved fields in use in the stream. */ + FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA + /**< The decoder encountered a corrupted metadata block. */ + } FLAC__StreamDecoderErrorStatus; /** Maps a FLAC__StreamDecoderErrorStatus to a C string. @@ -1006,6 +1013,16 @@ FLAC_API uint32_t FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder * */ FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamDecoder *decoder, FLAC__uint64 *position); +/** Return client_data from decoder. + * The data pointed to by the pointer should not be modified. + * + * \param decoder A decoder instance. + * \retval const void * + * The callee's client data set through FLAC__stream_decoder_init_*(). + * Do not modify the contents. + */ +FLAC_API const void *FLAC__stream_decoder_get_client_data(FLAC__StreamDecoder *decoder); + /** Initialize the decoder instance to decode native FLAC streams. * * This flavor of initialization sets up the decoder to decode from a @@ -1263,11 +1280,15 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_FILE( /** Initialize the decoder instance to decode native FLAC files. * * This flavor of initialization sets up the decoder to decode from a plain - * native FLAC file. If POSIX fopen() semantics are not sufficient, (for - * example, with Unicode filenames on Windows), you must use - * FLAC__stream_decoder_init_FILE(), or FLAC__stream_decoder_init_stream() + * native FLAC file. If POSIX fopen() semantics are not sufficient, you must + * use FLAC__stream_decoder_init_FILE(), or FLAC__stream_decoder_init_stream() * and provide callbacks for the I/O. * + * On Windows, filename must be a UTF-8 encoded filename, which libFLAC + * internally translates to an appropriate representation to use with + * _wfopen. On all other systems, filename is passed to fopen without + * any translation. + * * This function should be called after FLAC__stream_decoder_new() and * FLAC__stream_decoder_set_*() but before any of the * FLAC__stream_decoder_process_*() functions. Will set and return the @@ -1305,11 +1326,15 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file( /** Initialize the decoder instance to decode Ogg FLAC files. * * This flavor of initialization sets up the decoder to decode from a plain - * Ogg FLAC file. If POSIX fopen() semantics are not sufficient, (for - * example, with Unicode filenames on Windows), you must use + * Ogg FLAC file. If POSIX fopen() semantics are not sufficient, you must use * FLAC__stream_decoder_init_ogg_FILE(), or FLAC__stream_decoder_init_ogg_stream() * and provide callbacks for the I/O. * + * On Windows, filename must be a UTF-8 encoded filename, which libFLAC + * internally translates to an appropriate representation to use with + * _wfopen. On all other systems, filename is passed to fopen without + * any translation. + * * This function should be called after FLAC__stream_decoder_new() and * FLAC__stream_decoder_set_*() but before any of the * FLAC__stream_decoder_process_*() functions. Will set and return the diff --git a/sys/src/cmd/audio/libFLAC/FLAC/stream_encoder.h b/sys/src/cmd/audio/libFLAC/FLAC/stream_encoder.h index d154ac437..a39d0ed20 100644 --- a/sys/src/cmd/audio/libFLAC/FLAC/stream_encoder.h +++ b/sys/src/cmd/audio/libFLAC/FLAC/stream_encoder.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -991,10 +991,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder * * coefficients, or \c 0 to let the encoder select it based on the * blocksize. * - * \note - * In the current implementation, qlp_coeff_precision + bits_per_sample must - * be less than 32. - * * \default \c 0 * \param encoder An encoder instance to set. * \param value See above. @@ -1202,6 +1198,24 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__Stream */ FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, uint32_t num_blocks); +/** Set to \c true to make the encoder not output frames which contain + * only constant subframes. This is beneficial for streaming + * applications: very small frames can cause problems with buffering + * as bitrates can drop as low 1kbit/s for CDDA audio encoded within + * subset. The minimum bitrate for a FLAC file encoded with this + * function used is raised to 1bit/sample (i.e. 48kbit/s for 48kHz + * material). + * + * \default \c false + * \param encoder An encoder instance to set. + * \param value Flag value (see above). + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_limit_min_bitrate(FLAC__StreamEncoder *encoder, FLAC__bool value); + /** Get the current encoder state. * * \param encoder An encoder instance to query. @@ -1429,6 +1443,16 @@ FLAC_API uint32_t FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC */ FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder); +/** Get the "limit_min_bitrate" flag. + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * See FLAC__stream_encoder_set_limit_min_bitrate(). + */ +FLAC_API FLAC__bool FLAC__stream_encoder_get_limit_min_bitrate(const FLAC__StreamEncoder *encoder); + /** Initialize the encoder instance to encode native FLAC streams. * * This flavor of initialization sets up the encoder to encode to a @@ -1633,11 +1657,15 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_ogg_FILE(FLAC__ /** Initialize the encoder instance to encode native FLAC files. * * This flavor of initialization sets up the encoder to encode to a plain - * FLAC file. If POSIX fopen() semantics are not sufficient (for example, - * with Unicode filenames on Windows), you must use + * FLAC file. If POSIX fopen() semantics are not sufficient you must use * FLAC__stream_encoder_init_FILE(), or FLAC__stream_encoder_init_stream() * and provide callbacks for the I/O. * + * On Windows, filename must be a UTF-8 encoded filename, which libFLAC + * internally translates to an appropriate representation to use with + * _wfopen. On all other systems, filename is passed to fopen without + * any translation. + * * This function should be called after FLAC__stream_encoder_new() and * FLAC__stream_encoder_set_*() but before FLAC__stream_encoder_process() * or FLAC__stream_encoder_process_interleaved(). @@ -1665,11 +1693,15 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_file(FLAC__Stre /** Initialize the encoder instance to encode Ogg FLAC files. * * This flavor of initialization sets up the encoder to encode to a plain - * Ogg FLAC file. If POSIX fopen() semantics are not sufficient (for example, - * with Unicode filenames on Windows), you must use + * Ogg FLAC file. If POSIX fopen() semantics are not sufficient, you must use * FLAC__stream_encoder_init_ogg_FILE(), or FLAC__stream_encoder_init_ogg_stream() * and provide callbacks for the I/O. * + * On Windows, filename must be a UTF-8 encoded filename, which libFLAC + * internally translates to an appropriate representation to use with + * _wfopen. On all other systems, filename is passed to fopen without + * any translation. + * * This function should be called after FLAC__stream_encoder_new() and * FLAC__stream_encoder_set_*() but before FLAC__stream_encoder_process() * or FLAC__stream_encoder_process_interleaved(). diff --git a/sys/src/cmd/audio/libFLAC/bitmath.c b/sys/src/cmd/audio/libFLAC/bitmath.c index 32e31a799..7c73cc05e 100644 --- a/sys/src/cmd/audio/libFLAC/bitmath.c +++ b/sys/src/cmd/audio/libFLAC/bitmath.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/bitreader.c b/sys/src/cmd/audio/libFLAC/bitreader.c index 79cb5cc40..9a8a5f02d 100644 --- a/sys/src/cmd/audio/libFLAC/bitreader.c +++ b/sys/src/cmd/audio/libFLAC/bitreader.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2018 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -111,6 +111,9 @@ struct FLAC__BitReader { uint32_t read_crc16; /* the running frame CRC */ uint32_t crc16_offset; /* the number of words in the current buffer that should not be CRC'd */ uint32_t crc16_align; /* the number of bits in the current consumed word that should not be CRC'd */ + FLAC__bool read_limit_set; /* whether reads are limited */ + uint32_t read_limit; /* the remaining size of what can be read */ + uint32_t last_seen_framesync; /* the location of the last seen framesync, if it is in the buffer, in bits from front of buffer */ FLAC__BitReaderReadCallback read_callback; void *client_data; }; @@ -155,6 +158,13 @@ static FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br) uint32_t start, end; size_t bytes; FLAC__byte *target; +#if WORDS_BIGENDIAN +#else + brword preswap_backup; +#endif + + /* invalidate last seen framesync */ + br->last_seen_framesync = -1; /* first shift the unconsumed buffer data toward the front as much as possible */ if(br->consumed_words > 0) { @@ -186,6 +196,7 @@ static FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br) */ #if WORDS_BIGENDIAN #else + preswap_backup = br->buffer[br->words]; if(br->bytes) br->buffer[br->words] = SWAP_BE_WORD_TO_HOST(br->buffer[br->words]); #endif @@ -198,8 +209,16 @@ static FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br) */ /* read in the data; note that the callback may return a smaller number of bytes */ - if(!br->read_callback(target, &bytes, br->client_data)) + if(!br->read_callback(target, &bytes, br->client_data)){ + /* Despite the read callback failing, the data in the target + * might be used later, when the buffer is rewound. Therefore + * we revert the swap that was just done */ +#if WORDS_BIGENDIAN +#else + br->buffer[br->words] = preswap_backup; +#endif return false; + } /* after reading bytes 66 77 88 99 AA BB CC DD EE FF from the client: * bitstream : 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF @@ -275,6 +294,9 @@ FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__BitReaderReadCallback return false; br->read_callback = rcb; br->client_data = cd; + br->read_limit_set = false; + br->read_limit = -1; + br->last_seen_framesync = -1; return true; } @@ -291,15 +313,39 @@ void FLAC__bitreader_free(FLAC__BitReader *br) br->consumed_words = br->consumed_bits = 0; br->read_callback = 0; br->client_data = 0; + br->read_limit_set = false; + br->read_limit = -1; + br->last_seen_framesync = -1; } FLAC__bool FLAC__bitreader_clear(FLAC__BitReader *br) { br->words = br->bytes = 0; br->consumed_words = br->consumed_bits = 0; + br->read_limit_set = false; + br->read_limit = -1; + br->last_seen_framesync = -1; return true; } +void FLAC__bitreader_set_framesync_location(FLAC__BitReader *br) +{ + br->last_seen_framesync = br->consumed_words * FLAC__BYTES_PER_WORD + br->consumed_bits / 8; +} + +FLAC__bool FLAC__bitreader_rewind_to_after_last_seen_framesync(FLAC__BitReader *br) +{ + if(br->last_seen_framesync == (uint32_t)-1) { + br->consumed_words = br->consumed_bits = 0; + return false; + } + else { + br->consumed_words = (br->last_seen_framesync + 1) / FLAC__BYTES_PER_WORD; + br->consumed_bits = ((br->last_seen_framesync + 1) % FLAC__BYTES_PER_WORD) * 8; + return true; + } +} + void FLAC__bitreader_dump(const FLAC__BitReader *br, FILE *out) { uint32_t i, j; @@ -376,6 +422,28 @@ inline uint32_t FLAC__bitreader_get_input_bits_unconsumed(const FLAC__BitReader return (br->words-br->consumed_words)*FLAC__BITS_PER_WORD + br->bytes*8 - br->consumed_bits; } +void FLAC__bitreader_set_limit(FLAC__BitReader *br, uint32_t limit) +{ + br->read_limit = limit; + br->read_limit_set = true; +} + +void FLAC__bitreader_remove_limit(FLAC__BitReader *br) +{ + br->read_limit_set = false; + br->read_limit = -1; +} + +uint32_t FLAC__bitreader_limit_remaining(FLAC__BitReader *br) +{ + FLAC__ASSERT(br->read_limit_set); + return br->read_limit; +} +void FLAC__bitreader_limit_invalidate(FLAC__BitReader *br) +{ + br->read_limit = -1; +} + FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *val, uint32_t bits) { FLAC__ASSERT(0 != br); @@ -393,6 +461,15 @@ FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *va return true; } + if(br->read_limit_set && br->read_limit < (uint32_t)-1){ + if(br->read_limit < bits) { + br->read_limit = -1; + return false; + } + else + br->read_limit -= bits; + } + while((br->words-br->consumed_words)*FLAC__BITS_PER_WORD + br->bytes*8 - br->consumed_bits < bits) { if(!bitreader_read_from_client_(br)) return false; @@ -465,7 +542,7 @@ FLAC__bool FLAC__bitreader_read_raw_int32(FLAC__BitReader *br, FLAC__int32 *val, return false; /* sign-extend *val assuming it is currently bits wide. */ /* From: https://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend */ - mask = bits >= 33 ? 0 : 1u << (bits - 1); + mask = bits >= 33 ? 0 : 1lu << (bits - 1); *val = (uval ^ mask) - mask; return true; } @@ -491,6 +568,19 @@ FLAC__bool FLAC__bitreader_read_raw_uint64(FLAC__BitReader *br, FLAC__uint64 *va return true; } +FLAC__bool FLAC__bitreader_read_raw_int64(FLAC__BitReader *br, FLAC__int64 *val, uint32_t bits) +{ + FLAC__uint64 uval, mask; + /* OPT: inline raw uint64 code here, or make into a macro if possible in the .h file */ + if (bits < 1 || ! FLAC__bitreader_read_raw_uint64(br, &uval, bits)) + return false; + /* sign-extend *val assuming it is currently bits wide. */ + /* From: https://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend */ + mask = bits >= 65 ? 0 : 1llu << (bits - 1); + *val = (uval ^ mask) - mask; + return true; +} + inline FLAC__bool FLAC__bitreader_read_uint32_little_endian(FLAC__BitReader *br, FLAC__uint32 *val) { FLAC__uint32 x8, x32 = 0; @@ -559,6 +649,13 @@ FLAC__bool FLAC__bitreader_skip_byte_block_aligned_no_crc(FLAC__BitReader *br, u FLAC__ASSERT(0 != br->buffer); FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(br)); + if(br->read_limit_set && br->read_limit < (uint32_t)-1){ + if(br->read_limit < nvals*8){ + br->read_limit = -1; + return false; + } + } + /* step 1: skip over partial head word to get word aligned */ while(nvals && br->consumed_bits) { /* i.e. run until we read 'nvals' bytes or we hit the end of the head word */ if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) @@ -567,11 +664,14 @@ FLAC__bool FLAC__bitreader_skip_byte_block_aligned_no_crc(FLAC__BitReader *br, u } if(0 == nvals) return true; + /* step 2: skip whole words in chunks */ while(nvals >= FLAC__BYTES_PER_WORD) { if(br->consumed_words < br->words) { br->consumed_words++; nvals -= FLAC__BYTES_PER_WORD; + if(br->read_limit_set) + br->read_limit -= FLAC__BITS_PER_WORD; } else if(!bitreader_read_from_client_(br)) return false; @@ -594,6 +694,13 @@ FLAC__bool FLAC__bitreader_read_byte_block_aligned_no_crc(FLAC__BitReader *br, F FLAC__ASSERT(0 != br->buffer); FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(br)); + if(br->read_limit_set && br->read_limit < (uint32_t)-1){ + if(br->read_limit < nvals*8){ + br->read_limit = -1; + return false; + } + } + /* step 1: read from partial head word to get word aligned */ while(nvals && br->consumed_bits) { /* i.e. run until we read 'nvals' bytes or we hit the end of the head word */ if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) @@ -627,6 +734,8 @@ FLAC__bool FLAC__bitreader_read_byte_block_aligned_no_crc(FLAC__BitReader *br, F #endif val += FLAC__BYTES_PER_WORD; nvals -= FLAC__BYTES_PER_WORD; + if(br->read_limit_set) + br->read_limit -= FLAC__BITS_PER_WORD; } else if(!bitreader_read_from_client_(br)) return false; @@ -721,6 +830,7 @@ FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, uint32_t *va } #endif +#if 0 /* unused */ FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, uint32_t parameter) { FLAC__uint32 lsbs = 0, msbs = 0; @@ -747,6 +857,7 @@ FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, uint3 return true; } +#endif /* this is by far the most heavily used reader call. it ain't pretty but it's fast */ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[], uint32_t nvals, uint32_t parameter) @@ -754,7 +865,7 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[ /* try and get br->consumed_words and br->consumed_bits into register; * must remember to flush them back to *br before calling other * bitreader functions that use them, and before returning */ - uint32_t cwords, words, lsbs, msbs, x, y; + uint32_t cwords, words, lsbs, msbs, x, y, limit; uint32_t ucbits; /* keep track of the number of unconsumed bits in word */ brword b; int *val, *end; @@ -766,6 +877,8 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[ FLAC__ASSERT(parameter < 32); /* the above two asserts also guarantee that the binary part never straddles more than 2 words, so we don't have to loop to read it */ + limit = UINT32_MAX >> parameter; /* Maximal msbs that can occur with residual bounded to int32_t */ + val = vals; end = vals + nvals; @@ -774,7 +887,8 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[ /* read the unary MSBs and end bit */ if(!FLAC__bitreader_read_unary_unsigned(br, &msbs)) return false; - + /* Checking limit here would be overzealous: coding UINT32_MAX + * with parameter == 0 would take 4GiB */ *val++ = (int)(msbs >> 1) ^ -(int)(msbs & 1); } @@ -815,6 +929,9 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[ ucbits = (ucbits - x - 1) % FLAC__BITS_PER_WORD; msbs = x; + if(x > limit) + return false; + /* read the binary LSBs */ x = (FLAC__uint32)(b >> (FLAC__BITS_PER_WORD - parameter)); /* parameter < 32, so we can cast to 32-bit uint32_t */ if(parameter <= ucbits) { diff --git a/sys/src/cmd/audio/libFLAC/bitwriter.c b/sys/src/cmd/audio/libFLAC/bitwriter.c index 6e86585b7..8865a2f41 100644 --- a/sys/src/cmd/audio/libFLAC/bitwriter.c +++ b/sys/src/cmd/audio/libFLAC/bitwriter.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,7 +38,9 @@ #include <string.h> #include "private/bitwriter.h" #include "private/crc.h" +#include "private/format.h" #include "private/macros.h" +#include "private/stream_encoder.h" #include "FLAC/assert.h" #include "share/alloc.h" #include "share/compat.h" @@ -116,6 +118,13 @@ FLAC__bool bitwriter_grow_(FLAC__BitWriter *bw, uint32_t bits_to_add) if(bw->capacity >= new_capacity) return true; + if(new_capacity * sizeof(bwword) > (1u << FLAC__STREAM_METADATA_LENGTH_LEN)) + /* Requested new capacity is larger than the largest possible metadata block, + * which is also larger than the largest sane framesize. That means something + * went very wrong somewhere and previous checks failed. + * To prevent chrashing, give up */ + return false; + /* round up capacity increase to the nearest FLAC__BITWRITER_DEFAULT_INCREMENT */ if((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT) new_capacity += FLAC__BITWRITER_DEFAULT_INCREMENT - ((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT); @@ -124,7 +133,7 @@ FLAC__bool bitwriter_grow_(FLAC__BitWriter *bw, uint32_t bits_to_add) FLAC__ASSERT(new_capacity > bw->capacity); FLAC__ASSERT(new_capacity >= bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD)); - new_buffer = safe_realloc_mul_2op_(bw->buffer, sizeof(bwword), /*times*/new_capacity); + new_buffer = safe_realloc_nofree_mul_2op_(bw->buffer, sizeof(bwword), /*times*/new_capacity); if(new_buffer == 0) return false; bw->buffer = new_buffer; @@ -390,6 +399,15 @@ inline FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__ui return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, bits); } +inline FLAC__bool FLAC__bitwriter_write_raw_int64(FLAC__BitWriter *bw, FLAC__int64 val, uint32_t bits) +{ + FLAC__uint64 uval = val; + /* zero-out unused bits */ + if(bits < 64) + uval &= (~(UINT64_MAX << bits)); + return FLAC__bitwriter_write_raw_uint64(bw, uval, bits); +} + inline FLAC__bool FLAC__bitwriter_write_raw_uint32_little_endian(FLAC__BitWriter *bw, FLAC__uint32 val) { /* this doesn't need to be that fast as currently it is only used for vorbis comments */ @@ -881,5 +899,6 @@ extern FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, uint32_t bit extern FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FLAC__uint32 val, uint32_t bits); extern FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, uint32_t bits); extern FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, uint32_t bits); +extern FLAC__bool FLAC__bitwriter_write_raw_int64(FLAC__BitWriter *bw, FLAC__int64 val, uint32_t bits); extern FLAC__bool FLAC__bitwriter_write_raw_uint32_little_endian(FLAC__BitWriter *bw, FLAC__uint32 val); extern FLAC__bool FLAC__bitwriter_write_byte_block(FLAC__BitWriter *bw, const FLAC__byte vals[], uint32_t nvals); diff --git a/sys/src/cmd/audio/libFLAC/crc.c b/sys/src/cmd/audio/libFLAC/crc.c index faa349650..4f47e9865 100644 --- a/sys/src/cmd/audio/libFLAC/crc.c +++ b/sys/src/cmd/audio/libFLAC/crc.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2018 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/fixed.c b/sys/src/cmd/audio/libFLAC/fixed.c index 98f42a2f9..7d826f10a 100644 --- a/sys/src/cmd/audio/libFLAC/fixed.c +++ b/sys/src/cmd/audio/libFLAC/fixed.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -47,6 +47,11 @@ #endif #define local_abs(x) ((uint32_t)((x)<0? -(x) : (x))) +#ifdef local_abs64 +#undef local_abs64 +#endif +#define local_abs64(x) ((uint64_t)((x)<0? -(x) : (x))) + #ifdef FLAC__INTEGER_ONLY_LIBRARY /* rbps stands for residual bits per sample * @@ -219,29 +224,48 @@ uint32_t FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], uint32_t d uint32_t FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) #endif { + FLAC__uint32 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0; + uint32_t order; +#if 0 + /* This code has been around a long time, and was written when compilers weren't able + * to vectorize code. These days, compilers are better in optimizing the next block + * which is also much more readable + */ FLAC__int32 last_error_0 = data[-1]; FLAC__int32 last_error_1 = data[-1] - data[-2]; FLAC__int32 last_error_2 = last_error_1 - (data[-2] - data[-3]); FLAC__int32 last_error_3 = last_error_2 - (data[-2] - 2*data[-3] + data[-4]); FLAC__int32 error, save; - FLAC__uint32 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0; - uint32_t i, order; - - for(i = 0; i < data_len; i++) { + /* total_error_* are 64-bits to avoid overflow when encoding + * erratic signals when the bits-per-sample and blocksize are + * large. + */ + for(uint32_t i = 0; i < data_len; i++) { error = data[i] ; total_error_0 += local_abs(error); save = error; error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error; error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error; error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error; error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save; } +#else + for(int i = 0; i < (int)data_len; i++) { + total_error_0 += local_abs(data[i]); + total_error_1 += local_abs(data[i] - data[i-1]); + total_error_2 += local_abs(data[i] - 2 * data[i-1] + data[i-2]); + total_error_3 += local_abs(data[i] - 3 * data[i-1] + 3 * data[i-2] - data[i-3]); + total_error_4 += local_abs(data[i] - 4 * data[i-1] + 6 * data[i-2] - 4 * data[i-3] + data[i-4]); + } +#endif - if(total_error_0 < flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) + + /* prefer lower order */ + if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) order = 0; - else if(total_error_1 < flac_min(flac_min(total_error_2, total_error_3), total_error_4)) + else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4)) order = 1; - else if(total_error_2 < flac_min(total_error_3, total_error_4)) + else if(total_error_2 <= flac_min(total_error_3, total_error_4)) order = 2; - else if(total_error_3 < total_error_4) + else if(total_error_3 <= total_error_4) order = 3; else order = 4; @@ -277,33 +301,25 @@ uint32_t FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], uint3 uint32_t FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) #endif { - FLAC__int32 last_error_0 = data[-1]; - FLAC__int32 last_error_1 = data[-1] - data[-2]; - FLAC__int32 last_error_2 = last_error_1 - (data[-2] - data[-3]); - FLAC__int32 last_error_3 = last_error_2 - (data[-2] - 2*data[-3] + data[-4]); - FLAC__int32 error, save; - /* total_error_* are 64-bits to avoid overflow when encoding - * erratic signals when the bits-per-sample and blocksize are - * large. - */ FLAC__uint64 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0; - uint32_t i, order; - - for(i = 0; i < data_len; i++) { - error = data[i] ; total_error_0 += local_abs(error); save = error; - error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error; - error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error; - error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error; - error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save; + uint32_t order; + + for(int i = 0; i < (int)data_len; i++) { + total_error_0 += local_abs(data[i]); + total_error_1 += local_abs(data[i] - data[i-1]); + total_error_2 += local_abs(data[i] - 2 * data[i-1] + data[i-2]); + total_error_3 += local_abs(data[i] - 3 * data[i-1] + 3 * data[i-2] - data[i-3]); + total_error_4 += local_abs(data[i] - 4 * data[i-1] + 6 * data[i-2] - 4 * data[i-3] + data[i-4]); } - if(total_error_0 < flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) + /* prefer lower order */ + if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) order = 0; - else if(total_error_1 < flac_min(flac_min(total_error_2, total_error_3), total_error_4)) + else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4)) order = 1; - else if(total_error_2 < flac_min(total_error_3, total_error_4)) + else if(total_error_2 <= flac_min(total_error_3, total_error_4)) order = 2; - else if(total_error_3 < total_error_4) + else if(total_error_3 <= total_error_4) order = 3; else order = 4; @@ -333,6 +349,119 @@ uint32_t FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], uint3 return order; } +#ifndef FLAC__INTEGER_ONLY_LIBRARY +#define CHECK_ORDER_IS_VALID(macro_order) \ +if(order_##macro_order##_is_valid && total_error_##macro_order < smallest_error) { \ + order = macro_order; \ + smallest_error = total_error_##macro_order ; \ + residual_bits_per_sample[ macro_order ] = (float)((total_error_0 > 0) ? log(M_LN2 * (double)total_error_0 / (double)data_len) / M_LN2 : 0.0); \ +} \ +else \ + residual_bits_per_sample[ macro_order ] = 34.0f; +#else +#define CHECK_ORDER_IS_VALID(macro_order) \ +if(order_##macro_order##_is_valid && total_error_##macro_order < smallest_error) { \ + order = macro_order; \ + smallest_error = total_error_##macro_order ; \ + residual_bits_per_sample[ macro_order ] = (total_error_##macro_order > 0) ? local__compute_rbps_wide_integerized(total_error_##macro_order, data_len) : 0; \ +} \ +else \ + residual_bits_per_sample[ macro_order ] = 34 * FLAC__FP_ONE; +#endif + + +#ifndef FLAC__INTEGER_ONLY_LIBRARY +uint32_t FLAC__fixed_compute_best_predictor_limit_residual(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +#else +uint32_t FLAC__fixed_compute_best_predictor_limit_residual(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +#endif +{ + FLAC__uint64 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0, smallest_error = UINT64_MAX; + FLAC__uint64 error_0, error_1, error_2, error_3, error_4; + FLAC__bool order_0_is_valid = true, order_1_is_valid = true, order_2_is_valid = true, order_3_is_valid = true, order_4_is_valid = true; + uint32_t order = 0; + + for(int i = 0; i < (int)data_len; i++) { + error_0 = local_abs64((FLAC__int64)data[i]); + error_1 = (i > 0) ? local_abs64((FLAC__int64)data[i] - data[i-1]) : 0 ; + error_2 = (i > 1) ? local_abs64((FLAC__int64)data[i] - 2 * (FLAC__int64)data[i-1] + data[i-2]) : 0; + error_3 = (i > 2) ? local_abs64((FLAC__int64)data[i] - 3 * (FLAC__int64)data[i-1] + 3 * (FLAC__int64)data[i-2] - data[i-3]) : 0; + error_4 = (i > 3) ? local_abs64((FLAC__int64)data[i] - 4 * (FLAC__int64)data[i-1] + 6 * (FLAC__int64)data[i-2] - 4 * (FLAC__int64)data[i-3] + data[i-4]) : 0; + + total_error_0 += error_0; + total_error_1 += error_1; + total_error_2 += error_2; + total_error_3 += error_3; + total_error_4 += error_4; + + /* residual must not be INT32_MIN because abs(INT32_MIN) is undefined */ + if(error_0 > INT32_MAX) + order_0_is_valid = false; + if(error_1 > INT32_MAX) + order_1_is_valid = false; + if(error_2 > INT32_MAX) + order_2_is_valid = false; + if(error_3 > INT32_MAX) + order_3_is_valid = false; + if(error_4 > INT32_MAX) + order_4_is_valid = false; + } + + CHECK_ORDER_IS_VALID(0); + CHECK_ORDER_IS_VALID(1); + CHECK_ORDER_IS_VALID(2); + CHECK_ORDER_IS_VALID(3); + CHECK_ORDER_IS_VALID(4); + + return order; +} + +#ifndef FLAC__INTEGER_ONLY_LIBRARY +uint32_t FLAC__fixed_compute_best_predictor_limit_residual_33bit(const FLAC__int64 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +#else +uint32_t FLAC__fixed_compute_best_predictor_limit_residual_33bit(const FLAC__int64 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +#endif +{ + FLAC__uint64 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0, smallest_error = UINT64_MAX; + FLAC__uint64 error_0, error_1, error_2, error_3, error_4; + FLAC__bool order_0_is_valid = true, order_1_is_valid = true, order_2_is_valid = true, order_3_is_valid = true, order_4_is_valid = true; + uint32_t order = 0; + + for(int i = 0; i < (int)data_len; i++) { + error_0 = local_abs64(data[i]); + error_1 = (i > 0) ? local_abs64(data[i] - data[i-1]) : 0 ; + error_2 = (i > 1) ? local_abs64(data[i] - 2 * data[i-1] + data[i-2]) : 0; + error_3 = (i > 2) ? local_abs64(data[i] - 3 * data[i-1] + 3 * data[i-2] - data[i-3]) : 0; + error_4 = (i > 3) ? local_abs64(data[i] - 4 * data[i-1] + 6 * data[i-2] - 4 * data[i-3] + data[i-4]) : 0; + + total_error_0 += error_0; + total_error_1 += error_1; + total_error_2 += error_2; + total_error_3 += error_3; + total_error_4 += error_4; + + /* residual must not be INT32_MIN because abs(INT32_MIN) is undefined */ + if(error_0 > INT32_MAX) + order_0_is_valid = false; + if(error_1 > INT32_MAX) + order_1_is_valid = false; + if(error_2 > INT32_MAX) + order_2_is_valid = false; + if(error_3 > INT32_MAX) + order_3_is_valid = false; + if(error_4 > INT32_MAX) + order_4_is_valid = false; + } + + CHECK_ORDER_IS_VALID(0); + CHECK_ORDER_IS_VALID(1); + CHECK_ORDER_IS_VALID(2); + CHECK_ORDER_IS_VALID(3); + CHECK_ORDER_IS_VALID(4); + + return order; +} + void FLAC__fixed_compute_residual(const FLAC__int32 data[], uint32_t data_len, uint32_t order, FLAC__int32 residual[]) { const int idata_len = (int)data_len; @@ -364,6 +493,76 @@ void FLAC__fixed_compute_residual(const FLAC__int32 data[], uint32_t data_len, u } } +void FLAC__fixed_compute_residual_wide(const FLAC__int32 data[], uint32_t data_len, uint32_t order, FLAC__int32 residual[]) +{ + const int idata_len = (int)data_len; + int i; + + switch(order) { + case 0: + FLAC__ASSERT(sizeof(residual[0]) == sizeof(data[0])); + memcpy(residual, data, sizeof(residual[0])*data_len); + break; + case 1: + for(i = 0; i < idata_len; i++) + residual[i] = (FLAC__int64)data[i] - data[i-1]; + break; + case 2: + for(i = 0; i < idata_len; i++) + residual[i] = (FLAC__int64)data[i] - 2*(FLAC__int64)data[i-1] + data[i-2]; + break; + case 3: + for(i = 0; i < idata_len; i++) + residual[i] = (FLAC__int64)data[i] - 3*(FLAC__int64)data[i-1] + 3*(FLAC__int64)data[i-2] - data[i-3]; + break; + case 4: + for(i = 0; i < idata_len; i++) + residual[i] = (FLAC__int64)data[i] - 4*(FLAC__int64)data[i-1] + 6*(FLAC__int64)data[i-2] - 4*(FLAC__int64)data[i-3] + data[i-4]; + break; + default: + FLAC__ASSERT(0); + } +} + +void FLAC__fixed_compute_residual_wide_33bit(const FLAC__int64 data[], uint32_t data_len, uint32_t order, FLAC__int32 residual[]) +{ + const int idata_len = (int)data_len; + int i; + + switch(order) { + case 0: + for(i = 0; i < idata_len; i++) + residual[i] = data[i]; + break; + case 1: + for(i = 0; i < idata_len; i++) + residual[i] = data[i] - data[i-1]; + break; + case 2: + for(i = 0; i < idata_len; i++) + residual[i] = data[i] - 2*data[i-1] + data[i-2]; + break; + case 3: + for(i = 0; i < idata_len; i++) + residual[i] = data[i] - 3*data[i-1] + 3*data[i-2] - data[i-3]; + break; + case 4: + for(i = 0; i < idata_len; i++) + residual[i] = data[i] - 4*data[i-1] + 6*data[i-2] - 4*data[i-3] + data[i-4]; + break; + default: + FLAC__ASSERT(0); + } +} + +#ifdef FUZZING_BUILD_MODE_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW +/* The attribute below is to silence the undefined sanitizer of oss-fuzz. + * Because fuzzing feeds bogus predictors and residual samples to the + * decoder, having overflows in this section is unavoidable. Also, + * because the calculated values are audio path only, there is no + * potential for security problems */ +__attribute__((no_sanitize("signed-integer-overflow"))) +#endif void FLAC__fixed_restore_signal(const FLAC__int32 residual[], uint32_t data_len, uint32_t order, FLAC__int32 data[]) { int i, idata_len = (int)data_len; @@ -393,3 +592,71 @@ void FLAC__fixed_restore_signal(const FLAC__int32 residual[], uint32_t data_len, FLAC__ASSERT(0); } } + +void FLAC__fixed_restore_signal_wide(const FLAC__int32 residual[], uint32_t data_len, uint32_t order, FLAC__int32 data[]) +{ + int i, idata_len = (int)data_len; + + switch(order) { + case 0: + FLAC__ASSERT(sizeof(residual[0]) == sizeof(data[0])); + memcpy(data, residual, sizeof(residual[0])*data_len); + break; + case 1: + for(i = 0; i < idata_len; i++) + data[i] = (FLAC__int64)residual[i] + (FLAC__int64)data[i-1]; + break; + case 2: + for(i = 0; i < idata_len; i++) + data[i] = (FLAC__int64)residual[i] + 2*(FLAC__int64)data[i-1] - (FLAC__int64)data[i-2]; + break; + case 3: + for(i = 0; i < idata_len; i++) + data[i] = (FLAC__int64)residual[i] + 3*(FLAC__int64)data[i-1] - 3*(FLAC__int64)data[i-2] + (FLAC__int64)data[i-3]; + break; + case 4: + for(i = 0; i < idata_len; i++) + data[i] = (FLAC__int64)residual[i] + 4*(FLAC__int64)data[i-1] - 6*(FLAC__int64)data[i-2] + 4*(FLAC__int64)data[i-3] - (FLAC__int64)data[i-4]; + break; + default: + FLAC__ASSERT(0); + } +} + +#ifdef FUZZING_BUILD_MODE_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW +/* The attribute below is to silence the undefined sanitizer of oss-fuzz. + * Because fuzzing feeds bogus predictors and residual samples to the + * decoder, having overflows in this section is unavoidable. Also, + * because the calculated values are audio path only, there is no + * potential for security problems */ +__attribute__((no_sanitize("signed-integer-overflow"))) +#endif +void FLAC__fixed_restore_signal_wide_33bit(const FLAC__int32 residual[], uint32_t data_len, uint32_t order, FLAC__int64 data[]) +{ + int i, idata_len = (int)data_len; + + switch(order) { + case 0: + for(i = 0; i < idata_len; i++) + data[i] = residual[i]; + break; + case 1: + for(i = 0; i < idata_len; i++) + data[i] = (FLAC__int64)residual[i] + data[i-1]; + break; + case 2: + for(i = 0; i < idata_len; i++) + data[i] = (FLAC__int64)residual[i] + 2*data[i-1] - data[i-2]; + break; + case 3: + for(i = 0; i < idata_len; i++) + data[i] = (FLAC__int64)residual[i] + 3*data[i-1] - 3*data[i-2] + data[i-3]; + break; + case 4: + for(i = 0; i < idata_len; i++) + data[i] = (FLAC__int64)residual[i] + 4*data[i-1] - 6*data[i-2] + 4*data[i-3] - data[i-4]; + break; + default: + FLAC__ASSERT(0); + } +} diff --git a/sys/src/cmd/audio/libFLAC/float.c b/sys/src/cmd/audio/libFLAC/float.c index a49a083fb..1e2582759 100644 --- a/sys/src/cmd/audio/libFLAC/float.c +++ b/sys/src/cmd/audio/libFLAC/float.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2004-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/format.c b/sys/src/cmd/audio/libFLAC/format.c index ff6f30ffc..2729f9795 100644 --- a/sys/src/cmd/audio/libFLAC/format.c +++ b/sys/src/cmd/audio/libFLAC/format.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,10 +44,19 @@ #include "private/format.h" #include "private/macros.h" +#if (defined GIT_COMMIT_HASH && defined GIT_COMMIT_DATE) +# ifdef GIT_COMMIT_TAG +FLAC_API const char *FLAC__VERSION_STRING = GIT_COMMIT_TAG; +FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " GIT_COMMIT_TAG " " GIT_COMMIT_DATE; +# else +FLAC_API const char *FLAC__VERSION_STRING = "git-" GIT_COMMIT_HASH " " GIT_COMMIT_DATE; +FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC git-" GIT_COMMIT_HASH " " GIT_COMMIT_DATE; +# endif +#else /* PACKAGE_VERSION should come from configure */ FLAC_API const char *FLAC__VERSION_STRING = PACKAGE_VERSION; - -FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " PACKAGE_VERSION " 20220220"; +FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " PACKAGE_VERSION " 20220909"; +#endif FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' }; FLAC_API const uint32_t FLAC__STREAM_SYNC = 0x664C6143; @@ -218,12 +227,10 @@ FLAC_API FLAC__bool FLAC__format_blocksize_is_subset(uint32_t blocksize, uint32_ FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(uint32_t sample_rate) { - if( - !FLAC__format_sample_rate_is_valid(sample_rate) || - ( - sample_rate >= (1u << 16) && - !(sample_rate % 1000 == 0 || sample_rate % 10 == 0) - ) + if( // sample rate is not subset if + !FLAC__format_sample_rate_is_valid(sample_rate) || // sample rate is invalid or + sample_rate >= ((1u << 16) * 10) || // sample rate is larger then or equal to 655360 or + (sample_rate >= (1u << 16) && sample_rate % 10 != 0) //sample rate is >= 65536 and not divisible by 10 ) { return false; } @@ -570,13 +577,18 @@ void FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(FLAC__En FLAC__format_entropy_coding_method_partitioned_rice_contents_init(object); } +#if defined(_MSC_VER) +// silence three MSVC warnings 'result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)' +#pragma warning ( disable : 4334 ) +#endif + FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(FLAC__EntropyCodingMethod_PartitionedRiceContents *object, uint32_t max_partition_order) { FLAC__ASSERT(0 != object); FLAC__ASSERT(object->capacity_by_order > 0 || (0 == object->parameters && 0 == object->raw_bits)); - if(object->capacity_by_order < max_partition_order) { + if(object->capacity_by_order < max_partition_order || object->parameters == NULL || object->raw_bits == NULL) { if(0 == (object->parameters = safe_realloc_(object->parameters, sizeof(uint32_t)*(1 << max_partition_order)))) return false; if(0 == (object->raw_bits = safe_realloc_(object->raw_bits, sizeof(uint32_t)*(1 << max_partition_order)))) @@ -587,3 +599,7 @@ FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_s return true; } + +#if defined(_MSC_VER) +#pragma warning ( default : 4334 ) +#endif diff --git a/sys/src/cmd/audio/libFLAC/lpc.c b/sys/src/cmd/audio/libFLAC/lpc.c index 29555141e..eacfe48b1 100644 --- a/sys/src/cmd/audio/libFLAC/lpc.c +++ b/sys/src/cmd/audio/libFLAC/lpc.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,6 +35,7 @@ #endif #include <math.h> +#include <stdlib.h> #include "FLAC/assert.h" #include "FLAC/format.h" @@ -42,6 +43,7 @@ #include "private/bitmath.h" #include "private/lpc.h" #include "private/macros.h" + #if !defined(NDEBUG) || defined FLAC__OVERFLOW_DETECT || defined FLAC__OVERFLOW_DETECT_VERBOSE #include <stdio.h> #endif @@ -72,11 +74,46 @@ void FLAC__lpc_window_data(const FLAC__int32 in[], const FLAC__real window[], FL out[i] = in[i] * window[i]; } -void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]) +void FLAC__lpc_window_data_wide(const FLAC__int64 in[], const FLAC__real window[], FLAC__real out[], uint32_t data_len) +{ + uint32_t i; + for(i = 0; i < data_len; i++) + out[i] = in[i] * window[i]; +} + +void FLAC__lpc_window_data_partial(const FLAC__int32 in[], const FLAC__real window[], FLAC__real out[], uint32_t data_len, uint32_t part_size, uint32_t data_shift) +{ + uint32_t i, j; + if((part_size + data_shift) < data_len){ + for(i = 0; i < part_size; i++) + out[i] = in[data_shift+i] * window[i]; + i = flac_min(i,data_len - part_size - data_shift); + for(j = data_len - part_size; j < data_len; i++, j++) + out[i] = in[data_shift+i] * window[j]; + if(i < data_len) + out[i] = 0.0f; + } +} + +void FLAC__lpc_window_data_partial_wide(const FLAC__int64 in[], const FLAC__real window[], FLAC__real out[], uint32_t data_len, uint32_t part_size, uint32_t data_shift) +{ + uint32_t i, j; + if((part_size + data_shift) < data_len){ + for(i = 0; i < part_size; i++) + out[i] = in[data_shift+i] * window[i]; + i = flac_min(i,data_len - part_size - data_shift); + for(j = data_len - part_size; j < data_len; i++, j++) + out[i] = in[data_shift+i] * window[j]; + if(i < data_len) + out[i] = 0.0f; + } +} + +void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]) { /* a readable, but slower, version */ #if 0 - FLAC__real d; + double d; uint32_t i; FLAC__ASSERT(lag > 0); @@ -91,7 +128,7 @@ void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], uint32_t data_le */ while(lag--) { for(i = lag, d = 0.0; i < data_len; i++) - d += data[i] * data[i - lag]; + d += data[i] * (double)data[i - lag]; autoc[lag] = d; } #endif @@ -100,7 +137,7 @@ void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], uint32_t data_le * this version tends to run faster because of better data locality * ('data_len' is usually much larger than 'lag') */ - FLAC__real d; + double d; uint32_t sample, coeff; const uint32_t limit = data_len - lag; @@ -121,7 +158,7 @@ void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], uint32_t data_le } } -void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], uint32_t *max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], double error[]) +void FLAC__lpc_compute_lp_coefficients(const double autoc[], uint32_t *max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], double error[]) { uint32_t i, j; double r, err, lpc[FLAC__MAX_LPC_ORDER]; @@ -547,10 +584,6 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f history = data; for(j = 0; j < order; j++) sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history)); - if(FLAC__bitmath_silog2(sum >> lp_quantization) > 32) { - fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, sum=%" PRId64 "\n", i, (sum >> lp_quantization)); - break; - } if(FLAC__bitmath_silog2((FLAC__int64)(*data) - (sum >> lp_quantization)) > 32) { fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=%" PRId64 ", residual=%" PRId64 "\n", i, *data, (int64_t)(sum >> lp_quantization), ((FLAC__int64)(*data) - (sum >> lp_quantization))); break; @@ -589,7 +622,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; - residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + residual[i] = data[i] - (sum >> lp_quantization); } } else { /* order == 11 */ @@ -606,7 +639,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; - residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + residual[i] = data[i] - (sum >> lp_quantization); } } } @@ -624,7 +657,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; - residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + residual[i] = data[i] - (sum >> lp_quantization); } } else { /* order == 9 */ @@ -639,7 +672,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; - residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + residual[i] = data[i] - (sum >> lp_quantization); } } } @@ -657,7 +690,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; - residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + residual[i] = data[i] - (sum >> lp_quantization); } } else { /* order == 7 */ @@ -670,7 +703,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; - residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + residual[i] = data[i] - (sum >> lp_quantization); } } } @@ -684,7 +717,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; - residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + residual[i] = data[i] - (sum >> lp_quantization); } } else { /* order == 5 */ @@ -695,7 +728,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; - residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + residual[i] = data[i] - (sum >> lp_quantization); } } } @@ -709,7 +742,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; - residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + residual[i] = data[i] - (sum >> lp_quantization); } } else { /* order == 3 */ @@ -718,7 +751,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; - residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + residual[i] = data[i] - (sum >> lp_quantization); } } } @@ -728,12 +761,12 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f sum = 0; sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; - residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + residual[i] = data[i] - (sum >> lp_quantization); } } else { /* order == 1 */ for(i = 0; i < (int)data_len; i++) - residual[i] = data[i] - (FLAC__int32)((qlp_coeff[0] * (FLAC__int64)data[i-1]) >> lp_quantization); + residual[i] = data[i] - ((qlp_coeff[0] * (FLAC__int64)data[i-1]) >> lp_quantization); } } } @@ -775,14 +808,154 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f sum += qlp_coeff[ 1] * (FLAC__int64)data[i- 2]; sum += qlp_coeff[ 0] * (FLAC__int64)data[i- 1]; } - residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + residual[i] = data[i] - (sum >> lp_quantization); } } } #endif +FLAC__bool FLAC__lpc_compute_residual_from_qlp_coefficients_limit_residual(const FLAC__int32 * flac_restrict data, uint32_t data_len, const FLAC__int32 * flac_restrict qlp_coeff, uint32_t order, int lp_quantization, FLAC__int32 * flac_restrict residual) +{ + int i; + FLAC__int64 sum, residual_to_check; + + FLAC__ASSERT(order > 0); + FLAC__ASSERT(order <= 32); + + for(i = 0; i < (int)data_len; i++) { + sum = 0; + switch(order) { + case 32: sum += qlp_coeff[31] * (FLAC__int64)data[i-32]; /* Falls through. */ + case 31: sum += qlp_coeff[30] * (FLAC__int64)data[i-31]; /* Falls through. */ + case 30: sum += qlp_coeff[29] * (FLAC__int64)data[i-30]; /* Falls through. */ + case 29: sum += qlp_coeff[28] * (FLAC__int64)data[i-29]; /* Falls through. */ + case 28: sum += qlp_coeff[27] * (FLAC__int64)data[i-28]; /* Falls through. */ + case 27: sum += qlp_coeff[26] * (FLAC__int64)data[i-27]; /* Falls through. */ + case 26: sum += qlp_coeff[25] * (FLAC__int64)data[i-26]; /* Falls through. */ + case 25: sum += qlp_coeff[24] * (FLAC__int64)data[i-25]; /* Falls through. */ + case 24: sum += qlp_coeff[23] * (FLAC__int64)data[i-24]; /* Falls through. */ + case 23: sum += qlp_coeff[22] * (FLAC__int64)data[i-23]; /* Falls through. */ + case 22: sum += qlp_coeff[21] * (FLAC__int64)data[i-22]; /* Falls through. */ + case 21: sum += qlp_coeff[20] * (FLAC__int64)data[i-21]; /* Falls through. */ + case 20: sum += qlp_coeff[19] * (FLAC__int64)data[i-20]; /* Falls through. */ + case 19: sum += qlp_coeff[18] * (FLAC__int64)data[i-19]; /* Falls through. */ + case 18: sum += qlp_coeff[17] * (FLAC__int64)data[i-18]; /* Falls through. */ + case 17: sum += qlp_coeff[16] * (FLAC__int64)data[i-17]; /* Falls through. */ + case 16: sum += qlp_coeff[15] * (FLAC__int64)data[i-16]; /* Falls through. */ + case 15: sum += qlp_coeff[14] * (FLAC__int64)data[i-15]; /* Falls through. */ + case 14: sum += qlp_coeff[13] * (FLAC__int64)data[i-14]; /* Falls through. */ + case 13: sum += qlp_coeff[12] * (FLAC__int64)data[i-13]; /* Falls through. */ + case 12: sum += qlp_coeff[11] * (FLAC__int64)data[i-12]; /* Falls through. */ + case 11: sum += qlp_coeff[10] * (FLAC__int64)data[i-11]; /* Falls through. */ + case 10: sum += qlp_coeff[ 9] * (FLAC__int64)data[i-10]; /* Falls through. */ + case 9: sum += qlp_coeff[ 8] * (FLAC__int64)data[i- 9]; /* Falls through. */ + case 8: sum += qlp_coeff[ 7] * (FLAC__int64)data[i- 8]; /* Falls through. */ + case 7: sum += qlp_coeff[ 6] * (FLAC__int64)data[i- 7]; /* Falls through. */ + case 6: sum += qlp_coeff[ 5] * (FLAC__int64)data[i- 6]; /* Falls through. */ + case 5: sum += qlp_coeff[ 4] * (FLAC__int64)data[i- 5]; /* Falls through. */ + case 4: sum += qlp_coeff[ 3] * (FLAC__int64)data[i- 4]; /* Falls through. */ + case 3: sum += qlp_coeff[ 2] * (FLAC__int64)data[i- 3]; /* Falls through. */ + case 2: sum += qlp_coeff[ 1] * (FLAC__int64)data[i- 2]; /* Falls through. */ + case 1: sum += qlp_coeff[ 0] * (FLAC__int64)data[i- 1]; + } + residual_to_check = data[i] - (sum >> lp_quantization); + /* residual must not be INT32_MIN because abs(INT32_MIN) is undefined */ + if(residual_to_check <= INT32_MIN || residual_to_check > INT32_MAX) + return false; + else + residual[i] = residual_to_check; + } + return true; +} + +FLAC__bool FLAC__lpc_compute_residual_from_qlp_coefficients_limit_residual_33bit(const FLAC__int64 * flac_restrict data, uint32_t data_len, const FLAC__int32 * flac_restrict qlp_coeff, uint32_t order, int lp_quantization, FLAC__int32 * flac_restrict residual) +{ + int i; + FLAC__int64 sum, residual_to_check; + + FLAC__ASSERT(order > 0); + FLAC__ASSERT(order <= 32); + + for(i = 0; i < (int)data_len; i++) { + sum = 0; + switch(order) { + case 32: sum += qlp_coeff[31] * data[i-32]; /* Falls through. */ + case 31: sum += qlp_coeff[30] * data[i-31]; /* Falls through. */ + case 30: sum += qlp_coeff[29] * data[i-30]; /* Falls through. */ + case 29: sum += qlp_coeff[28] * data[i-29]; /* Falls through. */ + case 28: sum += qlp_coeff[27] * data[i-28]; /* Falls through. */ + case 27: sum += qlp_coeff[26] * data[i-27]; /* Falls through. */ + case 26: sum += qlp_coeff[25] * data[i-26]; /* Falls through. */ + case 25: sum += qlp_coeff[24] * data[i-25]; /* Falls through. */ + case 24: sum += qlp_coeff[23] * data[i-24]; /* Falls through. */ + case 23: sum += qlp_coeff[22] * data[i-23]; /* Falls through. */ + case 22: sum += qlp_coeff[21] * data[i-22]; /* Falls through. */ + case 21: sum += qlp_coeff[20] * data[i-21]; /* Falls through. */ + case 20: sum += qlp_coeff[19] * data[i-20]; /* Falls through. */ + case 19: sum += qlp_coeff[18] * data[i-19]; /* Falls through. */ + case 18: sum += qlp_coeff[17] * data[i-18]; /* Falls through. */ + case 17: sum += qlp_coeff[16] * data[i-17]; /* Falls through. */ + case 16: sum += qlp_coeff[15] * data[i-16]; /* Falls through. */ + case 15: sum += qlp_coeff[14] * data[i-15]; /* Falls through. */ + case 14: sum += qlp_coeff[13] * data[i-14]; /* Falls through. */ + case 13: sum += qlp_coeff[12] * data[i-13]; /* Falls through. */ + case 12: sum += qlp_coeff[11] * data[i-12]; /* Falls through. */ + case 11: sum += qlp_coeff[10] * data[i-11]; /* Falls through. */ + case 10: sum += qlp_coeff[ 9] * data[i-10]; /* Falls through. */ + case 9: sum += qlp_coeff[ 8] * data[i- 9]; /* Falls through. */ + case 8: sum += qlp_coeff[ 7] * data[i- 8]; /* Falls through. */ + case 7: sum += qlp_coeff[ 6] * data[i- 7]; /* Falls through. */ + case 6: sum += qlp_coeff[ 5] * data[i- 6]; /* Falls through. */ + case 5: sum += qlp_coeff[ 4] * data[i- 5]; /* Falls through. */ + case 4: sum += qlp_coeff[ 3] * data[i- 4]; /* Falls through. */ + case 3: sum += qlp_coeff[ 2] * data[i- 3]; /* Falls through. */ + case 2: sum += qlp_coeff[ 1] * data[i- 2]; /* Falls through. */ + case 1: sum += qlp_coeff[ 0] * data[i- 1]; + } + residual_to_check = data[i] - (sum >> lp_quantization); + /* residual must not be INT32_MIN because abs(INT32_MIN) is undefined */ + if(residual_to_check <= INT32_MIN || residual_to_check > INT32_MAX) + return false; + else + residual[i] = residual_to_check; + } + return true; +} + #endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ +uint32_t FLAC__lpc_max_prediction_before_shift_bps(uint32_t subframe_bps, const FLAC__int32 * flac_restrict qlp_coeff, uint32_t order) +{ + /* This used to be subframe_bps + qlp_coeff_precision + FLAC__bitmath_ilog2(order) + * but that treats both the samples as well as the predictor as unknown. The + * predictor is known however, so taking the log2 of the sum of the absolute values + * of all coefficients is a more accurate representation of the predictor */ + FLAC__int32 abs_sum_of_qlp_coeff = 0; + for(uint32_t i = 0; i < order; i++) + abs_sum_of_qlp_coeff += abs(qlp_coeff[i]); + if(abs_sum_of_qlp_coeff == 0) + abs_sum_of_qlp_coeff = 1; + return subframe_bps + FLAC__bitmath_silog2(abs_sum_of_qlp_coeff); +} + + +uint32_t FLAC__lpc_max_residual_bps(uint32_t subframe_bps, const FLAC__int32 * flac_restrict qlp_coeff, uint32_t order, int lp_quantization) +{ + FLAC__int32 predictor_sum_bps = FLAC__lpc_max_prediction_before_shift_bps(subframe_bps, qlp_coeff, order) - lp_quantization; + if((int)subframe_bps > predictor_sum_bps) + return subframe_bps + 1; + else + return predictor_sum_bps + 1; +} + +#ifdef FUZZING_BUILD_MODE_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW +/* The attribute below is to silence the undefined sanitizer of oss-fuzz. + * Because fuzzing feeds bogus predictors and residual samples to the + * decoder, having overflows in this section is unavoidable. Also, + * because the calculated values are audio path only, there is no + * potential for security problems */ +__attribute__((no_sanitize("signed-integer-overflow"))) +#endif void FLAC__lpc_restore_signal(const FLAC__int32 * flac_restrict residual, uint32_t data_len, const FLAC__int32 * flac_restrict qlp_coeff, uint32_t order, int lp_quantization, FLAC__int32 * flac_restrict data) #if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS) { @@ -806,8 +979,10 @@ void FLAC__lpc_restore_signal(const FLAC__int32 * flac_restrict residual, uint32 for(j = 0; j < order; j++) { sum += qlp_coeff[j] * (*(--history)); sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history); +#ifdef FLAC__OVERFLOW_DETECT if(sumo > 2147483647ll || sumo < -2147483648ll) fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%" PRId64 "\n",i,j,qlp_coeff[j],*history,sumo); +#endif } *(data++) = *(r++) + (sum >> lp_quantization); } @@ -1064,15 +1239,13 @@ void FLAC__lpc_restore_signal_wide(const FLAC__int32 * flac_restrict residual, u history = data; for(j = 0; j < order; j++) sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history)); - if(FLAC__bitmath_silog2(sum >> lp_quantization) > 32) { - fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, sum=%" PRId64 "\n", i, (sum >> lp_quantization)); - break; - } +#ifdef FLAC__OVERFLOW_DETECT if(FLAC__bitmath_silog2((FLAC__int64)(*r) + (sum >> lp_quantization)) > 32) { fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=%" PRId64 ", data=%" PRId64 "\n", i, *r, (sum >> lp_quantization), ((FLAC__int64)(*r) + (sum >> lp_quantization))); break; } - *(data++) = *(r++) + (FLAC__int32)(sum >> lp_quantization); +#endif + *(data++) = (FLAC__int32)(*(r++) + (sum >> lp_quantization)); } } #else /* fully unrolled version for normal use */ @@ -1250,7 +1423,7 @@ void FLAC__lpc_restore_signal_wide(const FLAC__int32 * flac_restrict residual, u } else { /* order == 1 */ for(i = 0; i < (int)data_len; i++) - data[i] = residual[i] + (FLAC__int32)((qlp_coeff[0] * (FLAC__int64)data[i-1]) >> lp_quantization); + data[i] = (FLAC__int32)(residual[i] + ((qlp_coeff[0] * (FLAC__int64)data[i-1]) >> lp_quantization)); } } } @@ -1298,6 +1471,87 @@ void FLAC__lpc_restore_signal_wide(const FLAC__int32 * flac_restrict residual, u } #endif +#ifdef FUZZING_BUILD_MODE_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW +/* The attribute below is to silence the undefined sanitizer of oss-fuzz. + * Because fuzzing feeds bogus predictors and residual samples to the + * decoder, having overflows in this section is unavoidable. Also, + * because the calculated values are audio path only, there is no + * potential for security problems */ +__attribute__((no_sanitize("signed-integer-overflow"))) +#endif +void FLAC__lpc_restore_signal_wide_33bit(const FLAC__int32 * flac_restrict residual, uint32_t data_len, const FLAC__int32 * flac_restrict qlp_coeff, uint32_t order, int lp_quantization, FLAC__int64 * flac_restrict data) +#if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS) +{ + uint32_t i, j; + FLAC__int64 sum; + const FLAC__int32 *r = residual; + const FLAC__int64 *history; + + FLAC__ASSERT(order > 0); + + for(i = 0; i < data_len; i++) { + sum = 0; + history = data; + for(j = 0; j < order; j++) + sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history)); +#ifdef FLAC__OVERFLOW_DETECT + if(FLAC__bitmath_silog2((FLAC__int64)(*r) + (sum >> lp_quantization)) > 33) { + fprintf(stderr,"FLAC__lpc_restore_signal_33bit: OVERFLOW, i=%u, residual=%d, sum=%" PRId64 ", data=%" PRId64 "\n", i, *r, (sum >> lp_quantization), ((FLAC__int64)(*r) + (sum >> lp_quantization))); + break; + } +#endif + *(data++) = (FLAC__int64)(*(r++)) + (sum >> lp_quantization); + } +} +#else /* unrolled version for normal use */ +{ + int i; + FLAC__int64 sum; + + FLAC__ASSERT(order > 0); + FLAC__ASSERT(order <= 32); + + for(i = 0; i < (int)data_len; i++) { + sum = 0; + switch(order) { + case 32: sum += qlp_coeff[31] * data[i-32]; /* Falls through. */ + case 31: sum += qlp_coeff[30] * data[i-31]; /* Falls through. */ + case 30: sum += qlp_coeff[29] * data[i-30]; /* Falls through. */ + case 29: sum += qlp_coeff[28] * data[i-29]; /* Falls through. */ + case 28: sum += qlp_coeff[27] * data[i-28]; /* Falls through. */ + case 27: sum += qlp_coeff[26] * data[i-27]; /* Falls through. */ + case 26: sum += qlp_coeff[25] * data[i-26]; /* Falls through. */ + case 25: sum += qlp_coeff[24] * data[i-25]; /* Falls through. */ + case 24: sum += qlp_coeff[23] * data[i-24]; /* Falls through. */ + case 23: sum += qlp_coeff[22] * data[i-23]; /* Falls through. */ + case 22: sum += qlp_coeff[21] * data[i-22]; /* Falls through. */ + case 21: sum += qlp_coeff[20] * data[i-21]; /* Falls through. */ + case 20: sum += qlp_coeff[19] * data[i-20]; /* Falls through. */ + case 19: sum += qlp_coeff[18] * data[i-19]; /* Falls through. */ + case 18: sum += qlp_coeff[17] * data[i-18]; /* Falls through. */ + case 17: sum += qlp_coeff[16] * data[i-17]; /* Falls through. */ + case 16: sum += qlp_coeff[15] * data[i-16]; /* Falls through. */ + case 15: sum += qlp_coeff[14] * data[i-15]; /* Falls through. */ + case 14: sum += qlp_coeff[13] * data[i-14]; /* Falls through. */ + case 13: sum += qlp_coeff[12] * data[i-13]; /* Falls through. */ + case 12: sum += qlp_coeff[11] * data[i-12]; /* Falls through. */ + case 11: sum += qlp_coeff[10] * data[i-11]; /* Falls through. */ + case 10: sum += qlp_coeff[ 9] * data[i-10]; /* Falls through. */ + case 9: sum += qlp_coeff[ 8] * data[i- 9]; /* Falls through. */ + case 8: sum += qlp_coeff[ 7] * data[i- 8]; /* Falls through. */ + case 7: sum += qlp_coeff[ 6] * data[i- 7]; /* Falls through. */ + case 6: sum += qlp_coeff[ 5] * data[i- 6]; /* Falls through. */ + case 5: sum += qlp_coeff[ 4] * data[i- 5]; /* Falls through. */ + case 4: sum += qlp_coeff[ 3] * data[i- 4]; /* Falls through. */ + case 3: sum += qlp_coeff[ 2] * data[i- 3]; /* Falls through. */ + case 2: sum += qlp_coeff[ 1] * data[i- 2]; /* Falls through. */ + case 1: sum += qlp_coeff[ 0] * data[i- 1]; + } + data[i] = residual[i] + (sum >> lp_quantization); + } +} +#endif + #if defined(_MSC_VER) #pragma warning ( default : 4028 ) #endif diff --git a/sys/src/cmd/audio/libFLAC/memory.c b/sys/src/cmd/audio/libFLAC/memory.c index 4d320a437..d0aa83775 100644 --- a/sys/src/cmd/audio/libFLAC/memory.c +++ b/sys/src/cmd/audio/libFLAC/memory.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -118,6 +118,35 @@ FLAC__bool FLAC__memory_alloc_aligned_uint32_array(size_t elements, FLAC__uint32 } } +FLAC__bool FLAC__memory_alloc_aligned_int64_array(size_t elements, FLAC__int64 **unaligned_pointer, FLAC__int64 **aligned_pointer) +{ + FLAC__int64 *pu; /* unaligned pointer */ + union { /* union needed to comply with C99 pointer aliasing rules */ + FLAC__int64 *pa; /* aligned pointer */ + void *pv; /* aligned pointer alias */ + } u; + + FLAC__ASSERT(elements > 0); + FLAC__ASSERT(0 != unaligned_pointer); + FLAC__ASSERT(0 != aligned_pointer); + FLAC__ASSERT(unaligned_pointer != aligned_pointer); + + if(elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ + return false; + + pu = FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); + if(0 == pu) { + return false; + } + else { + if(*unaligned_pointer != 0) + free(*unaligned_pointer); + *unaligned_pointer = pu; + *aligned_pointer = u.pa; + return true; + } +} + FLAC__bool FLAC__memory_alloc_aligned_uint64_array(size_t elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer) { FLAC__uint64 *pu; /* unaligned pointer */ diff --git a/sys/src/cmd/audio/libFLAC/metadata_iterators.c b/sys/src/cmd/audio/libFLAC/metadata_iterators.c index 17f25cd6e..168a3fbc2 100644 --- a/sys/src/cmd/audio/libFLAC/metadata_iterators.c +++ b/sys/src/cmd/audio/libFLAC/metadata_iterators.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -286,26 +286,29 @@ FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__Strea do { if(FLAC__metadata_simple_iterator_get_block_type(it) == FLAC__METADATA_TYPE_PICTURE) { FLAC__StreamMetadata *obj = FLAC__metadata_simple_iterator_get_block(it); - FLAC__uint64 area = (FLAC__uint64)obj->data.picture.width * (FLAC__uint64)obj->data.picture.height; - /* check constraints */ - if( - (type == (FLAC__StreamMetadata_Picture_Type)(-1) || type == obj->data.picture.type) && - (mime_type == 0 || !strcmp(mime_type, obj->data.picture.mime_type)) && - (description == 0 || !strcmp((const char *)description, (const char *)obj->data.picture.description)) && - obj->data.picture.width <= max_width && - obj->data.picture.height <= max_height && - obj->data.picture.depth <= max_depth && - obj->data.picture.colors <= max_colors && - (area > max_area_seen || (area == max_area_seen && obj->data.picture.depth > max_depth_seen)) - ) { - if(*picture) - FLAC__metadata_object_delete(*picture); - *picture = obj; - max_area_seen = area; - max_depth_seen = obj->data.picture.depth; - } - else { - FLAC__metadata_object_delete(obj); + if(0 != obj) { + FLAC__uint64 area = (FLAC__uint64)obj->data.picture.width * (FLAC__uint64)obj->data.picture.height; + + /* check constraints */ + if( + (type == (FLAC__StreamMetadata_Picture_Type)(-1) || type == obj->data.picture.type) && + (mime_type == 0 || !strcmp(mime_type, obj->data.picture.mime_type)) && + (description == 0 || !strcmp((const char *)description, (const char *)obj->data.picture.description)) && + obj->data.picture.width <= max_width && + obj->data.picture.height <= max_height && + obj->data.picture.depth <= max_depth && + obj->data.picture.colors <= max_colors && + (area > max_area_seen || (area == max_area_seen && obj->data.picture.depth > max_depth_seen)) + ) { + if(*picture) + FLAC__metadata_object_delete(*picture); + *picture = obj; + max_area_seen = area; + max_depth_seen = obj->data.picture.depth; + } + else { + FLAC__metadata_object_delete(obj); + } } } } while(FLAC__metadata_simple_iterator_next(it)); @@ -443,7 +446,15 @@ static FLAC__bool simple_iterator_prime_input_(FLAC__Metadata_SimpleIterator *it case 0: iterator->depth = 0; iterator->first_offset = iterator->offset[iterator->depth] = ftello(iterator->file); - return read_metadata_block_header_(iterator); + ret = read_metadata_block_header_(iterator); + /* The first metadata block must be a streaminfo. If this is not the + * case, the file is invalid and assumptions made elsewhere in the + * code are invalid */ + if(iterator->type != FLAC__METADATA_TYPE_STREAMINFO) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA; + return false; + } + return ret; case 1: iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; return false; @@ -576,7 +587,7 @@ FLAC_API off_t FLAC__metadata_simple_iterator_get_block_offset(const FLAC__Metad FLAC__ASSERT(0 != iterator); FLAC__ASSERT(0 != iterator->file); - return iterator->offset[iterator->depth]; + return (off_t)iterator->offset[iterator->depth]; } FLAC_API FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const FLAC__Metadata_SimpleIterator *iterator) @@ -1099,6 +1110,11 @@ static FLAC__bool chain_merge_adjacent_padding_(FLAC__Metadata_Chain *chain, FLA return false; } +#if defined(_MSC_VER) +// silence three MSVC warnings 'conversion from 'conversion from 'const __int64' to 'uint32_t', possible loss of data' +#pragma warning ( disable : 4244 ) +#endif + /* Returns the new length of the chain, or 0 if there was an error. */ /* WATCHOUT: This can get called multiple times before a write, so * it should still work when this happens. @@ -1176,6 +1192,10 @@ static FLAC__off_t chain_prepare_for_write_(FLAC__Metadata_Chain *chain, FLAC__b return current_length; } +#if defined(_MSC_VER) +#pragma warning ( default : 4244 ) +#endif + static FLAC__bool chain_read_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__IOCallback_Tell tell_cb) { FLAC__Metadata_Node *node; @@ -1348,6 +1368,12 @@ static FLAC__bool chain_read_ogg_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle chain->initial_length = chain_calculate_length_(chain); + if(chain->initial_length == 0) { + /* Ogg FLAC file must have at least streaminfo and vorbis comment */ + chain->status = FLAC__METADATA_CHAIN_STATUS_BAD_METADATA; + return false; + } + return true; } @@ -1625,6 +1651,11 @@ typedef enum { LBS_BLOCK_REMOVED } LastBlockState; +#if defined(_MSC_VER) +// silence three MSVC warnings 'conversion from 'conversion from 'const __int64' to 'uint32_t', possible loss of data' +#pragma warning ( disable : 4244 ) +#endif + FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding) { /* This does all the same checks that are in chain_prepare_for_write_() @@ -1702,6 +1733,10 @@ FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata return (current_length != chain->initial_length); } +#if defined(_MSC_VER) +#pragma warning ( default : 4244 ) +#endif + FLAC_API FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats) { struct flac_stat_s stats; @@ -2284,18 +2319,13 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entr if(0 != entry->entry) free(entry->entry); - if(entry->length == 0) { - entry->entry = 0; - } - else { - if(0 == (entry->entry = safe_malloc_add_2op_(entry->length, /*+*/1))) - return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + if(0 == (entry->entry = safe_malloc_add_2op_(entry->length, /*+*/1))) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; - if(read_cb(entry->entry, 1, entry->length, handle) != entry->length) - return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + if(entry->length > 0 && read_cb(entry->entry, 1, entry->length, handle) != entry->length) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; - entry->entry[entry->length] = '\0'; - } + entry->entry[entry->length] = '\0'; return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; } @@ -2326,6 +2356,11 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_( if(block->num_comments == 0) { block->comments = 0; } + else if(block->num_comments > (block_length >> 2)) { /* each comment needs at least 4 byte */ + block->num_comments = 0; + status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA; + goto skip; + } else if(0 == (block->comments = calloc(block->num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { block->num_comments = 0; return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; @@ -2482,6 +2517,9 @@ static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cstr return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; *length = unpack_uint32_(buffer, length_len); + if(*length > (1u << FLAC__STREAM_METADATA_LENGTH_LEN)) /* data cannot be larger than FLAC metadata block */ + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA; + if(0 != *data) free(*data); @@ -3422,7 +3460,7 @@ FLAC__bool get_file_stats_(const char *filename, struct flac_stat_s *stats) void set_file_stats_(const char *filename, struct flac_stat_s *stats) { -#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L) +#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L) && !defined(_WIN32) struct timespec srctime[2] = {}; srctime[0].tv_sec = stats->st_atime; srctime[1].tv_sec = stats->st_mtime; diff --git a/sys/src/cmd/audio/libFLAC/metadata_object.c b/sys/src/cmd/audio/libFLAC/metadata_object.c index de8e5139f..c1e54ab22 100644 --- a/sys/src/cmd/audio/libFLAC/metadata_object.c +++ b/sys/src/cmd/audio/libFLAC/metadata_object.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -98,7 +98,7 @@ static FLAC__bool free_copy_bytes_(FLAC__byte **to, const FLAC__byte *from, uint /* realloc() failure leaves entry unchanged */ static FLAC__bool ensure_null_terminated_(FLAC__byte **entry, uint32_t length) { - FLAC__byte *x = safe_realloc_add_2op_(*entry, length, /*+*/1); + FLAC__byte *x = safe_realloc_nofree_add_2op_(*entry, length, /*+*/1); if (x != NULL) { x[length] = '\0'; *entry = x; @@ -130,7 +130,9 @@ static FLAC__bool copy_vcentry_(FLAC__StreamMetadata_VorbisComment_Entry *to, co to->length = from->length; if (from->entry == 0) { FLAC__ASSERT(from->length == 0); - to->entry = 0; + if ((to->entry = safe_malloc_(1)) == NULL) + return false; + to->entry[0] = '\0'; } else { FLAC__byte *x; @@ -950,8 +952,13 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMe free(object->data.seek_table.points); object->data.seek_table.points = 0; } - else if ((object->data.seek_table.points = safe_realloc_(object->data.seek_table.points, new_size)) == NULL) - return false; + else { + /* Leave object->data.seek_table.points untouched if realloc fails */ + FLAC__StreamMetadata_SeekPoint *tmpptr; + if ((tmpptr = realloc(object->data.seek_table.points, new_size)) == NULL) + return false; + object->data.seek_table.points = tmpptr; + } /* if growing, set new elements to placeholders */ if (new_size > old_size) { @@ -1124,7 +1131,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_point if (num > 32768) { /* Set the bound and recalculate samples accordingly. */ num = 32768; - samples = total_samples / num; + samples = (uint32_t)(total_samples / num); } i = seek_table->num_points; @@ -1171,8 +1178,18 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__St FLAC__ASSERT(object->data.vorbis_comment.num_comments == 0); if (new_num_comments == 0) return true; - else if ((object->data.vorbis_comment.comments = vorbiscomment_entry_array_new_(new_num_comments)) == NULL) - return false; + else { + if ((object->data.vorbis_comment.comments = vorbiscomment_entry_array_new_(new_num_comments)) == NULL) + return false; + for (uint32_t i = 0; i < new_num_comments; i++) { + object->data.vorbis_comment.comments[i].length = 0; + if ((object->data.vorbis_comment.comments[i].entry = safe_malloc_(1)) == NULL) { + object->data.vorbis_comment.num_comments = i+1; + return false; + } + object->data.vorbis_comment.comments[i].entry[0] = '\0'; + } + } } else { const size_t old_size = object->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry); @@ -1197,17 +1214,24 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__St object->data.vorbis_comment.comments = 0; } else { - FLAC__StreamMetadata_VorbisComment_Entry *oldptr = object->data.vorbis_comment.comments; - if ((object->data.vorbis_comment.comments = realloc(object->data.vorbis_comment.comments, new_size)) == NULL) { - vorbiscomment_entry_array_delete_(oldptr, object->data.vorbis_comment.num_comments); - object->data.vorbis_comment.num_comments = 0; + /* Leave object->data.vorbis_comment.comments untouched if realloc fails */ + FLAC__StreamMetadata_VorbisComment_Entry *tmpptr; + if ((tmpptr = realloc(object->data.vorbis_comment.comments, new_size)) == NULL) return false; - } + object->data.vorbis_comment.comments = tmpptr; } /* if growing, zero all the length/pointers of new elements */ - if (new_size > old_size) - memset(object->data.vorbis_comment.comments + object->data.vorbis_comment.num_comments, 0, new_size - old_size); + if (new_size > old_size) { + for (uint32_t i = object->data.vorbis_comment.num_comments; i < new_num_comments; i++) { + object->data.vorbis_comment.comments[i].length = 0; + if ((object->data.vorbis_comment.comments[i].entry = safe_malloc_(1)) == NULL) { + object->data.vorbis_comment.num_comments = i+1; + return false; + } + object->data.vorbis_comment.comments[i].entry[0] = '\0'; + } + } } object->data.vorbis_comment.num_comments = new_num_comments; @@ -1229,6 +1253,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__Stream FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__StreamMetadata *object, uint32_t comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy) { FLAC__StreamMetadata_VorbisComment *vc; + FLAC__StreamMetadata_VorbisComment_Entry temp; FLAC__ASSERT(object != NULL); FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); @@ -1243,9 +1268,10 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__Str return false; /* move all comments >= comment_num forward one space */ + /* reuse newly added empty comment */ + temp = vc->comments[vc->num_comments-1]; memmove(&vc->comments[comment_num+1], &vc->comments[comment_num], sizeof(FLAC__StreamMetadata_VorbisComment_Entry)*(vc->num_comments-1-comment_num)); - vc->comments[comment_num].length = 0; - vc->comments[comment_num].entry = 0; + vc->comments[comment_num] = temp; return FLAC__metadata_object_vorbiscomment_set_comment(object, comment_num, entry, copy); } @@ -1502,8 +1528,13 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__St free(track->indices); track->indices = 0; } - else if ((track->indices = safe_realloc_(track->indices, new_size)) == NULL) - return false; + else { + /* Leave track->indices untouched if realloc fails */ + FLAC__StreamMetadata_CueSheet_Index *tmpptr; + if ((tmpptr = realloc(track->indices, new_size)) == NULL) + return false; + track->indices = tmpptr; + } /* if growing, zero all the lengths/pointers of new elements */ if (new_size > old_size) @@ -1597,8 +1628,13 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMet free(object->data.cue_sheet.tracks); object->data.cue_sheet.tracks = 0; } - else if ((object->data.cue_sheet.tracks = safe_realloc_(object->data.cue_sheet.tracks, new_size)) == NULL) - return false; + else { + /* Leave object->data.cue_sheet.tracks untouched if realloc fails */ + FLAC__StreamMetadata_CueSheet_Track *tmpptr; + if ((tmpptr = realloc(object->data.cue_sheet.tracks, new_size)) == NULL) + return false; + object->data.cue_sheet.tracks = tmpptr; + } /* if growing, zero all the lengths/pointers of new elements */ if (new_size > old_size) diff --git a/sys/src/cmd/audio/libFLAC/mkfile b/sys/src/cmd/audio/libFLAC/mkfile index 4de6ac9ac..b71f7a157 100644 --- a/sys/src/cmd/audio/libFLAC/mkfile +++ b/sys/src/cmd/audio/libFLAC/mkfile @@ -26,6 +26,6 @@ OFILES=\ window.$O\ CC=pcc -CFLAGS=-I. -I../libogg -DPACKAGE_VERSION="1.3.4" -DPlan9 -DFLAC__NO_ASM -DFLAC__HAS_OGG -DFLAC__ALIGN_MALLOC_DATA -D_C99_SNPRINTF_EXTENSION -D_BSD_EXTENSION -D_POSIX_SOURCE -DHAVE_STDINT_H -DNDEBUG -c +CFLAGS=-I. -I../libogg -DPACKAGE_VERSION="1.4.0" -DPlan9 -DFLAC__NO_ASM -DFLAC__HAS_OGG -DFLAC__ALIGN_MALLOC_DATA -D_C99_SNPRINTF_EXTENSION -D_BSD_EXTENSION -Dcosf=cos -Dfabsf=fabs -D_POSIX_SOURCE -DHAVE_STDINT_H -DNDEBUG -c </sys/src/cmd/mklib diff --git a/sys/src/cmd/audio/libFLAC/ogg_decoder_aspect.c b/sys/src/cmd/audio/libFLAC/ogg_decoder_aspect.c index 7c814a24c..e331db305 100644 --- a/sys/src/cmd/audio/libFLAC/ogg_decoder_aspect.c +++ b/sys/src/cmd/audio/libFLAC/ogg_decoder_aspect.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec * Copyright (C) 2002-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/ogg_encoder_aspect.c b/sys/src/cmd/audio/libFLAC/ogg_encoder_aspect.c index a655da936..ae055c843 100644 --- a/sys/src/cmd/audio/libFLAC/ogg_encoder_aspect.c +++ b/sys/src/cmd/audio/libFLAC/ogg_encoder_aspect.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec * Copyright (C) 2002-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/ogg_helper.c b/sys/src/cmd/audio/libFLAC/ogg_helper.c index cbe5bc611..acd945ac3 100644 --- a/sys/src/cmd/audio/libFLAC/ogg_helper.c +++ b/sys/src/cmd/audio/libFLAC/ogg_helper.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec * Copyright (C) 2004-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/ogg_mapping.c b/sys/src/cmd/audio/libFLAC/ogg_mapping.c index f6de60096..1bd8c3cb5 100644 --- a/sys/src/cmd/audio/libFLAC/ogg_mapping.c +++ b/sys/src/cmd/audio/libFLAC/ogg_mapping.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec * Copyright (C) 2004-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/all.h b/sys/src/cmd/audio/libFLAC/private/all.h index 771596206..c64f9acd0 100644 --- a/sys/src/cmd/audio/libFLAC/private/all.h +++ b/sys/src/cmd/audio/libFLAC/private/all.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/bitmath.h b/sys/src/cmd/audio/libFLAC/private/bitmath.h index 12a3fb90e..b1dc4e86d 100644 --- a/sys/src/cmd/audio/libFLAC/private/bitmath.h +++ b/sys/src/cmd/audio/libFLAC/private/bitmath.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/bitreader.h b/sys/src/cmd/audio/libFLAC/private/bitreader.h index 585a5db26..694cefc65 100644 --- a/sys/src/cmd/audio/libFLAC/private/bitreader.h +++ b/sys/src/cmd/audio/libFLAC/private/bitreader.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -53,6 +53,8 @@ void FLAC__bitreader_delete(FLAC__BitReader *br); FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__BitReaderReadCallback rcb, void *cd); void FLAC__bitreader_free(FLAC__BitReader *br); /* does not 'free(br)' */ FLAC__bool FLAC__bitreader_clear(FLAC__BitReader *br); +void FLAC__bitreader_set_framesync_location(FLAC__BitReader *br); +FLAC__bool FLAC__bitreader_rewind_to_after_last_seen_framesync(FLAC__BitReader *br); void FLAC__bitreader_dump(const FLAC__BitReader *br, FILE *out); /* @@ -67,6 +69,10 @@ FLAC__uint16 FLAC__bitreader_get_read_crc16(FLAC__BitReader *br); FLAC__bool FLAC__bitreader_is_consumed_byte_aligned(const FLAC__BitReader *br); uint32_t FLAC__bitreader_bits_left_for_byte_alignment(const FLAC__BitReader *br); uint32_t FLAC__bitreader_get_input_bits_unconsumed(const FLAC__BitReader *br); +void FLAC__bitreader_set_limit(FLAC__BitReader *br, uint32_t limit); +void FLAC__bitreader_remove_limit(FLAC__BitReader *br); +uint32_t FLAC__bitreader_limit_remaining(FLAC__BitReader *br); +void FLAC__bitreader_limit_invalidate(FLAC__BitReader *br); /* * read functions @@ -75,6 +81,7 @@ uint32_t FLAC__bitreader_get_input_bits_unconsumed(const FLAC__BitReader *br); FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *val, uint32_t bits); FLAC__bool FLAC__bitreader_read_raw_int32(FLAC__BitReader *br, FLAC__int32 *val, uint32_t bits); FLAC__bool FLAC__bitreader_read_raw_uint64(FLAC__BitReader *br, FLAC__uint64 *val, uint32_t bits); +FLAC__bool FLAC__bitreader_read_raw_int64(FLAC__BitReader *br, FLAC__int64 *val, uint32_t bits); FLAC__bool FLAC__bitreader_read_uint32_little_endian(FLAC__BitReader *br, FLAC__uint32 *val); /*only for bits=32*/ FLAC__bool FLAC__bitreader_skip_bits_no_crc(FLAC__BitReader *br, uint32_t bits); /* WATCHOUT: does not CRC the skipped data! */ /*@@@@ add to unit tests */ FLAC__bool FLAC__bitreader_skip_byte_block_aligned_no_crc(FLAC__BitReader *br, uint32_t nvals); /* WATCHOUT: does not CRC the read data! */ diff --git a/sys/src/cmd/audio/libFLAC/private/bitwriter.h b/sys/src/cmd/audio/libFLAC/private/bitwriter.h index 672f282ad..a61bc431b 100644 --- a/sys/src/cmd/audio/libFLAC/private/bitwriter.h +++ b/sys/src/cmd/audio/libFLAC/private/bitwriter.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -83,6 +83,7 @@ FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, uint32_t bits); FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FLAC__uint32 val, uint32_t bits); FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, uint32_t bits); FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, uint32_t bits); +FLAC__bool FLAC__bitwriter_write_raw_int64(FLAC__BitWriter *bw, FLAC__int64 val, uint32_t bits); FLAC__bool FLAC__bitwriter_write_raw_uint32_little_endian(FLAC__BitWriter *bw, FLAC__uint32 val); /*only for bits=32*/ FLAC__bool FLAC__bitwriter_write_byte_block(FLAC__BitWriter *bw, const FLAC__byte vals[], uint32_t nvals); FLAC__bool FLAC__bitwriter_write_unary_unsigned(FLAC__BitWriter *bw, uint32_t val); diff --git a/sys/src/cmd/audio/libFLAC/private/cpu.h b/sys/src/cmd/audio/libFLAC/private/cpu.h index 0b50839f9..e5d23a7f1 100644 --- a/sys/src/cmd/audio/libFLAC/private/cpu.h +++ b/sys/src/cmd/audio/libFLAC/private/cpu.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -63,21 +63,25 @@ /* SSE intrinsics support by ICC/MSVC/GCC */ #if defined __INTEL_COMPILER #define FLAC__SSE_TARGET(x) + #define FLAC__FAST_MATH_TARGET(x) #define FLAC__SSE_SUPPORTED 1 #define FLAC__SSE2_SUPPORTED 1 #if (__INTEL_COMPILER >= 1000) /* Intel C++ Compiler 10.0 */ #define FLAC__SSSE3_SUPPORTED 1 #define FLAC__SSE4_1_SUPPORTED 1 #endif - #if (__INTEL_COMPILER >= 1110) /* Intel C++ Compiler 11.1 */ - #define FLAC__AVX_SUPPORTED 1 - #endif - #if (__INTEL_COMPILER >= 1300) /* Intel C++ Compiler 13.0 */ - #define FLAC__AVX2_SUPPORTED 1 - #define FLAC__FMA_SUPPORTED 1 + #ifdef FLAC__USE_AVX + #if (__INTEL_COMPILER >= 1110) /* Intel C++ Compiler 11.1 */ + #define FLAC__AVX_SUPPORTED 1 + #endif + #if (__INTEL_COMPILER >= 1300) /* Intel C++ Compiler 13.0 */ + #define FLAC__AVX2_SUPPORTED 1 + #define FLAC__FMA_SUPPORTED 1 + #endif #endif #elif defined __clang__ && __has_attribute(__target__) /* clang */ #define FLAC__SSE_TARGET(x) __attribute__ ((__target__ (x))) + #define FLAC__FAST_MATH_TARGET(x) __attribute__ ((__target__ (x), optimize("-ffast-math"))) #if __has_builtin(__builtin_ia32_maxps) #define FLAC__SSE_SUPPORTED 1 #endif @@ -90,17 +94,20 @@ #if __has_builtin(__builtin_ia32_pmuldq128) #define FLAC__SSE4_1_SUPPORTED 1 #endif - #if __has_builtin(__builtin_ia32_maxps256) - #define FLAC__AVX_SUPPORTED 1 - #endif - #if __has_builtin(__builtin_ia32_pabsd256) - #define FLAC__AVX2_SUPPORTED 1 - #endif - #if __has_builtin(__builtin_ia32_vfmaddps) - #define FLAC__FMA_SUPPORTED 1 + #ifdef FLAC__USE_AVX + #if __has_builtin(__builtin_ia32_maxps256) + #define FLAC__AVX_SUPPORTED 1 + #endif + #if __has_builtin(__builtin_ia32_pabsd256) + #define FLAC__AVX2_SUPPORTED 1 + #endif + #if __has_builtin(__builtin_ia32_vfmaddps) + #define FLAC__FMA_SUPPORTED 1 + #endif #endif #elif defined __GNUC__ && !defined __clang__ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) /* GCC 4.9+ */ #define FLAC__SSE_TARGET(x) __attribute__ ((__target__ (x))) + #define FLAC__FAST_MATH_TARGET(x) __attribute__ ((__target__ (x), optimize("-ffast-math"))) #define FLAC__SSE_SUPPORTED 1 #define FLAC__SSE2_SUPPORTED 1 #define FLAC__SSSE3_SUPPORTED 1 @@ -112,21 +119,25 @@ #endif #elif defined _MSC_VER #define FLAC__SSE_TARGET(x) + #define FLAC__FAST_MATH_TARGET(x) #define FLAC__SSE_SUPPORTED 1 #define FLAC__SSE2_SUPPORTED 1 #if (_MSC_VER >= 1500) /* MS Visual Studio 2008 */ #define FLAC__SSSE3_SUPPORTED 1 #define FLAC__SSE4_1_SUPPORTED 1 #endif - #if (_MSC_FULL_VER >= 160040219) /* MS Visual Studio 2010 SP1 */ - #define FLAC__AVX_SUPPORTED 1 - #endif - #if (_MSC_VER >= 1700) /* MS Visual Studio 2012 */ - #define FLAC__AVX2_SUPPORTED 1 - #define FLAC__FMA_SUPPORTED 1 + #ifdef FLAC__USE_AVX + #if (_MSC_FULL_VER >= 160040219) /* MS Visual Studio 2010 SP1 */ + #define FLAC__AVX_SUPPORTED 1 + #endif + #if (_MSC_VER >= 1700) /* MS Visual Studio 2012 */ + #define FLAC__AVX2_SUPPORTED 1 + #define FLAC__FMA_SUPPORTED 1 + #endif #endif #else #define FLAC__SSE_TARGET(x) + #define FLAC__FAST_MATH_TARGET(x) #ifdef __SSE__ #define FLAC__SSE_SUPPORTED 1 #endif @@ -139,14 +150,16 @@ #ifdef __SSE4_1__ #define FLAC__SSE4_1_SUPPORTED 1 #endif - #ifdef __AVX__ - #define FLAC__AVX_SUPPORTED 1 - #endif - #ifdef __AVX2__ - #define FLAC__AVX2_SUPPORTED 1 - #endif - #ifdef __FMA__ - #define FLAC__FMA_SUPPORTED 1 + #ifdef FLAC__USE_AVX + #ifdef __AVX__ + #define FLAC__AVX_SUPPORTED 1 + #endif + #ifdef __AVX2__ + #define FLAC__AVX2_SUPPORTED 1 + #endif + #ifdef __FMA__ + #define FLAC__FMA_SUPPORTED 1 + #endif #endif #endif /* compiler version */ #endif /* intrinsics support */ diff --git a/sys/src/cmd/audio/libFLAC/private/crc.h b/sys/src/cmd/audio/libFLAC/private/crc.h index 5fc7e5eec..8c8fcd4c1 100644 --- a/sys/src/cmd/audio/libFLAC/private/crc.h +++ b/sys/src/cmd/audio/libFLAC/private/crc.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2018 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/fixed.h b/sys/src/cmd/audio/libFLAC/private/fixed.h index 9edf0abdc..aa742cac0 100644 --- a/sys/src/cmd/audio/libFLAC/private/fixed.h +++ b/sys/src/cmd/audio/libFLAC/private/fixed.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -56,6 +56,8 @@ #ifndef FLAC__INTEGER_ONLY_LIBRARY uint32_t FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); uint32_t FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +uint32_t FLAC__fixed_compute_best_predictor_limit_residual(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +uint32_t FLAC__fixed_compute_best_predictor_limit_residual_33bit(const FLAC__int64 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); # ifndef FLAC__NO_ASM # if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN # ifdef FLAC__SSE2_SUPPORTED @@ -74,6 +76,8 @@ uint32_t FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov(const FLAC__int32 #else uint32_t FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); uint32_t FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +uint32_t FLAC__fixed_compute_best_predictor_limit_residual(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +uint32_t FLAC__fixed_compute_best_predictor_limit_residual_33bit(const FLAC__int64 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); #endif /* @@ -88,6 +92,8 @@ uint32_t FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], uint3 * OUT residual[0,data_len-1] residual signal */ void FLAC__fixed_compute_residual(const FLAC__int32 data[], uint32_t data_len, uint32_t order, FLAC__int32 residual[]); +void FLAC__fixed_compute_residual_wide(const FLAC__int32 data[], uint32_t data_len, uint32_t order, FLAC__int32 residual[]); +void FLAC__fixed_compute_residual_wide_33bit(const FLAC__int64 data[], uint32_t data_len, uint32_t order, FLAC__int32 residual[]); /* * FLAC__fixed_restore_signal() @@ -103,5 +109,7 @@ void FLAC__fixed_compute_residual(const FLAC__int32 data[], uint32_t data_len, u * OUT data[0,data_len-1] original signal */ void FLAC__fixed_restore_signal(const FLAC__int32 residual[], uint32_t data_len, uint32_t order, FLAC__int32 data[]); +void FLAC__fixed_restore_signal_wide(const FLAC__int32 residual[], uint32_t data_len, uint32_t order, FLAC__int32 data[]); +void FLAC__fixed_restore_signal_wide_33bit(const FLAC__int32 residual[], uint32_t data_len, uint32_t order, FLAC__int64 data[]); #endif diff --git a/sys/src/cmd/audio/libFLAC/private/float.h b/sys/src/cmd/audio/libFLAC/private/float.h index cb32da402..096db7d2f 100644 --- a/sys/src/cmd/audio/libFLAC/private/float.h +++ b/sys/src/cmd/audio/libFLAC/private/float.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2004-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/format.h b/sys/src/cmd/audio/libFLAC/private/format.h index 8f28017cf..bb2983774 100644 --- a/sys/src/cmd/audio/libFLAC/private/format.h +++ b/sys/src/cmd/audio/libFLAC/private/format.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/lpc.h b/sys/src/cmd/audio/libFLAC/private/lpc.h index 64dfd1f8c..5212b35eb 100644 --- a/sys/src/cmd/audio/libFLAC/private/lpc.h +++ b/sys/src/cmd/audio/libFLAC/private/lpc.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -55,6 +55,9 @@ * IN data_len */ void FLAC__lpc_window_data(const FLAC__int32 in[], const FLAC__real window[], FLAC__real out[], uint32_t data_len); +void FLAC__lpc_window_data_wide(const FLAC__int64 in[], const FLAC__real window[], FLAC__real out[], uint32_t data_len); +void FLAC__lpc_window_data_partial(const FLAC__int32 in[], const FLAC__real window[], FLAC__real out[], uint32_t data_len, uint32_t part_size, uint32_t data_shift); +void FLAC__lpc_window_data_partial_wide(const FLAC__int64 in[], const FLAC__real window[], FLAC__real out[], uint32_t data_len, uint32_t part_size, uint32_t data_shift); /* * FLAC__lpc_compute_autocorrelation() @@ -68,44 +71,40 @@ void FLAC__lpc_window_data(const FLAC__int32 in[], const FLAC__real window[], FL * IN 0 < lag <= data_len * OUT autoc[0,lag-1] */ -void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); +void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); #ifndef FLAC__NO_ASM -# ifdef FLAC__CPU_IA32 -# ifdef FLAC__HAS_NASM -void FLAC__lpc_compute_autocorrelation_asm_ia32(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4_old(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8_old(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12_old(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_16_old(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); +# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN +# ifdef FLAC__SSE2_SUPPORTED +void FLAC__lpc_compute_autocorrelation_intrin_sse2_lag_8(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_sse2_lag_10(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_sse2_lag_14(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); # endif # endif -# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN -# ifdef FLAC__SSE_SUPPORTED -void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_4_old(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_8_old(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_12_old(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_16_old(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_4_new(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_8_new(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_12_new(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_16_new(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); +# if defined FLAC__CPU_X86_64 && FLAC__HAS_X86INTRIN +# ifdef FLAC__FMA_SUPPORTED +void FLAC__lpc_compute_autocorrelation_intrin_fma_lag_8(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_fma_lag_12(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_fma_lag_16(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); # endif # endif #if defined(FLAC__CPU_PPC64) && defined(FLAC__USE_VSX) #ifdef FLAC__HAS_TARGET_POWER9 -void FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_4(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_8(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_12(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_16(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_8(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_10(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_14(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); #endif #ifdef FLAC__HAS_TARGET_POWER8 -void FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_4(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_8(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_12(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_16(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_8(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_10(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_14(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); #endif #endif +#if defined FLAC__CPU_ARM64 && FLAC__HAS_NEONINTRIN && FLAC__HAS_A64NEONINTRIN +void FLAC__lpc_compute_autocorrelation_intrin_neon_lag_8(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_neon_lag_10(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_neon_lag_14(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); #endif +#endif /* FLAC__NO_ASM */ /* * FLAC__lpc_compute_lp_coefficients() @@ -128,7 +127,7 @@ void FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_16(const FLAC__real * in lp_coeff[8][0,8], the LP coefficients for order 8 will be * in lp_coeff[7][0,7], etc. */ -void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], uint32_t *max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], double error[]); +void FLAC__lpc_compute_lp_coefficients(const double autoc[], uint32_t *max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], double error[]); /* * FLAC__lpc_quantize_coefficients() @@ -167,7 +166,14 @@ int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], uint32_t order, */ void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]); void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]); +FLAC__bool FLAC__lpc_compute_residual_from_qlp_coefficients_limit_residual(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]); +FLAC__bool FLAC__lpc_compute_residual_from_qlp_coefficients_limit_residual_33bit(const FLAC__int64 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]); #ifndef FLAC__NO_ASM +# ifdef FLAC__CPU_ARM64 +void FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_neon(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]); +void FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_neon(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]); +# endif + # ifdef FLAC__CPU_IA32 # ifdef FLAC__HAS_NASM void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]); @@ -194,6 +200,9 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_avx2(const FLA #endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ +uint32_t FLAC__lpc_max_prediction_before_shift_bps(uint32_t subframe_bps, const FLAC__int32 qlp_coeff[], uint32_t order); +uint32_t FLAC__lpc_max_residual_bps(uint32_t subframe_bps, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization); + /* * FLAC__lpc_restore_signal() * -------------------------------------------------------------------- @@ -211,22 +220,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_avx2(const FLA */ void FLAC__lpc_restore_signal(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]); void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]); -#ifndef FLAC__NO_ASM -# ifdef FLAC__CPU_IA32 -# ifdef FLAC__HAS_NASM -void FLAC__lpc_restore_signal_asm_ia32(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]); -void FLAC__lpc_restore_signal_asm_ia32_mmx(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]); -void FLAC__lpc_restore_signal_wide_asm_ia32(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]); -# endif /* FLAC__HAS_NASM */ -# endif /* FLAC__CPU_IA32 */ -# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN -# ifdef FLAC__SSE4_1_SUPPORTED -void FLAC__lpc_restore_signal_intrin_sse41(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]); -void FLAC__lpc_restore_signal_16_intrin_sse41(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]); -void FLAC__lpc_restore_signal_wide_intrin_sse41(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]); -# endif -# endif -#endif /* FLAC__NO_ASM */ +void FLAC__lpc_restore_signal_wide_33bit(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int64 data[]); #ifndef FLAC__INTEGER_ONLY_LIBRARY diff --git a/sys/src/cmd/audio/libFLAC/private/macros.h b/sys/src/cmd/audio/libFLAC/private/macros.h index 3a8072ece..ee0d997be 100644 --- a/sys/src/cmd/audio/libFLAC/private/macros.h +++ b/sys/src/cmd/audio/libFLAC/private/macros.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2012-2016 Xiph.org Foundation + * Copyright (C) 2012-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/memory.h b/sys/src/cmd/audio/libFLAC/private/memory.h index a6d3faff5..cba58ac9b 100644 --- a/sys/src/cmd/audio/libFLAC/private/memory.h +++ b/sys/src/cmd/audio/libFLAC/private/memory.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -48,6 +48,7 @@ void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address); FLAC__bool FLAC__memory_alloc_aligned_int32_array(size_t elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer); FLAC__bool FLAC__memory_alloc_aligned_uint32_array(size_t elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer); +FLAC__bool FLAC__memory_alloc_aligned_int64_array(size_t elements, FLAC__int64 **unaligned_pointer, FLAC__int64 **aligned_pointer); FLAC__bool FLAC__memory_alloc_aligned_uint64_array(size_t elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer); FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(size_t elements, uint32_t **unaligned_pointer, uint32_t **aligned_pointer); #ifndef FLAC__INTEGER_ONLY_LIBRARY diff --git a/sys/src/cmd/audio/libFLAC/private/metadata.h b/sys/src/cmd/audio/libFLAC/private/metadata.h index 161947fd7..409b62cd7 100644 --- a/sys/src/cmd/audio/libFLAC/private/metadata.h +++ b/sys/src/cmd/audio/libFLAC/private/metadata.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2002-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/ogg_decoder_aspect.h b/sys/src/cmd/audio/libFLAC/private/ogg_decoder_aspect.h index 0a8534d41..2be979ccf 100644 --- a/sys/src/cmd/audio/libFLAC/private/ogg_decoder_aspect.h +++ b/sys/src/cmd/audio/libFLAC/private/ogg_decoder_aspect.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec * Copyright (C) 2002-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/ogg_encoder_aspect.h b/sys/src/cmd/audio/libFLAC/private/ogg_encoder_aspect.h index f3c95f96c..35a1ddf57 100644 --- a/sys/src/cmd/audio/libFLAC/private/ogg_encoder_aspect.h +++ b/sys/src/cmd/audio/libFLAC/private/ogg_encoder_aspect.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec * Copyright (C) 2002-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/ogg_helper.h b/sys/src/cmd/audio/libFLAC/private/ogg_helper.h index 4c1000c8f..3e15accae 100644 --- a/sys/src/cmd/audio/libFLAC/private/ogg_helper.h +++ b/sys/src/cmd/audio/libFLAC/private/ogg_helper.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec * Copyright (C) 2004-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/ogg_mapping.h b/sys/src/cmd/audio/libFLAC/private/ogg_mapping.h index 6eb609e08..224f7dc29 100644 --- a/sys/src/cmd/audio/libFLAC/private/ogg_mapping.h +++ b/sys/src/cmd/audio/libFLAC/private/ogg_mapping.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec * Copyright (C) 2004-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/stream_encoder.h b/sys/src/cmd/audio/libFLAC/private/stream_encoder.h index ade648bf2..1d22937ef 100644 --- a/sys/src/cmd/audio/libFLAC/private/stream_encoder.h +++ b/sys/src/cmd/audio/libFLAC/private/stream_encoder.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/stream_encoder_framing.h b/sys/src/cmd/audio/libFLAC/private/stream_encoder_framing.h index 8df104946..2799c6985 100644 --- a/sys/src/cmd/audio/libFLAC/private/stream_encoder_framing.h +++ b/sys/src/cmd/audio/libFLAC/private/stream_encoder_framing.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/private/window.h b/sys/src/cmd/audio/libFLAC/private/window.h index bfed7740b..4aaaaea63 100644 --- a/sys/src/cmd/audio/libFLAC/private/window.h +++ b/sys/src/cmd/audio/libFLAC/private/window.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2006-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/protected/all.h b/sys/src/cmd/audio/libFLAC/protected/all.h index 9468bd3ba..ad302308d 100644 --- a/sys/src/cmd/audio/libFLAC/protected/all.h +++ b/sys/src/cmd/audio/libFLAC/protected/all.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/protected/stream_decoder.h b/sys/src/cmd/audio/libFLAC/protected/stream_decoder.h index f7e20021e..f1c5d0eb6 100644 --- a/sys/src/cmd/audio/libFLAC/protected/stream_decoder.h +++ b/sys/src/cmd/audio/libFLAC/protected/stream_decoder.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -53,13 +53,8 @@ typedef struct FLAC__StreamDecoderProtected { } FLAC__StreamDecoderProtected; /* - * return the number of input bytes consumed + * Return the number of input bytes consumed */ uint32_t FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder); -/* - * return client_data from decoder - */ -FLAC_API void *get_client_data_from_decoder(FLAC__StreamDecoder *decoder); - #endif diff --git a/sys/src/cmd/audio/libFLAC/protected/stream_encoder.h b/sys/src/cmd/audio/libFLAC/protected/stream_encoder.h index c290904e7..3e045583e 100644 --- a/sys/src/cmd/audio/libFLAC/protected/stream_encoder.h +++ b/sys/src/cmd/audio/libFLAC/protected/stream_encoder.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -61,6 +61,7 @@ typedef enum { FLAC__APODIZATION_TUKEY, FLAC__APODIZATION_PARTIAL_TUKEY, FLAC__APODIZATION_PUNCHOUT_TUKEY, + FLAC__APODIZATION_SUBDIVIDE_TUKEY, FLAC__APODIZATION_WELCH } FLAC__ApodizationFunction; @@ -78,6 +79,10 @@ typedef struct { FLAC__real start; FLAC__real end; } multiple_tukey; + struct { + FLAC__real p; + FLAC__int32 parts; + } subdivide_tukey; } parameters; } FLAC__ApodizationSpecification; @@ -107,6 +112,7 @@ typedef struct FLAC__StreamEncoderProtected { uint32_t max_residual_partition_order; uint32_t rice_parameter_search_dist; FLAC__uint64 total_samples_estimate; + FLAC__bool limit_min_bitrate; FLAC__StreamMetadata **metadata; uint32_t num_metadata_blocks; FLAC__uint64 streaminfo_offset, seektable_offset, audio_offset; diff --git a/sys/src/cmd/audio/libFLAC/share/alloc.h b/sys/src/cmd/audio/libFLAC/share/alloc.h index 914de9ba6..0b40548e7 100644 --- a/sys/src/cmd/audio/libFLAC/share/alloc.h +++ b/sys/src/cmd/audio/libFLAC/share/alloc.h @@ -1,6 +1,6 @@ /* alloc - Convenience routines for safely allocating memory * Copyright (C) 2007-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -42,7 +42,7 @@ */ #include <limits.h> /* for SIZE_MAX */ -#if HAVE_STDINT_H +#ifdef HAVE_STDINT_H #include <stdint.h> /* for SIZE_MAX in case limits.h didn't get it */ #endif #include <stdlib.h> /* for size_t, malloc(), etc */ @@ -63,19 +63,58 @@ # define SIZE_MAX SIZE_T_MAX #endif +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +extern int alloc_check_threshold, alloc_check_counter; + +static inline int alloc_check() { + if(alloc_check_threshold == INT32_MAX) + return 0; + else if(alloc_check_counter++ == alloc_check_threshold) + return 1; + else + return 0; +} + +#endif + /* avoid malloc()ing 0 bytes, see: * https://www.securecoding.cert.org/confluence/display/seccode/MEM04-A.+Do+not+make+assumptions+about+the+result+of+allocating+0+bytes?focusedCommentId=5407003 */ + static inline void *safe_malloc_(size_t size) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + /* Fail if requested */ + if(alloc_check()) + return NULL; +#endif /* malloc(0) is undefined; FLAC src convention is to always allocate */ if(!size) size++; return malloc(size); } +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +static inline void *malloc_(size_t size) +{ + /* Fail if requested */ + if(alloc_check()) + return NULL; + return malloc(size); +} +#else +#define malloc_ malloc +#endif + + + static inline void *safe_calloc_(size_t nmemb, size_t size) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + /* Fail if requested */ + if(alloc_check()) + return NULL; +#endif if(!nmemb || !size) return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ return calloc(nmemb, size); @@ -127,7 +166,7 @@ static inline void *safe_malloc_mul_3op_(size_t size1, size_t size2, size_t size size1 *= size2; if(size1 > SIZE_MAX / size3) return 0; - return malloc(size1*size3); + return malloc_(size1*size3); } /* size1*size2 + size3 */ @@ -150,28 +189,62 @@ static inline void *safe_malloc_muladd2_(size_t size1, size_t size2, size_t size return 0; if(size1 > SIZE_MAX / size2) return 0; - return malloc(size1*size2); + return malloc_(size1*size2); } static inline void *safe_realloc_(void *ptr, size_t size) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + /* Fail if requested */ + if(alloc_check() && size > 0) { + free(ptr); + return NULL; + } +#endif void *oldptr = ptr; void *newptr = realloc(ptr, size); if(size > 0 && newptr == 0) free(oldptr); return newptr; } -static inline void *safe_realloc_add_2op_(void *ptr, size_t size1, size_t size2) + +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +static inline void *realloc_(void *ptr, size_t size) +{ + /* Fail if requested */ + if(alloc_check()) + return NULL; + return realloc(ptr, size); +} +#else +#define realloc_ realloc +#endif + + +static inline void *safe_realloc_nofree_add_2op_(void *ptr, size_t size1, size_t size2) +{ + size2 += size1; + if(size2 < size1) + return 0; + return realloc_(ptr, size2); +} + +static inline void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3) { size2 += size1; if(size2 < size1) { free(ptr); return 0; } - return realloc(ptr, size2); + size3 += size2; + if(size3 < size2) { + free(ptr); + return 0; + } + return safe_realloc_(ptr, size3); } -static inline void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3) +static inline void *safe_realloc_nofree_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3) { size2 += size1; if(size2 < size1) @@ -179,10 +252,10 @@ static inline void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size3 += size2; if(size3 < size2) return 0; - return realloc(ptr, size3); + return realloc_(ptr, size3); } -static inline void *safe_realloc_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4) +static inline void *safe_realloc_nofree_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4) { size2 += size1; if(size2 < size1) @@ -193,27 +266,51 @@ static inline void *safe_realloc_add_4op_(void *ptr, size_t size1, size_t size2, size4 += size3; if(size4 < size3) return 0; - return realloc(ptr, size4); + return realloc_(ptr, size4); } static inline void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t size2) { if(!size1 || !size2) return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ - if(size1 > SIZE_MAX / size2) + if(size1 > SIZE_MAX / size2) { + free(ptr); return 0; + } return safe_realloc_(ptr, size1*size2); } +static inline void *safe_realloc_nofree_mul_2op_(void *ptr, size_t size1, size_t size2) +{ + if(!size1 || !size2) + return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ + if(size1 > SIZE_MAX / size2) + return 0; + return realloc_(ptr, size1*size2); +} + /* size1 * (size2 + size3) */ static inline void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3) { if(!size1 || (!size2 && !size3)) return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ size2 += size3; - if(size2 < size3) + if(size2 < size3) { + free(ptr); return 0; + } return safe_realloc_mul_2op_(ptr, size1, size2); } +/* size1 * (size2 + size3) */ +static inline void *safe_realloc_nofree_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3) +{ + if(!size1 || (!size2 && !size3)) + return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ + size2 += size3; + if(size2 < size3) + return 0; + return safe_realloc_nofree_mul_2op_(ptr, size1, size2); +} + #endif diff --git a/sys/src/cmd/audio/libFLAC/share/compat.h b/sys/src/cmd/audio/libFLAC/share/compat.h index c28054be9..7a8651539 100644 --- a/sys/src/cmd/audio/libFLAC/share/compat.h +++ b/sys/src/cmd/audio/libFLAC/share/compat.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2012-2016 Xiph.org Foundation + * Copyright (C) 2012-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -39,6 +39,9 @@ #ifndef FLAC__SHARE__COMPAT_H #define FLAC__SHARE__COMPAT_H +#include <stddef.h> +#include <stdarg.h> + #if defined _WIN32 && !defined __CYGWIN__ /* where MSVC puts unlink() */ # include <io.h> @@ -62,7 +65,7 @@ #define FLAC__off_t off_t #endif -#if HAVE_INTTYPES_H +#ifdef HAVE_INTTYPES_H #define __STDC_FORMAT_MACROS #include <inttypes.h> #endif @@ -138,6 +141,29 @@ # define PRId64 "I64d" # define PRIx64 "I64x" # endif +# if defined(_USING_V110_SDK71_) && !defined(_DLL) +# pragma message("WARNING: This compile will NOT FUNCTION PROPERLY on Windows XP. See comments in include/share/compat.h for details") +#define FLAC__USE_FILELENGTHI64 +/* + ************************************************************************************* + * V110_SDK71, in MSVC 2017 also known as v141_xp, is a platform toolset that is supposed + * to target Windows XP. It turns out however that certain functions provided silently fail + * on Windows XP only, which makes debugging challenging. This only occurs when building with + * /MT. This problem has been reported to Microsoft, but there hasn't been a fix for years. See + * https://web.archive.org/web/20170327195018/https://connect.microsoft.com/VisualStudio/feedback/details/1557168/wstat64-returns-1-on-xp-always + * + * It is known that this problem affects the functions _wstat64 (used by flac_stat i.e. + * stat64_utf8) and _fstat64 (i.e. flac_fstat) and therefore affects both libFLAC in + * several places as well as the flac and metaflac command line tools + * + * As the extent of this problem is unknown and Microsoft seems unwilling to fix it, + * users of libFLAC building with Visual Studio are encouraged to not use the /MT compile + * switch when explicitly targeting Windows XP. When use of /MT is deemed necessary with + * this toolset, be sure to check whether your application works properly on Windows XP. + * It is also possible to build for Windows XP with MinGW instead. + ************************************************************************************* +*/ +# endif #endif /* defined _MSC_VER */ #ifdef _WIN32 @@ -147,14 +173,12 @@ #define flac_printf printf_utf8 #define flac_fprintf fprintf_utf8 #define flac_vfprintf vfprintf_utf8 - -#include "share/windows_unicode_filenames.h" -#define flac_fopen flac_internal_fopen_utf8 -#define flac_chmod flac_internal_chmod_utf8 -#define flac_utime flac_internal_utime_utf8 -#define flac_unlink flac_internal_unlink_utf8 -#define flac_rename flac_internal_rename_utf8 -#define flac_stat flac_internal_stat64_utf8 +#define flac_fopen fopen_utf8 +#define flac_chmod chmod_utf8 +#define flac_utime utime_utf8 +#define flac_unlink unlink_utf8 +#define flac_rename rename_utf8 +#define flac_stat stat64_utf8 #else @@ -200,7 +224,6 @@ * * This function wraps the MS version to behave more like the ISO version. */ -#include <stdarg.h> #ifdef __cplusplus extern "C" { #endif diff --git a/sys/src/cmd/audio/libFLAC/share/endswap.h b/sys/src/cmd/audio/libFLAC/share/endswap.h index 9088a7474..35ffc62e2 100644 --- a/sys/src/cmd/audio/libFLAC/share/endswap.h +++ b/sys/src/cmd/audio/libFLAC/share/endswap.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2012-2016 Xiph.org Foundation + * Copyright (C) 2012-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,10 +31,10 @@ /* It is assumed that this header will be included after "config.h". */ -#if HAVE_BSWAP32 /* GCC and Clang */ +#ifdef HAVE_BSWAP32 /* GCC and Clang */ /* GCC prior to 4.8 didn't provide bswap16 on x86_64 */ -#if ! HAVE_BSWAP16 +#ifndef HAVE_BSWAP16 static inline unsigned short __builtin_bswap16(unsigned short a) { return (a<<8)|(a>>8); diff --git a/sys/src/cmd/audio/libFLAC/share/macros.h b/sys/src/cmd/audio/libFLAC/share/macros.h index 20b3ea56b..d7f88feb7 100644 --- a/sys/src/cmd/audio/libFLAC/share/macros.h +++ b/sys/src/cmd/audio/libFLAC/share/macros.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2013-2016 Xiph.org Foundation + * Copyright (C) 2013-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/share/private.h b/sys/src/cmd/audio/libFLAC/share/private.h index 03083d3f4..a18566fbd 100644 --- a/sys/src/cmd/audio/libFLAC/share/private.h +++ b/sys/src/cmd/audio/libFLAC/share/private.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2013-2016 Xiph.org Foundation + * Copyright (C) 2013-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,6 +36,7 @@ * Unpublished debug routines from libFLAC. This should not be used from any * client code other than code shipped with the FLAC sources. */ +FLAC_API FLAC__bool FLAC__stream_encoder_disable_instruction_set(FLAC__StreamEncoder *encoder, FLAC__bool value); FLAC_API FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value); FLAC_API FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value); FLAC_API FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value); diff --git a/sys/src/cmd/audio/libFLAC/share/safe_str.h b/sys/src/cmd/audio/libFLAC/share/safe_str.h index 6709334e5..f52472ea9 100644 --- a/sys/src/cmd/audio/libFLAC/share/safe_str.h +++ b/sys/src/cmd/audio/libFLAC/share/safe_str.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2013-2016 Xiph.org Foundation + * Copyright (C) 2013-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/src/cmd/audio/libFLAC/stream_decoder.c b/sys/src/cmd/audio/libFLAC/stream_decoder.c index ef6da44e3..ac96c02f5 100644 --- a/sys/src/cmd/audio/libFLAC/stream_decoder.c +++ b/sys/src/cmd/audio/libFLAC/stream_decoder.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,7 +45,6 @@ #include "protected/stream_decoder.h" #include "private/bitreader.h" #include "private/bitmath.h" -#include "private/cpu.h" #include "private/crc.h" #include "private/fixed.h" #include "private/format.h" @@ -75,7 +74,7 @@ static const FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' }; static void set_defaults_(FLAC__StreamDecoder *decoder); static FILE *get_binary_stdin_(void); -static FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, uint32_t size, uint32_t channels); +static FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, uint32_t size, uint32_t channels, uint32_t bps); static FLAC__bool has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id); static FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder); static FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder); @@ -95,6 +94,7 @@ static FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, uint32_t chan static FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, FLAC__bool do_full_decode); static FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, uint32_t predictor_order, uint32_t partition_order, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, FLAC__int32 *residual, FLAC__bool is_extended); static FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder); +static void undo_channel_coding(FLAC__StreamDecoder *decoder); static FLAC__bool read_callback_(FLAC__byte buffer[], size_t *bytes, void *client_data); #if FLAC__HAS_OGG static FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes); @@ -128,17 +128,13 @@ typedef struct FLAC__StreamDecoderPrivate { FLAC__StreamDecoderWriteCallback write_callback; FLAC__StreamDecoderMetadataCallback metadata_callback; FLAC__StreamDecoderErrorCallback error_callback; - /* generic 32-bit datapath: */ - void (*local_lpc_restore_signal)(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]); - /* generic 64-bit datapath: */ - void (*local_lpc_restore_signal_64bit)(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]); - /* for use when the signal is <= 16 bits-per-sample, or <= 15 bits-per-sample on a side channel (which requires 1 extra bit): */ - void (*local_lpc_restore_signal_16bit)(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]); void *client_data; FILE *file; /* only used if FLAC__stream_decoder_init_file()/FLAC__stream_decoder_init_file() called, else NULL */ FLAC__BitReader *input; FLAC__int32 *output[FLAC__MAX_CHANNELS]; FLAC__int32 *residual[FLAC__MAX_CHANNELS]; /* WATCHOUT: these are the aligned pointers; the real pointers that should be free()'d are residual_unaligned[] below */ + FLAC__int64 *side_subframe; + FLAC__bool side_subframe_in_use; FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents[FLAC__MAX_CHANNELS]; uint32_t output_capacity, output_channels; FLAC__uint32 fixed_block_size, next_fixed_block_size; @@ -151,7 +147,6 @@ typedef struct FLAC__StreamDecoderPrivate { size_t metadata_filter_ids_count, metadata_filter_ids_capacity; /* units for both are IDs, not bytes */ FLAC__Frame frame; FLAC__bool cached; /* true if there is a byte in lookahead */ - FLAC__CPUInfo cpuinfo; FLAC__byte header_warmup[2]; /* contains the sync code and reserved bits */ FLAC__byte lookahead; /* temp storage when we need to look ahead one byte in the stream */ /* unaligned (original) pointers to allocated data */ @@ -162,8 +157,10 @@ typedef struct FLAC__StreamDecoderPrivate { FLAC__MD5Context md5context; FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */ /* (the rest of these are only used for seeking) */ - FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */ + FLAC__Frame last_frame; /* holds the info of the last frame we decoded or seeked to */ + FLAC__bool last_frame_is_set; FLAC__uint64 first_frame_offset; /* hint to the seek routine of where in the stream the first audio frame starts */ + FLAC__uint64 last_seen_framesync; /* if tell callback works, the location of the last seen frame sync code, to rewind to if needed */ FLAC__uint64 target_sample; uint32_t unparseable_frame_count; /* used to tell whether we're decoding a future version of FLAC or just got a bad sync */ FLAC__bool got_a_frame; /* hack needed in Ogg FLAC seek routine to check when process_single() actually writes a frame */ @@ -230,7 +227,8 @@ FLAC_API const char * const FLAC__StreamDecoderErrorStatusString[] = { "FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC", "FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER", "FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH", - "FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM" + "FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM", + "FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA" }; /*********************************************************************** @@ -285,6 +283,8 @@ FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new(void) decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0; } + decoder->private_->side_subframe = 0; + decoder->private_->output_capacity = 0; decoder->private_->output_channels = 0; decoder->private_->has_seek_table = false; @@ -369,48 +369,6 @@ static FLAC__StreamDecoderInitStatus init_stream_internal_( return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE; #endif - /* - * get the CPU info and set the function pointers - */ - FLAC__cpu_info(&decoder->private_->cpuinfo); - /* first default to the non-asm routines */ - decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal; - decoder->private_->local_lpc_restore_signal_64bit = FLAC__lpc_restore_signal_wide; - decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal; - /* now override with asm where appropriate */ -#ifndef FLAC__NO_ASM - if(decoder->private_->cpuinfo.use_asm) { -#ifdef FLAC__CPU_IA32 - FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32); -#ifdef FLAC__HAS_NASM - decoder->private_->local_lpc_restore_signal_64bit = FLAC__lpc_restore_signal_wide_asm_ia32; /* OPT_IA32: was really necessary for GCC < 4.9 */ - if (decoder->private_->cpuinfo.x86.mmx) { - decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal_asm_ia32; - decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ia32_mmx; - } - else { - decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal_asm_ia32; - decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ia32; - } -#endif -#if FLAC__HAS_X86INTRIN && ! defined FLAC__INTEGER_ONLY_LIBRARY -# if defined FLAC__SSE4_1_SUPPORTED - if (decoder->private_->cpuinfo.x86.sse41) { -# if !defined FLAC__HAS_NASM /* these are not undoubtedly faster than their MMX ASM counterparts */ - decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal_intrin_sse41; - decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_16_intrin_sse41; -# endif - decoder->private_->local_lpc_restore_signal_64bit = FLAC__lpc_restore_signal_wide_intrin_sse41; - } -# endif -#endif -#elif defined FLAC__CPU_X86_64 - FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_X86_64); - /* No useful SSE optimizations yet */ -#endif - } -#endif - /* from here on, errors are fatal */ if(!FLAC__bitreader_init(decoder->private_->input, read_callback_, decoder)) { @@ -663,6 +621,10 @@ FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder) decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0; } } + if(0 != decoder->private_->side_subframe) { + free(decoder->private_->side_subframe); + decoder->private_->side_subframe = 0; + } decoder->private_->output_capacity = 0; decoder->private_->output_channels = 0; @@ -915,6 +877,11 @@ FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamD return true; } +FLAC_API const void *FLAC__stream_decoder_get_client_data(FLAC__StreamDecoder *decoder) +{ + return decoder->private_->client_data; +} + FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder) { FLAC__ASSERT(0 != decoder); @@ -926,6 +893,7 @@ FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder) decoder->private_->samples_decoded = 0; decoder->private_->do_md5_checking = false; + decoder->private_->last_seen_framesync = 0; #if FLAC__HAS_OGG if(decoder->private_->is_ogg) @@ -969,8 +937,6 @@ FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder) if(decoder->private_->seek_callback && decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) == FLAC__STREAM_DECODER_SEEK_STATUS_ERROR) return false; /* seekable and seek fails, reset fails */ } - else - decoder->private_->internal_reset_hack = false; decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA; @@ -993,10 +959,19 @@ FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder) * FLAC__stream_decoder_finish() to make sure things are always cleaned up * properly. */ + if(!decoder->private_->internal_reset_hack) { + /* Only finish MD5 context when it has been initialized + * (i.e. when internal_reset_hack is not set) */ + FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context); + } + else + decoder->private_->internal_reset_hack = false; FLAC__MD5Init(&decoder->private_->md5context); decoder->private_->first_frame_offset = 0; decoder->private_->unparseable_frame_count = 0; + decoder->private_->last_seen_framesync = 0; + decoder->private_->last_frame_is_set = false; return true; } @@ -1259,12 +1234,13 @@ FILE *get_binary_stdin_(void) return stdin; } -FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, uint32_t size, uint32_t channels) +FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, uint32_t size, uint32_t channels, uint32_t bps) { uint32_t i; FLAC__int32 *tmp; - if(size <= decoder->private_->output_capacity && channels <= decoder->private_->output_channels) + if(size <= decoder->private_->output_capacity && channels <= decoder->private_->output_channels && + (bps < 32 || decoder->private_->side_subframe != 0)) return true; /* simply using realloc() is not practical because the number of channels may change mid-stream */ @@ -1280,6 +1256,11 @@ FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, uint32_t size, uint32_ } } + if(0 != decoder->private_->side_subframe) { + free(decoder->private_->side_subframe); + decoder->private_->side_subframe = 0; + } + for(i = 0; i < channels; i++) { /* WATCHOUT: * FLAC__lpc_restore_signal_asm_ia32_mmx() and ..._intrin_sseN() @@ -1301,6 +1282,14 @@ FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, uint32_t size, uint32_ } } + if(bps == 32) { + decoder->private_->side_subframe = safe_malloc_mul_2op_p(sizeof(FLAC__int64), /*times (*/size); + if(decoder->private_->side_subframe == NULL) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + } + decoder->private_->output_capacity = size; decoder->private_->output_channels = channels; @@ -1455,6 +1444,7 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) } else { FLAC__bool ok = true; + FLAC__bitreader_set_limit(decoder->private_->input, real_length*8); switch(type) { case FLAC__METADATA_TYPE_PADDING: /* skip the padding bytes */ @@ -1503,6 +1493,16 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) block.data.unknown.data = 0; break; } + if(FLAC__bitreader_limit_remaining(decoder->private_->input) > 0) { + /* Content in metadata block didn't fit in block length + * We cannot know whether the length or the content was + * corrupt, so stop parsing metadata */ + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA); + if(decoder->protected_->state == FLAC__STREAM_DECODER_READ_METADATA) + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + ok = false; + } + FLAC__bitreader_remove_limit(decoder->private_->input); if(ok && !decoder->private_->is_seeking && decoder->private_->metadata_callback) decoder->private_->metadata_callback(decoder, &block, decoder->private_->client_data); @@ -1525,7 +1525,7 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) free(block.data.vorbis_comment.comments); break; case FLAC__METADATA_TYPE_CUESHEET: - if(block.data.cue_sheet.num_tracks > 0) + if(block.data.cue_sheet.num_tracks > 0 && 0 != block.data.cue_sheet.tracks) for(i = 0; i < block.data.cue_sheet.num_tracks; i++) if(0 != block.data.cue_sheet.tracks[i].indices) free(block.data.cue_sheet.tracks[i].indices); @@ -1877,11 +1877,18 @@ FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMeta /* read type */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_TYPE_LEN)) return false; /* read_callback_ sets the state for us */ - obj->type = x; + if(x < FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED) + obj->type = x; + else + obj->type = FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER; /* read MIME type */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN)) return false; /* read_callback_ sets the state for us */ + if(FLAC__bitreader_limit_remaining(decoder->private_->input) < x){ + FLAC__bitreader_limit_invalidate(decoder->private_->input); + return false; + } if(0 == (obj->mime_type = safe_malloc_add_2op_(x, /*+*/1))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return false; @@ -1895,6 +1902,10 @@ FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMeta /* read description */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN)) return false; /* read_callback_ sets the state for us */ + if(FLAC__bitreader_limit_remaining(decoder->private_->input) < x){ + FLAC__bitreader_limit_invalidate(decoder->private_->input); + return false; + } if(0 == (obj->description = safe_malloc_add_2op_(x, /*+*/1))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return false; @@ -1924,6 +1935,10 @@ FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMeta /* read data */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &(obj->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN)) return false; /* read_callback_ sets the state for us */ + if(FLAC__bitreader_limit_remaining(decoder->private_->input) < obj->data_length){ + FLAC__bitreader_limit_invalidate(decoder->private_->input); + return false; + } if(0 == (obj->data = safe_malloc_(obj->data_length))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return false; @@ -1963,15 +1978,6 @@ FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder) FLAC__uint32 x; FLAC__bool first = true; - /* If we know the total number of samples in the stream, stop if we've read that many. */ - /* This will stop us, for example, from wasting time trying to sync on an ID3V1 tag. */ - if(FLAC__stream_decoder_get_total_samples(decoder) > 0) { - if(decoder->private_->samples_decoded >= FLAC__stream_decoder_get_total_samples(decoder)) { - decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM; - return true; - } - } - /* make sure we're byte aligned */ if(!FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)) { if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__bitreader_bits_left_for_byte_alignment(decoder->private_->input))) @@ -2001,6 +2007,12 @@ FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder) else if(x >> 1 == 0x7c) { /* MAGIC NUMBER for the last 6 sync bits and reserved 7th bit */ decoder->private_->header_warmup[1] = (FLAC__byte)x; decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME; + + /* Save location so we can rewind in case the frame turns + * out to be invalid after the header */ + FLAC__bitreader_set_framesync_location(decoder->private_->input); + if(!FLAC__stream_decoder_get_decode_position(decoder, &decoder->private_->last_seen_framesync)) + decoder->private_->last_seen_framesync = 0; return true; } } @@ -2017,11 +2029,11 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL { uint32_t channel; uint32_t i; - FLAC__int32 mid, side; uint32_t frame_crc; /* the one we calculate from the input stream */ FLAC__uint32 x; *got_a_frame = false; + decoder->private_->side_subframe_in_use = false; /* init the CRC */ frame_crc = 0; @@ -2033,7 +2045,7 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL return false; if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means we didn't sync on a valid header */ return true; - if(!allocate_output_(decoder, decoder->private_->frame.header.blocksize, decoder->private_->frame.header.channels)) + if(!allocate_output_(decoder, decoder->private_->frame.header.blocksize, decoder->private_->frame.header.channels, decoder->private_->frame.header.bits_per_sample)) return false; for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) { /* @@ -2065,98 +2077,168 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL /* * now read it */ - if(!read_subframe_(decoder, channel, bps, do_full_decode)) - return false; - if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means bad sync or got corruption */ - return true; + if(!read_subframe_(decoder, channel, bps, do_full_decode)){ + /* read_callback_ sets the state for us */ + if(decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM) + break; + else + return false; + } } - if(!read_zero_padding_(decoder)) - return false; - if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means bad sync or got corruption (i.e. "zero bits" were not all zeroes) */ - return true; + + if(decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM) + if(!read_zero_padding_(decoder)) + return false; /* * Read the frame CRC-16 from the footer and check */ - frame_crc = FLAC__bitreader_get_read_crc16(decoder->private_->input); - if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__FRAME_FOOTER_CRC_LEN)) - return false; /* read_callback_ sets the state for us */ -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - if(1){ -#else - if(frame_crc == x) { + if(decoder->protected_->state == FLAC__STREAM_DECODER_READ_FRAME) { + frame_crc = FLAC__bitreader_get_read_crc16(decoder->private_->input); + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__FRAME_FOOTER_CRC_LEN)) { + /* read_callback_ sets the state for us */ + if(decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM) + return false; + } +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + } + if(decoder->protected_->state == FLAC__STREAM_DECODER_READ_FRAME && frame_crc == x) { #endif if(do_full_decode) { /* Undo any special channel coding */ - switch(decoder->private_->frame.header.channel_assignment) { - case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: - /* do nothing */ - break; - case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: - FLAC__ASSERT(decoder->private_->frame.header.channels == 2); - for(i = 0; i < decoder->private_->frame.header.blocksize; i++) - decoder->private_->output[1][i] = decoder->private_->output[0][i] - decoder->private_->output[1][i]; - break; - case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE: - FLAC__ASSERT(decoder->private_->frame.header.channels == 2); - for(i = 0; i < decoder->private_->frame.header.blocksize; i++) - decoder->private_->output[0][i] += decoder->private_->output[1][i]; - break; - case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE: - FLAC__ASSERT(decoder->private_->frame.header.channels == 2); - for(i = 0; i < decoder->private_->frame.header.blocksize; i++) { -#if 1 - mid = decoder->private_->output[0][i]; - side = decoder->private_->output[1][i]; - mid = ((uint32_t) mid) << 1; - mid |= (side & 1); /* i.e. if 'side' is odd... */ - decoder->private_->output[0][i] = (mid + side) >> 1; - decoder->private_->output[1][i] = (mid - side) >> 1; -#else - /* OPT: without 'side' temp variable */ - mid = (decoder->private_->output[0][i] << 1) | (decoder->private_->output[1][i] & 1); /* i.e. if 'side' is odd... */ - decoder->private_->output[0][i] = (mid + decoder->private_->output[1][i]) >> 1; - decoder->private_->output[1][i] = (mid - decoder->private_->output[1][i]) >> 1; -#endif + undo_channel_coding(decoder); + /* Check whether decoded data actually fits bps */ + for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) { + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) { + int shift_bits = 32 - decoder->private_->frame.header.bits_per_sample; + /* Check whether shift_bits MSBs are 'empty' by shifting up and down */ + if((decoder->private_->output[channel][i] < (INT32_MIN >> shift_bits)) || + (decoder->private_->output[channel][i] > (INT32_MAX >> shift_bits))) { + /* Bad frame, emit error */ + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + break; } - break; - default: - FLAC__ASSERT(0); - break; + } } } } - else { - /* Bad frame, emit error and zero the output signal */ +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + else if (decoder->protected_->state == FLAC__STREAM_DECODER_READ_FRAME) { + /* Bad frame, emit error */ send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH); - if(do_full_decode) { - for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) { - memset(decoder->private_->output[channel], 0, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + } +#endif + + /* Check whether frames are missing, if so, add silence to compensate */ + if(decoder->private_->last_frame_is_set && decoder->protected_->state == FLAC__STREAM_DECODER_READ_FRAME && !decoder->private_->is_seeking && do_full_decode) { + FLAC__ASSERT(decoder->private_->frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); + FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); + if(decoder->private_->last_frame.header.number.sample_number + decoder->private_->last_frame.header.blocksize < decoder->private_->frame.header.number.sample_number) { + uint32_t padding_samples_needed = decoder->private_->frame.header.number.sample_number - (decoder->private_->last_frame.header.number.sample_number + decoder->private_->last_frame.header.blocksize); + + /* Do some extra validation to assure last frame an current frame + * header are both valid before adding silence inbetween + * Technically both frames could be valid with differing sample_rates, + * channels and bits_per_sample, but it is quite rare */ + if(decoder->private_->last_frame.header.sample_rate == decoder->private_->frame.header.sample_rate && + decoder->private_->last_frame.header.channels == decoder->private_->frame.header.channels && + decoder->private_->last_frame.header.bits_per_sample == decoder->private_->frame.header.bits_per_sample && + decoder->private_->last_frame.header.blocksize >= 16) { + + FLAC__Frame empty_frame; + empty_frame.header = decoder->private_->last_frame.header; + empty_frame.footer.crc = 0; + /* No repairs larger than 5 seconds or 50 frames are made, to not + * unexpectedly create enormous files when one of the headers was + * corrupt after all */ + if(padding_samples_needed > (5*empty_frame.header.sample_rate)) + padding_samples_needed = 5*empty_frame.header.sample_rate; + if(padding_samples_needed > (50*empty_frame.header.blocksize)) + padding_samples_needed = 50*empty_frame.header.blocksize; + while(padding_samples_needed){ + empty_frame.header.number.sample_number += empty_frame.header.blocksize; + if(padding_samples_needed < empty_frame.header.blocksize) + empty_frame.header.blocksize = padding_samples_needed; + padding_samples_needed -= empty_frame.header.blocksize; + decoder->protected_->blocksize = empty_frame.header.blocksize; + + FLAC__ASSERT(empty_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); + decoder->private_->samples_decoded = empty_frame.header.number.sample_number + empty_frame.header.blocksize; + + if(!allocate_output_(decoder, empty_frame.header.blocksize, empty_frame.header.channels, empty_frame.header.bits_per_sample)) + return false; + + for(channel = 0; channel < empty_frame.header.channels; channel++) { + empty_frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_CONSTANT; + empty_frame.subframes[channel].data.constant.value = 0; + empty_frame.subframes[channel].wasted_bits = 0; + memset(decoder->private_->output[channel], 0, sizeof(FLAC__int32) * empty_frame.header.blocksize); + } + + if(write_audio_frame_to_client_(decoder, &empty_frame, (const FLAC__int32 * const *)decoder->private_->output) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE) { + decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED; + return false; + } + } } } } - *got_a_frame = true; + if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC || decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM) { + /* Got corruption, rewind if possible. Return value of seek + * isn't checked, if the seek fails the decoder will continue anyway */ + if(!FLAC__bitreader_rewind_to_after_last_seen_framesync(decoder->private_->input)){ +#ifndef NDEBUG + fprintf(stderr, "Rewinding, seeking necessary\n"); +#endif + if(decoder->private_->seek_callback && decoder->private_->last_seen_framesync){ + /* Last framesync isn't in bitreader anymore, rewind with seek if possible */ +#ifndef NDEBUG + FLAC__uint64 current_decode_position; + if(FLAC__stream_decoder_get_decode_position(decoder, ¤t_decode_position)) + fprintf(stderr, "Bitreader was %lu bytes short\n", current_decode_position-decoder->private_->last_seen_framesync); +#endif + if(decoder->private_->seek_callback(decoder, decoder->private_->last_seen_framesync, decoder->private_->client_data) == FLAC__STREAM_DECODER_SEEK_STATUS_ERROR) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + if(!FLAC__bitreader_clear(decoder->private_->input)) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + } + } +#ifndef NDEBUG + else{ + fprintf(stderr, "Rewinding, seeking not necessary\n"); + } +#endif + } + else { + *got_a_frame = true; - /* we wait to update fixed_block_size until here, when we're sure we've got a proper frame and hence a correct blocksize */ - if(decoder->private_->next_fixed_block_size) - decoder->private_->fixed_block_size = decoder->private_->next_fixed_block_size; + /* we wait to update fixed_block_size until here, when we're sure we've got a proper frame and hence a correct blocksize */ + if(decoder->private_->next_fixed_block_size) + decoder->private_->fixed_block_size = decoder->private_->next_fixed_block_size; - /* put the latest values into the public section of the decoder instance */ - decoder->protected_->channels = decoder->private_->frame.header.channels; - decoder->protected_->channel_assignment = decoder->private_->frame.header.channel_assignment; - decoder->protected_->bits_per_sample = decoder->private_->frame.header.bits_per_sample; - decoder->protected_->sample_rate = decoder->private_->frame.header.sample_rate; - decoder->protected_->blocksize = decoder->private_->frame.header.blocksize; + /* put the latest values into the public section of the decoder instance */ + decoder->protected_->channels = decoder->private_->frame.header.channels; + decoder->protected_->channel_assignment = decoder->private_->frame.header.channel_assignment; + decoder->protected_->bits_per_sample = decoder->private_->frame.header.bits_per_sample; + decoder->protected_->sample_rate = decoder->private_->frame.header.sample_rate; + decoder->protected_->blocksize = decoder->private_->frame.header.blocksize; - FLAC__ASSERT(decoder->private_->frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); - decoder->private_->samples_decoded = decoder->private_->frame.header.number.sample_number + decoder->private_->frame.header.blocksize; + FLAC__ASSERT(decoder->private_->frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); + decoder->private_->samples_decoded = decoder->private_->frame.header.number.sample_number + decoder->private_->frame.header.blocksize; - /* write it */ - if(do_full_decode) { - if(write_audio_frame_to_client_(decoder, &decoder->private_->frame, (const FLAC__int32 * const *)decoder->private_->output) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE) { - decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED; - return false; + /* write it */ + if(do_full_decode) { + if(write_audio_frame_to_client_(decoder, &decoder->private_->frame, (const FLAC__int32 * const *)decoder->private_->output) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE) { + decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED; + return false; + } } } @@ -2341,6 +2423,9 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder) case 2: decoder->private_->frame.header.bits_per_sample = 12; break; + case 3: + is_unparseable = true; + break; case 4: decoder->private_->frame.header.bits_per_sample = 16; break; @@ -2350,20 +2435,14 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder) case 6: decoder->private_->frame.header.bits_per_sample = 24; break; - case 3: case 7: - is_unparseable = true; + decoder->private_->frame.header.bits_per_sample = 32; break; default: FLAC__ASSERT(0); break; } - if(decoder->private_->frame.header.bits_per_sample == 32 && decoder->private_->frame.header.channel_assignment != FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT){ - /* Decoder isn't equipped for 33-bit side frame */ - is_unparseable = true; - } - #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* check to make sure that reserved bit is 0 */ if(raw_header[3] & 0x01) /* MAGIC NUMBER */ @@ -2529,12 +2608,6 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32 } else if(x <= 24) { uint32_t predictor_order = (x>>1)&7; - if(decoder->private_->frame.header.bits_per_sample > 24){ - /* Decoder isn't equipped for fixed subframes with more than 24 bps */ - send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM); - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; - } if(decoder->private_->frame.header.blocksize <= predictor_order){ send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; @@ -2565,9 +2638,21 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32 if(wasted_bits && do_full_decode) { x = decoder->private_->frame.subframes[channel].wasted_bits; - for(i = 0; i < decoder->private_->frame.header.blocksize; i++) { - uint32_t val = decoder->private_->output[channel][i]; - decoder->private_->output[channel][i] = (val << x); + if((bps + x) < 33) { + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) { + uint32_t val = decoder->private_->output[channel][i]; + decoder->private_->output[channel][i] = (val << x); + } + } + else { + /* When there are wasted bits, bps is never 33 and so + * side_subframe is never already in use */ + FLAC__ASSERT(!decoder->private_->side_subframe_in_use); + decoder->private_->side_subframe_in_use = true; + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) { + uint64_t val = decoder->private_->output[channel][i]; + decoder->private_->side_subframe[i] = (val << x); + } } } @@ -2577,21 +2662,28 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32 FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, FLAC__bool do_full_decode) { FLAC__Subframe_Constant *subframe = &decoder->private_->frame.subframes[channel].data.constant; - FLAC__int32 x; + FLAC__int64 x; uint32_t i; - FLAC__int32 *output = decoder->private_->output[channel]; decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_CONSTANT; - if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &x, bps)) + if(!FLAC__bitreader_read_raw_int64(decoder->private_->input, &x, bps)) return false; /* read_callback_ sets the state for us */ subframe->value = x; /* decode the subframe */ if(do_full_decode) { - for(i = 0; i < decoder->private_->frame.header.blocksize; i++) - output[i] = x; + if(bps <= 32) { + FLAC__int32 *output = decoder->private_->output[channel]; + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) + output[i] = x; + } else { + FLAC__int64 *output = decoder->private_->side_subframe; + decoder->private_->side_subframe_in_use = true; + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) + output[i] = x; + } } return true; @@ -2600,7 +2692,7 @@ FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, uint32_t channe FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, const uint32_t order, FLAC__bool do_full_decode) { FLAC__Subframe_Fixed *subframe = &decoder->private_->frame.subframes[channel].data.fixed; - FLAC__int32 i32; + FLAC__int64 i64; FLAC__uint32 u32; uint32_t u; @@ -2611,9 +2703,9 @@ FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, uint32_t channel, /* read warm-up samples */ for(u = 0; u < order; u++) { - if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i32, bps)) + if(!FLAC__bitreader_read_raw_int64(decoder->private_->input, &i64, bps)) return false; /* read_callback_ sets the state for us */ - subframe->warmup[u] = i32; + subframe->warmup[u] = i64; } /* read entropy coding method info */ @@ -2653,8 +2745,19 @@ FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, uint32_t channel, /* decode the subframe */ if(do_full_decode) { - memcpy(decoder->private_->output[channel], subframe->warmup, sizeof(FLAC__int32) * order); - FLAC__fixed_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, order, decoder->private_->output[channel]+order); + if(bps < 33){ + for(uint32_t i = 0; i < order; i++) + decoder->private_->output[channel][i] = subframe->warmup[i]; + if(bps+order <= 32) + FLAC__fixed_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, order, decoder->private_->output[channel]+order); + else + FLAC__fixed_restore_signal_wide(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, order, decoder->private_->output[channel]+order); + } + else { + decoder->private_->side_subframe_in_use = true; + memcpy(decoder->private_->side_subframe, subframe->warmup, sizeof(FLAC__int64) * order); + FLAC__fixed_restore_signal_wide_33bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, order, decoder->private_->side_subframe+order); + } } return true; @@ -2664,6 +2767,7 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, uint32_t channel, ui { FLAC__Subframe_LPC *subframe = &decoder->private_->frame.subframes[channel].data.lpc; FLAC__int32 i32; + FLAC__int64 i64; FLAC__uint32 u32; uint32_t u; @@ -2674,9 +2778,9 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, uint32_t channel, ui /* read warm-up samples */ for(u = 0; u < order; u++) { - if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i32, bps)) + if(!FLAC__bitreader_read_raw_int64(decoder->private_->input, &i64, bps)) return false; /* read_callback_ sets the state for us */ - subframe->warmup[u] = i32; + subframe->warmup[u] = i64; } /* read qlp coeff precision */ @@ -2743,14 +2847,20 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, uint32_t channel, ui /* decode the subframe */ if(do_full_decode) { - memcpy(decoder->private_->output[channel], subframe->warmup, sizeof(FLAC__int32) * order); - if(bps + subframe->qlp_coeff_precision + FLAC__bitmath_ilog2(order) <= 32) - if(bps <= 16 && subframe->qlp_coeff_precision <= 16) - decoder->private_->local_lpc_restore_signal_16bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); + if(bps <= 32) { + for(uint32_t i = 0; i < order; i++) + decoder->private_->output[channel][i] = subframe->warmup[i]; + if(FLAC__lpc_max_residual_bps(bps, subframe->qlp_coeff, order, subframe->quantization_level) <= 32 && + FLAC__lpc_max_prediction_before_shift_bps(bps, subframe->qlp_coeff, order) <= 32) + FLAC__lpc_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); else - decoder->private_->local_lpc_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); - else - decoder->private_->local_lpc_restore_signal_64bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); + FLAC__lpc_restore_signal_wide(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); + } + else { + decoder->private_->side_subframe_in_use = true; + memcpy(decoder->private_->side_subframe, subframe->warmup, sizeof(FLAC__int64) * order); + FLAC__lpc_restore_signal_wide_33bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->side_subframe+order); + } } return true; @@ -2759,22 +2869,39 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, uint32_t channel, ui FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, FLAC__bool do_full_decode) { FLAC__Subframe_Verbatim *subframe = &decoder->private_->frame.subframes[channel].data.verbatim; - FLAC__int32 x, *residual = decoder->private_->residual[channel]; uint32_t i; decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_VERBATIM; - subframe->data = residual; + if(bps < 33) { + FLAC__int32 x, *residual = decoder->private_->residual[channel]; - for(i = 0; i < decoder->private_->frame.header.blocksize; i++) { - if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &x, bps)) - return false; /* read_callback_ sets the state for us */ - residual[i] = x; + subframe->data_type = FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT32; + subframe->data.int32 = residual; + + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) { + if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &x, bps)) + return false; /* read_callback_ sets the state for us */ + residual[i] = x; + } + + /* decode the subframe */ + if(do_full_decode) + memcpy(decoder->private_->output[channel], subframe->data.int32, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize); } + else { + FLAC__int64 x, *side = decoder->private_->side_subframe; - /* decode the subframe */ - if(do_full_decode) - memcpy(decoder->private_->output[channel], subframe->data, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize); + subframe->data_type = FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT64; + subframe->data.int64 = side; + decoder->private_->side_subframe_in_use = true; + + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) { + if(!FLAC__bitreader_read_raw_int64(decoder->private_->input, &x, bps)) + return false; /* read_callback_ sets the state for us */ + side[i] = x; + } + } return true; } @@ -2805,18 +2932,33 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, uint32_ if(rice_parameter < pesc) { partitioned_rice_contents->raw_bits[partition] = 0; u = (partition == 0) ? partition_samples - predictor_order : partition_samples; - if(!FLAC__bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter)) - return false; /* read_callback_ sets the state for us */ + if(!FLAC__bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter)){ + if(decoder->protected_->state == FLAC__STREAM_DECODER_READ_FRAME) { + /* no error was set, read_callback_ didn't set it, so + * invalid rice symbol was found */ + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + else + return false; /* read_callback_ sets the state for us */ + } sample += u; } else { if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN)) return false; /* read_callback_ sets the state for us */ partitioned_rice_contents->raw_bits[partition] = rice_parameter; - for(u = (partition == 0)? predictor_order : 0; u < partition_samples; u++, sample++) { - if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i, rice_parameter)) - return false; /* read_callback_ sets the state for us */ - residual[sample] = i; + if(rice_parameter == 0) { + for(u = (partition == 0)? predictor_order : 0; u < partition_samples; u++, sample++) + residual[sample] = 0; + } + else{ + for(u = (partition == 0)? predictor_order : 0; u < partition_samples; u++, sample++) { + if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i, rice_parameter)) + return false; /* read_callback_ sets the state for us */ + residual[sample] = i; + } } } } @@ -2920,6 +3062,65 @@ FLAC__bool read_callback_(FLAC__byte buffer[], size_t *bytes, void *client_data) */ } +#ifdef FUZZING_BUILD_MODE_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW +/* The attribute below is to silence the undefined sanitizer of oss-fuzz. + * Because fuzzing feeds bogus predictors and residual samples to the + * decoder, having overflows in this section is unavoidable. Also, + * because the calculated values are audio path only, there is no + * potential for security problems */ +__attribute__((no_sanitize("signed-integer-overflow"))) +#endif +void undo_channel_coding(FLAC__StreamDecoder *decoder) { + switch(decoder->private_->frame.header.channel_assignment) { + case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: + /* do nothing */ + break; + case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: + FLAC__ASSERT(decoder->private_->frame.header.channels == 2); + FLAC__ASSERT(decoder->private_->side_subframe_in_use != /* logical XOR */ (decoder->private_->frame.header.bits_per_sample < 32)); + for(uint32_t i = 0; i < decoder->private_->frame.header.blocksize; i++) + if(decoder->private_->side_subframe_in_use) + decoder->private_->output[1][i] = decoder->private_->output[0][i] - decoder->private_->side_subframe[i]; + else + decoder->private_->output[1][i] = decoder->private_->output[0][i] - decoder->private_->output[1][i]; + break; + case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE: + FLAC__ASSERT(decoder->private_->frame.header.channels == 2); + FLAC__ASSERT(decoder->private_->side_subframe_in_use != /* logical XOR */ (decoder->private_->frame.header.bits_per_sample < 32)); + for(uint32_t i = 0; i < decoder->private_->frame.header.blocksize; i++) + if(decoder->private_->side_subframe_in_use) + decoder->private_->output[0][i] = decoder->private_->output[1][i] + decoder->private_->side_subframe[i]; + else + decoder->private_->output[0][i] += decoder->private_->output[1][i]; + break; + case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE: + FLAC__ASSERT(decoder->private_->frame.header.channels == 2); + FLAC__ASSERT(decoder->private_->side_subframe_in_use != /* logical XOR */ (decoder->private_->frame.header.bits_per_sample < 32)); + for(uint32_t i = 0; i < decoder->private_->frame.header.blocksize; i++) { + if(!decoder->private_->side_subframe_in_use){ + FLAC__int32 mid, side; + mid = decoder->private_->output[0][i]; + side = decoder->private_->output[1][i]; + mid = ((uint32_t) mid) << 1; + mid |= (side & 1); /* i.e. if 'side' is odd... */ + decoder->private_->output[0][i] = (mid + side) >> 1; + decoder->private_->output[1][i] = (mid - side) >> 1; + } + else { /* bps == 32 */ + FLAC__int64 mid; + mid = ((uint64_t)decoder->private_->output[0][i]) << 1; + mid |= (decoder->private_->side_subframe[i] & 1); /* i.e. if 'side' is odd... */ + decoder->private_->output[0][i] = (mid + decoder->private_->side_subframe[i]) >> 1; + decoder->private_->output[1][i] = (mid - decoder->private_->side_subframe[i]) >> 1; + } + } + break; + default: + FLAC__ASSERT(0); + break; + } +} + #if FLAC__HAS_OGG FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes) { @@ -2968,6 +3169,8 @@ FLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]) { + decoder->private_->last_frame = *frame; /* save the frame */ + decoder->private_->last_frame_is_set = true; if(decoder->private_->is_seeking) { FLAC__uint64 this_frame_sample = frame->header.number.sample_number; FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize; @@ -2978,7 +3181,6 @@ FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder #if FLAC__HAS_OGG decoder->private_->got_a_frame = true; #endif - decoder->private_->last_frame = *frame; /* save the frame */ if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */ uint32_t delta = (uint32_t)(target_sample - this_frame_sample); /* kick out of seek mode */ @@ -3032,7 +3234,7 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s FLAC__int64 pos = -1; int i; uint32_t approx_bytes_per_frame; - FLAC__bool first_seek = true; + FLAC__bool first_seek = true, seek_from_lower_bound = false; const FLAC__uint64 total_samples = FLAC__stream_decoder_get_total_samples(decoder); const uint32_t min_blocksize = decoder->private_->stream_info.data.stream_info.min_blocksize; const uint32_t max_blocksize = decoder->private_->stream_info.data.stream_info.max_blocksize; @@ -3077,7 +3279,8 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s upper_bound = stream_length; upper_bound_sample = total_samples > 0 ? total_samples : target_sample /*estimate it*/; - if(decoder->protected_->state == FLAC__STREAM_DECODER_READ_FRAME) { + if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC && + decoder->private_->samples_decoded != 0) { if(target_sample < decoder->private_->samples_decoded) { if(FLAC__stream_decoder_get_decode_position(decoder, &upper_bound)) upper_bound_sample = decoder->private_->samples_decoded; @@ -3093,7 +3296,9 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s * must be ordered by ascending sample number. * * Note: to protect against invalid seek tables we will ignore points - * that have frame_samples==0 or sample_number>=total_samples + * that have frame_samples==0 or sample_number>=total_samples. Also, + * because math is limited to 64-bit ints, seekpoints with an offset + * larger than 2^63 (8 exbibyte) are rejected. */ if(seek_table) { FLAC__uint64 new_lower_bound = lower_bound; @@ -3154,22 +3359,34 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s decoder->private_->target_sample = target_sample; while(1) { + /* check whether decoder is still valid so bad state isn't overwritten + * with seek error */ + if(decoder->protected_->state == FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR || + decoder->protected_->state == FLAC__STREAM_DECODER_ABORTED) + return false; /* check if the bounds are still ok */ - if (lower_bound_sample >= upper_bound_sample || lower_bound > upper_bound) { + if (lower_bound_sample >= upper_bound_sample || + lower_bound > upper_bound || + upper_bound >= INT64_MAX) { decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; return false; } + if(seek_from_lower_bound) { + pos = lower_bound; + } + else { #ifndef FLAC__INTEGER_ONLY_LIBRARY - pos = (FLAC__int64)lower_bound + (FLAC__int64)((double)(target_sample - lower_bound_sample) / (double)(upper_bound_sample - lower_bound_sample) * (double)(upper_bound - lower_bound)) - approx_bytes_per_frame; + pos = (FLAC__int64)lower_bound + (FLAC__int64)((double)(target_sample - lower_bound_sample) / (double)(upper_bound_sample - lower_bound_sample) * (double)(upper_bound - lower_bound)) - approx_bytes_per_frame; #else - /* a little less accurate: */ - if(upper_bound - lower_bound < 0xffffffff) - pos = (FLAC__int64)lower_bound + (FLAC__int64)(((target_sample - lower_bound_sample) * (upper_bound - lower_bound)) / (upper_bound_sample - lower_bound_sample)) - approx_bytes_per_frame; - else { /* @@@ WATCHOUT, ~2TB limit */ - FLAC__uint64 ratio = (1<<16) / (upper_bound_sample - lower_bound_sample); - pos = (FLAC__int64)lower_bound + (FLAC__int64)((((target_sample - lower_bound_sample)>>8) * ((upper_bound - lower_bound)>>8) * ratio)) - approx_bytes_per_frame; - } + /* a little less accurate: */ + if(upper_bound - lower_bound < 0xffffffff) + pos = (FLAC__int64)lower_bound + (FLAC__int64)(((target_sample - lower_bound_sample) * (upper_bound - lower_bound)) / (upper_bound_sample - lower_bound_sample)) - approx_bytes_per_frame; + else { /* @@@ WATCHOUT, ~2TB limit */ + FLAC__uint64 ratio = (1<<16) / (upper_bound_sample - lower_bound_sample); + pos = (FLAC__int64)lower_bound + (FLAC__int64)((((target_sample - lower_bound_sample)>>8) * ((upper_bound - lower_bound)>>8) * ratio)) - approx_bytes_per_frame; + } #endif + } if(pos >= (FLAC__int64)upper_bound) pos = (FLAC__int64)upper_bound - 1; if(pos < (FLAC__int64)lower_bound) @@ -3189,25 +3406,32 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s * FLAC__stream_decoder_process_single() to return false. */ decoder->private_->unparseable_frame_count = 0; - if(!FLAC__stream_decoder_process_single(decoder) || - decoder->protected_->state == FLAC__STREAM_DECODER_ABORTED) { - decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; - return false; + if(!FLAC__stream_decoder_process_single(decoder) || decoder->protected_->state == FLAC__STREAM_DECODER_ABORTED || 0 == decoder->private_->samples_decoded) { + /* No frame could be decoded */ + if(decoder->protected_->state != FLAC__STREAM_DECODER_ABORTED && decoder->private_->eof_callback(decoder, decoder->private_->client_data) && !seek_from_lower_bound){ + /* decoder has hit end of stream while processing corrupt + * frame. To remedy this, try decoding a frame at the lower + * bound so the seek after that hopefully ends up somewhere + * else */ + seek_from_lower_bound = true; + continue; + } + else { + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } } + seek_from_lower_bound = false; + /* our write callback will change the state when it gets to the target frame */ /* actually, we could have got_a_frame if our decoder is at FLAC__STREAM_DECODER_END_OF_STREAM so we need to check for that also */ -#if 0 - /*@@@@@@ used to be the following; not clear if the check for end of stream is needed anymore */ - if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_SEEKING && decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM) - break; -#endif if(!decoder->private_->is_seeking) break; FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); this_frame_sample = decoder->private_->last_frame.header.number.sample_number; - if (0 == decoder->private_->samples_decoded || (this_frame_sample + decoder->private_->last_frame.header.blocksize >= upper_bound_sample && !first_seek)) { + if(this_frame_sample + decoder->private_->last_frame.header.blocksize >= upper_bound_sample && !first_seek) { if (pos == (FLAC__int64)lower_bound) { /* can't move back any more than the first frame, something is fatally wrong */ decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; @@ -3281,6 +3505,12 @@ FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint decoder->private_->target_sample = target_sample; for( ; ; iteration++) { + /* Do sanity checks on bounds */ + if(right_pos <= left_pos || right_pos - left_pos < 9) { + /* FLAC frame is at least 9 byte in size */ + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) { if (iteration >= BINARY_SEARCH_AFTER_ITERATION) { pos = (right_pos + left_pos) / 2; @@ -3433,7 +3663,13 @@ FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder if(decoder->private_->file == stdin) return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; - else if(flac_fstat(fileno(decoder->private_->file), &filestats) != 0) + +#ifndef FLAC__USE_FILELENGTHI64 + if(flac_fstat(fileno(decoder->private_->file), &filestats) != 0) +#else + filestats.st_size = _filelengthi64(fileno(decoder->private_->file)); + if(filestats.st_size < 0) +#endif return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; else { *stream_length = (FLAC__uint64)filestats.st_size; @@ -3447,8 +3683,3 @@ FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_d return feof(decoder->private_->file)? true : false; } - -void *get_client_data_from_decoder(FLAC__StreamDecoder *decoder) -{ - return decoder->private_->client_data; -} diff --git a/sys/src/cmd/audio/libFLAC/stream_encoder.c b/sys/src/cmd/audio/libFLAC/stream_encoder.c index 7109802c2..2879c51c2 100644 --- a/sys/src/cmd/audio/libFLAC/stream_encoder.c +++ b/sys/src/cmd/audio/libFLAC/stream_encoder.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -118,9 +118,9 @@ static const struct CompressionLevels { { false, false, 6, 0, false, false, false, 0, 4, 0, "tukey(5e-1)" }, { true , true , 8, 0, false, false, false, 0, 4, 0, "tukey(5e-1)" }, { true , false, 8, 0, false, false, false, 0, 5, 0, "tukey(5e-1)" }, - { true , false, 8, 0, false, false, false, 0, 6, 0, "tukey(5e-1);partial_tukey(2)" }, - { true , false, 12, 0, false, false, false, 0, 6, 0, "tukey(5e-1);partial_tukey(2)" }, - { true , false, 12, 0, false, false, false, 0, 6, 0, "tukey(5e-1);partial_tukey(2);punchout_tukey(3)" } + { true , false, 8, 0, false, false, false, 0, 6, 0, "subdivide_tukey(2)" }, + { true , false, 12, 0, false, false, false, 0, 6, 0, "subdivide_tukey(2)" }, + { true , false, 12, 0, false, false, false, 0, 6, 0, "subdivide_tukey(3)" } /* here we use locale-independent 5e-1 instead of 0.5 or 0,5 */ }; @@ -140,8 +140,8 @@ static void update_metadata_(const FLAC__StreamEncoder *encoder); #if FLAC__HAS_OGG static void update_ogg_metadata_(FLAC__StreamEncoder *encoder); #endif -static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block, FLAC__bool is_last_block); -static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block); +static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_block); +static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder); static FLAC__bool process_subframe_( FLAC__StreamEncoder *encoder, @@ -149,7 +149,7 @@ static FLAC__bool process_subframe_( uint32_t max_partition_order, const FLAC__FrameHeader *frame_header, uint32_t subframe_bps, - const FLAC__int32 integer_signal[], + const void *integer_signal, FLAC__Subframe *subframe[2], FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2], FLAC__int32 *residual[2], @@ -167,7 +167,7 @@ static FLAC__bool add_subframe_( static uint32_t evaluate_constant_subframe_( FLAC__StreamEncoder *encoder, - const FLAC__int32 signal, + const FLAC__int64 signal, uint32_t blocksize, uint32_t subframe_bps, FLAC__Subframe *subframe @@ -175,14 +175,13 @@ static uint32_t evaluate_constant_subframe_( static uint32_t evaluate_fixed_subframe_( FLAC__StreamEncoder *encoder, - const FLAC__int32 signal[], + const void *signal, FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t raw_bits_per_partition[], uint32_t blocksize, uint32_t subframe_bps, uint32_t order, - uint32_t rice_parameter, uint32_t rice_parameter_limit, uint32_t min_partition_order, uint32_t max_partition_order, @@ -195,7 +194,7 @@ static uint32_t evaluate_fixed_subframe_( #ifndef FLAC__INTEGER_ONLY_LIBRARY static uint32_t evaluate_lpc_subframe_( FLAC__StreamEncoder *encoder, - const FLAC__int32 signal[], + const void *signal, FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t raw_bits_per_partition[], @@ -204,7 +203,6 @@ static uint32_t evaluate_lpc_subframe_( uint32_t subframe_bps, uint32_t order, uint32_t qlp_coeff_precision, - uint32_t rice_parameter, uint32_t rice_parameter_limit, uint32_t min_partition_order, uint32_t max_partition_order, @@ -217,7 +215,7 @@ static uint32_t evaluate_lpc_subframe_( static uint32_t evaluate_verbatim_subframe_( FLAC__StreamEncoder *encoder, - const FLAC__int32 signal[], + const void *signal, uint32_t blocksize, uint32_t subframe_bps, FLAC__Subframe *subframe @@ -230,7 +228,6 @@ static uint32_t find_best_partition_order_( uint32_t raw_bits_per_partition[], uint32_t residual_samples, uint32_t predictor_order, - uint32_t rice_parameter, uint32_t rice_parameter_limit, uint32_t min_partition_order, uint32_t max_partition_order, @@ -267,7 +264,6 @@ static FLAC__bool set_partitioned_rice_( const uint32_t raw_bits_per_partition[], const uint32_t residual_samples, const uint32_t predictor_order, - const uint32_t suggested_rice_parameter, const uint32_t rice_parameter_limit, const uint32_t rice_parameter_search_dist, const uint32_t partition_order, @@ -277,6 +273,7 @@ static FLAC__bool set_partitioned_rice_( ); static uint32_t get_wasted_bits_(FLAC__int32 signal[], uint32_t samples); +static uint32_t get_wasted_bits_wide_(FLAC__int64 signal_wide[], FLAC__int32 signal[], uint32_t samples); /* verify-related routines: */ static void append_to_verify_fifo_( @@ -317,6 +314,7 @@ typedef struct FLAC__StreamEncoderPrivate { uint32_t input_capacity; /* current size (in samples) of the signal and residual buffers */ FLAC__int32 *integer_signal[FLAC__MAX_CHANNELS]; /* the integer version of the input signal */ FLAC__int32 *integer_signal_mid_side[2]; /* the integer version of the mid-side input signal (stereo only) */ + FLAC__int64 *integer_signal_33bit_side; /* 33-bit side for 32-bit stereo decorrelation */ #ifndef FLAC__INTEGER_ONLY_LIBRARY FLAC__real *real_signal[FLAC__MAX_CHANNELS]; /* (@@@ currently unused) the floating-point version of the input signal */ FLAC__real *real_signal_mid_side[2]; /* (@@@ currently unused) the floating-point version of the mid-side input signal (stereo only) */ @@ -360,11 +358,17 @@ typedef struct FLAC__StreamEncoderPrivate { uint32_t (*local_fixed_compute_best_predictor_wide)(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); #endif #ifndef FLAC__INTEGER_ONLY_LIBRARY - void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], uint32_t data_len, uint32_t lag, FLAC__real autoc[]); + void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]); void (*local_lpc_compute_residual_from_qlp_coefficients)(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]); void (*local_lpc_compute_residual_from_qlp_coefficients_64bit)(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]); void (*local_lpc_compute_residual_from_qlp_coefficients_16bit)(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]); #endif + FLAC__bool disable_mmx; + FLAC__bool disable_sse2; + FLAC__bool disable_ssse3; + FLAC__bool disable_sse41; + FLAC__bool disable_avx2; + FLAC__bool disable_fma; FLAC__bool disable_constant_subframes; FLAC__bool disable_fixed_subframes; FLAC__bool disable_verbatim_subframes; @@ -385,6 +389,7 @@ typedef struct FLAC__StreamEncoderPrivate { /* unaligned (original) pointers to allocated data */ FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS]; FLAC__int32 *integer_signal_mid_side_unaligned[2]; + FLAC__int64 *integer_signal_33bit_side_unaligned; #ifndef FLAC__INTEGER_ONLY_LIBRARY FLAC__real *real_signal_unaligned[FLAC__MAX_CHANNELS]; /* (@@@ currently unused) */ FLAC__real *real_signal_mid_side_unaligned[2]; /* (@@@ currently unused) */ @@ -536,6 +541,8 @@ FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new(void) encoder->private_->file = 0; + encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED; + set_defaults_(encoder); encoder->private_->is_being_deleted = false; @@ -568,8 +575,6 @@ FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new(void) for(i = 0; i < 2; i++) FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_extra[i]); - encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED; - return encoder; } @@ -649,10 +654,7 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( else if(!encoder->protected_->do_mid_side_stereo) encoder->protected_->loose_mid_side_stereo = false; - if(encoder->protected_->bits_per_sample >= 32) - encoder->protected_->do_mid_side_stereo = false; /* since we currently do 32-bit math, the side channel would have 33 bps and overflow */ - - if(encoder->protected_->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected_->bits_per_sample > FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE) + if(encoder->protected_->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected_->bits_per_sample > FLAC__MAX_BITS_PER_SAMPLE) return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE; if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate)) @@ -719,7 +721,8 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( encoder->protected_->bits_per_sample != 12 && encoder->protected_->bits_per_sample != 16 && encoder->protected_->bits_per_sample != 20 && - encoder->protected_->bits_per_sample != 24 + encoder->protected_->bits_per_sample != 24 && + encoder->protected_->bits_per_sample != 32 ) return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE; if(encoder->protected_->max_residual_partition_order > FLAC__SUBSET_MAX_RICE_PARTITION_ORDER) @@ -832,6 +835,7 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0; #endif } + encoder->private_->integer_signal_33bit_side_unaligned = encoder->private_->integer_signal_33bit_side = 0; #ifndef FLAC__INTEGER_ONLY_LIBRARY for(i = 0; i < encoder->protected_->num_apodizations; i++) encoder->private_->window_unaligned[i] = encoder->private_->window[i] = 0; @@ -853,10 +857,10 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( encoder->private_->loose_mid_side_stereo_frames = (uint32_t)((double)encoder->protected_->sample_rate * 0.4 / (double)encoder->protected_->blocksize + 0.5); #else /* 26214 is the approximate fixed-point equivalent to 0.4 (0.4 * 2^16) */ - /* sample rate can be up to 655350 Hz, and thus use 20 bits, so we do the multiply÷ by hand */ - FLAC__ASSERT(FLAC__MAX_SAMPLE_RATE <= 655350); + /* sample rate can be up to 1048575 Hz, and thus use 20 bits, so we do the multiply÷ by hand */ + FLAC__ASSERT(FLAC__MAX_SAMPLE_RATE <= 1048575); FLAC__ASSERT(FLAC__MAX_BLOCK_SIZE <= 65535); - FLAC__ASSERT(encoder->protected_->sample_rate <= 655350); + FLAC__ASSERT(encoder->protected_->sample_rate <= 1048575); FLAC__ASSERT(encoder->protected_->blocksize <= 65535); encoder->private_->loose_mid_side_stereo_frames = (uint32_t)FLAC__fixedpoint_trunc((((FLAC__uint64)(encoder->protected_->sample_rate) * (FLAC__uint64)(26214)) << 16) / (encoder->protected_->blocksize<<16) + FLAC__FP_ONE_HALF); #endif @@ -870,6 +874,20 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( * get the CPU info and set the function pointers */ FLAC__cpu_info(&encoder->private_->cpuinfo); + /* remove cpu info as requested by + * FLAC__stream_encoder_disable_instruction_set */ + if(encoder->private_->disable_mmx) + encoder->private_->cpuinfo.x86.mmx = false; + if(encoder->private_->disable_sse2) + encoder->private_->cpuinfo.x86.sse2 = false; + if(encoder->private_->disable_ssse3) + encoder->private_->cpuinfo.x86.ssse3 = false; + if(encoder->private_->disable_sse41) + encoder->private_->cpuinfo.x86.sse41 = false; + if(encoder->private_->disable_avx2) + encoder->private_->cpuinfo.x86.avx2 = false; + if(encoder->private_->disable_fma) + encoder->private_->cpuinfo.x86.fma = false; /* first default to the non-asm routines */ #ifndef FLAC__INTEGER_ONLY_LIBRARY encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation; @@ -889,51 +907,49 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( #ifdef FLAC__HAS_TARGET_POWER8 #ifdef FLAC__HAS_TARGET_POWER9 if (encoder->private_->cpuinfo.ppc.arch_3_00) { - if(encoder->protected_->max_lpc_order < 4) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_4; - else if(encoder->protected_->max_lpc_order < 8) + if(encoder->protected_->max_lpc_order < 8) encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_8; - else if(encoder->protected_->max_lpc_order < 12) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_12; - else if(encoder->protected_->max_lpc_order < 16) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_16; + else if(encoder->protected_->max_lpc_order < 10) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_10; + else if(encoder->protected_->max_lpc_order < 14) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_power9_vsx_lag_14; else encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation; } else #endif if (encoder->private_->cpuinfo.ppc.arch_2_07) { - if(encoder->protected_->max_lpc_order < 4) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_4; - else if(encoder->protected_->max_lpc_order < 8) + if(encoder->protected_->max_lpc_order < 8) encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_8; - else if(encoder->protected_->max_lpc_order < 12) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_12; - else if(encoder->protected_->max_lpc_order < 16) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_16; + else if(encoder->protected_->max_lpc_order < 10) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_10; + else if(encoder->protected_->max_lpc_order < 14) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_power8_vsx_lag_14; else encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation; } #endif +#endif /* defined(FLAC__CPU_PPC64) && defined(FLAC__USE_VSX) */ + +#if defined FLAC__CPU_ARM64 && FLAC__HAS_NEONINTRIN +#if FLAC__HAS_A64NEONINTRIN + if(encoder->protected_->max_lpc_order < 8) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_neon_lag_8; + else if(encoder->protected_->max_lpc_order < 10) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_neon_lag_10; + else if(encoder->protected_->max_lpc_order < 14) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_neon_lag_14; + else + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation; #endif + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_neon; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_neon; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_neon; +#endif /* defined FLAC__CPU_ARM64 && FLAC__HAS_NEONINTRIN */ + if(encoder->private_->cpuinfo.use_asm) { # ifdef FLAC__CPU_IA32 FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32); # ifdef FLAC__HAS_NASM - if (encoder->private_->cpuinfo.x86.sse) { - if(encoder->protected_->max_lpc_order < 4) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4_old; - else if(encoder->protected_->max_lpc_order < 8) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8_old; - else if(encoder->protected_->max_lpc_order < 12) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12_old; - else if(encoder->protected_->max_lpc_order < 16) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_16_old; - else - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32; - } - else - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32; - encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide_asm_ia32; /* OPT_IA32: was really necessary for GCC < 4.9 */ if (encoder->private_->cpuinfo.x86.mmx) { encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32; @@ -948,37 +964,15 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov; # endif /* FLAC__HAS_NASM */ # if FLAC__HAS_X86INTRIN -# if defined FLAC__SSE_SUPPORTED - if (encoder->private_->cpuinfo.x86.sse) { - if (encoder->private_->cpuinfo.x86.sse42 || !encoder->private_->cpuinfo.x86.intel) { /* use new autocorrelation functions */ - if(encoder->protected_->max_lpc_order < 4) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_4_new; - else if(encoder->protected_->max_lpc_order < 8) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_8_new; - else if(encoder->protected_->max_lpc_order < 12) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_12_new; - else if(encoder->protected_->max_lpc_order < 16) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_16_new; - else - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation; - } - else { /* use old autocorrelation functions */ - if(encoder->protected_->max_lpc_order < 4) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_4_old; - else if(encoder->protected_->max_lpc_order < 8) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_8_old; - else if(encoder->protected_->max_lpc_order < 12) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_12_old; - else if(encoder->protected_->max_lpc_order < 16) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_16_old; - else - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation; - } - } -# endif - # ifdef FLAC__SSE2_SUPPORTED if (encoder->private_->cpuinfo.x86.sse2) { + if(encoder->protected_->max_lpc_order < 8) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse2_lag_8; + else if(encoder->protected_->max_lpc_order < 10) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse2_lag_10; + else if(encoder->protected_->max_lpc_order < 14) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse2_lag_14; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_sse2; encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_sse2; } @@ -1013,31 +1007,17 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( # elif defined FLAC__CPU_X86_64 FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_X86_64); # if FLAC__HAS_X86INTRIN -# ifdef FLAC__SSE_SUPPORTED - if(encoder->private_->cpuinfo.x86.sse42 || !encoder->private_->cpuinfo.x86.intel) { /* use new autocorrelation functions */ - if(encoder->protected_->max_lpc_order < 4) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_4_new; - else if(encoder->protected_->max_lpc_order < 8) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_8_new; - else if(encoder->protected_->max_lpc_order < 12) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_12_new; - else if(encoder->protected_->max_lpc_order < 16) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_16_new; - } - else { - if(encoder->protected_->max_lpc_order < 4) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_4_old; - else if(encoder->protected_->max_lpc_order < 8) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_8_old; - else if(encoder->protected_->max_lpc_order < 12) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_12_old; - else if(encoder->protected_->max_lpc_order < 16) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_16_old; - } -# endif - # ifdef FLAC__SSE2_SUPPORTED - encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_sse2; + if(encoder->private_->cpuinfo.x86.sse2) { /* For fuzzing */ + if(encoder->protected_->max_lpc_order < 8) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse2_lag_8; + else if(encoder->protected_->max_lpc_order < 10) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse2_lag_10; + else if(encoder->protected_->max_lpc_order < 14) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse2_lag_14; + + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_sse2; + } # endif # ifdef FLAC__SSE4_1_SUPPORTED if(encoder->private_->cpuinfo.x86.sse41) { @@ -1051,10 +1031,23 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_avx2; } # endif +# ifdef FLAC__FMA_SUPPORTED + if(encoder->private_->cpuinfo.x86.fma) { + if(encoder->protected_->max_lpc_order < 8) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_fma_lag_8; + else if(encoder->protected_->max_lpc_order < 12) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_fma_lag_12; + else if(encoder->protected_->max_lpc_order < 16) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_fma_lag_16; + } +# endif + # ifdef FLAC__SSE2_SUPPORTED - encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_intrin_sse2; - encoder->private_->local_fixed_compute_best_predictor_wide = FLAC__fixed_compute_best_predictor_wide_intrin_sse2; + if(encoder->private_->cpuinfo.x86.sse2) { /* For fuzzing */ + encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_intrin_sse2; + encoder->private_->local_fixed_compute_best_predictor_wide = FLAC__fixed_compute_best_predictor_wide_intrin_sse2; + } # endif # ifdef FLAC__SSSE3_SUPPORTED if (encoder->private_->cpuinfo.x86.ssse3) { @@ -1066,6 +1059,7 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( # endif /* FLAC__CPU_... */ } # endif /* !FLAC__NO_ASM */ + #endif /* !FLAC__INTEGER_ONLY_LIBRARY */ #if !defined FLAC__NO_ASM && FLAC__HAS_X86INTRIN if(encoder->private_->cpuinfo.use_asm) { @@ -1475,14 +1469,24 @@ FLAC_API FLAC__bool FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder) FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - if(encoder->protected_->state == FLAC__STREAM_ENCODER_UNINITIALIZED) + if(encoder->protected_->state == FLAC__STREAM_ENCODER_UNINITIALIZED){ + if(encoder->protected_->metadata){ // True in case FLAC__stream_encoder_set_metadata was used but init failed + free(encoder->protected_->metadata); + encoder->protected_->metadata = 0; + encoder->protected_->num_metadata_blocks = 0; + } + if(0 != encoder->private_->file) { + if(encoder->private_->file != stdout) + fclose(encoder->private_->file); + encoder->private_->file = 0; + } return true; + } if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) { if(encoder->private_->current_sample_number != 0) { - const FLAC__bool is_fractional_block = encoder->protected_->blocksize != encoder->private_->current_sample_number; encoder->protected_->blocksize = encoder->private_->current_sample_number; - if(!process_frame_(encoder, is_fractional_block, /*is_last_block=*/true)) + if(!process_frame_(encoder, /*is_last_block=*/true)) error = true; } } @@ -1740,7 +1744,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *en encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_TUKEY; } } - else if(n>15 && 0 == strncmp("partial_tukey(" , specification, 14)) { + else if(n>15 && 0 == strncmp("partial_tukey(", specification, 14)) { FLAC__int32 tukey_parts = (FLAC__int32)strtod(specification+14, 0); const char *si_1 = strchr(specification, '/'); FLAC__real overlap = si_1?flac_min((FLAC__real)strtod(si_1+1, 0),0.99f):0.1f; @@ -1761,7 +1765,7 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *en } } } - else if(n>16 && 0 == strncmp("punchout_tukey(" , specification, 15)) { + else if(n>16 && 0 == strncmp("punchout_tukey(", specification, 15)) { FLAC__int32 tukey_parts = (FLAC__int32)strtod(specification+15, 0); const char *si_1 = strchr(specification, '/'); FLAC__real overlap = si_1?flac_min((FLAC__real)strtod(si_1+1, 0),0.99f):0.2f; @@ -1782,6 +1786,20 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *en } } } + else if(n>17 && 0 == strncmp("subdivide_tukey(", specification, 16)){ + FLAC__int32 parts = (FLAC__int32)strtod(specification+16, 0); + if(parts > 1){ + const char *si_1 = strchr(specification, '/'); + FLAC__real p = si_1?(FLAC__real)strtod(si_1+1, 0):5e-1; + if(p > 1) + p = 1; + else if(p < 0) + p = 0; + encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.subdivide_tukey.parts = parts; + encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.subdivide_tukey.p = p/parts; + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_SUBDIVIDE_TUKEY; + } + } else if(n==5 && 0 == strncmp("welch" , specification, n)) encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_WELCH; if (encoder->protected_->num_apodizations == 32) @@ -1840,8 +1858,10 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_do_escape_coding(FLAC__StreamEncode FLAC__ASSERT(0 != encoder->protected_); if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) return false; -#if 0 - /*@@@ deprecated: */ +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + /* was deprecated since FLAC 1.0.4 (24-Sep-2002), but is needed for + * full spec coverage, so this should be reenabled at some point. + * For now only enable while fuzzing */ encoder->protected_->do_escape_coding = value; #else (void)value; @@ -1942,10 +1962,37 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encod return true; } +FLAC_API FLAC__bool FLAC__stream_encoder_set_limit_min_bitrate(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->limit_min_bitrate = value; + return true; +} + /* - * These three functions are not static, but not publicly exposed in - * include/FLAC/ either. They are used by the test suite. + * These four functions are not static, but not publicly exposed in + * include/FLAC/ either. They are used by the test suite and in fuzzing */ +FLAC_API FLAC__bool FLAC__stream_encoder_disable_instruction_set(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->private_->disable_mmx = value & 1; + encoder->private_->disable_sse2 = value & 2; + encoder->private_->disable_ssse3 = value & 4; + encoder->private_->disable_sse41 = value & 8; + encoder->private_->disable_avx2 = value & 16; + encoder->private_->disable_fma = value & 32; + return true; +} + FLAC_API FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value) { FLAC__ASSERT(0 != encoder); @@ -2172,15 +2219,27 @@ FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC return encoder->protected_->total_samples_estimate; } +FLAC_API FLAC__bool FLAC__stream_encoder_get_limit_min_bitrate(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->limit_min_bitrate; +} + FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], uint32_t samples) { - uint32_t i, j = 0, channel; - const uint32_t channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize; + uint32_t i, j = 0, k = 0, channel; + const uint32_t channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize, bps = encoder->protected_->bits_per_sample; + const FLAC__int32 sample_max = INT32_MAX >> (32 - encoder->protected_->bits_per_sample); + const FLAC__int32 sample_min = INT32_MIN >> (32 - encoder->protected_->bits_per_sample); FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK); + + if(encoder->protected_->state != FLAC__STREAM_ENCODER_OK) + return false; do { const uint32_t n = flac_min(blocksize+OVERREAD_-encoder->private_->current_sample_number, samples-j); @@ -2189,6 +2248,12 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, c append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, n); for(channel = 0; channel < channels; channel++) { + for(i = encoder->private_->current_sample_number, k = j; i <= blocksize && k < samples; i++, k++) { + if(buffer[channel][k] < sample_min || buffer[channel][k] > sample_max){ + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return false; + } + } if (buffer[channel] == NULL) { return false; } @@ -2198,10 +2263,16 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, c if(encoder->protected_->do_mid_side_stereo) { FLAC__ASSERT(channels == 2); /* "i <= blocksize" to overread 1 sample; see comment in OVERREAD_ decl */ - for(i = encoder->private_->current_sample_number; i <= blocksize && j < samples; i++, j++) { - encoder->private_->integer_signal_mid_side[1][i] = buffer[0][j] - buffer[1][j]; - encoder->private_->integer_signal_mid_side[0][i] = (buffer[0][j] + buffer[1][j]) >> 1; /* NOTE: not the same as 'mid = (buffer[0][j] + buffer[1][j]) / 2' ! */ - } + if(bps < 32) + for(i = encoder->private_->current_sample_number; i <= blocksize && j < samples; i++, j++) { + encoder->private_->integer_signal_mid_side[1][i] = buffer[0][j] - buffer[1][j]; + encoder->private_->integer_signal_mid_side[0][i] = (buffer[0][j] + buffer[1][j]) >> 1; /* NOTE: not the same as 'mid = (buffer[0][j] + buffer[1][j]) / 2' ! */ + } + else + for(i = encoder->private_->current_sample_number; i <= blocksize && j < samples; i++, j++) { + encoder->private_->integer_signal_33bit_side[i] = (FLAC__int64)buffer[0][j] - (FLAC__int64)buffer[1][j]; + encoder->private_->integer_signal_mid_side[0][i] = ((FLAC__int64)buffer[0][j] + (FLAC__int64)buffer[1][j]) >> 1; /* NOTE: not the same as 'mid = (buffer[0][j] + buffer[1][j]) / 2' ! */ + } } else j += n; @@ -2212,14 +2283,17 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, c if(encoder->private_->current_sample_number > blocksize) { FLAC__ASSERT(encoder->private_->current_sample_number == blocksize+OVERREAD_); FLAC__ASSERT(OVERREAD_ == 1); /* assert we only overread 1 sample which simplifies the rest of the code below */ - if(!process_frame_(encoder, /*is_fractional_block=*/false, /*is_last_block=*/false)) + if(!process_frame_(encoder, /*is_last_block=*/false)) return false; /* move unprocessed overread samples to beginnings of arrays */ for(channel = 0; channel < channels; channel++) encoder->private_->integer_signal[channel][0] = encoder->private_->integer_signal[channel][blocksize]; if(encoder->protected_->do_mid_side_stereo) { encoder->private_->integer_signal_mid_side[0][0] = encoder->private_->integer_signal_mid_side[0][blocksize]; - encoder->private_->integer_signal_mid_side[1][0] = encoder->private_->integer_signal_mid_side[1][blocksize]; + if(bps < 32) + encoder->private_->integer_signal_mid_side[1][0] = encoder->private_->integer_signal_mid_side[1][blocksize]; + else + encoder->private_->integer_signal_33bit_side[0] = encoder->private_->integer_signal_33bit_side[blocksize]; } encoder->private_->current_sample_number = 1; } @@ -2231,13 +2305,16 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, c FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], uint32_t samples) { uint32_t i, j, k, channel; - FLAC__int32 x, mid, side; - const uint32_t channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize; + const uint32_t channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize, bps = encoder->protected_->bits_per_sample; + const FLAC__int32 sample_max = INT32_MAX >> (32 - encoder->protected_->bits_per_sample); + const FLAC__int32 sample_min = INT32_MIN >> (32 - encoder->protected_->bits_per_sample); FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK); + + if(encoder->protected_->state != FLAC__STREAM_ENCODER_OK) + return false; j = k = 0; /* @@ -2254,19 +2331,26 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder /* "i <= blocksize" to overread 1 sample; see comment in OVERREAD_ decl */ for(i = encoder->private_->current_sample_number; i <= blocksize && j < samples; i++, j++) { - encoder->private_->integer_signal[0][i] = mid = side = buffer[k++]; - x = buffer[k++]; - encoder->private_->integer_signal[1][i] = x; - mid += x; - side -= x; - mid >>= 1; /* NOTE: not the same as 'mid = (left + right) / 2' ! */ - encoder->private_->integer_signal_mid_side[1][i] = side; - encoder->private_->integer_signal_mid_side[0][i] = mid; + if(buffer[k] < sample_min || buffer[k] > sample_max || + buffer[k+1] < sample_min || buffer[k+1] > sample_max){ + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return false; + } + encoder->private_->integer_signal[0][i] = buffer[k++]; + encoder->private_->integer_signal[1][i] = buffer[k++]; + if(bps < 32){ + encoder->private_->integer_signal_mid_side[1][i] = encoder->private_->integer_signal[0][i] - encoder->private_->integer_signal[1][i]; + encoder->private_->integer_signal_mid_side[0][i] = (encoder->private_->integer_signal[0][i] + encoder->private_->integer_signal[1][i]) >> 1; + } + else { + encoder->private_->integer_signal_33bit_side[i] = (FLAC__int64)encoder->private_->integer_signal[0][i] - (FLAC__int64)encoder->private_->integer_signal[1][i]; + encoder->private_->integer_signal_mid_side[0][i] = ((FLAC__int64)encoder->private_->integer_signal[0][i] + (FLAC__int64)encoder->private_->integer_signal[1][i]) >> 1; + } } encoder->private_->current_sample_number = i; /* we only process if we have a full block + 1 extra sample; final block is always handled by FLAC__stream_encoder_finish() */ if(i > blocksize) { - if(!process_frame_(encoder, /*is_fractional_block=*/false, /*is_last_block=*/false)) + if(!process_frame_(encoder, /*is_last_block=*/false)) return false; /* move unprocessed overread samples to beginnings of arrays */ FLAC__ASSERT(i == blocksize+OVERREAD_); @@ -2274,7 +2358,10 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder encoder->private_->integer_signal[0][0] = encoder->private_->integer_signal[0][blocksize]; encoder->private_->integer_signal[1][0] = encoder->private_->integer_signal[1][blocksize]; encoder->private_->integer_signal_mid_side[0][0] = encoder->private_->integer_signal_mid_side[0][blocksize]; - encoder->private_->integer_signal_mid_side[1][0] = encoder->private_->integer_signal_mid_side[1][blocksize]; + if(bps < 32) + encoder->private_->integer_signal_mid_side[1][0] = encoder->private_->integer_signal_mid_side[1][blocksize]; + else + encoder->private_->integer_signal_33bit_side[0] = encoder->private_->integer_signal_33bit_side[blocksize]; encoder->private_->current_sample_number = 1; } } while(j < samples); @@ -2289,13 +2376,18 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder /* "i <= blocksize" to overread 1 sample; see comment in OVERREAD_ decl */ for(i = encoder->private_->current_sample_number; i <= blocksize && j < samples; i++, j++) { - for(channel = 0; channel < channels; channel++) + for(channel = 0; channel < channels; channel++){ + if(buffer[k] < sample_min || buffer[k] > sample_max){ + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return false; + } encoder->private_->integer_signal[channel][i] = buffer[k++]; + } } encoder->private_->current_sample_number = i; /* we only process if we have a full block + 1 extra sample; final block is always handled by FLAC__stream_encoder_finish() */ if(i > blocksize) { - if(!process_frame_(encoder, /*is_fractional_block=*/false, /*is_last_block=*/false)) + if(!process_frame_(encoder, /*is_last_block=*/false)) return false; /* move unprocessed overread samples to beginnings of arrays */ FLAC__ASSERT(i == blocksize+OVERREAD_); @@ -2347,10 +2439,16 @@ void set_defaults_(FLAC__StreamEncoder *encoder) encoder->protected_->max_residual_partition_order = 0; encoder->protected_->rice_parameter_search_dist = 0; encoder->protected_->total_samples_estimate = 0; + encoder->protected_->limit_min_bitrate = false; encoder->protected_->metadata = 0; encoder->protected_->num_metadata_blocks = 0; encoder->private_->seek_table = 0; + encoder->private_->disable_mmx = false; + encoder->private_->disable_sse2 = false; + encoder->private_->disable_ssse3 = false; + encoder->private_->disable_sse41 = false; + encoder->private_->disable_avx2 = false; encoder->private_->disable_constant_subframes = false; encoder->private_->disable_fixed_subframes = false; encoder->private_->disable_verbatim_subframes = false; @@ -2404,6 +2502,10 @@ void free_(FLAC__StreamEncoder *encoder) } #endif } + if(0 != encoder->private_->integer_signal_33bit_side_unaligned){ + free(encoder->private_->integer_signal_33bit_side_unaligned); + encoder->private_->integer_signal_33bit_side_unaligned = 0; + } #ifndef FLAC__INTEGER_ONLY_LIBRARY for(i = 0; i < encoder->protected_->num_apodizations; i++) { if(0 != encoder->private_->window_unaligned[i]) { @@ -2474,26 +2576,19 @@ FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, uint32_t new_blocksize) for(i = 0; ok && i < encoder->protected_->channels; i++) { ok = ok && FLAC__memory_alloc_aligned_int32_array(new_blocksize+4+OVERREAD_, &encoder->private_->integer_signal_unaligned[i], &encoder->private_->integer_signal[i]); - memset(encoder->private_->integer_signal[i], 0, sizeof(FLAC__int32)*4); - encoder->private_->integer_signal[i] += 4; -#ifndef FLAC__INTEGER_ONLY_LIBRARY -#if 0 /* @@@ currently unused */ - if(encoder->protected_->max_lpc_order > 0) - ok = ok && FLAC__memory_alloc_aligned_real_array(new_blocksize+OVERREAD_, &encoder->private_->real_signal_unaligned[i], &encoder->private_->real_signal[i]); -#endif -#endif + if(ok) { + memset(encoder->private_->integer_signal[i], 0, sizeof(FLAC__int32)*4); + encoder->private_->integer_signal[i] += 4; + } } for(i = 0; ok && i < 2; i++) { ok = ok && FLAC__memory_alloc_aligned_int32_array(new_blocksize+4+OVERREAD_, &encoder->private_->integer_signal_mid_side_unaligned[i], &encoder->private_->integer_signal_mid_side[i]); - memset(encoder->private_->integer_signal_mid_side[i], 0, sizeof(FLAC__int32)*4); - encoder->private_->integer_signal_mid_side[i] += 4; -#ifndef FLAC__INTEGER_ONLY_LIBRARY -#if 0 /* @@@ currently unused */ - if(encoder->protected_->max_lpc_order > 0) - ok = ok && FLAC__memory_alloc_aligned_real_array(new_blocksize+OVERREAD_, &encoder->private_->real_signal_mid_side_unaligned[i], &encoder->private_->real_signal_mid_side[i]); -#endif -#endif + if(ok) { + memset(encoder->private_->integer_signal_mid_side[i], 0, sizeof(FLAC__int32)*4); + encoder->private_->integer_signal_mid_side[i] += 4; + } } + ok = ok && FLAC__memory_alloc_aligned_int64_array(new_blocksize+4+OVERREAD_, &encoder->private_->integer_signal_33bit_side_unaligned, &encoder->private_->integer_signal_33bit_side); #ifndef FLAC__INTEGER_ONLY_LIBRARY if(ok && encoder->protected_->max_lpc_order > 0) { for(i = 0; ok && i < encoder->protected_->num_apodizations; i++) @@ -2506,11 +2601,32 @@ FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, uint32_t new_blocksize) ok = ok && FLAC__memory_alloc_aligned_int32_array(new_blocksize, &encoder->private_->residual_workspace_unaligned[channel][i], &encoder->private_->residual_workspace[channel][i]); } } + + + for(channel = 0; ok && channel < encoder->protected_->channels; channel++) { + for(i = 0; ok && i < 2; i++) { + ok = ok && FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(&encoder->private_->partitioned_rice_contents_workspace[channel][i], encoder->protected_->max_residual_partition_order); + ok = ok && FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(&encoder->private_->partitioned_rice_contents_workspace[channel][i], encoder->protected_->max_residual_partition_order); + } + } + for(channel = 0; ok && channel < 2; channel++) { for(i = 0; ok && i < 2; i++) { ok = ok && FLAC__memory_alloc_aligned_int32_array(new_blocksize, &encoder->private_->residual_workspace_mid_side_unaligned[channel][i], &encoder->private_->residual_workspace_mid_side[channel][i]); } } + + for(channel = 0; ok && channel < 2; channel++) { + for(i = 0; ok && i < 2; i++) { + ok = ok && FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(&encoder->private_->partitioned_rice_contents_workspace_mid_side[channel][i], encoder->protected_->max_residual_partition_order); + } + } + + for(i = 0; ok && i < 2; i++) { + ok = ok && FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(&encoder->private_->partitioned_rice_contents_extra[i], encoder->protected_->max_residual_partition_order); + } + + /* the *2 is an approximation to the series 1 + 1/2 + 1/4 + ... that sums tree occupies in a flat array */ /*@@@ new_blocksize*2 is too pessimistic, but to fix, we need smarter logic because a smaller new_blocksize can actually increase the # of partitions; would require moving this out into a separate function, then checking its capacity against the need of the current blocksize&min/max_partition_order (and maybe predictor order) */ ok = ok && FLAC__memory_alloc_aligned_uint64_array(new_blocksize * 2, &encoder->private_->abs_residual_partition_sums_unaligned, &encoder->private_->abs_residual_partition_sums); @@ -2570,6 +2686,9 @@ FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, uint32_t new_blocksize) case FLAC__APODIZATION_PUNCHOUT_TUKEY: FLAC__window_punchout_tukey(encoder->private_->window[i], new_blocksize, encoder->protected_->apodizations[i].parameters.multiple_tukey.p, encoder->protected_->apodizations[i].parameters.multiple_tukey.start, encoder->protected_->apodizations[i].parameters.multiple_tukey.end); break; + case FLAC__APODIZATION_SUBDIVIDE_TUKEY: + FLAC__window_tukey(encoder->private_->window[i], new_blocksize, encoder->protected_->apodizations[i].parameters.tukey.p); + break; case FLAC__APODIZATION_WELCH: FLAC__window_welch(encoder->private_->window[i], new_blocksize); break; @@ -2612,7 +2731,8 @@ FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, uint32_t samples, FLAC else { if(!FLAC__stream_decoder_process_single(encoder->private_->verify.decoder) || (!is_last_block - && (FLAC__stream_encoder_get_verify_decoder_state(encoder) == FLAC__STREAM_DECODER_END_OF_STREAM))) { + && (FLAC__stream_encoder_get_verify_decoder_state(encoder) == FLAC__STREAM_DECODER_END_OF_STREAM)) + || encoder->protected_->state == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR /* Happens when error callback was used */) { FLAC__bitwriter_release_buffer(encoder->private_->frame); FLAC__bitwriter_clear(encoder->private_->frame); if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) @@ -2738,7 +2858,7 @@ void update_metadata_(const FLAC__StreamEncoder *encoder) { FLAC__byte b[flac_max(6u, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)]; const FLAC__StreamMetadata *metadata = &encoder->private_->streaminfo; - const FLAC__uint64 samples = metadata->data.stream_info.total_samples; + FLAC__uint64 samples = metadata->data.stream_info.total_samples; const uint32_t min_framesize = metadata->data.stream_info.min_framesize; const uint32_t max_framesize = metadata->data.stream_info.max_framesize; const uint32_t bps = metadata->data.stream_info.bits_per_sample; @@ -2795,6 +2915,8 @@ void update_metadata_(const FLAC__StreamEncoder *encoder) FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN - 4 ) / 8; + if(samples > (FLAC__U64L(1) << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN)) + samples = 0; b[0] = ((FLAC__byte)(bps-1) << 4) | (FLAC__byte)((samples >> 32) & 0x0F); b[1] = (FLAC__byte)((samples >> 24) & 0xFF); @@ -3079,7 +3201,7 @@ void update_ogg_metadata_(FLAC__StreamEncoder *encoder) } #endif -FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block, FLAC__bool is_last_block) +FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_block) { FLAC__uint16 crc; FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK); @@ -3095,7 +3217,7 @@ FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional /* * Process the frame header and subframes into the frame bitbuffer */ - if(!process_subframes_(encoder, is_fractional_block)) { + if(!process_subframes_(encoder)) { /* the above function sets the state for us in case of an error */ return false; } @@ -3138,22 +3260,18 @@ FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional return true; } -FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block) +FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder) { FLAC__FrameHeader frame_header; uint32_t channel, min_partition_order = encoder->protected_->min_residual_partition_order, max_partition_order; - FLAC__bool do_independent, do_mid_side; + FLAC__bool do_independent, do_mid_side, backup_disable_constant_subframes = encoder->private_->disable_constant_subframes, all_subframes_constant = true; /* * Calculate the min,max Rice partition orders */ - if(is_fractional_block) { - max_partition_order = 0; - } - else { - max_partition_order = FLAC__format_get_max_rice_partition_order_from_blocksize(encoder->protected_->blocksize); - max_partition_order = flac_min(max_partition_order, encoder->protected_->max_residual_partition_order); - } + + max_partition_order = FLAC__format_get_max_rice_partition_order_from_blocksize(encoder->protected_->blocksize); + max_partition_order = flac_min(max_partition_order, encoder->protected_->max_residual_partition_order); min_partition_order = flac_min(min_partition_order, max_partition_order); /* @@ -3209,7 +3327,12 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti if(do_mid_side) { FLAC__ASSERT(encoder->protected_->channels == 2); for(channel = 0; channel < 2; channel++) { - uint32_t w = get_wasted_bits_(encoder->private_->integer_signal_mid_side[channel], encoder->protected_->blocksize); + uint32_t w; + if(encoder->protected_->bits_per_sample < 32 || channel == 0) + w = get_wasted_bits_(encoder->private_->integer_signal_mid_side[channel], encoder->protected_->blocksize); + else + w = get_wasted_bits_wide_(encoder->private_->integer_signal_33bit_side, encoder->private_->integer_signal_mid_side[channel], encoder->protected_->blocksize); + if (w > encoder->protected_->bits_per_sample) { w = encoder->protected_->bits_per_sample; } @@ -3223,6 +3346,12 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti */ if(do_independent) { for(channel = 0; channel < encoder->protected_->channels; channel++) { + if(encoder->protected_->limit_min_bitrate && all_subframes_constant && (channel + 1) == encoder->protected_->channels){ + /* This frame contains only constant subframes at this point. + * To prevent the frame from becoming too small, make sure + * the last subframe isn't constant */ + encoder->private_->disable_constant_subframes = true; + } if(! process_subframe_( encoder, @@ -3239,6 +3368,8 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti ) ) return false; + if(encoder->private_->subframe_workspace[channel][encoder->private_->best_subframe[channel]].type != FLAC__SUBFRAME_TYPE_CONSTANT) + all_subframes_constant = false; } } @@ -3249,6 +3380,11 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti FLAC__ASSERT(encoder->protected_->channels == 2); for(channel = 0; channel < 2; channel++) { + void *integer_signal_; + if(encoder->private_->subframe_bps_mid_side[channel] <= 32) + integer_signal_ = encoder->private_->integer_signal_mid_side[channel]; + else + integer_signal_ = encoder->private_->integer_signal_33bit_side; if(! process_subframe_( encoder, @@ -3256,7 +3392,7 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti max_partition_order, &frame_header, encoder->private_->subframe_bps_mid_side[channel], - encoder->private_->integer_signal_mid_side[channel], + integer_signal_, encoder->private_->subframe_workspace_ptr_mid_side[channel], encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[channel], encoder->private_->residual_workspace_mid_side[channel], @@ -3300,7 +3436,11 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; min_bits = bits[channel_assignment]; - for(ca = 1; ca <= 3; ca++) { + + /* When doing loose mid-side stereo, ignore left-side + * and right-side options */ + ca = encoder->protected_->loose_mid_side_stereo ? 3 : 1; + for( ; ca <= 3; ca++) { if(bits[ca] < min_bits) { min_bits = bits[ca]; channel_assignment = (FLAC__ChannelAssignment)ca; @@ -3384,17 +3524,43 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti } encoder->private_->last_channel_assignment = frame_header.channel_assignment; + encoder->private_->disable_constant_subframes = backup_disable_constant_subframes; return true; } +static inline void set_next_subdivide_tukey(FLAC__int32 parts, uint32_t * apodizations, uint32_t * current_depth, uint32_t * current_part){ + // current_part is interleaved: even are partial, odd are punchout + if(*current_depth == 2){ + // For depth 2, we only do partial, no punchout as that is almost redundant + if(*current_part == 0){ + *current_part = 2; + }else{ /* *current_path == 2 */ + *current_part = 0; + (*current_depth)++; + } + }else if((*current_part) < (2*(*current_depth)-1)){ + (*current_part)++; + }else{ /* (*current_part) >= (2*(*current_depth)-1) */ + *current_part = 0; + (*current_depth)++; + } + + /* Now check if we are done with this SUBDIVIDE_TUKEY apodization */ + if(*current_depth > (uint32_t) parts){ + (*apodizations)++; + *current_depth = 1; + *current_part = 0; + } +} + FLAC__bool process_subframe_( FLAC__StreamEncoder *encoder, uint32_t min_partition_order, uint32_t max_partition_order, const FLAC__FrameHeader *frame_header, uint32_t subframe_bps, - const FLAC__int32 integer_signal[], + const void *integer_signal, FLAC__Subframe *subframe[2], FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2], FLAC__int32 *residual[2], @@ -3409,13 +3575,13 @@ FLAC__bool process_subframe_( #endif #ifndef FLAC__INTEGER_ONLY_LIBRARY double lpc_residual_bits_per_sample; - FLAC__real autoc[FLAC__MAX_LPC_ORDER+1]; /* WATCHOUT: the size is important even though encoder->protected_->max_lpc_order might be less; some asm and x86 intrinsic routines need all the space */ + double autoc[FLAC__MAX_LPC_ORDER+1]; /* WATCHOUT: the size is important even though encoder->protected_->max_lpc_order might be less; some asm and x86 intrinsic routines need all the space */ + double autoc_root[FLAC__MAX_LPC_ORDER+1]; /* This is for subdivide_tukey apodization */ double lpc_error[FLAC__MAX_LPC_ORDER]; uint32_t min_lpc_order, max_lpc_order, lpc_order; uint32_t min_qlp_coeff_precision, max_qlp_coeff_precision, qlp_coeff_precision; #endif uint32_t min_fixed_order, max_fixed_order, guess_fixed_order, fixed_order; - uint32_t rice_parameter; uint32_t _candidate_bits, _best_bits; uint32_t _best_subframe; /* only use RICE2 partitions if stream bps > 16 */ @@ -3426,16 +3592,33 @@ FLAC__bool process_subframe_( /* verbatim subframe is the baseline against which we measure other compressed subframes */ _best_subframe = 0; if(encoder->private_->disable_verbatim_subframes && frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) - _best_bits = UINT_MAX; + _best_bits = UINT32_MAX; else _best_bits = evaluate_verbatim_subframe_(encoder, integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]); + *best_bits = _best_bits; - if(frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) { + if(frame_header->blocksize > FLAC__MAX_FIXED_ORDER) { uint32_t signal_is_constant = false; - if(subframe_bps + 4 + FLAC__bitmath_ilog2((frame_header->blocksize-FLAC__MAX_FIXED_ORDER)|1) <= 32) - guess_fixed_order = encoder->private_->local_fixed_compute_best_predictor(integer_signal+FLAC__MAX_FIXED_ORDER, frame_header->blocksize-FLAC__MAX_FIXED_ORDER, fixed_residual_bits_per_sample); + /* The next formula determines when to use a 64-bit accumulator + * for the error of a fixed predictor, and when a 32-bit one. As + * the error of a 4th order predictor for a given sample is the + * sum of 17 sample values (1+4+6+4+1) and there are blocksize - + * order error values to be summed, the maximum total error is + * maximum_sample_value * (blocksize - order) * 17. As ilog2(x) + * calculates floor(2log(x)), the result must be 31 or lower + */ + if(subframe_bps < 28){ + if(subframe_bps + FLAC__bitmath_ilog2((frame_header->blocksize-FLAC__MAX_FIXED_ORDER)*17) < 32) + guess_fixed_order = encoder->private_->local_fixed_compute_best_predictor(((FLAC__int32 *)integer_signal)+FLAC__MAX_FIXED_ORDER, frame_header->blocksize-FLAC__MAX_FIXED_ORDER, fixed_residual_bits_per_sample); + else + guess_fixed_order = encoder->private_->local_fixed_compute_best_predictor_wide(((FLAC__int32 *)integer_signal)+FLAC__MAX_FIXED_ORDER, frame_header->blocksize-FLAC__MAX_FIXED_ORDER, fixed_residual_bits_per_sample); + } else - guess_fixed_order = encoder->private_->local_fixed_compute_best_predictor_wide(integer_signal+FLAC__MAX_FIXED_ORDER, frame_header->blocksize-FLAC__MAX_FIXED_ORDER, fixed_residual_bits_per_sample); + if(subframe_bps <= 32) + guess_fixed_order = FLAC__fixed_compute_best_predictor_limit_residual(((FLAC__int32 *)integer_signal),frame_header->blocksize, fixed_residual_bits_per_sample); + else + guess_fixed_order = FLAC__fixed_compute_best_predictor_limit_residual_33bit(((FLAC__int64 *)integer_signal),frame_header->blocksize, fixed_residual_bits_per_sample); + /* check for constant subframe */ if( !encoder->private_->disable_constant_subframes && @@ -3448,15 +3631,31 @@ FLAC__bool process_subframe_( /* the above means it's possible all samples are the same value; now double-check it: */ uint32_t i; signal_is_constant = true; - for(i = 1; i < frame_header->blocksize; i++) { - if(integer_signal[0] != integer_signal[i]) { - signal_is_constant = false; - break; + if(subframe_bps <= 32){ + const FLAC__int32 *integer_signal_ = integer_signal; + for(i = 1; i < frame_header->blocksize; i++) { + if(integer_signal_[0] != integer_signal_[i]) { + signal_is_constant = false; + break; + } + } + } + else { + const FLAC__int64 *integer_signal_ = integer_signal; + for(i = 1; i < frame_header->blocksize; i++) { + if(integer_signal_[0] != integer_signal_[i]) { + signal_is_constant = false; + break; + } } } } if(signal_is_constant) { - _candidate_bits = evaluate_constant_subframe_(encoder, integer_signal[0], frame_header->blocksize, subframe_bps, subframe[!_best_subframe]); + if(subframe_bps <= 32) + _candidate_bits = evaluate_constant_subframe_(encoder, ((FLAC__int32 *)integer_signal)[0], frame_header->blocksize, subframe_bps, subframe[!_best_subframe]); + else + _candidate_bits = evaluate_constant_subframe_(encoder, ((FLAC__int64 *)integer_signal)[0], frame_header->blocksize, subframe_bps, subframe[!_best_subframe]); + if(_candidate_bits < _best_bits) { _best_subframe = !_best_subframe; _best_bits = _candidate_bits; @@ -3478,19 +3677,10 @@ FLAC__bool process_subframe_( #ifndef FLAC__INTEGER_ONLY_LIBRARY if(fixed_residual_bits_per_sample[fixed_order] >= (float)subframe_bps) continue; /* don't even try */ - rice_parameter = (fixed_residual_bits_per_sample[fixed_order] > 0.0)? (uint32_t)(fixed_residual_bits_per_sample[fixed_order]+0.5) : 0; /* 0.5 is for rounding */ #else if(FLAC__fixedpoint_trunc(fixed_residual_bits_per_sample[fixed_order]) >= (int)subframe_bps) continue; /* don't even try */ - rice_parameter = (fixed_residual_bits_per_sample[fixed_order] > FLAC__FP_ZERO)? (uint32_t)FLAC__fixedpoint_trunc(fixed_residual_bits_per_sample[fixed_order]+FLAC__FP_ONE_HALF) : 0; /* 0.5 is for rounding */ -#endif - rice_parameter++; /* to account for the signed->uint32_t conversion during rice coding */ - if(rice_parameter >= rice_parameter_limit) { -#ifndef NDEBUG - fprintf(stderr, "clipping rice_parameter (%u -> %u) @0\n", rice_parameter, rice_parameter_limit - 1); #endif - rice_parameter = rice_parameter_limit - 1; - } _candidate_bits = evaluate_fixed_subframe_( encoder, @@ -3501,7 +3691,6 @@ FLAC__bool process_subframe_( frame_header->blocksize, subframe_bps, fixed_order, - rice_parameter, rice_parameter_limit, min_partition_order, max_partition_order, @@ -3525,13 +3714,55 @@ FLAC__bool process_subframe_( else max_lpc_order = encoder->protected_->max_lpc_order; if(max_lpc_order > 0) { - uint32_t a; - for (a = 0; a < encoder->protected_->num_apodizations; a++) { - FLAC__lpc_window_data(integer_signal, encoder->private_->window[a], encoder->private_->windowed_signal, frame_header->blocksize); - encoder->private_->local_lpc_compute_autocorrelation(encoder->private_->windowed_signal, frame_header->blocksize, max_lpc_order+1, autoc); + uint32_t a, b = 1, c = 0; + for (a = 0; a < encoder->protected_->num_apodizations;) { + uint32_t max_lpc_order_this_apodization = max_lpc_order; + if(b == 1){ + /* window full subblock */ + if(subframe_bps <= 32) + FLAC__lpc_window_data(integer_signal, encoder->private_->window[a], encoder->private_->windowed_signal, frame_header->blocksize); + else + FLAC__lpc_window_data_wide(integer_signal, encoder->private_->window[a], encoder->private_->windowed_signal, frame_header->blocksize); + encoder->private_->local_lpc_compute_autocorrelation(encoder->private_->windowed_signal, frame_header->blocksize, max_lpc_order_this_apodization+1, autoc); + if(encoder->protected_->apodizations[a].type == FLAC__APODIZATION_SUBDIVIDE_TUKEY){ + for(uint32_t i = 0; i < max_lpc_order_this_apodization; i++) + autoc_root[i] = autoc[i]; + b++; + }else{ + a++; + } + } + else { + /* window part of subblock */ + if(max_lpc_order_this_apodization >= frame_header->blocksize/b) { + max_lpc_order_this_apodization = frame_header->blocksize/b - 1; + if(frame_header->blocksize/b > 0) + max_lpc_order_this_apodization = frame_header->blocksize/b - 1; + else { + set_next_subdivide_tukey(encoder->protected_->apodizations[a].parameters.subdivide_tukey.parts, &a, &b, &c); + continue; + } + } + if(!(c % 2)){ + /* on even c, evaluate the (c/2)th partial window of size blocksize/b */ + if(subframe_bps <= 32) + FLAC__lpc_window_data_partial(integer_signal, encoder->private_->window[a], encoder->private_->windowed_signal, frame_header->blocksize, frame_header->blocksize/b/2, (c/2*frame_header->blocksize)/b); + else + FLAC__lpc_window_data_partial(integer_signal, encoder->private_->window[a], encoder->private_->windowed_signal, frame_header->blocksize, frame_header->blocksize/b/2, (c/2*frame_header->blocksize)/b); + encoder->private_->local_lpc_compute_autocorrelation(encoder->private_->windowed_signal, frame_header->blocksize/b, max_lpc_order_this_apodization+1, autoc); + }else{ + /* on uneven c, evaluate the root window (over the whole block) minus the previous partial window + * similar to tukey_punchout apodization but more efficient */ + for(uint32_t i = 0; i < max_lpc_order_this_apodization; i++) + autoc[i] = autoc_root[i] - autoc[i]; + } + /* Next function sets a, b and c appropriate for next iteration */ + set_next_subdivide_tukey(encoder->protected_->apodizations[a].parameters.subdivide_tukey.parts, &a, &b, &c); + } + /* if autoc[0] == 0.0, the signal is constant and we usually won't get here, but it can happen */ if(autoc[0] != 0.0) { - FLAC__lpc_compute_lp_coefficients(autoc, &max_lpc_order, encoder->private_->lp_coeff, lpc_error); + FLAC__lpc_compute_lp_coefficients(autoc, &max_lpc_order_this_apodization, encoder->private_->lp_coeff, lpc_error); if(encoder->protected_->do_exhaustive_model_search) { min_lpc_order = 1; } @@ -3539,7 +3770,7 @@ FLAC__bool process_subframe_( const uint32_t guess_lpc_order = FLAC__lpc_compute_best_order( lpc_error, - max_lpc_order, + max_lpc_order_this_apodization, frame_header->blocksize, subframe_bps + ( encoder->protected_->do_qlp_coeff_prec_search? @@ -3547,22 +3778,14 @@ FLAC__bool process_subframe_( encoder->protected_->qlp_coeff_precision ) ); - min_lpc_order = max_lpc_order = guess_lpc_order; + min_lpc_order = max_lpc_order_this_apodization = guess_lpc_order; } - if(max_lpc_order >= frame_header->blocksize) - max_lpc_order = frame_header->blocksize - 1; - for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order; lpc_order++) { + if(max_lpc_order_this_apodization >= frame_header->blocksize) + max_lpc_order_this_apodization = frame_header->blocksize - 1; + for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order_this_apodization; lpc_order++) { lpc_residual_bits_per_sample = FLAC__lpc_compute_expected_bits_per_residual_sample(lpc_error[lpc_order-1], frame_header->blocksize-lpc_order); if(lpc_residual_bits_per_sample >= (double)subframe_bps) continue; /* don't even try */ - rice_parameter = (lpc_residual_bits_per_sample > 0.0)? (uint32_t)(lpc_residual_bits_per_sample+0.5) : 0; /* 0.5 is for rounding */ - rice_parameter++; /* to account for the signed->uint32_t conversion during rice coding */ - if(rice_parameter >= rice_parameter_limit) { -#ifndef NDEBUG - fprintf(stderr, "clipping rice_parameter (%u -> %u) @1\n", rice_parameter, rice_parameter_limit - 1); -#endif - rice_parameter = rice_parameter_limit - 1; - } if(encoder->protected_->do_qlp_coeff_prec_search) { min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION; /* try to keep qlp coeff precision such that only 32-bit math is required for decode of <=16bps(+1bps for side channel) streams */ @@ -3589,7 +3812,6 @@ FLAC__bool process_subframe_( subframe_bps, lpc_order, qlp_coeff_precision, - rice_parameter, rice_parameter_limit, min_partition_order, max_partition_order, @@ -3615,7 +3837,7 @@ FLAC__bool process_subframe_( } /* under rare circumstances this can happen when all but lpc subframe types are disabled: */ - if(_best_bits == UINT_MAX) { + if(_best_bits == UINT32_MAX) { FLAC__ASSERT(_best_subframe == 0); _best_bits = evaluate_verbatim_subframe_(encoder, integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]); } @@ -3699,7 +3921,7 @@ static void spotcheck_subframe_estimate_( uint32_t evaluate_constant_subframe_( FLAC__StreamEncoder *encoder, - const FLAC__int32 signal, + const FLAC__int64 signal, uint32_t blocksize, uint32_t subframe_bps, FLAC__Subframe *subframe @@ -3722,14 +3944,13 @@ uint32_t evaluate_constant_subframe_( uint32_t evaluate_fixed_subframe_( FLAC__StreamEncoder *encoder, - const FLAC__int32 signal[], + const void *signal, FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t raw_bits_per_partition[], uint32_t blocksize, uint32_t subframe_bps, uint32_t order, - uint32_t rice_parameter, uint32_t rice_parameter_limit, uint32_t min_partition_order, uint32_t max_partition_order, @@ -3742,7 +3963,12 @@ uint32_t evaluate_fixed_subframe_( uint32_t i, residual_bits, estimate; const uint32_t residual_samples = blocksize - order; - FLAC__fixed_compute_residual(signal+order, residual_samples, order, residual); + if((subframe_bps + order) <= 32) + FLAC__fixed_compute_residual(((FLAC__int32 *)signal)+order, residual_samples, order, residual); + else if(subframe_bps <= 32) + FLAC__fixed_compute_residual_wide(((FLAC__int32 *)signal)+order, residual_samples, order, residual); + else + FLAC__fixed_compute_residual_wide_33bit(((FLAC__int64 *)signal)+order, residual_samples, order, residual); subframe->type = FLAC__SUBFRAME_TYPE_FIXED; @@ -3758,7 +3984,6 @@ uint32_t evaluate_fixed_subframe_( raw_bits_per_partition, residual_samples, order, - rice_parameter, rice_parameter_limit, min_partition_order, max_partition_order, @@ -3769,10 +3994,18 @@ uint32_t evaluate_fixed_subframe_( ); subframe->data.fixed.order = order; - for(i = 0; i < order; i++) - subframe->data.fixed.warmup[i] = signal[i]; + if(subframe_bps <= 32) + for(i = 0; i < order; i++) + subframe->data.fixed.warmup[i] = ((FLAC__int32 *)signal)[i]; + else + for(i = 0; i < order; i++) + subframe->data.fixed.warmup[i] = ((FLAC__int64 *)signal)[i]; - estimate = FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe->wasted_bits + (order * subframe_bps) + residual_bits; + estimate = FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe->wasted_bits + (order * subframe_bps); + if(residual_bits < UINT32_MAX - estimate) // To make sure estimate doesn't overflow + estimate += residual_bits; + else + estimate = UINT32_MAX; #if SPOTCHECK_ESTIMATE spotcheck_subframe_estimate_(encoder, blocksize, subframe_bps, subframe, estimate); @@ -3784,7 +4017,7 @@ uint32_t evaluate_fixed_subframe_( #ifndef FLAC__INTEGER_ONLY_LIBRARY uint32_t evaluate_lpc_subframe_( FLAC__StreamEncoder *encoder, - const FLAC__int32 signal[], + const void *signal, FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t raw_bits_per_partition[], @@ -3793,7 +4026,6 @@ uint32_t evaluate_lpc_subframe_( uint32_t subframe_bps, uint32_t order, uint32_t qlp_coeff_precision, - uint32_t rice_parameter, uint32_t rice_parameter_limit, uint32_t min_partition_order, uint32_t max_partition_order, @@ -3819,13 +4051,23 @@ uint32_t evaluate_lpc_subframe_( if(ret != 0) return 0; /* this is a hack to indicate to the caller that we can't do lp at this order on this subframe */ - if(subframe_bps + qlp_coeff_precision + FLAC__bitmath_ilog2(order) <= 32) - if(subframe_bps <= 16 && qlp_coeff_precision <= 16) - encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit(signal+order, residual_samples, qlp_coeff, order, quantization, residual); + if(FLAC__lpc_max_residual_bps(subframe_bps, qlp_coeff, order, quantization) > 32) { + if(subframe_bps <= 32){ + if(!FLAC__lpc_compute_residual_from_qlp_coefficients_limit_residual(((FLAC__int32 *)signal)+order, residual_samples, qlp_coeff, order, quantization, residual)) + return 0; + } else - encoder->private_->local_lpc_compute_residual_from_qlp_coefficients(signal+order, residual_samples, qlp_coeff, order, quantization, residual); + if(!FLAC__lpc_compute_residual_from_qlp_coefficients_limit_residual_33bit(((FLAC__int64 *)signal)+order, residual_samples, qlp_coeff, order, quantization, residual)) + return 0; + } else - encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit(signal+order, residual_samples, qlp_coeff, order, quantization, residual); + if(FLAC__lpc_max_prediction_before_shift_bps(subframe_bps, qlp_coeff, order) <= 32) + if(subframe_bps <= 16 && qlp_coeff_precision <= 16) + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit(((FLAC__int32 *)signal)+order, residual_samples, qlp_coeff, order, quantization, residual); + else + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients(((FLAC__int32 *)signal)+order, residual_samples, qlp_coeff, order, quantization, residual); + else + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit(((FLAC__int32 *)signal)+order, residual_samples, qlp_coeff, order, quantization, residual); subframe->type = FLAC__SUBFRAME_TYPE_LPC; @@ -3841,7 +4083,6 @@ uint32_t evaluate_lpc_subframe_( raw_bits_per_partition, residual_samples, order, - rice_parameter, rice_parameter_limit, min_partition_order, max_partition_order, @@ -3855,10 +4096,19 @@ uint32_t evaluate_lpc_subframe_( subframe->data.lpc.qlp_coeff_precision = qlp_coeff_precision; subframe->data.lpc.quantization_level = quantization; memcpy(subframe->data.lpc.qlp_coeff, qlp_coeff, sizeof(FLAC__int32)*FLAC__MAX_LPC_ORDER); - for(i = 0; i < order; i++) - subframe->data.lpc.warmup[i] = signal[i]; + if(subframe_bps <= 32) + for(i = 0; i < order; i++) + subframe->data.lpc.warmup[i] = ((FLAC__int32 *)signal)[i]; + else + for(i = 0; i < order; i++) + subframe->data.lpc.warmup[i] = ((FLAC__int64 *)signal)[i]; + - estimate = FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe->wasted_bits + FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN + FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN + (order * (qlp_coeff_precision + subframe_bps)) + residual_bits; + estimate = FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe->wasted_bits + FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN + FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN + (order * (qlp_coeff_precision + subframe_bps)); + if(residual_bits < UINT32_MAX - estimate) // To make sure estimate doesn't overflow + estimate += residual_bits; + else + estimate = UINT32_MAX; #if SPOTCHECK_ESTIMATE spotcheck_subframe_estimate_(encoder, blocksize, subframe_bps, subframe, estimate); @@ -3870,7 +4120,7 @@ uint32_t evaluate_lpc_subframe_( uint32_t evaluate_verbatim_subframe_( FLAC__StreamEncoder *encoder, - const FLAC__int32 signal[], + const void *signal, uint32_t blocksize, uint32_t subframe_bps, FLAC__Subframe *subframe @@ -3880,7 +4130,14 @@ uint32_t evaluate_verbatim_subframe_( subframe->type = FLAC__SUBFRAME_TYPE_VERBATIM; - subframe->data.verbatim.data = signal; + if(subframe_bps <= 32){ + subframe->data.verbatim.data_type = FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT32; + subframe->data.verbatim.data.int32 = signal; + } + else { + subframe->data.verbatim.data_type = FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT64; + subframe->data.verbatim.data.int64 = signal; + } estimate = FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe->wasted_bits + (blocksize * subframe_bps); @@ -3900,7 +4157,6 @@ uint32_t find_best_partition_order_( uint32_t raw_bits_per_partition[], uint32_t residual_samples, uint32_t predictor_order, - uint32_t rice_parameter, uint32_t rice_parameter_limit, uint32_t min_partition_order, uint32_t max_partition_order, @@ -3937,7 +4193,6 @@ uint32_t find_best_partition_order_( raw_bits_per_partition+sum, residual_samples, predictor_order, - rice_parameter, rice_parameter_limit, rice_parameter_search_dist, (uint32_t)partition_order, @@ -3970,10 +4225,9 @@ uint32_t find_best_partition_order_( uint32_t partition; /* save best parameters and raw_bits */ - FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(prc, flac_max(6u, best_partition_order)); - memcpy(prc->parameters, private_->partitioned_rice_contents_extra[best_parameters_index].parameters, sizeof(uint32_t)*(1<<(best_partition_order))); + memcpy(prc->parameters, private_->partitioned_rice_contents_extra[best_parameters_index].parameters, (uint32_t)sizeof(uint32_t)*(1<<(best_partition_order))); if(do_escape_coding) - memcpy(prc->raw_bits, private_->partitioned_rice_contents_extra[best_parameters_index].raw_bits, sizeof(uint32_t)*(1<<(best_partition_order))); + memcpy(prc->raw_bits, private_->partitioned_rice_contents_extra[best_parameters_index].raw_bits, (uint32_t)sizeof(uint32_t)*(1<<(best_partition_order))); /* * Now need to check if the type should be changed to * FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2 based on the @@ -4119,7 +4373,7 @@ static inline uint32_t count_rice_bits_in_partition_( ; for(i = 0; i < partition_samples; i++) partition_bits += ( (FLAC__uint32)((residual[i]<<1)^(residual[i]>>31)) >> rice_parameter ); - return (uint32_t)(flac_min(partition_bits,(uint32_t)(-1))); // To make sure the return value doesn't overflow + return (uint32_t)(flac_min(partition_bits,UINT32_MAX)); // To make sure the return value doesn't overflow } #else static inline uint32_t count_rice_bits_in_partition_( @@ -4136,7 +4390,7 @@ static inline uint32_t count_rice_bits_in_partition_( (abs_residual_partition_sum >> (rice_parameter-1)) /* rice_parameter-1 because the real coder sign-folds instead of using a sign bit */ : (abs_residual_partition_sum << 1) /* can't shift by negative number, so reverse */ ) - - (partition_samples >> 1),(uint32_t)(-1))); + - (partition_samples >> 1),UINT32_MAX)); /* -(partition_samples>>1) to subtract out extra contributions to the abs_residual_partition_sum. * The actual number of bits used is closer to the sum(for all i in the partition) of abs(residual[i])>>(rice_parameter-1) * By using the abs_residual_partition sum, we also add in bits in the LSBs that would normally be shifted out. @@ -4155,7 +4409,6 @@ FLAC__bool set_partitioned_rice_( const uint32_t raw_bits_per_partition[], const uint32_t residual_samples, const uint32_t predictor_order, - const uint32_t suggested_rice_parameter, const uint32_t rice_parameter_limit, const uint32_t rice_parameter_search_dist, const uint32_t partition_order, @@ -4168,46 +4421,98 @@ FLAC__bool set_partitioned_rice_( uint32_t best_partition_bits, best_rice_parameter = 0; uint32_t bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN; uint32_t *parameters, *raw_bits; + uint32_t partition, residual_sample; + uint32_t partition_samples; + const uint32_t partitions = 1u << partition_order; + FLAC__uint64 mean, k; #ifdef ENABLE_RICE_PARAMETER_SEARCH uint32_t min_rice_parameter, max_rice_parameter; #else (void)rice_parameter_search_dist; #endif - FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER); FLAC__ASSERT(rice_parameter_limit <= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER); - FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, flac_max(6u, partition_order)); parameters = partitioned_rice_contents->parameters; raw_bits = partitioned_rice_contents->raw_bits; - if(partition_order == 0) { - best_partition_bits = (uint32_t)(-1); + for(partition = residual_sample = 0; partition < partitions; partition++) { + partition_samples = (residual_samples+predictor_order) >> partition_order; + if(partition == 0) { + if(partition_samples <= predictor_order) + return false; + else + partition_samples -= predictor_order; + } + mean = abs_residual_partition_sums[partition]; + /* we are basically calculating the size in bits of the + * average residual magnitude in the partition: + * rice_parameter = floor(log2(mean/partition_samples)) + * 'mean' is not a good name for the variable, it is + * actually the sum of magnitudes of all residual values + * in the partition, so the actual mean is + * mean/partition_samples + */ +#if 0 /* old simple code */ + for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1) + ; +#else +#if defined FLAC__CPU_X86_64 /* and other 64-bit arch, too */ + if(mean <= 0x80000000/512) { /* 512: more or less optimal for both 16- and 24-bit input */ +#else + if(mean <= 0x80000000/8) { /* 32-bit arch: use 32-bit math if possible */ +#endif + FLAC__uint32 k2, mean2 = (FLAC__uint32) mean; + rice_parameter = 0; k2 = partition_samples; + while(k2*8 < mean2) { /* requires: mean <= (2^31)/8 */ + rice_parameter += 4; k2 <<= 4; /* tuned for 16-bit input */ + } + while(k2 < mean2) { /* requires: mean <= 2^31 */ + rice_parameter++; k2 <<= 1; + } + } + else { + rice_parameter = 0; k = partition_samples; + if(mean <= FLAC__U64L(0x8000000000000000)/128) /* usually mean is _much_ smaller than this value */ + while(k*128 < mean) { /* requires: mean <= (2^63)/128 */ + rice_parameter += 8; k <<= 8; /* tuned for 24-bit input */ + } + while(k < mean) { /* requires: mean <= 2^63 */ + rice_parameter++; k <<= 1; + } + } +#endif + if(rice_parameter >= rice_parameter_limit) { +#ifndef NDEBUG + fprintf(stderr, "clipping rice_parameter (%u -> %u) @6\n", rice_parameter, rice_parameter_limit - 1); +#endif + rice_parameter = rice_parameter_limit - 1; + } + + best_partition_bits = UINT32_MAX; #ifdef ENABLE_RICE_PARAMETER_SEARCH if(rice_parameter_search_dist) { - if(suggested_rice_parameter < rice_parameter_search_dist) + if(rice_parameter < rice_parameter_search_dist) min_rice_parameter = 0; else - min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist; - max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist; + min_rice_parameter = rice_parameter - rice_parameter_search_dist; + max_rice_parameter = rice_parameter + rice_parameter_search_dist; if(max_rice_parameter >= rice_parameter_limit) { #ifndef NDEBUG - fprintf(stderr, "clipping rice_parameter (%u -> %u) @5\n", max_rice_parameter, rice_parameter_limit - 1); + fprintf(stderr, "clipping rice_parameter (%u -> %u) @7\n", max_rice_parameter, rice_parameter_limit - 1); #endif max_rice_parameter = rice_parameter_limit - 1; } } else - min_rice_parameter = max_rice_parameter = suggested_rice_parameter; + min_rice_parameter = max_rice_parameter = rice_parameter; for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) { -#else - rice_parameter = suggested_rice_parameter; #endif #ifdef EXACT_RICE_BITS_CALCULATION - partition_bits = count_rice_bits_in_partition_(rice_parameter, residual_samples, residual); + partition_bits = count_rice_bits_in_partition_(rice_parameter, partition_samples, residual+residual_sample); #else - partition_bits = count_rice_bits_in_partition_(rice_parameter, residual_samples, abs_residual_partition_sums[0]); + partition_bits = count_rice_bits_in_partition_(rice_parameter, partition_samples, abs_residual_partition_sums[partition]); #endif if(partition_bits < best_partition_bits) { best_rice_parameter = rice_parameter; @@ -4217,128 +4522,21 @@ FLAC__bool set_partitioned_rice_( } #endif if(search_for_escapes) { - partition_bits = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN + raw_bits_per_partition[0] * residual_samples; - if(partition_bits <= best_partition_bits) { - raw_bits[0] = raw_bits_per_partition[0]; + partition_bits = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN + raw_bits_per_partition[partition] * partition_samples; + if(partition_bits <= best_partition_bits && raw_bits_per_partition[partition] < 32) { + raw_bits[partition] = raw_bits_per_partition[partition]; best_rice_parameter = 0; /* will be converted to appropriate escape parameter later */ best_partition_bits = partition_bits; } else - raw_bits[0] = 0; + raw_bits[partition] = 0; } - parameters[0] = best_rice_parameter; - if(best_partition_bits < UINT_MAX - bits_) // To make sure _bits doesn't overflow + parameters[partition] = best_rice_parameter; + if(best_partition_bits < UINT32_MAX - bits_) // To make sure _bits doesn't overflow bits_ += best_partition_bits; else - bits_ = UINT_MAX; - } - else { - uint32_t partition, residual_sample; - uint32_t partition_samples; - FLAC__uint64 mean, k; - const uint32_t partitions = 1u << partition_order; - for(partition = residual_sample = 0; partition < partitions; partition++) { - partition_samples = (residual_samples+predictor_order) >> partition_order; - if(partition == 0) { - if(partition_samples <= predictor_order) - return false; - else - partition_samples -= predictor_order; - } - mean = abs_residual_partition_sums[partition]; - /* we are basically calculating the size in bits of the - * average residual magnitude in the partition: - * rice_parameter = floor(log2(mean/partition_samples)) - * 'mean' is not a good name for the variable, it is - * actually the sum of magnitudes of all residual values - * in the partition, so the actual mean is - * mean/partition_samples - */ -#if 0 /* old simple code */ - for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1) - ; -#else -#if defined FLAC__CPU_X86_64 /* and other 64-bit arch, too */ - if(mean <= 0x80000000/512) { /* 512: more or less optimal for both 16- and 24-bit input */ -#else - if(mean <= 0x80000000/8) { /* 32-bit arch: use 32-bit math if possible */ -#endif - FLAC__uint32 k2, mean2 = (FLAC__uint32) mean; - rice_parameter = 0; k2 = partition_samples; - while(k2*8 < mean2) { /* requires: mean <= (2^31)/8 */ - rice_parameter += 4; k2 <<= 4; /* tuned for 16-bit input */ - } - while(k2 < mean2) { /* requires: mean <= 2^31 */ - rice_parameter++; k2 <<= 1; - } - } - else { - rice_parameter = 0; k = partition_samples; - if(mean <= FLAC__U64L(0x8000000000000000)/128) /* usually mean is _much_ smaller than this value */ - while(k*128 < mean) { /* requires: mean <= (2^63)/128 */ - rice_parameter += 8; k <<= 8; /* tuned for 24-bit input */ - } - while(k < mean) { /* requires: mean <= 2^63 */ - rice_parameter++; k <<= 1; - } - } -#endif - if(rice_parameter >= rice_parameter_limit) { -#ifndef NDEBUG - fprintf(stderr, "clipping rice_parameter (%u -> %u) @6\n", rice_parameter, rice_parameter_limit - 1); -#endif - rice_parameter = rice_parameter_limit - 1; - } - - best_partition_bits = (uint32_t)(-1); -#ifdef ENABLE_RICE_PARAMETER_SEARCH - if(rice_parameter_search_dist) { - if(rice_parameter < rice_parameter_search_dist) - min_rice_parameter = 0; - else - min_rice_parameter = rice_parameter - rice_parameter_search_dist; - max_rice_parameter = rice_parameter + rice_parameter_search_dist; - if(max_rice_parameter >= rice_parameter_limit) { -#ifndef NDEBUG - fprintf(stderr, "clipping rice_parameter (%u -> %u) @7\n", max_rice_parameter, rice_parameter_limit - 1); -#endif - max_rice_parameter = rice_parameter_limit - 1; - } - } - else - min_rice_parameter = max_rice_parameter = rice_parameter; - - for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) { -#endif -#ifdef EXACT_RICE_BITS_CALCULATION - partition_bits = count_rice_bits_in_partition_(rice_parameter, partition_samples, residual+residual_sample); -#else - partition_bits = count_rice_bits_in_partition_(rice_parameter, partition_samples, abs_residual_partition_sums[partition]); -#endif - if(partition_bits < best_partition_bits) { - best_rice_parameter = rice_parameter; - best_partition_bits = partition_bits; - } -#ifdef ENABLE_RICE_PARAMETER_SEARCH - } -#endif - if(search_for_escapes) { - partition_bits = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN + raw_bits_per_partition[partition] * partition_samples; - if(partition_bits <= best_partition_bits) { - raw_bits[partition] = raw_bits_per_partition[partition]; - best_rice_parameter = 0; /* will be converted to appropriate escape parameter later */ - best_partition_bits = partition_bits; - } - else - raw_bits[partition] = 0; - } - parameters[partition] = best_rice_parameter; - if(best_partition_bits < UINT_MAX - bits_) // To make sure _bits doesn't overflow - bits_ += best_partition_bits; - else - bits_ = UINT_MAX; - residual_sample += partition_samples; - } + bits_ = UINT32_MAX; + residual_sample += partition_samples; } *bits = bits_; @@ -4369,6 +4567,31 @@ uint32_t get_wasted_bits_(FLAC__int32 signal[], uint32_t samples) return shift; } +uint32_t get_wasted_bits_wide_(FLAC__int64 signal_wide[], FLAC__int32 signal[], uint32_t samples) +{ + uint32_t i, shift; + FLAC__int64 x = 0; + + for(i = 0; i < samples && !(x&1); i++) + x |= signal_wide[i]; + + if(x == 0) { + shift = 1; + } + else { + for(shift = 0; !(x&1); shift++) + x >>= 1; + } + + if(shift > 0) { + for(i = 0; i < samples; i++) + signal[i] = (FLAC__int32)(signal_wide[i] >> shift); + } + + return shift; +} + + void append_to_verify_fifo_(verify_input_fifo *fifo, const FLAC__int32 * const input[], uint32_t input_offset, uint32_t channels, uint32_t wide_samples) { uint32_t channel; @@ -4439,6 +4662,11 @@ FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder (void)decoder; + if(encoder->protected_->state == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) { + /* This is set when verify_error_callback_ was called */ + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + for(channel = 0; channel < channels; channel++) { if(0 != memcmp(buffer[channel], encoder->private_->verify.input_fifo.data[channel], bytes_per_block)) { uint32_t i, sample = 0; diff --git a/sys/src/cmd/audio/libFLAC/stream_encoder_framing.c b/sys/src/cmd/audio/libFLAC/stream_encoder_framing.c index 2c78916db..a3bdd7161 100644 --- a/sys/src/cmd/audio/libFLAC/stream_encoder_framing.c +++ b/sys/src/cmd/audio/libFLAC/stream_encoder_framing.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -96,9 +96,13 @@ FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__ FLAC__ASSERT(metadata->data.stream_info.bits_per_sample <= (1u << FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN)); if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.bits_per_sample-1, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN)) return false; - FLAC__ASSERT(metadata->data.stream_info.total_samples < (FLAC__U64L(1) << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN)); - if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN)) - return false; + if(metadata->data.stream_info.total_samples >= (FLAC__U64L(1) << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN)){ + if(!FLAC__bitwriter_write_raw_uint64(bw, 0, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN)) + return false; + }else{ + if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN)) + return false; + } if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.stream_info.md5sum, 16)) return false; break; @@ -278,7 +282,7 @@ FLAC__bool FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__BitWrit default: if(header->sample_rate <= 255000 && header->sample_rate % 1000 == 0) sample_rate_hint = u = 12; - else if(header->sample_rate % 10 == 0) + else if(header->sample_rate <= 655350 && header->sample_rate % 10 == 0) sample_rate_hint = u = 14; else if(header->sample_rate <= 0xffff) sample_rate_hint = u = 13; @@ -319,6 +323,7 @@ FLAC__bool FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__BitWrit case 16: u = 4; break; case 20: u = 5; break; case 24: u = 6; break; + case 32: u = 7; break; default: u = 0; break; } if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN)) @@ -371,7 +376,7 @@ FLAC__bool FLAC__subframe_add_constant(const FLAC__Subframe_Constant *subframe, ok = FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN) && (wasted_bits? FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1) : true) && - FLAC__bitwriter_write_raw_int32(bw, subframe->value, subframe_bps) + FLAC__bitwriter_write_raw_int64(bw, subframe->value, subframe_bps) ; return ok; @@ -388,7 +393,7 @@ FLAC__bool FLAC__subframe_add_fixed(const FLAC__Subframe_Fixed *subframe, uint32 return false; for(i = 0; i < subframe->order; i++) - if(!FLAC__bitwriter_write_raw_int32(bw, subframe->warmup[i], subframe_bps)) + if(!FLAC__bitwriter_write_raw_int64(bw, subframe->warmup[i], subframe_bps)) return false; if(!add_entropy_coding_method_(bw, &subframe->entropy_coding_method)) @@ -426,7 +431,7 @@ FLAC__bool FLAC__subframe_add_lpc(const FLAC__Subframe_LPC *subframe, uint32_t r return false; for(i = 0; i < subframe->order; i++) - if(!FLAC__bitwriter_write_raw_int32(bw, subframe->warmup[i], subframe_bps)) + if(!FLAC__bitwriter_write_raw_int64(bw, subframe->warmup[i], subframe_bps)) return false; if(!FLAC__bitwriter_write_raw_uint32(bw, subframe->qlp_coeff_precision-1, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN)) @@ -464,7 +469,6 @@ FLAC__bool FLAC__subframe_add_lpc(const FLAC__Subframe_LPC *subframe, uint32_t r FLAC__bool FLAC__subframe_add_verbatim(const FLAC__Subframe_Verbatim *subframe, uint32_t samples, uint32_t subframe_bps, uint32_t wasted_bits, FLAC__BitWriter *bw) { uint32_t i; - const FLAC__int32 *signal = subframe->data; if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN)) return false; @@ -472,9 +476,24 @@ FLAC__bool FLAC__subframe_add_verbatim(const FLAC__Subframe_Verbatim *subframe, if(!FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1)) return false; - for(i = 0; i < samples; i++) - if(!FLAC__bitwriter_write_raw_int32(bw, signal[i], subframe_bps)) - return false; + if(subframe->data_type == FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT32) { + const FLAC__int32 *signal = subframe->data.int32; + + FLAC__ASSERT(subframe_bps < 33); + + for(i = 0; i < samples; i++) + if(!FLAC__bitwriter_write_raw_int32(bw, signal[i], subframe_bps)) + return false; + } + else { + const FLAC__int64 *signal = subframe->data.int64; + + FLAC__ASSERT(subframe_bps == 33); + + for(i = 0; i < samples; i++) + if(!FLAC__bitwriter_write_raw_int64(bw, (FLAC__int64)signal[i], subframe_bps)) + return false; + } return true; } diff --git a/sys/src/cmd/audio/libFLAC/window.c b/sys/src/cmd/audio/libFLAC/window.c index 8bf6bb84b..4ee6f79d4 100644 --- a/sys/src/cmd/audio/libFLAC/window.c +++ b/sys/src/cmd/audio/libFLAC/window.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2006-2009 Josh Coalson - * Copyright (C) 2011-2016 Xiph.Org Foundation + * Copyright (C) 2011-2022 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -42,9 +42,9 @@ #ifndef FLAC__INTEGER_ONLY_LIBRARY -#ifdef Plan9 -#define cosf cos -#define fabsf fabs +#if defined(_MSC_VER) +// silence 25 MSVC warnings 'conversion from 'double' to 'float', possible loss of data' +#pragma warning ( disable : 4244 ) #endif void FLAC__window_bartlett(FLAC__real *window, const FLAC__int32 L) @@ -122,9 +122,15 @@ void FLAC__window_gauss(FLAC__real *window, const FLAC__int32 L, const FLAC__rea const double N2 = (double)N / 2.; FLAC__int32 n; - for (n = 0; n <= N; n++) { - const double k = ((double)n - N2) / (stddev * N2); - window[n] = (FLAC__real)exp(-0.5f * k * k); + if(!(stddev > 0.0f && stddev <= 0.5f)) + /* stddev is not between 0 and 0.5, might be NaN. + * Default to 0.5 */ + FLAC__window_gauss(window, L, 0.25f); + else { + for (n = 0; n <= N; n++) { + const double k = ((double)n - N2) / (stddev * N2); + window[n] = (FLAC__real)exp(-0.5f * k * k); + } } } @@ -196,6 +202,10 @@ void FLAC__window_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__rea FLAC__window_rectangle(window, L); else if (p >= 1.0) FLAC__window_hann(window, L); + else if (!(p > 0.0f && p < 1.0f)) + /* p is not between 0 and 1, probably NaN. + * Default to 0.5 */ + FLAC__window_tukey(window, L, 0.5f); else { const FLAC__int32 Np = (FLAC__int32)(p / 2.0f * L) - 1; FLAC__int32 n; @@ -222,6 +232,10 @@ void FLAC__window_partial_tukey(FLAC__real *window, const FLAC__int32 L, const F FLAC__window_partial_tukey(window, L, 0.05f, start, end); else if (p >= 1.0f) FLAC__window_partial_tukey(window, L, 0.95f, start, end); + else if (!(p > 0.0f && p < 1.0f)) + /* p is not between 0 and 1, probably NaN. + * Default to 0.5 */ + FLAC__window_partial_tukey(window, L, 0.5f, start, end); else { Np = (FLAC__int32)(p / 2.0f * N); @@ -249,6 +263,10 @@ void FLAC__window_punchout_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__window_punchout_tukey(window, L, 0.05f, start, end); else if (p >= 1.0f) FLAC__window_punchout_tukey(window, L, 0.95f, start, end); + else if (!(p > 0.0f && p < 1.0f)) + /* p is not between 0 and 1, probably NaN. + * Default to 0.5 */ + FLAC__window_punchout_tukey(window, L, 0.5f, start, end); else { Ns = (FLAC__int32)(p / 2.0f * start_n); @@ -283,4 +301,8 @@ void FLAC__window_welch(FLAC__real *window, const FLAC__int32 L) } } +#if defined(_MSC_VER) +#pragma warning ( default : 4244 ) +#endif + #endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ |