/* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson * 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 * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the Xiph.org Foundation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H# include <config.h>#endif #include <limits.h>#include <stdio.h>#include <stdlib.h> /* for malloc() */#include <string.h> /* for memcpy() */#include <sys/types.h> /* for off_t */#ifdef _WIN32#include <windows.h> /* for GetFileType() */#include <io.h> /* for _get_osfhandle() */#endif#include "share/compat.h"#include "FLAC/assert.h"#include "FLAC/stream_decoder.h"#include "protected/stream_encoder.h"#include "private/bitwriter.h"#include "private/bitmath.h"#include "private/crc.h"#include "private/cpu.h"#include "private/fixed.h"#include "private/format.h"#include "private/lpc.h"#include "private/md5.h"#include "private/memory.h"#include "private/macros.h"#if FLAC__HAS_OGG#include "private/ogg_helper.h"#include "private/ogg_mapping.h"#endif#include "private/stream_encoder.h"#include "private/stream_encoder_framing.h"#include "private/window.h"#include "share/alloc.h"#include "share/private.h" /* Exact Rice codeword length calculation is off by default. The simple * (and fast) estimation (of how many bits a residual value will be * encoded with) in this encoder is very good, almost always yielding * compression within 0.1% of exact calculation. */#undef EXACT_RICE_BITS_CALCULATION/* Rice parameter searching is off by default. The simple (and fast) * parameter estimation in this encoder is very good, almost always * yielding compression within 0.1% of the optimal parameters. */#undef ENABLE_RICE_PARAMETER_SEARCH typedef struct { FLAC__int32 *data[FLAC__MAX_CHANNELS]; uint32_t size; /* of each data[] in samples */ uint32_t tail;} verify_input_fifo; typedef struct { const FLAC__byte *data; uint32_t capacity; uint32_t bytes;} verify_output; typedef enum { ENCODER_IN_MAGIC = 0, ENCODER_IN_METADATA = 1, ENCODER_IN_AUDIO = 2} EncoderStateHint; static const struct CompressionLevels { FLAC__bool do_mid_side_stereo; FLAC__bool loose_mid_side_stereo; uint32_t max_lpc_order; uint32_t qlp_coeff_precision; FLAC__bool do_qlp_coeff_prec_search; FLAC__bool do_escape_coding; FLAC__bool do_exhaustive_model_search; uint32_t min_residual_partition_order; uint32_t max_residual_partition_order; uint32_t rice_parameter_search_dist; const char *apodization;} compression_levels_[] = { { false, false, 0, 0, false, false, false, 0, 3, 0, "tukey(5e-1)" }, { true , true , 0, 0, false, false, false, 0, 3, 0, "tukey(5e-1)" }, { true , false, 0, 0, false, false, false, 0, 3, 0, "tukey(5e-1)" }, { 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, "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 */}; /*********************************************************************** * * Private class method prototypes * ***********************************************************************/ static void set_defaults_(FLAC__StreamEncoder *encoder);static void free_(FLAC__StreamEncoder *encoder);static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, uint32_t new_blocksize);static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, uint32_t samples, FLAC__bool is_last_block);static FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, uint32_t samples, FLAC__bool is_last_block);static void update_metadata_(const FLAC__StreamEncoder *encoder);#if FLAC__HAS_OGGstatic void update_ogg_metadata_(FLAC__StreamEncoder *encoder);#endifstatic 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, uint32_t min_partition_order, uint32_t max_partition_order, const FLAC__FrameHeader *frame_header, uint32_t subframe_bps, const void *integer_signal, FLAC__Subframe *subframe[2], FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2], FLAC__int32 *residual[2], uint32_t *best_subframe, uint32_t *best_bits); static FLAC__bool add_subframe_( FLAC__StreamEncoder *encoder, uint32_t blocksize, uint32_t subframe_bps, const FLAC__Subframe *subframe, FLAC__BitWriter *frame); static uint32_t evaluate_constant_subframe_( FLAC__StreamEncoder *encoder, const FLAC__int64 signal, uint32_t blocksize, uint32_t subframe_bps, FLAC__Subframe *subframe); static uint32_t evaluate_fixed_subframe_( FLAC__StreamEncoder *encoder, const void *signal, FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t raw_bits_per_partition[], uint32_t blocksize, uint32_t subframe_bps, uint32_t order, uint32_t rice_parameter_limit, uint32_t min_partition_order, uint32_t max_partition_order, FLAC__bool do_escape_coding, uint32_t rice_parameter_search_dist, FLAC__Subframe *subframe, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents); #ifndef FLAC__INTEGER_ONLY_LIBRARYstatic uint32_t evaluate_lpc_subframe_( FLAC__StreamEncoder *encoder, const void *signal, FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t raw_bits_per_partition[], const FLAC__real lp_coeff[], uint32_t blocksize, uint32_t subframe_bps, uint32_t order, uint32_t qlp_coeff_precision, uint32_t rice_parameter_limit, uint32_t min_partition_order, uint32_t max_partition_order, FLAC__bool do_escape_coding, uint32_t rice_parameter_search_dist, FLAC__Subframe *subframe, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents);#endif static uint32_t evaluate_verbatim_subframe_( FLAC__StreamEncoder *encoder, const void *signal, uint32_t blocksize, uint32_t subframe_bps, FLAC__Subframe *subframe); static uint32_t find_best_partition_order_( struct FLAC__StreamEncoderPrivate *private_, const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t raw_bits_per_partition[], uint32_t residual_samples, uint32_t predictor_order, uint32_t rice_parameter_limit, uint32_t min_partition_order, uint32_t max_partition_order, uint32_t bps, FLAC__bool do_escape_coding, uint32_t rice_parameter_search_dist, FLAC__EntropyCodingMethod *best_ecm); static void precompute_partition_info_sums_( const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t residual_samples, uint32_t predictor_order, uint32_t min_partition_order, uint32_t max_partition_order, uint32_t bps); static void precompute_partition_info_escapes_( const FLAC__int32 residual[], uint32_t raw_bits_per_partition[], uint32_t residual_samples, uint32_t predictor_order, uint32_t min_partition_order, uint32_t max_partition_order); static FLAC__bool set_partitioned_rice_(#ifdef EXACT_RICE_BITS_CALCULATION const FLAC__int32 residual[],#endif const FLAC__uint64 abs_residual_partition_sums[], const uint32_t raw_bits_per_partition[], const uint32_t residual_samples, const uint32_t predictor_order, const uint32_t rice_parameter_limit, const uint32_t rice_parameter_search_dist, const uint32_t partition_order, const FLAC__bool search_for_escapes, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, uint32_t *bits); 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_( verify_input_fifo *fifo, const FLAC__int32 * const input[], uint32_t input_offset, uint32_t channels, uint32_t wide_samples); static void append_to_verify_fifo_interleaved_( verify_input_fifo *fifo, const FLAC__int32 input[], uint32_t input_offset, uint32_t channels, uint32_t wide_samples); static FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);static FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);static void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);static void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); static FLAC__StreamEncoderReadStatus file_read_callback_(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data);static FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);static FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);static FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, uint32_t samples, uint32_t current_frame, void *client_data);static FILE *get_binary_stdout_(void); /*********************************************************************** * * Private class data * ***********************************************************************/ typedef struct FLAC__StreamEncoderPrivate { uint32_t input_capacity; /* current size (in samples) of the signal and residual buffers */ FLAC__int32 *integer_signal[FLAC__MAX_CHANNELS]; /* the integer version of the input signal */ FLAC__int32 *integer_signal_mid_side[2]; /* the integer version of the mid-side input signal (stereo only) */ FLAC__int64 *integer_signal_33bit_side; /* 33-bit side for 32-bit stereo decorrelation */#ifndef FLAC__INTEGER_ONLY_LIBRARY FLAC__real *real_signal[FLAC__MAX_CHANNELS]; /* (@@@ currently unused) the floating-point version of the input signal */ FLAC__real *real_signal_mid_side[2]; /* (@@@ currently unused) the floating-point version of the mid-side input signal (stereo only) */ FLAC__real *window[FLAC__MAX_APODIZATION_FUNCTIONS]; /* the pre-computed floating-point window for each apodization function */ FLAC__real *windowed_signal; /* the integer_signal[] * current window[] */#endif uint32_t subframe_bps[FLAC__MAX_CHANNELS]; /* the effective bits per sample of the input signal (stream bps - wasted bits) */ uint32_t subframe_bps_mid_side[2]; /* the effective bits per sample of the mid-side input signal (stream bps - wasted bits + 0/1) */ FLAC__int32 *residual_workspace[FLAC__MAX_CHANNELS][2]; /* each channel has a candidate and best workspace where the subframe residual signals will be stored */ FLAC__int32 *residual_workspace_mid_side[2][2]; FLAC__Subframe subframe_workspace[FLAC__MAX_CHANNELS][2]; FLAC__Subframe subframe_workspace_mid_side[2][2]; FLAC__Subframe *subframe_workspace_ptr[FLAC__MAX_CHANNELS][2]; FLAC__Subframe *subframe_workspace_ptr_mid_side[2][2]; FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace[FLAC__MAX_CHANNELS][2]; FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace_mid_side[FLAC__MAX_CHANNELS][2]; FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr[FLAC__MAX_CHANNELS][2]; FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr_mid_side[FLAC__MAX_CHANNELS][2]; uint32_t best_subframe[FLAC__MAX_CHANNELS]; /* index (0 or 1) into 2nd dimension of the above workspaces */ uint32_t best_subframe_mid_side[2]; uint32_t best_subframe_bits[FLAC__MAX_CHANNELS]; /* size in bits of the best subframe for each channel */ uint32_t best_subframe_bits_mid_side[2]; FLAC__uint64 *abs_residual_partition_sums; /* workspace where the sum of abs(candidate residual) for each partition is stored */ uint32_t *raw_bits_per_partition; /* workspace where the sum of silog2(candidate residual) for each partition is stored */ FLAC__BitWriter *frame; /* the current frame being worked on */ uint32_t loose_mid_side_stereo_frames; /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */ uint32_t loose_mid_side_stereo_frame_count; /* number of frames using the current channel assignment */ FLAC__ChannelAssignment last_channel_assignment; FLAC__StreamMetadata streaminfo; /* scratchpad for STREAMINFO as it is built */ FLAC__StreamMetadata_SeekTable *seek_table; /* pointer into encoder->protected_->metadata_ where the seek table is */ uint32_t current_sample_number; uint32_t current_frame_number; FLAC__MD5Context md5context; FLAC__CPUInfo cpuinfo; void (*local_precompute_partition_info_sums)(const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t residual_samples, uint32_t predictor_order, uint32_t min_partition_order, uint32_t max_partition_order, uint32_t bps);#ifndef FLAC__INTEGER_ONLY_LIBRARY uint32_t (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); uint32_t (*local_fixed_compute_best_predictor_wide)(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);#else uint32_t (*local_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 (*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, 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; FLAC__bool is_ogg; FLAC__StreamEncoderReadCallback read_callback; /* currently only needed for Ogg FLAC */ FLAC__StreamEncoderSeekCallback seek_callback; FLAC__StreamEncoderTellCallback tell_callback; FLAC__StreamEncoderWriteCallback write_callback; FLAC__StreamEncoderMetadataCallback metadata_callback; FLAC__StreamEncoderProgressCallback progress_callback; void *client_data; uint32_t first_seekpoint_to_check; FILE *file; /* only used when encoding to a file */ FLAC__uint64 bytes_written; FLAC__uint64 samples_written; uint32_t frames_written; uint32_t total_frames_estimate; /* 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) */ FLAC__real *window_unaligned[FLAC__MAX_APODIZATION_FUNCTIONS]; FLAC__real *windowed_signal_unaligned;#endif FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2]; FLAC__int32 *residual_workspace_mid_side_unaligned[2][2]; FLAC__uint64 *abs_residual_partition_sums_unaligned; uint32_t *raw_bits_per_partition_unaligned; /* * These fields have been moved here from private function local * declarations merely to save stack space during encoding. */#ifndef FLAC__INTEGER_ONLY_LIBRARY FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */#endif FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */ /* * The data for the verify section */ struct { FLAC__StreamDecoder *decoder; EncoderStateHint state_hint; FLAC__bool needs_magic_hack; verify_input_fifo input_fifo; verify_output output; struct { FLAC__uint64 absolute_sample; uint32_t frame_number; uint32_t channel; uint32_t sample; FLAC__int32 expected; FLAC__int32 got; } error_stats; } verify; FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */} FLAC__StreamEncoderPrivate; /*********************************************************************** * * Public static class data * ***********************************************************************/ FLAC_API const char * const FLAC__StreamEncoderStateString[] = { "FLAC__STREAM_ENCODER_OK", "FLAC__STREAM_ENCODER_UNINITIALIZED", "FLAC__STREAM_ENCODER_OGG_ERROR", "FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR", "FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA", "FLAC__STREAM_ENCODER_CLIENT_ERROR", "FLAC__STREAM_ENCODER_IO_ERROR", "FLAC__STREAM_ENCODER_FRAMING_ERROR", "FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR"}; FLAC_API const char * const FLAC__StreamEncoderInitStatusString[] = { "FLAC__STREAM_ENCODER_INIT_STATUS_OK", "FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR", "FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION", "FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER", "FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA", "FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED"}; FLAC_API const char * const FLAC__StreamEncoderReadStatusString[] = { "FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE", "FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM", "FLAC__STREAM_ENCODER_READ_STATUS_ABORT", "FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED"}; FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = { "FLAC__STREAM_ENCODER_WRITE_STATUS_OK", "FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"}; FLAC_API const char * const FLAC__StreamEncoderSeekStatusString[] = { "FLAC__STREAM_ENCODER_SEEK_STATUS_OK", "FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR", "FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED"}; FLAC_API const char * const FLAC__StreamEncoderTellStatusString[] = { "FLAC__STREAM_ENCODER_TELL_STATUS_OK", "FLAC__STREAM_ENCODER_TELL_STATUS_ERROR", "FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED"}; /* Number of samples that will be overread to watch for end of stream. By * 'overread', we mean that the FLAC__stream_encoder_process*() calls will * always try to read blocksize+1 samples before encoding a block, so that * even if the stream has a total sample count that is an integral multiple * of the blocksize, we will still notice when we are encoding the last * block. This is needed, for example, to correctly set the end-of-stream * marker in Ogg FLAC. * * WATCHOUT: some parts of the code assert that OVERREAD_ == 1 and there's * not really any reason to change it.Lines 1–500 of 4815. Load more
/* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson * 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 * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the Xiph.org Foundation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <limits.h> #include <stdio.h> #include <stdlib.h> /* for malloc() */ #include <string.h> /* for memcpy() */ #include <sys/types.h> /* for off_t */ #ifdef _WIN32 #include <windows.h> /* for GetFileType() */ #include <io.h> /* for _get_osfhandle() */ #endif #include "share/compat.h" #include "FLAC/assert.h" #include "FLAC/stream_decoder.h" #include "protected/stream_encoder.h" #include "private/bitwriter.h" #include "private/bitmath.h" #include "private/crc.h" #include "private/cpu.h" #include "private/fixed.h" #include "private/format.h" #include "private/lpc.h" #include "private/md5.h" #include "private/memory.h" #include "private/macros.h" #if FLAC__HAS_OGG #include "private/ogg_helper.h" #include "private/ogg_mapping.h" #endif #include "private/stream_encoder.h" #include "private/stream_encoder_framing.h" #include "private/window.h" #include "share/alloc.h" #include "share/private.h" /* Exact Rice codeword length calculation is off by default. The simple * (and fast) estimation (of how many bits a residual value will be * encoded with) in this encoder is very good, almost always yielding * compression within 0.1% of exact calculation. */ #undef EXACT_RICE_BITS_CALCULATION /* Rice parameter searching is off by default. The simple (and fast) * parameter estimation in this encoder is very good, almost always * yielding compression within 0.1% of the optimal parameters. */ #undef ENABLE_RICE_PARAMETER_SEARCH typedef struct { FLAC__int32 *data[FLAC__MAX_CHANNELS]; uint32_t size; /* of each data[] in samples */ uint32_t tail; } verify_input_fifo; typedef struct { const FLAC__byte *data; uint32_t capacity; uint32_t bytes; } verify_output; typedef enum { ENCODER_IN_MAGIC = 0, ENCODER_IN_METADATA = 1, ENCODER_IN_AUDIO = 2 } EncoderStateHint; static const struct CompressionLevels { FLAC__bool do_mid_side_stereo; FLAC__bool loose_mid_side_stereo; uint32_t max_lpc_order; uint32_t qlp_coeff_precision; FLAC__bool do_qlp_coeff_prec_search; FLAC__bool do_escape_coding; FLAC__bool do_exhaustive_model_search; uint32_t min_residual_partition_order; uint32_t max_residual_partition_order; uint32_t rice_parameter_search_dist; const char *apodization; } compression_levels_[] = { { false, false, 0, 0, false, false, false, 0, 3, 0, "tukey(5e-1)" }, { true , true , 0, 0, false, false, false, 0, 3, 0, "tukey(5e-1)" }, { true , false, 0, 0, false, false, false, 0, 3, 0, "tukey(5e-1)" }, { 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, "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 */ }; /*********************************************************************** * * Private class method prototypes * ***********************************************************************/ static void set_defaults_(FLAC__StreamEncoder *encoder); static void free_(FLAC__StreamEncoder *encoder); static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, uint32_t new_blocksize); static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, uint32_t samples, FLAC__bool is_last_block); static FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, uint32_t samples, FLAC__bool is_last_block); static void update_metadata_(const FLAC__StreamEncoder *encoder); #if FLAC__HAS_OGG static void update_ogg_metadata_(FLAC__StreamEncoder *encoder); #endif static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_block); static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder); static FLAC__bool process_subframe_( FLAC__StreamEncoder *encoder, uint32_t min_partition_order, uint32_t max_partition_order, const FLAC__FrameHeader *frame_header, uint32_t subframe_bps, const void *integer_signal, FLAC__Subframe *subframe[2], FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2], FLAC__int32 *residual[2], uint32_t *best_subframe, uint32_t *best_bits ); static FLAC__bool add_subframe_( FLAC__StreamEncoder *encoder, uint32_t blocksize, uint32_t subframe_bps, const FLAC__Subframe *subframe, FLAC__BitWriter *frame ); static uint32_t evaluate_constant_subframe_( FLAC__StreamEncoder *encoder, const FLAC__int64 signal, uint32_t blocksize, uint32_t subframe_bps, FLAC__Subframe *subframe ); static uint32_t evaluate_fixed_subframe_( FLAC__StreamEncoder *encoder, const void *signal, FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t raw_bits_per_partition[], uint32_t blocksize, uint32_t subframe_bps, uint32_t order, uint32_t rice_parameter_limit, uint32_t min_partition_order, uint32_t max_partition_order, FLAC__bool do_escape_coding, uint32_t rice_parameter_search_dist, FLAC__Subframe *subframe, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents ); #ifndef FLAC__INTEGER_ONLY_LIBRARY static uint32_t evaluate_lpc_subframe_( FLAC__StreamEncoder *encoder, const void *signal, FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t raw_bits_per_partition[], const FLAC__real lp_coeff[], uint32_t blocksize, uint32_t subframe_bps, uint32_t order, uint32_t qlp_coeff_precision, uint32_t rice_parameter_limit, uint32_t min_partition_order, uint32_t max_partition_order, FLAC__bool do_escape_coding, uint32_t rice_parameter_search_dist, FLAC__Subframe *subframe, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents ); #endif static uint32_t evaluate_verbatim_subframe_( FLAC__StreamEncoder *encoder, const void *signal, uint32_t blocksize, uint32_t subframe_bps, FLAC__Subframe *subframe ); static uint32_t find_best_partition_order_( struct FLAC__StreamEncoderPrivate *private_, const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t raw_bits_per_partition[], uint32_t residual_samples, uint32_t predictor_order, uint32_t rice_parameter_limit, uint32_t min_partition_order, uint32_t max_partition_order, uint32_t bps, FLAC__bool do_escape_coding, uint32_t rice_parameter_search_dist, FLAC__EntropyCodingMethod *best_ecm ); static void precompute_partition_info_sums_( const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t residual_samples, uint32_t predictor_order, uint32_t min_partition_order, uint32_t max_partition_order, uint32_t bps ); static void precompute_partition_info_escapes_( const FLAC__int32 residual[], uint32_t raw_bits_per_partition[], uint32_t residual_samples, uint32_t predictor_order, uint32_t min_partition_order, uint32_t max_partition_order ); static FLAC__bool set_partitioned_rice_( #ifdef EXACT_RICE_BITS_CALCULATION const FLAC__int32 residual[], #endif const FLAC__uint64 abs_residual_partition_sums[], const uint32_t raw_bits_per_partition[], const uint32_t residual_samples, const uint32_t predictor_order, const uint32_t rice_parameter_limit, const uint32_t rice_parameter_search_dist, const uint32_t partition_order, const FLAC__bool search_for_escapes, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, uint32_t *bits ); 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_( verify_input_fifo *fifo, const FLAC__int32 * const input[], uint32_t input_offset, uint32_t channels, uint32_t wide_samples ); static void append_to_verify_fifo_interleaved_( verify_input_fifo *fifo, const FLAC__int32 input[], uint32_t input_offset, uint32_t channels, uint32_t wide_samples ); static FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); static FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); static void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); static void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); static FLAC__StreamEncoderReadStatus file_read_callback_(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data); static FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data); static FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data); static FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, uint32_t samples, uint32_t current_frame, void *client_data); static FILE *get_binary_stdout_(void); /*********************************************************************** * * Private class data * ***********************************************************************/ typedef struct FLAC__StreamEncoderPrivate { uint32_t input_capacity; /* current size (in samples) of the signal and residual buffers */ FLAC__int32 *integer_signal[FLAC__MAX_CHANNELS]; /* the integer version of the input signal */ FLAC__int32 *integer_signal_mid_side[2]; /* the integer version of the mid-side input signal (stereo only) */ FLAC__int64 *integer_signal_33bit_side; /* 33-bit side for 32-bit stereo decorrelation */ #ifndef FLAC__INTEGER_ONLY_LIBRARY FLAC__real *real_signal[FLAC__MAX_CHANNELS]; /* (@@@ currently unused) the floating-point version of the input signal */ FLAC__real *real_signal_mid_side[2]; /* (@@@ currently unused) the floating-point version of the mid-side input signal (stereo only) */ FLAC__real *window[FLAC__MAX_APODIZATION_FUNCTIONS]; /* the pre-computed floating-point window for each apodization function */ FLAC__real *windowed_signal; /* the integer_signal[] * current window[] */ #endif uint32_t subframe_bps[FLAC__MAX_CHANNELS]; /* the effective bits per sample of the input signal (stream bps - wasted bits) */ uint32_t subframe_bps_mid_side[2]; /* the effective bits per sample of the mid-side input signal (stream bps - wasted bits + 0/1) */ FLAC__int32 *residual_workspace[FLAC__MAX_CHANNELS][2]; /* each channel has a candidate and best workspace where the subframe residual signals will be stored */ FLAC__int32 *residual_workspace_mid_side[2][2]; FLAC__Subframe subframe_workspace[FLAC__MAX_CHANNELS][2]; FLAC__Subframe subframe_workspace_mid_side[2][2]; FLAC__Subframe *subframe_workspace_ptr[FLAC__MAX_CHANNELS][2]; FLAC__Subframe *subframe_workspace_ptr_mid_side[2][2]; FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace[FLAC__MAX_CHANNELS][2]; FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace_mid_side[FLAC__MAX_CHANNELS][2]; FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr[FLAC__MAX_CHANNELS][2]; FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr_mid_side[FLAC__MAX_CHANNELS][2]; uint32_t best_subframe[FLAC__MAX_CHANNELS]; /* index (0 or 1) into 2nd dimension of the above workspaces */ uint32_t best_subframe_mid_side[2]; uint32_t best_subframe_bits[FLAC__MAX_CHANNELS]; /* size in bits of the best subframe for each channel */ uint32_t best_subframe_bits_mid_side[2]; FLAC__uint64 *abs_residual_partition_sums; /* workspace where the sum of abs(candidate residual) for each partition is stored */ uint32_t *raw_bits_per_partition; /* workspace where the sum of silog2(candidate residual) for each partition is stored */ FLAC__BitWriter *frame; /* the current frame being worked on */ uint32_t loose_mid_side_stereo_frames; /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */ uint32_t loose_mid_side_stereo_frame_count; /* number of frames using the current channel assignment */ FLAC__ChannelAssignment last_channel_assignment; FLAC__StreamMetadata streaminfo; /* scratchpad for STREAMINFO as it is built */ FLAC__StreamMetadata_SeekTable *seek_table; /* pointer into encoder->protected_->metadata_ where the seek table is */ uint32_t current_sample_number; uint32_t current_frame_number; FLAC__MD5Context md5context; FLAC__CPUInfo cpuinfo; void (*local_precompute_partition_info_sums)(const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], uint32_t residual_samples, uint32_t predictor_order, uint32_t min_partition_order, uint32_t max_partition_order, uint32_t bps); #ifndef FLAC__INTEGER_ONLY_LIBRARY uint32_t (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); uint32_t (*local_fixed_compute_best_predictor_wide)(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); #else uint32_t (*local_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 (*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, 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; FLAC__bool is_ogg; FLAC__StreamEncoderReadCallback read_callback; /* currently only needed for Ogg FLAC */ FLAC__StreamEncoderSeekCallback seek_callback; FLAC__StreamEncoderTellCallback tell_callback; FLAC__StreamEncoderWriteCallback write_callback; FLAC__StreamEncoderMetadataCallback metadata_callback; FLAC__StreamEncoderProgressCallback progress_callback; void *client_data; uint32_t first_seekpoint_to_check; FILE *file; /* only used when encoding to a file */ FLAC__uint64 bytes_written; FLAC__uint64 samples_written; uint32_t frames_written; uint32_t total_frames_estimate; /* 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) */ FLAC__real *window_unaligned[FLAC__MAX_APODIZATION_FUNCTIONS]; FLAC__real *windowed_signal_unaligned; #endif FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2]; FLAC__int32 *residual_workspace_mid_side_unaligned[2][2]; FLAC__uint64 *abs_residual_partition_sums_unaligned; uint32_t *raw_bits_per_partition_unaligned; /* * These fields have been moved here from private function local * declarations merely to save stack space during encoding. */ #ifndef FLAC__INTEGER_ONLY_LIBRARY FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */ #endif FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */ /* * The data for the verify section */ struct { FLAC__StreamDecoder *decoder; EncoderStateHint state_hint; FLAC__bool needs_magic_hack; verify_input_fifo input_fifo; verify_output output; struct { FLAC__uint64 absolute_sample; uint32_t frame_number; uint32_t channel; uint32_t sample; FLAC__int32 expected; FLAC__int32 got; } error_stats; } verify; FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */ } FLAC__StreamEncoderPrivate; /*********************************************************************** * * Public static class data * ***********************************************************************/ FLAC_API const char * const FLAC__StreamEncoderStateString[] = { "FLAC__STREAM_ENCODER_OK", "FLAC__STREAM_ENCODER_UNINITIALIZED", "FLAC__STREAM_ENCODER_OGG_ERROR", "FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR", "FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA", "FLAC__STREAM_ENCODER_CLIENT_ERROR", "FLAC__STREAM_ENCODER_IO_ERROR", "FLAC__STREAM_ENCODER_FRAMING_ERROR", "FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR" }; FLAC_API const char * const FLAC__StreamEncoderInitStatusString[] = { "FLAC__STREAM_ENCODER_INIT_STATUS_OK", "FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR", "FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION", "FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER", "FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE", "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA", "FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED" }; FLAC_API const char * const FLAC__StreamEncoderReadStatusString[] = { "FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE", "FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM", "FLAC__STREAM_ENCODER_READ_STATUS_ABORT", "FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED" }; FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = { "FLAC__STREAM_ENCODER_WRITE_STATUS_OK", "FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR" }; FLAC_API const char * const FLAC__StreamEncoderSeekStatusString[] = { "FLAC__STREAM_ENCODER_SEEK_STATUS_OK", "FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR", "FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED" }; FLAC_API const char * const FLAC__StreamEncoderTellStatusString[] = { "FLAC__STREAM_ENCODER_TELL_STATUS_OK", "FLAC__STREAM_ENCODER_TELL_STATUS_ERROR", "FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED" }; /* Number of samples that will be overread to watch for end of stream. By * 'overread', we mean that the FLAC__stream_encoder_process*() calls will * always try to read blocksize+1 samples before encoding a block, so that * even if the stream has a total sample count that is an integral multiple * of the blocksize, we will still notice when we are encoding the last * block. This is needed, for example, to correctly set the end-of-stream * marker in Ogg FLAC. * * WATCHOUT: some parts of the code assert that OVERREAD_ == 1 and there's * not really any reason to change it.