ref: a5d6746e4d2dc7961910ce7d1729f5500a4dc0f3
parent: 341502a0fd20bd3188b8d4e100b2d975f2d94007
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Fri Sep 9 12:15:52 EDT 2022
libFLAC: update 1.3.4 → 1.4.0
--- 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.
@@ -355,6 +355,85 @@
* FLAC frame header length has not changed, so to skip the proper
* number of bits, use \c FLAC__FRAME_HEADER_RESERVED_LEN +
* \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
--- 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
--- 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
--- 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" {
--- 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 @@
/** 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 @@
/** 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 @@
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 @@
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 @@
/** 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
--- 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 @@
* 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 @@
/** 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 @@
/** 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 @@
/** 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 @@
/** 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 @@
/** 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 @@
/** 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 @@
/** 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.
--- 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
--- 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 @@
* 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 @@
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 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 @@
/** 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,10 +1326,14 @@
/** 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
--- 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 @@
* 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_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 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 @@
/** 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,10 +1693,14 @@
/** 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()
--- 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
--- 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 @@
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,7 +158,14 @@
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) {
crc16_update_block_(br); /* CRC consumed words */
@@ -186,6 +196,7 @@
*/
#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 @@
*/
/* 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 @@
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,6 +313,9 @@
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)
@@ -297,9 +322,30 @@
{
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 @@
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 @@
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 @@
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 @@
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__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 @@
}
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__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 @@
#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 @@
}
#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 @@
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 @@
/* 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__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 @@
/* 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);
}
@@ -814,6 +928,9 @@
b <<= 1; /* account for stop bit */
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 */
--- 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 @@
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__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 @@
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_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);
--- 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
--- 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,15 +224,23 @@
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;
@@ -234,14 +247,25 @@
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[], 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;
+ uint32_t 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;
+ 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 @@
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_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;
@@ -388,6 +587,74 @@
case 4:
for(i = 0; i < idata_len; i++)
data[i] = residual[i] + 4*data[i-1] - 6*data[i-2] + 4*data[i-3] - data[i-4];
+ break;
+ default:
+ 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);
--- 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
--- 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,11 +44,20 @@
#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 " 20220909";
+#endif
-FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " PACKAGE_VERSION " 20220220";
-
FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' };
FLAC_API const uint32_t FLAC__STREAM_SYNC = 0x664C6143;
FLAC_API const uint32_t FLAC__STREAM_SYNC_LEN = 32; /* bits */
@@ -218,12 +227,10 @@
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,6 +577,11 @@
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);
@@ -576,7 +588,7 @@
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 @@
return true;
}
+
+#if defined(_MSC_VER)
+#pragma warning ( default : 4334 )
+#endif
--- 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 @@
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 @@
*/
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 @@
* 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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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));
}
}
}
@@ -1294,6 +1467,87 @@
}
data[i] = (FLAC__int32) (residual[i] + (sum >> lp_quantization));
}
+ }
+}
+#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
--- 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
@@ -94,6 +94,35 @@
FLAC__uint32 *pu; /* unaligned pointer */
union { /* union needed to comply with C99 pointer aliasing rules */
FLAC__uint32 *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_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;
--- 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,27 +286,30 @@
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;
+ 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);
+ }
}
- else {
- FLAC__metadata_object_delete(obj);
- }
}
} while(FLAC__metadata_simple_iterator_next(it));
@@ -443,7 +446,15 @@
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__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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
--- 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 @@
/* 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 @@
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 @@
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 @@
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__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 @@
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_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 @@
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 @@
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 @@
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)
--- a/sys/src/cmd/audio/libFLAC/mkfile
+++ b/sys/src/cmd/audio/libFLAC/mkfile
@@ -26,6 +26,6 @@
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
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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 @@
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__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 @@
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! */
--- 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_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);
--- 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,6 +63,7 @@
/* 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 */
@@ -69,15 +70,18 @@
#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
+ #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
- #if (__INTEL_COMPILER >= 1300) /* Intel C++ Compiler 13.0 */
- #define FLAC__AVX2_SUPPORTED 1
- #define FLAC__FMA_SUPPORTED 1
- #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
+ #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
- #if __has_builtin(__builtin_ia32_pabsd256)
- #define FLAC__AVX2_SUPPORTED 1
- #endif
- #if __has_builtin(__builtin_ia32_vfmaddps)
- #define FLAC__FMA_SUPPORTED 1
- #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,6 +119,7 @@
#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 */
@@ -118,15 +126,18 @@
#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
+ #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
- #if (_MSC_VER >= 1700) /* MS Visual Studio 2012 */
- #define FLAC__AVX2_SUPPORTED 1
- #define FLAC__FMA_SUPPORTED 1
- #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 */
--- 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
--- 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 @@
#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 @@
* 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 @@
* 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
--- 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
--- 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
--- 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 @@
* 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 @@
* 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 @@
*/
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 @@
#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_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
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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 @@
} 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
--- 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 @@
FLAC__APODIZATION_TUKEY,
FLAC__APODIZATION_PARTIAL_TUKEY,
FLAC__APODIZATION_PUNCHOUT_TUKEY,
+ FLAC__APODIZATION_SUBDIVIDE_TUKEY,
FLAC__APODIZATION_WELCH
} FLAC__ApodizationFunction;
@@ -78,6 +79,10 @@
FLAC__real start;
FLAC__real end;
} multiple_tukey;
+ struct {
+ FLAC__real p;
+ FLAC__int32 parts;
+ } subdivide_tukey;
} parameters;
} FLAC__ApodizationSpecification;
@@ -107,6 +112,7 @@
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;
--- 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,11 +63,31 @@
# 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++;
@@ -74,8 +94,27 @@
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 @@
size1 *= size2;
if(size1 > SIZE_MAX / size3)
return 0;
- return malloc(size1*size3);
+ return malloc_(size1*size3);
}
/* size1*size2 + size3 */
@@ -150,11 +189,18 @@
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)
@@ -161,17 +207,44 @@
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 @@
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,7 +266,7 @@
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)
@@ -200,11 +273,22 @@
{
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)
{
@@ -211,9 +295,22 @@
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
--- 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,15 +173,13 @@
#define flac_printf printf_utf8
#define flac_fprintf fprintf_utf8
#define flac_vfprintf vfprintf_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
-#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
-
#else
#define flac_printf printf
@@ -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
--- 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);
--- 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
--- 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);
--- 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
--- 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 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_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 @@
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 @@
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 @@
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__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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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__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 @@
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 @@
}
}
+ 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 @@
}
}
+ 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 @@
}
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 @@
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 @@
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 @@
/* 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 @@
/* 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 @@
/* 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__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 @@
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 @@
{
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 @@
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 @@
/*
* 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 @@
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,9 +2435,8 @@
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);
@@ -2359,11 +2443,6 @@
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 @@
}
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,10 +2638,22 @@
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);
+ }
+ }
}
return true;
@@ -2577,13 +2662,12 @@
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;
@@ -2590,8 +2674,16 @@
/* 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_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 @@
/* 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 @@
/* 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__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 @@
/* 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 @@
/* 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,23 +2869,40 @@
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,8 +2932,17 @@
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 {
@@ -2813,11 +2949,17 @@
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 @@
*/
}
+#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__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 @@
#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__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 @@
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 @@
* 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 @@
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,18 +3406,25 @@
* 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;
@@ -3207,7 +3431,7 @@
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 @@
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 @@
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;
@@ -3446,9 +3682,4 @@
(void)client_data;
return feof(decoder->private_->file)? true : false;
-}
-
-void *get_client_data_from_decoder(FLAC__StreamDecoder *decoder)
-{
- return decoder->private_->client_data;
}
--- 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 @@
{ 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 @@
#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 @@
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 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,7 +175,7 @@
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[],
@@ -182,7 +182,6 @@
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 @@
#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 @@
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_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 @@
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 @@
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 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 @@
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 @@
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 @@
/* 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 @@
encoder->private_->file = 0;
+ encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
+
set_defaults_(encoder);
encoder->private_->is_being_deleted = false;
@@ -568,8 +575,6 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
#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 @@
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,32 +1007,18 @@
# 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;
+# ifdef FLAC__SSE2_SUPPORTED
+ 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;
}
- 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;
-# endif
# ifdef FLAC__SSE4_1_SUPPORTED
if(encoder->private_->cpuinfo.x86.sse41) {
encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_sse41;
@@ -1051,10 +1031,23 @@
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 @@
# 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__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 @@
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 @@
}
}
}
- 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 @@
}
}
}
+ 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__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 @@
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,16 +2219,28 @@
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 @@
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 @@
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,7 +2283,7 @@
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++)
@@ -2219,7 +2290,10 @@
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,14 +2305,17 @@
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;
/*
* we have several flavors of the same basic loop, optimized for
@@ -2254,19 +2331,26 @@
/* "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 @@
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 @@
/* "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 @@
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 @@
}
#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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
}
#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 @@
/*
* 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 @@
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 @@
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 @@
*/
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 @@
)
)
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__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 @@
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 @@
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,10 +3524,36 @@
}
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,
@@ -3394,7 +3560,7 @@
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 @@
#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 @@
/* 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 @@
/* 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 @@
#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 @@
frame_header->blocksize,
subframe_bps,
fixed_order,
- rice_parameter,
rice_parameter_limit,
min_partition_order,
max_partition_order,
@@ -3525,13 +3714,55 @@
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 @@
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 @@
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 @@
subframe_bps,
lpc_order,
qlp_coeff_precision,
- rice_parameter,
rice_parameter_limit,
min_partition_order,
max_partition_order,
@@ -3615,7 +3837,7 @@
}
/* 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 @@
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,7 +3944,7 @@
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[],
@@ -3729,7 +3951,6 @@
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 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 @@
raw_bits_per_partition,
residual_samples,
order,
- rice_parameter,
rice_parameter_limit,
min_partition_order,
max_partition_order,
@@ -3769,10 +3994,18 @@
);
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 @@
#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 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 @@
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 @@
raw_bits_per_partition,
residual_samples,
order,
- rice_parameter,
rice_parameter_limit,
min_partition_order,
max_partition_order,
@@ -3855,11 +4096,20 @@
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);
#endif
@@ -3870,7 +4120,7 @@
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 @@
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 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 @@
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 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 @@
;
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 @@
(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 @@
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,6 +4421,10 @@
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
@@ -4174,40 +4431,88 @@
(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,130 +4522,23 @@
}
#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;
+ bits_ = UINT32_MAX;
+ residual_sample += partition_samples;
}
- 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 = bits_;
return true;
}
@@ -4369,6 +4567,31 @@
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;
@@ -4438,6 +4661,11 @@
const uint32_t bytes_per_block = sizeof(FLAC__int32) * blocksize;
(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)) {
--- 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__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 @@
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 @@
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 @@
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 @@
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 @@
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_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 @@
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;
}
--- 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 @@
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 @@
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 @@
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 @@
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);
@@ -282,5 +300,9 @@
window[n] = (FLAC__real)(1.0f - k * k);
}
}
+
+#if defined(_MSC_VER)
+#pragma warning ( default : 4244 )
+#endif
#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */