From 7138ab86a8644c60e9b8323e680815cc030943ce Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 13 Apr 2006 22:18:41 +0000 Subject: [PATCH] Updated FLAC code to version 1.1.2. SVN r40 (trunk) --- FLAC/FLAC++/decoder.h | 13 +- FLAC/FLAC++/export.h | 94 +- FLAC/FLAC.vcproj | 10 +- FLAC/FLAC/assert.h | 90 +- FLAC/FLAC/export.h | 94 +- FLAC/FLAC/format.h | 1673 +++++----- FLAC/FLAC/ordinals.h | 154 +- FLAC/FLAC/stream_decoder.h | 1746 +++++------ FLAC/Makefile.mgw | 2 +- FLAC/bitbuffer.c | 5069 ++++++++++++++++--------------- FLAC/bitmath.c | 281 +- FLAC/cpu.c | 310 +- FLAC/crc.c | 298 +- FLAC/fixed.c | 653 ++-- FLAC/format.c | 916 +++--- FLAC/ia32/cpu_asm.nasm | 2 +- FLAC/ia32/fixed_asm.nasm | 24 +- FLAC/ia32/lpc_asm.nasm | 4 +- FLAC/ia32/nasm.h | 2 +- FLAC/lpc.c | 853 +++--- FLAC/memory.c | 357 +-- FLAC/private/bitbuffer.h | 12 +- FLAC/private/bitmath.h | 5 +- FLAC/private/cpu.h | 9 +- FLAC/private/crc.h | 2 +- FLAC/private/fixed.h | 28 +- FLAC/private/format.h | 2 +- FLAC/private/lpc.h | 60 +- FLAC/private/memory.h | 105 +- FLAC/protected/stream_decoder.h | 2 +- FLAC/stream_decoder.c | 4265 +++++++++++++------------- FLAC/stream_decoder_pp.cpp | 444 +-- 32 files changed, 9063 insertions(+), 8516 deletions(-) diff --git a/FLAC/FLAC++/decoder.h b/FLAC/FLAC++/decoder.h index d3ca72fb3..57a6ee650 100644 --- a/FLAC/FLAC++/decoder.h +++ b/FLAC/FLAC++/decoder.h @@ -1,5 +1,5 @@ /* libFLAC++ - Free Lossless Audio Codec library - * Copyright (C) 2002,2003,2004 Josh Coalson + * Copyright (C) 2002,2003,2004,2005 Josh Coalson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -142,7 +142,7 @@ namespace FLAC { virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0; virtual void error_callback(::FLAC__StreamDecoderErrorStatus status) = 0; -#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) +#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC) // lame hack: some MSVC/GCC versions can't see a protected decoder_ from nested State::resolved_as_cstring() friend State; #endif @@ -238,7 +238,7 @@ namespace FLAC { virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0; virtual void error_callback(::FLAC__StreamDecoderErrorStatus status) = 0; -#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) +#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC) // lame hack: some MSVC/GCC versions can't see a protected decoder_ from nested State::resolved_as_cstring() friend State; #endif @@ -331,7 +331,7 @@ namespace FLAC { virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0; virtual void error_callback(::FLAC__StreamDecoderErrorStatus status) = 0; -#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) +#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC) // lame hack: some MSVC/GCC versions can't see a protected decoder_ from nested State::resolved_as_cstring() friend State; #endif @@ -348,7 +348,8 @@ namespace FLAC { /* \} */ #endif // [RH] - }; -}; + + } +} #endif diff --git a/FLAC/FLAC++/export.h b/FLAC/FLAC++/export.h index 262569097..ba4a4b4c8 100644 --- a/FLAC/FLAC++/export.h +++ b/FLAC/FLAC++/export.h @@ -1,47 +1,47 @@ -/* libFLAC++ - Free Lossless Audio Codec library - * Copyright (C) 2002,2003,2004 Josh Coalson - * - * 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. - */ - -#ifndef FLACPP__EXPORT_H -#define FLACPP__EXPORT_H - -#if defined(FLAC__NO_DLL) || !defined(_MSC_VER) || 1 -#define FLACPP_API - -#else - -#ifdef FLACPP_API_EXPORTS -#define FLACPP_API _declspec(dllexport) -#else -#define FLACPP_API _declspec(dllimport) - -#endif -#endif -#endif +/* libFLAC++ - Free Lossless Audio Codec library + * Copyright (C) 2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#ifndef FLACPP__EXPORT_H +#define FLACPP__EXPORT_H + +#if defined(FLAC__NO_DLL) || !defined(_MSC_VER) +#define FLACPP_API + +#else + +#ifdef FLACPP_API_EXPORTS +#define FLACPP_API _declspec(dllexport) +#else +#define FLACPP_API _declspec(dllimport) + +#endif +#endif +#endif diff --git a/FLAC/FLAC.vcproj b/FLAC/FLAC.vcproj index 85599facc..51944ad1f 100644 --- a/FLAC/FLAC.vcproj +++ b/FLAC/FLAC.vcproj @@ -19,7 +19,7 @@ + + + + -#define FLAC__ASSERT(x) assert(x) -#define FLAC__ASSERT_DECLARATION(x) x -#else -#define FLAC__ASSERT(x) -#define FLAC__ASSERT_DECLARATION(x) -#endif - -#endif +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#ifndef FLAC__ASSERT_H +#define FLAC__ASSERT_H + +/* we need this since some compilers (like MSVC) leave assert()s on release code (and we don't want to use their ASSERT) */ +#ifdef DEBUG +#include +#define FLAC__ASSERT(x) assert(x) +#define FLAC__ASSERT_DECLARATION(x) x +#else +#define FLAC__ASSERT(x) +#define FLAC__ASSERT_DECLARATION(x) +#endif + +#endif diff --git a/FLAC/FLAC/export.h b/FLAC/FLAC/export.h index 613af7423..740f6034d 100644 --- a/FLAC/FLAC/export.h +++ b/FLAC/FLAC/export.h @@ -1,47 +1,47 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#ifndef FLAC__EXPORT_H -#define FLAC__EXPORT_H - -#if defined(FLAC__NO_DLL) || !defined(_MSC_VER) || 1 -#define FLAC_API - -#else - -#ifdef FLAC_API_EXPORTS -#define FLAC_API _declspec(dllexport) -#else -#define FLAC_API _declspec(dllimport) - -#endif -#endif -#endif +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#ifndef FLAC__EXPORT_H +#define FLAC__EXPORT_H + +#if defined(FLAC__NO_DLL) || !defined(_MSC_VER) +#define FLAC_API + +#else + +#ifdef FLAC_API_EXPORTS +#define FLAC_API _declspec(dllexport) +#else +#define FLAC_API _declspec(dllimport) + +#endif +#endif +#endif diff --git a/FLAC/FLAC/format.h b/FLAC/FLAC/format.h index e003c34fe..35fa76d1d 100644 --- a/FLAC/FLAC/format.h +++ b/FLAC/FLAC/format.h @@ -1,812 +1,861 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#ifndef FLAC__FORMAT_H -#define FLAC__FORMAT_H - -#include "export.h" -#include "ordinals.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file include/FLAC/format.h - * - * \brief - * This module contains structure definitions for the representation - * of FLAC format components in memory. These are the basic - * structures used by the rest of the interfaces. - * - * See the detailed documentation in the - * \link flac_format format \endlink module. - */ - -/** \defgroup flac_format FLAC/format.h: format components - * \ingroup flac - * - * \brief - * This module contains structure definitions for the representation - * of FLAC format components in memory. These are the basic - * structures used by the rest of the interfaces. - * - * First, you should be familiar with the - * FLAC format. Many of the values here - * follow directly from the specification. As a user of libFLAC, the - * interesting parts really are the structures that describe the frame - * header and metadata blocks. - * - * The format structures here are very primitive, designed to store - * information in an efficient way. Reading information from the - * structures is easy but creating or modifying them directly is - * more complex. For the most part, as a user of a library, editing - * is not necessary; however, for metadata blocks it is, so there are - * convenience functions provided in the \link flac_metadata metadata - * module \endlink to simplify the manipulation of metadata blocks. - * - * \note - * It's not the best convention, but symbols ending in _LEN are in bits - * and _LENGTH are in bytes. _LENGTH symbols are \#defines instead of - * global variables because they are usually used when declaring byte - * arrays and some compilers require compile-time knowledge of array - * sizes when declared on the stack. - * - * \{ - */ - - -/* - Most of the values described in this file are defined by the FLAC - format specification. There is nothing to tune here. -*/ - -/** The largest legal metadata type code. */ -#define FLAC__MAX_METADATA_TYPE_CODE (126u) - -/** The minimum block size, in samples, permitted by the format. */ -#define FLAC__MIN_BLOCK_SIZE (16u) - -/** The maximum block size, in samples, permitted by the format. */ -#define FLAC__MAX_BLOCK_SIZE (65535u) - -/** The maximum number of channels permitted by the format. */ -#define FLAC__MAX_CHANNELS (8u) - -/** The minimum sample resolution permitted by the format. */ -#define FLAC__MIN_BITS_PER_SAMPLE (4u) - -/** The maximum sample resolution permitted by the format. */ -#define FLAC__MAX_BITS_PER_SAMPLE (32u) - -/** 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. - */ -#define FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE (24u) - -/** The maximum sample rate permitted by the format. The value is - * ((2 ^ 16) - 1) * 10; see FLAC format - * as to why. - */ -#define FLAC__MAX_SAMPLE_RATE (655350u) - -/** The maximum LPC order permitted by the format. */ -#define FLAC__MAX_LPC_ORDER (32u) - -/** The minimum quantized linear predictor coefficient precision - * permitted by the format. - */ -#define FLAC__MIN_QLP_COEFF_PRECISION (5u) - -/** The maximum quantized linear predictor coefficient precision - * permitted by the format. - */ -#define FLAC__MAX_QLP_COEFF_PRECISION (15u) - -/** The maximum order of the fixed predictors permitted by the format. */ -#define FLAC__MAX_FIXED_ORDER (4u) - -/** The maximum Rice partition order permitted by the format. */ -#define FLAC__MAX_RICE_PARTITION_ORDER (15u) - -/** The maximum Rice partition order permitted by the FLAC Subset. */ -#define FLAC__SUBSET_MAX_RICE_PARTITION_ORDER (8u) - -/** The version string of the release, stamped onto the libraries and binaries. - * - * \note - * This does not correspond to the shared library version number, which - * is used to determine binary compatibility. - */ -extern FLAC_API const char *FLAC__VERSION_STRING; - -/** The vendor string inserted by the encoder into the VORBIS_COMMENT block. - * This is a nulL-terminated ASCII string; when inserted into the - * VORBIS_COMMENT the trailing null is stripped. - */ -extern FLAC_API const char *FLAC__VENDOR_STRING; - -/** The byte string representation of the beginning of a FLAC stream. */ -extern FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4]; /* = "fLaC" */ - -/** The 32-bit integer big-endian representation of the beginning of - * a FLAC stream. - */ -extern FLAC_API const unsigned FLAC__STREAM_SYNC; /* = 0x664C6143 */ - -/** The length of the FLAC signature in bits. */ -extern FLAC_API const unsigned FLAC__STREAM_SYNC_LEN; /* = 32 bits */ - -/** The length of the FLAC signature in bytes. */ -#define FLAC__STREAM_SYNC_LENGTH (4u) - - -/***************************************************************************** - * - * Subframe structures - * - *****************************************************************************/ - -/*****************************************************************************/ - -/** An enumeration of the available entropy coding methods. */ -typedef enum { - FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE = 0 - /**< Residual is coded by partitioning into contexts, each with it's own - * Rice parameter. */ -} FLAC__EntropyCodingMethodType; - -/** Maps a FLAC__EntropyCodingMethodType to a C string. - * - * Using a FLAC__EntropyCodingMethodType as the index to this array will - * give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[]; - - -/** Contents of a Rice partitioned residual - */ -typedef struct { - - unsigned *parameters; - /**< The Rice parameters for each context. */ - - unsigned *raw_bits; - /**< Widths for escape-coded partitions. */ - - unsigned capacity_by_order; - /**< The capacity of the \a parameters and \a raw_bits arrays - * specified as an order, i.e. the number of array elements - * allocated is 2 ^ \a capacity_by_order. - */ -} FLAC__EntropyCodingMethod_PartitionedRiceContents; - -/** Header for a Rice partitioned residual. (c.f. format specification) - */ -typedef struct { - - unsigned order; - /**< The partition order, i.e. # of contexts = 2 ^ \a order. */ - - const FLAC__EntropyCodingMethod_PartitionedRiceContents *contents; - /**< The context's Rice parameters and/or raw bits. */ - -} FLAC__EntropyCodingMethod_PartitionedRice; - -extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN; /**< == 4 (bits) */ -extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN; /**< == 4 (bits) */ -extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN; /**< == 5 (bits) */ - -extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; -/**< == (1<format specification) - */ -typedef struct { - FLAC__EntropyCodingMethodType type; - union { - FLAC__EntropyCodingMethod_PartitionedRice partitioned_rice; - } data; -} FLAC__EntropyCodingMethod; - -extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN; /**< == 2 (bits) */ - -/*****************************************************************************/ - -/** An enumeration of the available subframe types. */ -typedef enum { - FLAC__SUBFRAME_TYPE_CONSTANT = 0, /**< constant signal */ - FLAC__SUBFRAME_TYPE_VERBATIM = 1, /**< uncompressed signal */ - FLAC__SUBFRAME_TYPE_FIXED = 2, /**< fixed polynomial prediction */ - FLAC__SUBFRAME_TYPE_LPC = 3 /**< linear prediction */ -} FLAC__SubframeType; - -/** Maps a FLAC__SubframeType to a C string. - * - * Using a FLAC__SubframeType as the index to this array will - * give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__SubframeTypeString[]; - - -/** CONSTANT subframe. (c.f. format specification) - */ -typedef struct { - FLAC__int32 value; /**< The constant signal value. */ -} FLAC__Subframe_Constant; - - -/** VERBATIM subframe. (c.f. format specification) - */ -typedef struct { - const FLAC__int32 *data; /**< A pointer to verbatim signal. */ -} FLAC__Subframe_Verbatim; - - -/** FIXED subframe. (c.f. format specification) - */ -typedef struct { - FLAC__EntropyCodingMethod entropy_coding_method; - /**< The residual coding method. */ - - unsigned order; - /**< The polynomial order. */ - - FLAC__int32 warmup[FLAC__MAX_FIXED_ORDER]; - /**< Warmup samples to prime the predictor, length == order. */ - - const FLAC__int32 *residual; - /**< The residual signal, length == (blocksize minus order) samples. */ -} FLAC__Subframe_Fixed; - - -/** LPC subframe. (c.f. format specification) - */ -typedef struct { - FLAC__EntropyCodingMethod entropy_coding_method; - /**< The residual coding method. */ - - unsigned order; - /**< The FIR order. */ - - unsigned qlp_coeff_precision; - /**< Quantized FIR filter coefficient precision in bits. */ - - int quantization_level; - /**< The qlp coeff shift needed. */ - - FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER]; - /**< FIR filter coefficients. */ - - FLAC__int32 warmup[FLAC__MAX_LPC_ORDER]; - /**< Warmup samples to prime the predictor, length == order. */ - - const FLAC__int32 *residual; - /**< The residual signal, length == (blocksize minus order) samples. */ -} FLAC__Subframe_LPC; - -extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN; /**< == 4 (bits) */ -extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN; /**< == 5 (bits) */ - - -/** FLAC subframe structure. (c.f. format specification) - */ -typedef struct { - FLAC__SubframeType type; - union { - FLAC__Subframe_Constant constant; - FLAC__Subframe_Fixed fixed; - FLAC__Subframe_LPC lpc; - FLAC__Subframe_Verbatim verbatim; - } data; - unsigned wasted_bits; -} FLAC__Subframe; - -extern FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN; /**< == 1 (bit) */ -extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN; /**< == 6 (bits) */ -extern FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN; /**< == 1 (bit) */ - -extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK; /* = 0x00 */ -extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK; /* = 0x02 */ -extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK; /* = 0x10 */ -extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK; /* = 0x40 */ - -/*****************************************************************************/ - - -/***************************************************************************** - * - * Frame structures - * - *****************************************************************************/ - -/** An enumeration of the available channel assignments. */ -typedef enum { - FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT = 0, /**< independent channels */ - FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE = 1, /**< left+side stereo */ - FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE = 2, /**< right+side stereo */ - FLAC__CHANNEL_ASSIGNMENT_MID_SIDE = 3 /**< mid+side stereo */ -} FLAC__ChannelAssignment; - -/** Maps a FLAC__ChannelAssignment to a C string. - * - * Using a FLAC__ChannelAssignment as the index to this array will - * give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__ChannelAssignmentString[]; - -/** An enumeration of the possible frame numbering methods. */ -typedef enum { - FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER, /**< number contains the frame number */ - FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER /**< number contains the sample number of first sample in frame */ -} FLAC__FrameNumberType; - -/** Maps a FLAC__FrameNumberType to a C string. - * - * Using a FLAC__FrameNumberType as the index to this array will - * give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__FrameNumberTypeString[]; - - -/** FLAC frame header structure. (c.f. format specification) - */ -typedef struct { - unsigned blocksize; - /**< The number of samples per subframe. */ - - unsigned sample_rate; - /**< The sample rate in Hz. */ - - unsigned channels; - /**< The number of channels (== number of subframes). */ - - FLAC__ChannelAssignment channel_assignment; - /**< The channel assignment for the frame. */ - - unsigned bits_per_sample; - /**< The sample resolution. */ - - FLAC__FrameNumberType number_type; - /**< The numbering scheme used for the frame. */ - - union { - FLAC__uint32 frame_number; - FLAC__uint64 sample_number; - } number; - /**< The frame number or sample number of first sample in frame; - * use the \a number_type value to determine which to use. */ - - FLAC__uint8 crc; - /**< CRC-8 (polynomial = x^8 + x^2 + x^1 + x^0, initialized with 0) - * of the raw frame header bytes, meaning everything before the CRC byte - * including the sync code. - */ -} FLAC__FrameHeader; - -extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC; /**< == 0x3ffe; the frame header sync code */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN; /**< == 14 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN; /**< == 2 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN; /**< == 4 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN; /**< == 4 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN; /**< == 4 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN; /**< == 3 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN; /**< == 1 (bit) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN; /**< == 8 (bits) */ - - -/** FLAC frame footer structure. (c.f. format specification) - */ -typedef struct { - FLAC__uint16 crc; - /**< CRC-16 (polynomial = x^16 + x^15 + x^2 + x^0, initialized with - * 0) of the bytes before the crc, back to and including the frame header - * sync code. - */ -} FLAC__FrameFooter; - -extern FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN; /**< == 16 (bits) */ - - -/** FLAC frame structure. (c.f. format specification) - */ -typedef struct { - FLAC__FrameHeader header; - FLAC__Subframe subframes[FLAC__MAX_CHANNELS]; - FLAC__FrameFooter footer; -} FLAC__Frame; - -/*****************************************************************************/ - - -/***************************************************************************** - * - * Meta-data structures - * - *****************************************************************************/ - -/** An enumeration of the available metadata block types. */ -typedef enum { - - FLAC__METADATA_TYPE_STREAMINFO = 0, - /**< STREAMINFO block */ - - FLAC__METADATA_TYPE_PADDING = 1, - /**< PADDING block */ - - FLAC__METADATA_TYPE_APPLICATION = 2, - /**< APPLICATION block */ - - FLAC__METADATA_TYPE_SEEKTABLE = 3, - /**< SEEKTABLE block */ - - FLAC__METADATA_TYPE_VORBIS_COMMENT = 4, - /**< VORBISCOMMENT block */ - - FLAC__METADATA_TYPE_CUESHEET = 5, - /**< CUESHEET block */ - - FLAC__METADATA_TYPE_UNDEFINED = 6 - /**< marker to denote beginning of undefined type range; this number will increase as new metadata types are added */ - -} FLAC__MetadataType; - -/** Maps a FLAC__MetadataType to a C string. - * - * Using a FLAC__MetadataType as the index to this array will - * give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__MetadataTypeString[]; - - -/** FLAC STREAMINFO structure. (c.f. format specification) - */ -typedef struct { - unsigned min_blocksize, max_blocksize; - unsigned min_framesize, max_framesize; - unsigned sample_rate; - unsigned channels; - unsigned bits_per_sample; - FLAC__uint64 total_samples; - FLAC__byte md5sum[16]; -} FLAC__StreamMetadata_StreamInfo; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN; /**< == 16 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN; /**< == 16 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN; /**< == 24 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN; /**< == 24 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN; /**< == 20 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN; /**< == 3 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN; /**< == 5 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN; /**< == 36 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN; /**< == 128 (bits) */ - -/** The total stream length of the STREAMINFO block in bytes. */ -#define FLAC__STREAM_METADATA_STREAMINFO_LENGTH (34u) - -/** FLAC PADDING structure. (c.f. format specification) - */ -typedef struct { - int dummy; - /**< Conceptually this is an empty struct since we don't store the - * padding bytes. Empty structs are not allowed by some C compilers, - * hence the dummy. - */ -} FLAC__StreamMetadata_Padding; - - -/** FLAC APPLICATION structure. (c.f. format specification) - */ -typedef struct { - FLAC__byte id[4]; - FLAC__byte *data; -} FLAC__StreamMetadata_Application; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN; /**< == 32 (bits) */ - -/** SeekPoint structure used in SEEKTABLE blocks. (c.f. format specification) - */ -typedef struct { - FLAC__uint64 sample_number; - /**< The sample number of the target frame. */ - - FLAC__uint64 stream_offset; - /**< The offset, in bytes, of the target frame with respect to - * beginning of the first frame. */ - - unsigned frame_samples; - /**< The number of samples in the target frame. */ -} FLAC__StreamMetadata_SeekPoint; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN; /**< == 64 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN; /**< == 64 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN; /**< == 16 (bits) */ - -/** The total stream length of a seek point in bytes. */ -#define FLAC__STREAM_METADATA_SEEKPOINT_LENGTH (18u) - -/** The value used in the \a sample_number field of - * FLAC__StreamMetadataSeekPoint used to indicate a placeholder - * point (== 0xffffffffffffffff). - */ -extern FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; - - -/** FLAC SEEKTABLE structure. (c.f. format specification) - * - * \note From the format specification: - * - The seek points must be sorted by ascending sample number. - * - Each seek point's sample number must be the first sample of the - * target frame. - * - Each seek point's sample number must be unique within the table. - * - Existence of a SEEKTABLE block implies a correct setting of - * total_samples in the stream_info block. - * - Behavior is undefined when more than one SEEKTABLE block is - * present in a stream. - */ -typedef struct { - unsigned num_points; - FLAC__StreamMetadata_SeekPoint *points; -} FLAC__StreamMetadata_SeekTable; - - -/** Vorbis comment entry structure used in VORBIS_COMMENT blocks. (c.f. format specification) - */ -typedef struct { - FLAC__uint32 length; - FLAC__byte *entry; -} FLAC__StreamMetadata_VorbisComment_Entry; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN; /**< == 32 (bits) */ - - -/** FLAC VORBIS_COMMENT structure. (c.f. format specification) - */ -typedef struct { - FLAC__StreamMetadata_VorbisComment_Entry vendor_string; - FLAC__uint32 num_comments; - FLAC__StreamMetadata_VorbisComment_Entry *comments; -} FLAC__StreamMetadata_VorbisComment; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN; /**< == 32 (bits) */ - - -/** FLAC CUESHEET track index structure. (See the - * format specification for - * the full description of each field.) - */ -typedef struct { - FLAC__uint64 offset; - /**< Offset in samples, relative to the track offset, of the index - * point. - */ - - FLAC__byte number; - /**< The index point number. */ -} FLAC__StreamMetadata_CueSheet_Index; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN; /**< == 64 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN; /**< == 8 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN; /**< == 3*8 (bits) */ - - -/** FLAC CUESHEET track structure. (See the - * format specification for - * the full description of each field.) - */ -typedef struct { - FLAC__uint64 offset; - /**< Track offset in samples, relative to the beginning of the FLAC audio stream. */ - - FLAC__byte number; - /**< The track number. */ - - char isrc[13]; - /**< Track ISRC. This is a 12-digit alphanumeric code plus a trailing '\0' */ - - unsigned type:1; - /**< The track type: 0 for audio, 1 for non-audio. */ - - unsigned pre_emphasis:1; - /**< The pre-emphasis flag: 0 for no pre-emphasis, 1 for pre-emphasis. */ - - FLAC__byte num_indices; - /**< The number of track index points. */ - - FLAC__StreamMetadata_CueSheet_Index *indices; - /**< NULL if num_indices == 0, else pointer to array of index points. */ - -} FLAC__StreamMetadata_CueSheet_Track; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN; /**< == 64 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN; /**< == 8 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN; /**< == 12*8 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN; /**< == 1 (bit) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN; /**< == 1 (bit) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN; /**< == 6+13*8 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN; /**< == 8 (bits) */ - - -/** FLAC CUESHEET structure. (See the - * format specification - * for the full description of each field.) - */ -typedef struct { - char media_catalog_number[129]; - /**< Media catalog number, in ASCII printable characters 0x20-0x7e. In - * general, the media catalog number may be 0 to 128 bytes long; any - * unused characters should be right-padded with NUL characters. - */ - - FLAC__uint64 lead_in; - /**< The number of lead-in samples. */ - - FLAC__bool is_cd; - /**< \c true if CUESHEET corresponds to a Compact Disc, else \c false */ - - unsigned num_tracks; - /**< The number of tracks. */ - - FLAC__StreamMetadata_CueSheet_Track *tracks; - /**< NULL if num_tracks == 0, else pointer to array of tracks. */ - -} FLAC__StreamMetadata_CueSheet; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN; /**< == 128*8 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN; /**< == 64 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN; /**< == 1 (bit) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN; /**< == 7+258*8 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN; /**< == 8 (bits) */ - - -/** Structure that is used when a metadata block of unknown type is loaded. - * The contents are opaque. The structure is used only internally to - * correctly handle unknown metadata. - */ -typedef struct { - FLAC__byte *data; -} FLAC__StreamMetadata_Unknown; - - -/** FLAC metadata block structure. (c.f. format specification) - */ -typedef struct { - 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 - * then \a data.unknown must be used. */ - - FLAC__bool is_last; - /**< \c true if this metadata block is the last, else \a false */ - - unsigned length; - /**< Length, in bytes, of the block data as it appears in the stream. */ - - union { - FLAC__StreamMetadata_StreamInfo stream_info; - FLAC__StreamMetadata_Padding padding; - FLAC__StreamMetadata_Application application; - FLAC__StreamMetadata_SeekTable seek_table; - FLAC__StreamMetadata_VorbisComment vorbis_comment; - FLAC__StreamMetadata_CueSheet cue_sheet; - FLAC__StreamMetadata_Unknown unknown; - } data; - /**< Polymorphic block data; use the \a type value to determine which - * to use. */ -} FLAC__StreamMetadata; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN; /**< == 1 (bit) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN; /**< == 7 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN; /**< == 24 (bits) */ - -/** The total stream length of a metadata block header in bytes. */ -#define FLAC__STREAM_METADATA_HEADER_LENGTH (4u) - -/*****************************************************************************/ - - -/***************************************************************************** - * - * Utility functions - * - *****************************************************************************/ - -/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ -/** Tests that a sample rate is valid for FLAC. Since the rules for valid - * sample rates are slightly complex, they are encapsulated in this function. - * - * \param sample_rate The sample rate to test for compliance. - * \retval FLAC__bool - * \c true if the given sample rate conforms to the specification, else - * \c false. - */ -FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate); - -/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ -/** Check a seek table to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * seek table. - * - * \param seek_table A pointer to a seek table to be checked. - * \assert - * \code seek_table != NULL \endcode - * \retval FLAC__bool - * \c false if seek table is illegal, else \c true. - */ -FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table); - -/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ -/** Sort a seek table's seek points according to the format specification. - * This includes a "unique-ification" step to remove duplicates, i.e. - * seek points with identical \a sample_number values. Duplicate seek - * points are converted into placeholder points and sorted to the end of - * the table. - * - * \param seek_table A pointer to a seek table to be sorted. - * \assert - * \code seek_table != NULL \endcode - * \retval unsigned - * The number of duplicate seek points converted into placeholders. - */ -FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table); - -/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ -/** Check a cue sheet to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * cue sheet. - * - * \param cue_sheet A pointer to an existing cue sheet to be checked. - * \param check_cd_da_subset If \c true, check CUESHEET against more - * stringent requirements for a CD-DA (audio) disc. - * \param violation Address of a pointer to a string. If there is a - * violation, a pointer to a string explanation of the - * violation will be returned here. \a violation may be - * \c NULL if you don't need the returned string. Do not - * free the returned string; it will always point to static - * data. - * \assert - * \code cue_sheet != NULL \endcode - * \retval FLAC__bool - * \c false if cue sheet is illegal, else \c true. - */ -FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation); - -/* \} */ - -#ifdef __cplusplus -} -#endif - -#endif +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#ifndef FLAC__FORMAT_H +#define FLAC__FORMAT_H + +#include "export.h" +#include "ordinals.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file include/FLAC/format.h + * + * \brief + * This module contains structure definitions for the representation + * of FLAC format components in memory. These are the basic + * structures used by the rest of the interfaces. + * + * See the detailed documentation in the + * \link flac_format format \endlink module. + */ + +/** \defgroup flac_format FLAC/format.h: format components + * \ingroup flac + * + * \brief + * This module contains structure definitions for the representation + * of FLAC format components in memory. These are the basic + * structures used by the rest of the interfaces. + * + * First, you should be familiar with the + * FLAC format. Many of the values here + * follow directly from the specification. As a user of libFLAC, the + * interesting parts really are the structures that describe the frame + * header and metadata blocks. + * + * The format structures here are very primitive, designed to store + * information in an efficient way. Reading information from the + * structures is easy but creating or modifying them directly is + * more complex. For the most part, as a user of a library, editing + * is not necessary; however, for metadata blocks it is, so there are + * convenience functions provided in the \link flac_metadata metadata + * module \endlink to simplify the manipulation of metadata blocks. + * + * \note + * It's not the best convention, but symbols ending in _LEN are in bits + * and _LENGTH are in bytes. _LENGTH symbols are \#defines instead of + * global variables because they are usually used when declaring byte + * arrays and some compilers require compile-time knowledge of array + * sizes when declared on the stack. + * + * \{ + */ + + +/* + Most of the values described in this file are defined by the FLAC + format specification. There is nothing to tune here. +*/ + +/** The largest legal metadata type code. */ +#define FLAC__MAX_METADATA_TYPE_CODE (126u) + +/** The minimum block size, in samples, permitted by the format. */ +#define FLAC__MIN_BLOCK_SIZE (16u) + +/** The maximum block size, in samples, permitted by the format. */ +#define FLAC__MAX_BLOCK_SIZE (65535u) + +/** The maximum number of channels permitted by the format. */ +#define FLAC__MAX_CHANNELS (8u) + +/** The minimum sample resolution permitted by the format. */ +#define FLAC__MIN_BITS_PER_SAMPLE (4u) + +/** The maximum sample resolution permitted by the format. */ +#define FLAC__MAX_BITS_PER_SAMPLE (32u) + +/** 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. + */ +#define FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE (24u) + +/** The maximum sample rate permitted by the format. The value is + * ((2 ^ 16) - 1) * 10; see FLAC format + * as to why. + */ +#define FLAC__MAX_SAMPLE_RATE (655350u) + +/** The maximum LPC order permitted by the format. */ +#define FLAC__MAX_LPC_ORDER (32u) + +/** The minimum quantized linear predictor coefficient precision + * permitted by the format. + */ +#define FLAC__MIN_QLP_COEFF_PRECISION (5u) + +/** The maximum quantized linear predictor coefficient precision + * permitted by the format. + */ +#define FLAC__MAX_QLP_COEFF_PRECISION (15u) + +/** The maximum order of the fixed predictors permitted by the format. */ +#define FLAC__MAX_FIXED_ORDER (4u) + +/** The maximum Rice partition order permitted by the format. */ +#define FLAC__MAX_RICE_PARTITION_ORDER (15u) + +/** The maximum Rice partition order permitted by the FLAC Subset. */ +#define FLAC__SUBSET_MAX_RICE_PARTITION_ORDER (8u) + +/** The version string of the release, stamped onto the libraries and binaries. + * + * \note + * This does not correspond to the shared library version number, which + * is used to determine binary compatibility. + */ +extern FLAC_API const char *FLAC__VERSION_STRING; + +/** The vendor string inserted by the encoder into the VORBIS_COMMENT block. + * This is a NUL-terminated ASCII string; when inserted into the + * VORBIS_COMMENT the trailing null is stripped. + */ +extern FLAC_API const char *FLAC__VENDOR_STRING; + +/** The byte string representation of the beginning of a FLAC stream. */ +extern FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4]; /* = "fLaC" */ + +/** The 32-bit integer big-endian representation of the beginning of + * a FLAC stream. + */ +extern FLAC_API const unsigned FLAC__STREAM_SYNC; /* = 0x664C6143 */ + +/** The length of the FLAC signature in bits. */ +extern FLAC_API const unsigned FLAC__STREAM_SYNC_LEN; /* = 32 bits */ + +/** The length of the FLAC signature in bytes. */ +#define FLAC__STREAM_SYNC_LENGTH (4u) + + +/***************************************************************************** + * + * Subframe structures + * + *****************************************************************************/ + +/*****************************************************************************/ + +/** An enumeration of the available entropy coding methods. */ +typedef enum { + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE = 0 + /**< Residual is coded by partitioning into contexts, each with it's own + * Rice parameter. */ +} FLAC__EntropyCodingMethodType; + +/** Maps a FLAC__EntropyCodingMethodType to a C string. + * + * Using a FLAC__EntropyCodingMethodType as the index to this array will + * give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[]; + + +/** Contents of a Rice partitioned residual + */ +typedef struct { + + unsigned *parameters; + /**< The Rice parameters for each context. */ + + unsigned *raw_bits; + /**< Widths for escape-coded partitions. */ + + unsigned capacity_by_order; + /**< The capacity of the \a parameters and \a raw_bits arrays + * specified as an order, i.e. the number of array elements + * allocated is 2 ^ \a capacity_by_order. + */ +} FLAC__EntropyCodingMethod_PartitionedRiceContents; + +/** Header for a Rice partitioned residual. (c.f. format specification) + */ +typedef struct { + + unsigned order; + /**< The partition order, i.e. # of contexts = 2 ^ \a order. */ + + const FLAC__EntropyCodingMethod_PartitionedRiceContents *contents; + /**< The context's Rice parameters and/or raw bits. */ + +} FLAC__EntropyCodingMethod_PartitionedRice; + +extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN; /**< == 4 (bits) */ +extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN; /**< == 4 (bits) */ +extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN; /**< == 5 (bits) */ + +extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; +/**< == (1<format specification) + */ +typedef struct { + FLAC__EntropyCodingMethodType type; + union { + FLAC__EntropyCodingMethod_PartitionedRice partitioned_rice; + } data; +} FLAC__EntropyCodingMethod; + +extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN; /**< == 2 (bits) */ + +/*****************************************************************************/ + +/** An enumeration of the available subframe types. */ +typedef enum { + FLAC__SUBFRAME_TYPE_CONSTANT = 0, /**< constant signal */ + FLAC__SUBFRAME_TYPE_VERBATIM = 1, /**< uncompressed signal */ + FLAC__SUBFRAME_TYPE_FIXED = 2, /**< fixed polynomial prediction */ + FLAC__SUBFRAME_TYPE_LPC = 3 /**< linear prediction */ +} FLAC__SubframeType; + +/** Maps a FLAC__SubframeType to a C string. + * + * Using a FLAC__SubframeType as the index to this array will + * give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__SubframeTypeString[]; + + +/** CONSTANT subframe. (c.f. format specification) + */ +typedef struct { + FLAC__int32 value; /**< The constant signal value. */ +} FLAC__Subframe_Constant; + + +/** VERBATIM subframe. (c.f. format specification) + */ +typedef struct { + const FLAC__int32 *data; /**< A pointer to verbatim signal. */ +} FLAC__Subframe_Verbatim; + + +/** FIXED subframe. (c.f. format specification) + */ +typedef struct { + FLAC__EntropyCodingMethod entropy_coding_method; + /**< The residual coding method. */ + + unsigned order; + /**< The polynomial order. */ + + FLAC__int32 warmup[FLAC__MAX_FIXED_ORDER]; + /**< Warmup samples to prime the predictor, length == order. */ + + const FLAC__int32 *residual; + /**< The residual signal, length == (blocksize minus order) samples. */ +} FLAC__Subframe_Fixed; + + +/** LPC subframe. (c.f. format specification) + */ +typedef struct { + FLAC__EntropyCodingMethod entropy_coding_method; + /**< The residual coding method. */ + + unsigned order; + /**< The FIR order. */ + + unsigned qlp_coeff_precision; + /**< Quantized FIR filter coefficient precision in bits. */ + + int quantization_level; + /**< The qlp coeff shift needed. */ + + FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER]; + /**< FIR filter coefficients. */ + + FLAC__int32 warmup[FLAC__MAX_LPC_ORDER]; + /**< Warmup samples to prime the predictor, length == order. */ + + const FLAC__int32 *residual; + /**< The residual signal, length == (blocksize minus order) samples. */ +} FLAC__Subframe_LPC; + +extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN; /**< == 4 (bits) */ +extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN; /**< == 5 (bits) */ + + +/** FLAC subframe structure. (c.f. format specification) + */ +typedef struct { + FLAC__SubframeType type; + union { + FLAC__Subframe_Constant constant; + FLAC__Subframe_Fixed fixed; + FLAC__Subframe_LPC lpc; + FLAC__Subframe_Verbatim verbatim; + } data; + unsigned wasted_bits; +} FLAC__Subframe; + +extern FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN; /**< == 1 (bit) */ +extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN; /**< == 6 (bits) */ +extern FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN; /**< == 1 (bit) */ + +extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK; /* = 0x00 */ +extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK; /* = 0x02 */ +extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK; /* = 0x10 */ +extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK; /* = 0x40 */ + +/*****************************************************************************/ + + +/***************************************************************************** + * + * Frame structures + * + *****************************************************************************/ + +/** An enumeration of the available channel assignments. */ +typedef enum { + FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT = 0, /**< independent channels */ + FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE = 1, /**< left+side stereo */ + FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE = 2, /**< right+side stereo */ + FLAC__CHANNEL_ASSIGNMENT_MID_SIDE = 3 /**< mid+side stereo */ +} FLAC__ChannelAssignment; + +/** Maps a FLAC__ChannelAssignment to a C string. + * + * Using a FLAC__ChannelAssignment as the index to this array will + * give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__ChannelAssignmentString[]; + +/** An enumeration of the possible frame numbering methods. */ +typedef enum { + FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER, /**< number contains the frame number */ + FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER /**< number contains the sample number of first sample in frame */ +} FLAC__FrameNumberType; + +/** Maps a FLAC__FrameNumberType to a C string. + * + * Using a FLAC__FrameNumberType as the index to this array will + * give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__FrameNumberTypeString[]; + + +/** FLAC frame header structure. (c.f. format specification) + */ +typedef struct { + unsigned blocksize; + /**< The number of samples per subframe. */ + + unsigned sample_rate; + /**< The sample rate in Hz. */ + + unsigned channels; + /**< The number of channels (== number of subframes). */ + + FLAC__ChannelAssignment channel_assignment; + /**< The channel assignment for the frame. */ + + unsigned bits_per_sample; + /**< The sample resolution. */ + + FLAC__FrameNumberType number_type; + /**< The numbering scheme used for the frame. */ + + union { + FLAC__uint32 frame_number; + FLAC__uint64 sample_number; + } number; + /**< The frame number or sample number of first sample in frame; + * use the \a number_type value to determine which to use. */ + + FLAC__uint8 crc; + /**< CRC-8 (polynomial = x^8 + x^2 + x^1 + x^0, initialized with 0) + * of the raw frame header bytes, meaning everything before the CRC byte + * including the sync code. + */ +} FLAC__FrameHeader; + +extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC; /**< == 0x3ffe; the frame header sync code */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN; /**< == 14 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN; /**< == 2 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN; /**< == 4 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN; /**< == 4 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN; /**< == 4 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN; /**< == 3 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN; /**< == 1 (bit) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN; /**< == 8 (bits) */ + + +/** FLAC frame footer structure. (c.f. format specification) + */ +typedef struct { + FLAC__uint16 crc; + /**< CRC-16 (polynomial = x^16 + x^15 + x^2 + x^0, initialized with + * 0) of the bytes before the crc, back to and including the frame header + * sync code. + */ +} FLAC__FrameFooter; + +extern FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN; /**< == 16 (bits) */ + + +/** FLAC frame structure. (c.f. format specification) + */ +typedef struct { + FLAC__FrameHeader header; + FLAC__Subframe subframes[FLAC__MAX_CHANNELS]; + FLAC__FrameFooter footer; +} FLAC__Frame; + +/*****************************************************************************/ + + +/***************************************************************************** + * + * Meta-data structures + * + *****************************************************************************/ + +/** An enumeration of the available metadata block types. */ +typedef enum { + + FLAC__METADATA_TYPE_STREAMINFO = 0, + /**< STREAMINFO block */ + + FLAC__METADATA_TYPE_PADDING = 1, + /**< PADDING block */ + + FLAC__METADATA_TYPE_APPLICATION = 2, + /**< APPLICATION block */ + + FLAC__METADATA_TYPE_SEEKTABLE = 3, + /**< SEEKTABLE block */ + + FLAC__METADATA_TYPE_VORBIS_COMMENT = 4, + /**< VORBISCOMMENT block (a.k.a. FLAC tags) */ + + FLAC__METADATA_TYPE_CUESHEET = 5, + /**< CUESHEET block */ + + FLAC__METADATA_TYPE_UNDEFINED = 6 + /**< marker to denote beginning of undefined type range; this number will increase as new metadata types are added */ + +} FLAC__MetadataType; + +/** Maps a FLAC__MetadataType to a C string. + * + * Using a FLAC__MetadataType as the index to this array will + * give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__MetadataTypeString[]; + + +/** FLAC STREAMINFO structure. (c.f. format specification) + */ +typedef struct { + unsigned min_blocksize, max_blocksize; + unsigned min_framesize, max_framesize; + unsigned sample_rate; + unsigned channels; + unsigned bits_per_sample; + FLAC__uint64 total_samples; + FLAC__byte md5sum[16]; +} FLAC__StreamMetadata_StreamInfo; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN; /**< == 16 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN; /**< == 16 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN; /**< == 24 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN; /**< == 24 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN; /**< == 20 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN; /**< == 3 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN; /**< == 5 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN; /**< == 36 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN; /**< == 128 (bits) */ + +/** The total stream length of the STREAMINFO block in bytes. */ +#define FLAC__STREAM_METADATA_STREAMINFO_LENGTH (34u) + +/** FLAC PADDING structure. (c.f. format specification) + */ +typedef struct { + int dummy; + /**< Conceptually this is an empty struct since we don't store the + * padding bytes. Empty structs are not allowed by some C compilers, + * hence the dummy. + */ +} FLAC__StreamMetadata_Padding; + + +/** FLAC APPLICATION structure. (c.f. format specification) + */ +typedef struct { + FLAC__byte id[4]; + FLAC__byte *data; +} FLAC__StreamMetadata_Application; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN; /**< == 32 (bits) */ + +/** SeekPoint structure used in SEEKTABLE blocks. (c.f. format specification) + */ +typedef struct { + FLAC__uint64 sample_number; + /**< The sample number of the target frame. */ + + FLAC__uint64 stream_offset; + /**< The offset, in bytes, of the target frame with respect to + * beginning of the first frame. */ + + unsigned frame_samples; + /**< The number of samples in the target frame. */ +} FLAC__StreamMetadata_SeekPoint; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN; /**< == 64 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN; /**< == 64 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN; /**< == 16 (bits) */ + +/** The total stream length of a seek point in bytes. */ +#define FLAC__STREAM_METADATA_SEEKPOINT_LENGTH (18u) + +/** The value used in the \a sample_number field of + * FLAC__StreamMetadataSeekPoint used to indicate a placeholder + * point (== 0xffffffffffffffff). + */ +extern FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; + + +/** FLAC SEEKTABLE structure. (c.f. format specification) + * + * \note From the format specification: + * - The seek points must be sorted by ascending sample number. + * - Each seek point's sample number must be the first sample of the + * target frame. + * - Each seek point's sample number must be unique within the table. + * - Existence of a SEEKTABLE block implies a correct setting of + * total_samples in the stream_info block. + * - Behavior is undefined when more than one SEEKTABLE block is + * present in a stream. + */ +typedef struct { + unsigned num_points; + FLAC__StreamMetadata_SeekPoint *points; +} FLAC__StreamMetadata_SeekTable; + + +/** Vorbis comment entry structure used in VORBIS_COMMENT blocks. (c.f. format specification) + * + * For convenience, the APIs maintain a trailing NUL character at the end of + * \a entry which is not counted toward \a length, i.e. + * \code strlen(entry) == length \endcode + */ +typedef struct { + FLAC__uint32 length; + FLAC__byte *entry; +} FLAC__StreamMetadata_VorbisComment_Entry; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN; /**< == 32 (bits) */ + + +/** FLAC VORBIS_COMMENT structure. (c.f. format specification) + */ +typedef struct { + FLAC__StreamMetadata_VorbisComment_Entry vendor_string; + FLAC__uint32 num_comments; + FLAC__StreamMetadata_VorbisComment_Entry *comments; +} FLAC__StreamMetadata_VorbisComment; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN; /**< == 32 (bits) */ + + +/** FLAC CUESHEET track index structure. (See the + * format specification for + * the full description of each field.) + */ +typedef struct { + FLAC__uint64 offset; + /**< Offset in samples, relative to the track offset, of the index + * point. + */ + + FLAC__byte number; + /**< The index point number. */ +} FLAC__StreamMetadata_CueSheet_Index; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN; /**< == 64 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN; /**< == 8 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN; /**< == 3*8 (bits) */ + + +/** FLAC CUESHEET track structure. (See the + * format specification for + * the full description of each field.) + */ +typedef struct { + FLAC__uint64 offset; + /**< Track offset in samples, relative to the beginning of the FLAC audio stream. */ + + FLAC__byte number; + /**< The track number. */ + + char isrc[13]; + /**< Track ISRC. This is a 12-digit alphanumeric code plus a trailing '\0' */ + + unsigned type:1; + /**< The track type: 0 for audio, 1 for non-audio. */ + + unsigned pre_emphasis:1; + /**< The pre-emphasis flag: 0 for no pre-emphasis, 1 for pre-emphasis. */ + + FLAC__byte num_indices; + /**< The number of track index points. */ + + FLAC__StreamMetadata_CueSheet_Index *indices; + /**< NULL if num_indices == 0, else pointer to array of index points. */ + +} FLAC__StreamMetadata_CueSheet_Track; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN; /**< == 64 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN; /**< == 8 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN; /**< == 12*8 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN; /**< == 1 (bit) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN; /**< == 1 (bit) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN; /**< == 6+13*8 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN; /**< == 8 (bits) */ + + +/** FLAC CUESHEET structure. (See the + * format specification + * for the full description of each field.) + */ +typedef struct { + char media_catalog_number[129]; + /**< Media catalog number, in ASCII printable characters 0x20-0x7e. In + * general, the media catalog number may be 0 to 128 bytes long; any + * unused characters should be right-padded with NUL characters. + */ + + FLAC__uint64 lead_in; + /**< The number of lead-in samples. */ + + FLAC__bool is_cd; + /**< \c true if CUESHEET corresponds to a Compact Disc, else \c false */ + + unsigned num_tracks; + /**< The number of tracks. */ + + FLAC__StreamMetadata_CueSheet_Track *tracks; + /**< NULL if num_tracks == 0, else pointer to array of tracks. */ + +} FLAC__StreamMetadata_CueSheet; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN; /**< == 128*8 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN; /**< == 64 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN; /**< == 1 (bit) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN; /**< == 7+258*8 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN; /**< == 8 (bits) */ + + +/** Structure that is used when a metadata block of unknown type is loaded. + * The contents are opaque. The structure is used only internally to + * correctly handle unknown metadata. + */ +typedef struct { + FLAC__byte *data; +} FLAC__StreamMetadata_Unknown; + + +/** FLAC metadata block structure. (c.f. format specification) + */ +typedef struct { + 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 + * then \a data.unknown must be used. */ + + FLAC__bool is_last; + /**< \c true if this metadata block is the last, else \a false */ + + unsigned length; + /**< Length, in bytes, of the block data as it appears in the stream. */ + + union { + FLAC__StreamMetadata_StreamInfo stream_info; + FLAC__StreamMetadata_Padding padding; + FLAC__StreamMetadata_Application application; + FLAC__StreamMetadata_SeekTable seek_table; + FLAC__StreamMetadata_VorbisComment vorbis_comment; + FLAC__StreamMetadata_CueSheet cue_sheet; + FLAC__StreamMetadata_Unknown unknown; + } data; + /**< Polymorphic block data; use the \a type value to determine which + * to use. */ +} FLAC__StreamMetadata; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN; /**< == 1 (bit) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN; /**< == 7 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN; /**< == 24 (bits) */ + +/** The total stream length of a metadata block header in bytes. */ +#define FLAC__STREAM_METADATA_HEADER_LENGTH (4u) + +/*****************************************************************************/ + + +/***************************************************************************** + * + * Utility functions + * + *****************************************************************************/ + +/** Tests that a sample rate is valid for FLAC. Since the rules for valid + * sample rates are slightly complex, they are encapsulated in this function. + * + * \param sample_rate The sample rate to test for compliance. + * \retval FLAC__bool + * \c true if the given sample rate conforms to the specification, else + * \c false. + */ +FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate); + +/** Check a Vorbis comment entry name to see if it conforms to the Vorbis + * comment specification. + * + * Vorbis comment names must be composed only of characters from + * [0x20-0x3C,0x3E-0x7D]. + * + * \param name A NUL-terminated string to be checked. + * \assert + * \code name != NULL \endcode + * \retval FLAC__bool + * \c false if entry name is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_name_is_legal(const char *name); + +/** Check a Vorbis comment entry value to see if it conforms to the Vorbis + * comment specification. + * + * Vorbis comment values must be valid UTF-8 sequences. + * + * \param value A string to be checked. + * \param length A the length of \a value in bytes. May be + * \c (unsigned)(-1) to indicate that \a value is a plain + * UTF-8 NUL-terminated string. + * \assert + * \code value != NULL \endcode + * \retval FLAC__bool + * \c false if entry name is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, unsigned length); + +/** Check a Vorbis comment entry to see if it conforms to the Vorbis + * comment specification. + * + * Vorbis comment entries must be of the form 'name=value', and 'name' and + * 'value' must be legal according to + * FLAC__format_vorbiscomment_entry_name_is_legal() and + * FLAC__format_vorbiscomment_entry_value_is_legal() respectively. + * + * \param value A string to be checked. + * \assert + * \code value != NULL \endcode + * \retval FLAC__bool + * \c false if entry name is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, unsigned length); + +/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ +/** Check a seek table to see if it conforms to the FLAC specification. + * See the format specification for limits on the contents of the + * seek table. + * + * \param seek_table A pointer to a seek table to be checked. + * \assert + * \code seek_table != NULL \endcode + * \retval FLAC__bool + * \c false if seek table is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table); + +/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ +/** Sort a seek table's seek points according to the format specification. + * This includes a "unique-ification" step to remove duplicates, i.e. + * seek points with identical \a sample_number values. Duplicate seek + * points are converted into placeholder points and sorted to the end of + * the table. + * + * \param seek_table A pointer to a seek table to be sorted. + * \assert + * \code seek_table != NULL \endcode + * \retval unsigned + * The number of duplicate seek points converted into placeholders. + */ +FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table); + +/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ +/** Check a cue sheet to see if it conforms to the FLAC specification. + * See the format specification for limits on the contents of the + * cue sheet. + * + * \param cue_sheet A pointer to an existing cue sheet to be checked. + * \param check_cd_da_subset If \c true, check CUESHEET against more + * stringent requirements for a CD-DA (audio) disc. + * \param violation Address of a pointer to a string. If there is a + * violation, a pointer to a string explanation of the + * violation will be returned here. \a violation may be + * \c NULL if you don't need the returned string. Do not + * free the returned string; it will always point to static + * data. + * \assert + * \code cue_sheet != NULL \endcode + * \retval FLAC__bool + * \c false if cue sheet is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation); + +/* \} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/FLAC/FLAC/ordinals.h b/FLAC/FLAC/ordinals.h index 77ec76085..6160dcd72 100644 --- a/FLAC/FLAC/ordinals.h +++ b/FLAC/FLAC/ordinals.h @@ -1,74 +1,80 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#ifndef FLAC__ORDINALS_H -#define FLAC__ORDINALS_H - -#ifndef _MSC_VER -#include -#endif - -typedef signed char FLAC__int8; -typedef unsigned char FLAC__uint8; - -#if defined _MSC_VER -typedef __int16 FLAC__int16; -typedef __int32 FLAC__int32; -typedef __int64 FLAC__int64; -typedef unsigned __int16 FLAC__uint16; -typedef unsigned __int32 FLAC__uint32; -typedef unsigned __int64 FLAC__uint64; -#else -typedef int16_t FLAC__int16; -typedef int32_t FLAC__int32; -typedef int64_t FLAC__int64; -typedef uint16_t FLAC__uint16; -typedef uint32_t FLAC__uint32; -typedef uint64_t FLAC__uint64; -#endif - -typedef int FLAC__bool; - -typedef FLAC__uint8 FLAC__byte; -typedef float FLAC__real; - -#ifdef true -#undef true -#endif -#ifdef false -#undef false -#endif -#ifndef __cplusplus -#define true 1 -#define false 0 -#endif - -#endif +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#ifndef FLAC__ORDINALS_H +#define FLAC__ORDINALS_H + +#if !(defined(_MSC_VER) || defined(__EMX__)) +#include +#endif + +typedef signed char FLAC__int8; +typedef unsigned char FLAC__uint8; + +#if defined _MSC_VER +typedef __int16 FLAC__int16; +typedef __int32 FLAC__int32; +typedef __int64 FLAC__int64; +typedef unsigned __int16 FLAC__uint16; +typedef unsigned __int32 FLAC__uint32; +typedef unsigned __int64 FLAC__uint64; +#elif defined(__EMX__) +typedef short FLAC__int16; +typedef long FLAC__int32; +typedef long long FLAC__int64; +typedef unsigned short FLAC__uint16; +typedef unsigned long FLAC__uint32; +typedef unsigned long long FLAC__uint64; +#else +typedef int16_t FLAC__int16; +typedef int32_t FLAC__int32; +typedef int64_t FLAC__int64; +typedef uint16_t FLAC__uint16; +typedef uint32_t FLAC__uint32; +typedef uint64_t FLAC__uint64; +#endif + +typedef int FLAC__bool; + +typedef FLAC__uint8 FLAC__byte; + +#ifdef true +#undef true +#endif +#ifdef false +#undef false +#endif +#ifndef __cplusplus +#define true 1 +#define false 0 +#endif + +#endif diff --git a/FLAC/FLAC/stream_decoder.h b/FLAC/FLAC/stream_decoder.h index 9c2c36703..5b8d13d38 100644 --- a/FLAC/FLAC/stream_decoder.h +++ b/FLAC/FLAC/stream_decoder.h @@ -1,873 +1,873 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#ifndef FLAC__STREAM_DECODER_H -#define FLAC__STREAM_DECODER_H - -#include "export.h" -#include "format.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** \file include/FLAC/stream_decoder.h - * - * \brief - * This module contains the functions which implement the stream - * decoder. - * - * See the detailed documentation in the - * \link flac_stream_decoder stream decoder \endlink module. - */ - -/** \defgroup flac_decoder FLAC/ *_decoder.h: decoder interfaces - * \ingroup flac - * - * \brief - * This module describes the three decoder layers provided by libFLAC. - * - * For decoding FLAC streams, libFLAC provides three layers of access. The - * lowest layer is non-seekable stream-level decoding, the next is seekable - * stream-level decoding, and the highest layer is file-level decoding. The - * interfaces are described in the \link flac_stream_decoder stream decoder - * \endlink, \link flac_seekable_stream_decoder seekable stream decoder - * \endlink, and \link flac_file_decoder file decoder \endlink modules - * respectively. Typically you will choose the highest layer that your input - * source will support. - * - * The stream decoder relies on callbacks for all input and output and has no - * provisions for seeking. The seekable stream decoder wraps the stream - * decoder and exposes functions for seeking. However, you must provide - * extra callbacks for seek-related operations on your stream, like seek and - * tell. The file decoder wraps the seekable stream decoder and supplies - * most of the callbacks internally, simplifying the processing of standard - * files. - */ - -/** \defgroup flac_stream_decoder FLAC/stream_decoder.h: stream decoder interface - * \ingroup flac_decoder - * - * \brief - * This module contains the functions which implement the stream - * decoder. - * - * The basic usage of this decoder is as follows: - * - The program creates an instance of a decoder using - * FLAC__stream_decoder_new(). - * - The program overrides the default settings and sets callbacks for - * reading, writing, error reporting, and metadata reporting using - * FLAC__stream_decoder_set_*() functions. - * - The program initializes the instance to validate the settings and - * prepare for decoding using FLAC__stream_decoder_init(). - * - The program calls the FLAC__stream_decoder_process_*() functions - * to decode data, which subsequently calls the callbacks. - * - The program finishes the decoding with FLAC__stream_decoder_finish(), - * which flushes the input and output and resets the decoder to the - * uninitialized state. - * - The instance may be used again or deleted with - * FLAC__stream_decoder_delete(). - * - * In more detail, the program will create a new instance by calling - * FLAC__stream_decoder_new(), then call FLAC__stream_decoder_set_*() - * functions to set the callbacks and client data, and call - * FLAC__stream_decoder_init(). The required callbacks are: - * - * - Read callback - This function will be called when the decoder needs - * more input data. The address of the buffer to be filled is supplied, - * along with the number of bytes the buffer can hold. The callback may - * choose to supply less data and modify the byte count but must be careful - * not to overflow the buffer. The callback then returns a status code - * chosen from FLAC__StreamDecoderReadStatus. - * - Write callback - This function will be called when the decoder has - * decoded a single frame of data. The decoder will pass the frame - * metadata as well as an array of pointers (one for each channel) - * pointing to the decoded audio. - * - Metadata callback - This function will be called when the decoder has - * decoded a metadata block. In a valid FLAC file there will always be - * one STREAMINFO block, followed by zero or more other metadata - * blocks. These will be supplied by the decoder in the same order as - * they appear in the stream and always before the first audio frame - * (i.e. write callback). The metadata block that is passed in must not - * be modified, and it doesn't live beyond the callback, so you should - * make a copy of it with FLAC__metadata_object_clone() if you will need - * it elsewhere. Since metadata blocks can potentially be large, by - * default the decoder only calls the metadata callback for the STREAMINFO - * block; you can instruct the decoder to pass or filter other blocks with - * FLAC__stream_decoder_set_metadata_*() calls. - * - Error callback - This function will be called whenever an error occurs - * during decoding. - * - * Once the decoder is initialized, your program will call one of several - * functions to start the decoding process: - * - * - FLAC__stream_decoder_process_single() - Tells the decoder to process at - * most one metadata block or audio frame and return, calling either the - * metadata callback or write callback, respectively, once. If the decoder - * loses sync it will return with only the error callback being called. - * - FLAC__stream_decoder_process_until_end_of_metadata() - Tells the decoder - * to process the stream from the current location and stop upon reaching - * the first audio frame. The user will get one metadata, write, or error - * callback per metadata block, audio frame, or sync error, respectively. - * - FLAC__stream_decoder_process_until_end_of_stream() - Tells the decoder - * to process the stream from the current location until the read callback - * returns FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM or - * FLAC__STREAM_DECODER_READ_STATUS_ABORT. The user will get one metadata, - * write, or error callback per metadata block, audio frame, or sync error, - * respectively. - * - * When the decoder has finished decoding (normally or through an abort), - * the instance is finished by calling FLAC__stream_decoder_finish(), which - * ensures the decoder is in the correct state and frees memory. Then the - * instance may be deleted with FLAC__stream_decoder_delete() or initialized - * again to decode another stream. - * - * Note that the stream decoder has no real concept of stream position, it - * just converts data. To seek within a stream the callbacks have only to - * flush the decoder using FLAC__stream_decoder_flush() and start feeding - * data from the new position through the read callback. The seekable - * stream decoder does just this. - * - * The FLAC__stream_decoder_set_metadata_*() functions deserve special - * attention. By default, the decoder only calls the metadata_callback for - * the STREAMINFO block. These functions allow you to tell the decoder - * explicitly which blocks to parse and return via the metadata_callback - * and/or which to skip. Use a FLAC__stream_decoder_set_metadata_respond_all(), - * FLAC__stream_decoder_set_metadata_ignore() ... or FLAC__stream_decoder_set_metadata_ignore_all(), - * FLAC__stream_decoder_set_metadata_respond() ... sequence to exactly specify which - * blocks to return. Remember that some metadata blocks can be big so - * filtering out the ones you don't use can reduce the memory requirements - * of the decoder. Also note the special forms - * FLAC__stream_decoder_set_metadata_respond_application(id) and - * FLAC__stream_decoder_set_metadata_ignore_application(id) for filtering APPLICATION - * blocks based on the application ID. - * - * STREAMINFO and SEEKTABLE blocks are always parsed and used internally, but - * they still can legally be filtered from the metadata_callback. - * - * \note - * The "set" functions may only be called when the decoder is in the - * state FLAC__STREAM_DECODER_UNINITIALIZED, i.e. after - * FLAC__stream_decoder_new() or FLAC__stream_decoder_finish(), but - * before FLAC__stream_decoder_init(). If this is the case they will - * return \c true, otherwise \c false. - * - * \note - * FLAC__stream_decoder_finish() resets all settings to the constructor - * defaults, including the callbacks. - * - * \{ - */ - - -/** State values for a FLAC__StreamDecoder - * - * The decoder's state can be obtained by calling FLAC__stream_decoder_get_state(). - */ -typedef enum { - - FLAC__STREAM_DECODER_SEARCH_FOR_METADATA = 0, - /**< The decoder is ready to search for metadata. */ - - FLAC__STREAM_DECODER_READ_METADATA, - /**< The decoder is ready to or is in the process of reading metadata. */ - - FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC, - /**< The decoder is ready to or is in the process of searching for the frame sync code. */ - - FLAC__STREAM_DECODER_READ_FRAME, - /**< The decoder is ready to or is in the process of reading a frame. */ - - FLAC__STREAM_DECODER_END_OF_STREAM, - /**< The decoder has reached the end of the stream. */ - - FLAC__STREAM_DECODER_ABORTED, - /**< The decoder was aborted by the read callback. */ - - FLAC__STREAM_DECODER_UNPARSEABLE_STREAM, - /**< The decoder encountered reserved fields in use in the stream. */ - - FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR, - /**< An error occurred allocating memory. */ - - FLAC__STREAM_DECODER_ALREADY_INITIALIZED, - /**< FLAC__stream_decoder_init() was called when the decoder was - * already initialized, usually because - * FLAC__stream_decoder_finish() was not called. - */ - - FLAC__STREAM_DECODER_INVALID_CALLBACK, - /**< FLAC__stream_decoder_init() was called without all callbacks being set. */ - - FLAC__STREAM_DECODER_UNINITIALIZED - /**< The decoder is in the uninitialized state. */ - -} FLAC__StreamDecoderState; - -/** Maps a FLAC__StreamDecoderState to a C string. - * - * Using a FLAC__StreamDecoderState as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamDecoderStateString[]; - - -/** Return values for the FLAC__StreamDecoder read callback. - */ -typedef enum { - - FLAC__STREAM_DECODER_READ_STATUS_CONTINUE, - /**< The read was OK and decoding can continue. */ - - FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM, - /**< The read was attempted at the end of the stream. */ - - FLAC__STREAM_DECODER_READ_STATUS_ABORT - /**< An unrecoverable error occurred. The decoder will return from the process call. */ - -} FLAC__StreamDecoderReadStatus; - -/** Maps a FLAC__StreamDecoderReadStatus to a C string. - * - * Using a FLAC__StreamDecoderReadStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamDecoderReadStatusString[]; - - -/** Return values for the FLAC__StreamDecoder write callback. - */ -typedef enum { - - FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE, - /**< The write was OK and decoding can continue. */ - - FLAC__STREAM_DECODER_WRITE_STATUS_ABORT - /**< An unrecoverable error occurred. The decoder will return from the process call. */ - -} FLAC__StreamDecoderWriteStatus; - -/** Maps a FLAC__StreamDecoderWriteStatus to a C string. - * - * Using a FLAC__StreamDecoderWriteStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[]; - - -/** Possible values passed in to the FLAC__StreamDecoder error callback. - */ -typedef enum { - - FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, - /**< An error in the stream caused the decoder to lose synchronization. */ - - FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, - /**< The decoder encountered a corrupted frame header. */ - - FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH - /**< The frame's data did not match the CRC in the footer. */ - -} FLAC__StreamDecoderErrorStatus; - -/** Maps a FLAC__StreamDecoderErrorStatus to a C string. - * - * Using a FLAC__StreamDecoderErrorStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamDecoderErrorStatusString[]; - - -/*********************************************************************** - * - * class FLAC__StreamDecoder - * - ***********************************************************************/ - -struct FLAC__StreamDecoderProtected; -struct FLAC__StreamDecoderPrivate; -/** The opaque structure definition for the stream decoder type. - * See the \link flac_stream_decoder stream decoder module \endlink - * for a detailed description. - */ -typedef struct { - struct FLAC__StreamDecoderProtected *protected_; /* avoid the C++ keyword 'protected' */ - struct FLAC__StreamDecoderPrivate *private_; /* avoid the C++ keyword 'private' */ -} FLAC__StreamDecoder; - -/** Signature for the read callback. - * See FLAC__stream_decoder_set_read_callback() for more info. - * - * \param decoder The decoder instance calling the callback. - * \param buffer A pointer to a location for the callee to store - * data to be decoded. - * \param bytes A pointer to the size of the buffer. On entry - * to the callback, it contains the maximum number - * of bytes that may be stored in \a buffer. The - * callee must set it to the actual number of bytes - * stored (0 in case of error or end-of-stream) before - * returning. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_set_client_data(). - * \retval FLAC__StreamDecoderReadStatus - * The callee's return status. - */ -typedef FLAC__StreamDecoderReadStatus (*FLAC__StreamDecoderReadCallback)(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); - -/** Signature for the write callback. - * See FLAC__stream_decoder_set_write_callback() for more info. - * - * \param decoder The decoder instance calling the callback. - * \param frame The description of the decoded frame. See - * FLAC__Frame. - * \param buffer An array of pointers to decoded channels of data. - * Each pointer will point to an array of signed - * samples of length \a frame->header.blocksize. - * Currently, the channel order has no meaning - * except for stereo streams; in this case channel - * 0 is left and 1 is right. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_set_client_data(). - * \retval FLAC__StreamDecoderWriteStatus - * The callee's return status. - */ -typedef FLAC__StreamDecoderWriteStatus (*FLAC__StreamDecoderWriteCallback)(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); - -/** Signature for the metadata callback. - * See FLAC__stream_decoder_set_metadata_callback() for more info. - * - * \param decoder The decoder instance calling the callback. - * \param metadata The decoded metadata block. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_set_client_data(). - */ -typedef void (*FLAC__StreamDecoderMetadataCallback)(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); - -/** Signature for the error callback. - * See FLAC__stream_decoder_set_error_callback() for more info. - * - * \param decoder The decoder instance calling the callback. - * \param status The error encountered by the decoder. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_set_client_data(). - */ -typedef void (*FLAC__StreamDecoderErrorCallback)(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); - - -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ - -/** Create a new stream decoder instance. The instance is created with - * default settings; see the individual FLAC__stream_decoder_set_*() - * functions for each setting's default. - * - * \retval FLAC__StreamDecoder* - * \c NULL if there was an error allocating memory, else the new instance. - */ -FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new(); - -/** Free a decoder instance. Deletes the object pointed to by \a decoder. - * - * \param decoder A pointer to an existing decoder. - * \assert - * \code decoder != NULL \endcode - */ -FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder); - - -/*********************************************************************** - * - * Public class method prototypes - * - ***********************************************************************/ - -/** Set the read callback. - * The supplied function will be called when the decoder needs more input - * data. The address of the buffer to be filled is supplied, along with - * the number of bytes the buffer can hold. The callback may choose to - * supply less data and modify the byte count but must be careful not to - * overflow the buffer. The callback then returns a status code chosen - * from FLAC__StreamDecoderReadStatus. - * - * \note - * The callback is mandatory and must be set before initialization. - * - * \default \c NULL - * \param decoder A decoder instance to set. - * \param value See above. - * \assert - * \code decoder != NULL \endcode - * \code value != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_read_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadCallback value); - -/** Set the write callback. - * The supplied function will be called when the decoder has decoded a - * single frame of data. The decoder will pass the frame metadata as - * well as an array of pointers (one for each channel) pointing to the - * decoded audio. - * - * \note - * The callback is mandatory and must be set before initialization. - * - * \default \c NULL - * \param decoder A decoder instance to set. - * \param value See above. - * \assert - * \code decoder != NULL \endcode - * \code value != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_write_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderWriteCallback value); - -/** Set the metadata callback. - * The supplied function will be called when the decoder has decoded a metadata - * block. In a valid FLAC file there will always be one STREAMINFO block, - * followed by zero or more other metadata blocks. These will be supplied - * by the decoder in the same order as they appear in the stream and always - * before the first audio frame (i.e. write callback). The metadata block - * that is passed in must not be modified, and it doesn't live beyond the - * callback, so you should make a copy of it with - * FLAC__metadata_object_clone() if you will need it elsewhere. Since - * metadata blocks can potentially be large, by default the decoder only - * calls the metadata callback for the STREAMINFO block; you can instruct - * the decoder to pass or filter other blocks with - * FLAC__stream_decoder_set_metadata_*() calls. - * - * \note - * The callback is mandatory and must be set before initialization. - * - * \default \c NULL - * \param decoder A decoder instance to set. - * \param value See above. - * \assert - * \code decoder != NULL \endcode - * \code value != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderMetadataCallback value); - -/** Set the error callback. - * The supplied function will be called whenever an error occurs during - * decoding. - * - * \note - * The callback is mandatory and must be set before initialization. - * - * \default \c NULL - * \param decoder A decoder instance to set. - * \param value See above. - * \assert - * \code decoder != NULL \endcode - * \code value != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_error_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorCallback value); - -/** Set the client data to be passed back to callbacks. - * This value will be supplied to callbacks in their \a client_data - * argument. - * - * \default \c NULL - * \param decoder A decoder instance to set. - * \param value See above. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_client_data(FLAC__StreamDecoder *decoder, void *value); - -/** Direct the decoder to pass on all metadata blocks of type \a type. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \param type See above. - * \assert - * \code decoder != NULL \endcode - * \a type is valid - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond(FLAC__StreamDecoder *decoder, FLAC__MetadataType type); - -/** Direct the decoder to pass on all APPLICATION metadata blocks of the - * given \a id. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \param id See above. - * \assert - * \code decoder != NULL \endcode - * \code id != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]); - -/** Direct the decoder to pass on all metadata blocks of any type. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_all(FLAC__StreamDecoder *decoder); - -/** Direct the decoder to filter out all metadata blocks of type \a type. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \param type See above. - * \assert - * \code decoder != NULL \endcode - * \a type is valid - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore(FLAC__StreamDecoder *decoder, FLAC__MetadataType type); - -/** Direct the decoder to filter out all APPLICATION metadata blocks of - * the given \a id. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \param id See above. - * \assert - * \code decoder != NULL \endcode - * \code id != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]); - -/** Direct the decoder to filter out all metadata blocks of any type. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_all(FLAC__StreamDecoder *decoder); - -/** Get the current decoder state. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__StreamDecoderState - * The current decoder state. - */ -FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__StreamDecoder *decoder); - -/** Get the current decoder state as a C string. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval const char * - * The decoder state as a C string. Do not modify the contents. - */ -FLAC_API const char *FLAC__stream_decoder_get_resolved_state_string(const FLAC__StreamDecoder *decoder); - -/** Get the current number of channels in the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ -FLAC_API unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder); - -/** Get the current channel assignment in the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__ChannelAssignment - * See above. - */ -FLAC_API FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(const FLAC__StreamDecoder *decoder); - -/** Get the current sample resolution in the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ -FLAC_API unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder); - -/** Get the current sample rate in Hz of the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ -FLAC_API unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder); - -/** Get the current blocksize of the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ -FLAC_API unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder); - -/** Initialize the decoder instance. - * 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 - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \param decoder An uninitialized decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__StreamDecoderState - * \c FLAC__STREAM_DECODER_SEARCH_FOR_METADATA if initialization was - * successful; see FLAC__StreamDecoderState for the meanings of other - * return values. - */ -FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder *decoder); - -/** Finish the decoding process. - * Flushes the decoding buffer, releases resources, resets the decoder - * settings to their defaults, and returns the decoder state to - * FLAC__STREAM_DECODER_UNINITIALIZED. - * - * In the event of a prematurely-terminated decode, it is not strictly - * necessary to call this immediately before FLAC__stream_decoder_delete() - * but it is good practice to match every FLAC__stream_decoder_init() - * with a FLAC__stream_decoder_finish(). - * - * \param decoder An uninitialized decoder instance. - * \assert - * \code decoder != NULL \endcode - */ -FLAC_API void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder); - -/** Flush the stream input. - * The decoder's input buffer will be cleared and the state set to - * \c FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC. - * - * \param decoder A decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c true if successful, else \c false if a memory allocation - * error occurs. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder); - -/** Reset the decoding process. - * The decoder's input buffer will be cleared and the state set to - * \c FLAC__STREAM_DECODER_SEARCH_FOR_METADATA. This is similar to - * FLAC__stream_decoder_finish() except that the settings are - * preserved; there is no need to call FLAC__stream_decoder_init() - * before decoding again. - * - * \param decoder A decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c true if successful, else \c false if a memory allocation - * error occurs. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder); - -/** Decode one metadata block or audio frame. - * This version instructs the decoder to decode a either a single metadata - * block or a single frame and stop, unless the callbacks return a fatal - * error or the read callback returns - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. - * - * As the decoder needs more input it will call the read callback. - * Depending on what was decoded, the metadata or write callback will be - * called with the decoded metadata block or audio frame, unless an error - * occurred. If the decoder loses sync it will call the error callback - * instead. - * - * Unless there is a fatal read error or end of stream, this function - * will return once one whole frame is decoded. In other words, if the - * stream is not synchronized or points to a corrupt frame header, the - * decoder will continue to try and resync until it gets to a valid - * frame, then decode one frame, then return. If the decoder points to - * frame whose frame CRC in the frame footer does not match the - * computed frame CRC, this function will issue a - * FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH error to the - * error callback, and return, having decoded one complete, although - * corrupt, frame. (Such corrupted frames are sent as silence of the - * correct length to the write callback.) - * - * \param decoder An initialized decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if any read or write error occurred (except - * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), else \c true; - * in any case, check the decoder state with - * FLAC__stream_decoder_get_state() to see what went wrong or to - * check for lost synchronization (a sign of stream corruption). - */ -FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *decoder); - -/** Decode until the end of the metadata. - * This version instructs the decoder to decode from the current position - * and continue until all the metadata has been read, or until the - * callbacks return a fatal error or the read callback returns - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. - * - * As the decoder needs more input it will call the read callback. - * As each metadata block is decoded, the metadata callback will be called - * with the decoded metadata. If the decoder loses sync it will call the - * error callback. - * - * \param decoder An initialized decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if any read or write error occurred (except - * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), else \c true; - * in any case, check the decoder state with - * FLAC__stream_decoder_get_state() to see what went wrong or to - * check for lost synchronization (a sign of stream corruption). - */ -FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_metadata(FLAC__StreamDecoder *decoder); - -/** Decode until the end of the stream. - * This version instructs the decoder to decode from the current position - * and continue until the end of stream (the read callback returns - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM), or until the - * callbacks return a fatal error. - * - * As the decoder needs more input it will call the read callback. - * As each metadata block and frame is decoded, the metadata or write - * callback will be called with the decoded metadata or frame. If the - * decoder loses sync it will call the error callback. - * - * \param decoder An initialized decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if any read or write error occurred (except - * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), else \c true; - * in any case, check the decoder state with - * FLAC__stream_decoder_get_state() to see what went wrong or to - * check for lost synchronization (a sign of stream corruption). - */ -FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder); - -/** Skip one audio frame. - * This version instructs the decoder to 'skip' a single frame and stop, - * unless the callbacks return a fatal error or the read callback returns - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. - * - * The decoding flow is the same as what occurs when - * FLAC__stream_decoder_process_single() is called to process an audio - * frame, except that this function does not decode the parsed data into - * PCM or call the write callback. The integrity of the frame is still - * checked the same way as in the other process functions. - * - * This function will return once one whole frame is skipped, in the - * same way that FLAC__stream_decoder_process_single() will return once - * one whole frame is decoded. - * - * This function, when used from the higher FLAC__SeekableStreamDecoder - * layer, can be used in more quickly determining FLAC frame boundaries - * when decoding of the actual data is not needed, for example when a - * application is separating a FLAC stream into frames for editing or - * storing in a container. To do this, the application can use - * FLAC__seekable_stream_decoder_skip_single_frame() to quickly advance - * to the next frame, then use - * FLAC__seekable_stream_decoder_get_decode_position() to find the new - * frame boundary. - * - * This function should only be called when the stream has advanced - * past all the metadata, otherwise it will return \c false. - * - * \param decoder An initialized decoder instance not in a metadata - * state. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if any read or write error occurred (except - * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), or if the decoder - * is in the FLAC__STREAM_DECODER_SEARCH_FOR_METADATA or - * FLAC__STREAM_DECODER_READ_METADATA state, else \c true; - * in any case, check the decoder state with - * FLAC__stream_decoder_get_state() to see what went wrong or to - * check for lost synchronization (a sign of stream corruption). - */ -FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder); - -/* \} */ - -#ifdef __cplusplus -} -#endif - -#endif +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#ifndef FLAC__STREAM_DECODER_H +#define FLAC__STREAM_DECODER_H + +#include "export.h" +#include "format.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** \file include/FLAC/stream_decoder.h + * + * \brief + * This module contains the functions which implement the stream + * decoder. + * + * See the detailed documentation in the + * \link flac_stream_decoder stream decoder \endlink module. + */ + +/** \defgroup flac_decoder FLAC/ *_decoder.h: decoder interfaces + * \ingroup flac + * + * \brief + * This module describes the three decoder layers provided by libFLAC. + * + * For decoding FLAC streams, libFLAC provides three layers of access. The + * lowest layer is non-seekable stream-level decoding, the next is seekable + * stream-level decoding, and the highest layer is file-level decoding. The + * interfaces are described in the \link flac_stream_decoder stream decoder + * \endlink, \link flac_seekable_stream_decoder seekable stream decoder + * \endlink, and \link flac_file_decoder file decoder \endlink modules + * respectively. Typically you will choose the highest layer that your input + * source will support. + * + * The stream decoder relies on callbacks for all input and output and has no + * provisions for seeking. The seekable stream decoder wraps the stream + * decoder and exposes functions for seeking. However, you must provide + * extra callbacks for seek-related operations on your stream, like seek and + * tell. The file decoder wraps the seekable stream decoder and supplies + * most of the callbacks internally, simplifying the processing of standard + * files. + */ + +/** \defgroup flac_stream_decoder FLAC/stream_decoder.h: stream decoder interface + * \ingroup flac_decoder + * + * \brief + * This module contains the functions which implement the stream + * decoder. + * + * The basic usage of this decoder is as follows: + * - The program creates an instance of a decoder using + * FLAC__stream_decoder_new(). + * - The program overrides the default settings and sets callbacks for + * reading, writing, error reporting, and metadata reporting using + * FLAC__stream_decoder_set_*() functions. + * - The program initializes the instance to validate the settings and + * prepare for decoding using FLAC__stream_decoder_init(). + * - The program calls the FLAC__stream_decoder_process_*() functions + * to decode data, which subsequently calls the callbacks. + * - The program finishes the decoding with FLAC__stream_decoder_finish(), + * which flushes the input and output and resets the decoder to the + * uninitialized state. + * - The instance may be used again or deleted with + * FLAC__stream_decoder_delete(). + * + * In more detail, the program will create a new instance by calling + * FLAC__stream_decoder_new(), then call FLAC__stream_decoder_set_*() + * functions to set the callbacks and client data, and call + * FLAC__stream_decoder_init(). The required callbacks are: + * + * - Read callback - This function will be called when the decoder needs + * more input data. The address of the buffer to be filled is supplied, + * along with the number of bytes the buffer can hold. The callback may + * choose to supply less data and modify the byte count but must be careful + * not to overflow the buffer. The callback then returns a status code + * chosen from FLAC__StreamDecoderReadStatus. + * - Write callback - This function will be called when the decoder has + * decoded a single frame of data. The decoder will pass the frame + * metadata as well as an array of pointers (one for each channel) + * pointing to the decoded audio. + * - Metadata callback - This function will be called when the decoder has + * decoded a metadata block. In a valid FLAC file there will always be + * one STREAMINFO block, followed by zero or more other metadata + * blocks. These will be supplied by the decoder in the same order as + * they appear in the stream and always before the first audio frame + * (i.e. write callback). The metadata block that is passed in must not + * be modified, and it doesn't live beyond the callback, so you should + * make a copy of it with FLAC__metadata_object_clone() if you will need + * it elsewhere. Since metadata blocks can potentially be large, by + * default the decoder only calls the metadata callback for the STREAMINFO + * block; you can instruct the decoder to pass or filter other blocks with + * FLAC__stream_decoder_set_metadata_*() calls. + * - Error callback - This function will be called whenever an error occurs + * during decoding. + * + * Once the decoder is initialized, your program will call one of several + * functions to start the decoding process: + * + * - FLAC__stream_decoder_process_single() - Tells the decoder to process at + * most one metadata block or audio frame and return, calling either the + * metadata callback or write callback, respectively, once. If the decoder + * loses sync it will return with only the error callback being called. + * - FLAC__stream_decoder_process_until_end_of_metadata() - Tells the decoder + * to process the stream from the current location and stop upon reaching + * the first audio frame. The user will get one metadata, write, or error + * callback per metadata block, audio frame, or sync error, respectively. + * - FLAC__stream_decoder_process_until_end_of_stream() - Tells the decoder + * to process the stream from the current location until the read callback + * returns FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM or + * FLAC__STREAM_DECODER_READ_STATUS_ABORT. The user will get one metadata, + * write, or error callback per metadata block, audio frame, or sync error, + * respectively. + * + * When the decoder has finished decoding (normally or through an abort), + * the instance is finished by calling FLAC__stream_decoder_finish(), which + * ensures the decoder is in the correct state and frees memory. Then the + * instance may be deleted with FLAC__stream_decoder_delete() or initialized + * again to decode another stream. + * + * Note that the stream decoder has no real concept of stream position, it + * just converts data. To seek within a stream the callbacks have only to + * flush the decoder using FLAC__stream_decoder_flush() and start feeding + * data from the new position through the read callback. The seekable + * stream decoder does just this. + * + * The FLAC__stream_decoder_set_metadata_*() functions deserve special + * attention. By default, the decoder only calls the metadata_callback for + * the STREAMINFO block. These functions allow you to tell the decoder + * explicitly which blocks to parse and return via the metadata_callback + * and/or which to skip. Use a FLAC__stream_decoder_set_metadata_respond_all(), + * FLAC__stream_decoder_set_metadata_ignore() ... or FLAC__stream_decoder_set_metadata_ignore_all(), + * FLAC__stream_decoder_set_metadata_respond() ... sequence to exactly specify which + * blocks to return. Remember that some metadata blocks can be big so + * filtering out the ones you don't use can reduce the memory requirements + * of the decoder. Also note the special forms + * FLAC__stream_decoder_set_metadata_respond_application(id) and + * FLAC__stream_decoder_set_metadata_ignore_application(id) for filtering APPLICATION + * blocks based on the application ID. + * + * STREAMINFO and SEEKTABLE blocks are always parsed and used internally, but + * they still can legally be filtered from the metadata_callback. + * + * \note + * The "set" functions may only be called when the decoder is in the + * state FLAC__STREAM_DECODER_UNINITIALIZED, i.e. after + * FLAC__stream_decoder_new() or FLAC__stream_decoder_finish(), but + * before FLAC__stream_decoder_init(). If this is the case they will + * return \c true, otherwise \c false. + * + * \note + * FLAC__stream_decoder_finish() resets all settings to the constructor + * defaults, including the callbacks. + * + * \{ + */ + + +/** State values for a FLAC__StreamDecoder + * + * The decoder's state can be obtained by calling FLAC__stream_decoder_get_state(). + */ +typedef enum { + + FLAC__STREAM_DECODER_SEARCH_FOR_METADATA = 0, + /**< The decoder is ready to search for metadata. */ + + FLAC__STREAM_DECODER_READ_METADATA, + /**< The decoder is ready to or is in the process of reading metadata. */ + + FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC, + /**< The decoder is ready to or is in the process of searching for the frame sync code. */ + + FLAC__STREAM_DECODER_READ_FRAME, + /**< The decoder is ready to or is in the process of reading a frame. */ + + FLAC__STREAM_DECODER_END_OF_STREAM, + /**< The decoder has reached the end of the stream. */ + + FLAC__STREAM_DECODER_ABORTED, + /**< The decoder was aborted by the read callback. */ + + FLAC__STREAM_DECODER_UNPARSEABLE_STREAM, + /**< The decoder encountered reserved fields in use in the stream. */ + + FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR, + /**< An error occurred allocating memory. */ + + FLAC__STREAM_DECODER_ALREADY_INITIALIZED, + /**< FLAC__stream_decoder_init() was called when the decoder was + * already initialized, usually because + * FLAC__stream_decoder_finish() was not called. + */ + + FLAC__STREAM_DECODER_INVALID_CALLBACK, + /**< FLAC__stream_decoder_init() was called without all callbacks being set. */ + + FLAC__STREAM_DECODER_UNINITIALIZED + /**< The decoder is in the uninitialized state. */ + +} FLAC__StreamDecoderState; + +/** Maps a FLAC__StreamDecoderState to a C string. + * + * Using a FLAC__StreamDecoderState as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamDecoderStateString[]; + + +/** Return values for the FLAC__StreamDecoder read callback. + */ +typedef enum { + + FLAC__STREAM_DECODER_READ_STATUS_CONTINUE, + /**< The read was OK and decoding can continue. */ + + FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM, + /**< The read was attempted at the end of the stream. */ + + FLAC__STREAM_DECODER_READ_STATUS_ABORT + /**< An unrecoverable error occurred. The decoder will return from the process call. */ + +} FLAC__StreamDecoderReadStatus; + +/** Maps a FLAC__StreamDecoderReadStatus to a C string. + * + * Using a FLAC__StreamDecoderReadStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamDecoderReadStatusString[]; + + +/** Return values for the FLAC__StreamDecoder write callback. + */ +typedef enum { + + FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE, + /**< The write was OK and decoding can continue. */ + + FLAC__STREAM_DECODER_WRITE_STATUS_ABORT + /**< An unrecoverable error occurred. The decoder will return from the process call. */ + +} FLAC__StreamDecoderWriteStatus; + +/** Maps a FLAC__StreamDecoderWriteStatus to a C string. + * + * Using a FLAC__StreamDecoderWriteStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[]; + + +/** Possible values passed in to the FLAC__StreamDecoder error callback. + */ +typedef enum { + + FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, + /**< An error in the stream caused the decoder to lose synchronization. */ + + FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, + /**< The decoder encountered a corrupted frame header. */ + + FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH + /**< The frame's data did not match the CRC in the footer. */ + +} FLAC__StreamDecoderErrorStatus; + +/** Maps a FLAC__StreamDecoderErrorStatus to a C string. + * + * Using a FLAC__StreamDecoderErrorStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamDecoderErrorStatusString[]; + + +/*********************************************************************** + * + * class FLAC__StreamDecoder + * + ***********************************************************************/ + +struct FLAC__StreamDecoderProtected; +struct FLAC__StreamDecoderPrivate; +/** The opaque structure definition for the stream decoder type. + * See the \link flac_stream_decoder stream decoder module \endlink + * for a detailed description. + */ +typedef struct { + struct FLAC__StreamDecoderProtected *protected_; /* avoid the C++ keyword 'protected' */ + struct FLAC__StreamDecoderPrivate *private_; /* avoid the C++ keyword 'private' */ +} FLAC__StreamDecoder; + +/** Signature for the read callback. + * See FLAC__stream_decoder_set_read_callback() for more info. + * + * \param decoder The decoder instance calling the callback. + * \param buffer A pointer to a location for the callee to store + * data to be decoded. + * \param bytes A pointer to the size of the buffer. On entry + * to the callback, it contains the maximum number + * of bytes that may be stored in \a buffer. The + * callee must set it to the actual number of bytes + * stored (0 in case of error or end-of-stream) before + * returning. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_set_client_data(). + * \retval FLAC__StreamDecoderReadStatus + * The callee's return status. + */ +typedef FLAC__StreamDecoderReadStatus (*FLAC__StreamDecoderReadCallback)(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); + +/** Signature for the write callback. + * See FLAC__stream_decoder_set_write_callback() for more info. + * + * \param decoder The decoder instance calling the callback. + * \param frame The description of the decoded frame. See + * FLAC__Frame. + * \param buffer An array of pointers to decoded channels of data. + * Each pointer will point to an array of signed + * samples of length \a frame->header.blocksize. + * Currently, the channel order has no meaning + * except for stereo streams; in this case channel + * 0 is left and 1 is right. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_set_client_data(). + * \retval FLAC__StreamDecoderWriteStatus + * The callee's return status. + */ +typedef FLAC__StreamDecoderWriteStatus (*FLAC__StreamDecoderWriteCallback)(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); + +/** Signature for the metadata callback. + * See FLAC__stream_decoder_set_metadata_callback() for more info. + * + * \param decoder The decoder instance calling the callback. + * \param metadata The decoded metadata block. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_set_client_data(). + */ +typedef void (*FLAC__StreamDecoderMetadataCallback)(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); + +/** Signature for the error callback. + * See FLAC__stream_decoder_set_error_callback() for more info. + * + * \param decoder The decoder instance calling the callback. + * \param status The error encountered by the decoder. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_set_client_data(). + */ +typedef void (*FLAC__StreamDecoderErrorCallback)(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); + + +/*********************************************************************** + * + * Class constructor/destructor + * + ***********************************************************************/ + +/** Create a new stream decoder instance. The instance is created with + * default settings; see the individual FLAC__stream_decoder_set_*() + * functions for each setting's default. + * + * \retval FLAC__StreamDecoder* + * \c NULL if there was an error allocating memory, else the new instance. + */ +FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new(); + +/** Free a decoder instance. Deletes the object pointed to by \a decoder. + * + * \param decoder A pointer to an existing decoder. + * \assert + * \code decoder != NULL \endcode + */ +FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder); + + +/*********************************************************************** + * + * Public class method prototypes + * + ***********************************************************************/ + +/** Set the read callback. + * The supplied function will be called when the decoder needs more input + * data. The address of the buffer to be filled is supplied, along with + * the number of bytes the buffer can hold. The callback may choose to + * supply less data and modify the byte count but must be careful not to + * overflow the buffer. The callback then returns a status code chosen + * from FLAC__StreamDecoderReadStatus. + * + * \note + * The callback is mandatory and must be set before initialization. + * + * \default \c NULL + * \param decoder A decoder instance to set. + * \param value See above. + * \assert + * \code decoder != NULL \endcode + * \code value != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_read_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadCallback value); + +/** Set the write callback. + * The supplied function will be called when the decoder has decoded a + * single frame of data. The decoder will pass the frame metadata as + * well as an array of pointers (one for each channel) pointing to the + * decoded audio. + * + * \note + * The callback is mandatory and must be set before initialization. + * + * \default \c NULL + * \param decoder A decoder instance to set. + * \param value See above. + * \assert + * \code decoder != NULL \endcode + * \code value != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_write_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderWriteCallback value); + +/** Set the metadata callback. + * The supplied function will be called when the decoder has decoded a metadata + * block. In a valid FLAC file there will always be one STREAMINFO block, + * followed by zero or more other metadata blocks. These will be supplied + * by the decoder in the same order as they appear in the stream and always + * before the first audio frame (i.e. write callback). The metadata block + * that is passed in must not be modified, and it doesn't live beyond the + * callback, so you should make a copy of it with + * FLAC__metadata_object_clone() if you will need it elsewhere. Since + * metadata blocks can potentially be large, by default the decoder only + * calls the metadata callback for the STREAMINFO block; you can instruct + * the decoder to pass or filter other blocks with + * FLAC__stream_decoder_set_metadata_*() calls. + * + * \note + * The callback is mandatory and must be set before initialization. + * + * \default \c NULL + * \param decoder A decoder instance to set. + * \param value See above. + * \assert + * \code decoder != NULL \endcode + * \code value != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderMetadataCallback value); + +/** Set the error callback. + * The supplied function will be called whenever an error occurs during + * decoding. + * + * \note + * The callback is mandatory and must be set before initialization. + * + * \default \c NULL + * \param decoder A decoder instance to set. + * \param value See above. + * \assert + * \code decoder != NULL \endcode + * \code value != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_error_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorCallback value); + +/** Set the client data to be passed back to callbacks. + * This value will be supplied to callbacks in their \a client_data + * argument. + * + * \default \c NULL + * \param decoder A decoder instance to set. + * \param value See above. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_client_data(FLAC__StreamDecoder *decoder, void *value); + +/** Direct the decoder to pass on all metadata blocks of type \a type. + * + * \default By default, only the \c STREAMINFO block is returned via the + * metadata callback. + * \param decoder A decoder instance to set. + * \param type See above. + * \assert + * \code decoder != NULL \endcode + * \a type is valid + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond(FLAC__StreamDecoder *decoder, FLAC__MetadataType type); + +/** Direct the decoder to pass on all APPLICATION metadata blocks of the + * given \a id. + * + * \default By default, only the \c STREAMINFO block is returned via the + * metadata callback. + * \param decoder A decoder instance to set. + * \param id See above. + * \assert + * \code decoder != NULL \endcode + * \code id != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]); + +/** Direct the decoder to pass on all metadata blocks of any type. + * + * \default By default, only the \c STREAMINFO block is returned via the + * metadata callback. + * \param decoder A decoder instance to set. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_all(FLAC__StreamDecoder *decoder); + +/** Direct the decoder to filter out all metadata blocks of type \a type. + * + * \default By default, only the \c STREAMINFO block is returned via the + * metadata callback. + * \param decoder A decoder instance to set. + * \param type See above. + * \assert + * \code decoder != NULL \endcode + * \a type is valid + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore(FLAC__StreamDecoder *decoder, FLAC__MetadataType type); + +/** Direct the decoder to filter out all APPLICATION metadata blocks of + * the given \a id. + * + * \default By default, only the \c STREAMINFO block is returned via the + * metadata callback. + * \param decoder A decoder instance to set. + * \param id See above. + * \assert + * \code decoder != NULL \endcode + * \code id != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]); + +/** Direct the decoder to filter out all metadata blocks of any type. + * + * \default By default, only the \c STREAMINFO block is returned via the + * metadata callback. + * \param decoder A decoder instance to set. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_all(FLAC__StreamDecoder *decoder); + +/** Get the current decoder state. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__StreamDecoderState + * The current decoder state. + */ +FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__StreamDecoder *decoder); + +/** Get the current decoder state as a C string. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval const char * + * The decoder state as a C string. Do not modify the contents. + */ +FLAC_API const char *FLAC__stream_decoder_get_resolved_state_string(const FLAC__StreamDecoder *decoder); + +/** Get the current number of channels in the stream being decoded. + * Will only be valid after decoding has started and will contain the + * value from the most recently decoded frame header. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval unsigned + * See above. + */ +FLAC_API unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder); + +/** Get the current channel assignment in the stream being decoded. + * Will only be valid after decoding has started and will contain the + * value from the most recently decoded frame header. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__ChannelAssignment + * See above. + */ +FLAC_API FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(const FLAC__StreamDecoder *decoder); + +/** Get the current sample resolution in the stream being decoded. + * Will only be valid after decoding has started and will contain the + * value from the most recently decoded frame header. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval unsigned + * See above. + */ +FLAC_API unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder); + +/** Get the current sample rate in Hz of the stream being decoded. + * Will only be valid after decoding has started and will contain the + * value from the most recently decoded frame header. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval unsigned + * See above. + */ +FLAC_API unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder); + +/** Get the current blocksize of the stream being decoded. + * Will only be valid after decoding has started and will contain the + * value from the most recently decoded frame header. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval unsigned + * See above. + */ +FLAC_API unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder); + +/** Initialize the decoder instance. + * 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 + * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA + * if initialization succeeded. + * + * \param decoder An uninitialized decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__StreamDecoderState + * \c FLAC__STREAM_DECODER_SEARCH_FOR_METADATA if initialization was + * successful; see FLAC__StreamDecoderState for the meanings of other + * return values. + */ +FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder *decoder); + +/** Finish the decoding process. + * Flushes the decoding buffer, releases resources, resets the decoder + * settings to their defaults, and returns the decoder state to + * FLAC__STREAM_DECODER_UNINITIALIZED. + * + * In the event of a prematurely-terminated decode, it is not strictly + * necessary to call this immediately before FLAC__stream_decoder_delete() + * but it is good practice to match every FLAC__stream_decoder_init() + * with a FLAC__stream_decoder_finish(). + * + * \param decoder An uninitialized decoder instance. + * \assert + * \code decoder != NULL \endcode + */ +FLAC_API void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder); + +/** Flush the stream input. + * The decoder's input buffer will be cleared and the state set to + * \c FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC. + * + * \param decoder A decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c true if successful, else \c false if a memory allocation + * error occurs. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder); + +/** Reset the decoding process. + * The decoder's input buffer will be cleared and the state set to + * \c FLAC__STREAM_DECODER_SEARCH_FOR_METADATA. This is similar to + * FLAC__stream_decoder_finish() except that the settings are + * preserved; there is no need to call FLAC__stream_decoder_init() + * before decoding again. + * + * \param decoder A decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c true if successful, else \c false if a memory allocation + * error occurs. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder); + +/** Decode one metadata block or audio frame. + * This version instructs the decoder to decode a either a single metadata + * block or a single frame and stop, unless the callbacks return a fatal + * error or the read callback returns + * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. + * + * As the decoder needs more input it will call the read callback. + * Depending on what was decoded, the metadata or write callback will be + * called with the decoded metadata block or audio frame, unless an error + * occurred. If the decoder loses sync it will call the error callback + * instead. + * + * Unless there is a fatal read error or end of stream, this function + * will return once one whole frame is decoded. In other words, if the + * stream is not synchronized or points to a corrupt frame header, the + * decoder will continue to try and resync until it gets to a valid + * frame, then decode one frame, then return. If the decoder points to + * frame whose frame CRC in the frame footer does not match the + * computed frame CRC, this function will issue a + * FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH error to the + * error callback, and return, having decoded one complete, although + * corrupt, frame. (Such corrupted frames are sent as silence of the + * correct length to the write callback.) + * + * \param decoder An initialized decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if any read or write error occurred (except + * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), else \c true; + * in any case, check the decoder state with + * FLAC__stream_decoder_get_state() to see what went wrong or to + * check for lost synchronization (a sign of stream corruption). + */ +FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *decoder); + +/** Decode until the end of the metadata. + * This version instructs the decoder to decode from the current position + * and continue until all the metadata has been read, or until the + * callbacks return a fatal error or the read callback returns + * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. + * + * As the decoder needs more input it will call the read callback. + * As each metadata block is decoded, the metadata callback will be called + * with the decoded metadata. If the decoder loses sync it will call the + * error callback. + * + * \param decoder An initialized decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if any read or write error occurred (except + * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), else \c true; + * in any case, check the decoder state with + * FLAC__stream_decoder_get_state() to see what went wrong or to + * check for lost synchronization (a sign of stream corruption). + */ +FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_metadata(FLAC__StreamDecoder *decoder); + +/** Decode until the end of the stream. + * This version instructs the decoder to decode from the current position + * and continue until the end of stream (the read callback returns + * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM), or until the + * callbacks return a fatal error. + * + * As the decoder needs more input it will call the read callback. + * As each metadata block and frame is decoded, the metadata or write + * callback will be called with the decoded metadata or frame. If the + * decoder loses sync it will call the error callback. + * + * \param decoder An initialized decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if any read or write error occurred (except + * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), else \c true; + * in any case, check the decoder state with + * FLAC__stream_decoder_get_state() to see what went wrong or to + * check for lost synchronization (a sign of stream corruption). + */ +FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder); + +/** Skip one audio frame. + * This version instructs the decoder to 'skip' a single frame and stop, + * unless the callbacks return a fatal error or the read callback returns + * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. + * + * The decoding flow is the same as what occurs when + * FLAC__stream_decoder_process_single() is called to process an audio + * frame, except that this function does not decode the parsed data into + * PCM or call the write callback. The integrity of the frame is still + * checked the same way as in the other process functions. + * + * This function will return once one whole frame is skipped, in the + * same way that FLAC__stream_decoder_process_single() will return once + * one whole frame is decoded. + * + * This function, when used from the higher FLAC__SeekableStreamDecoder + * layer, can be used in more quickly determining FLAC frame boundaries + * when decoding of the actual data is not needed, for example when an + * application is separating a FLAC stream into frames for editing or + * storing in a container. To do this, the application can use + * FLAC__seekable_stream_decoder_skip_single_frame() to quickly advance + * to the next frame, then use + * FLAC__seekable_stream_decoder_get_decode_position() to find the new + * frame boundary. + * + * This function should only be called when the stream has advanced + * past all the metadata, otherwise it will return \c false. + * + * \param decoder An initialized decoder instance not in a metadata + * state. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if any read or write error occurred (except + * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC), or if the decoder + * is in the FLAC__STREAM_DECODER_SEARCH_FOR_METADATA or + * FLAC__STREAM_DECODER_READ_METADATA state, else \c true; + * in any case, check the decoder state with + * FLAC__stream_decoder_get_state() to see what went wrong or to + * check for lost synchronization (a sign of stream corruption). + */ +FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder); + +/* \} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/FLAC/Makefile.mgw b/FLAC/Makefile.mgw index 103847fa8..3d402d64b 100644 --- a/FLAC/Makefile.mgw +++ b/FLAC/Makefile.mgw @@ -12,7 +12,7 @@ STATICLIB = libflac.a #LOC = -DASMV #LOC = -DDEBUG -g -DEFINES = -D__MINW32__ -DWIN32 -DNDEBUG -D_LIB -DFLAC__CPU_IA32 -DFLAC_HAS_NASM -DFLAC__SSE_OS -DFLAC__USE_3DNOW -I. +DEFINES = -D__MINW32__ -DWIN32 -DNDEBUG -D_LIB -DFLAC__CPU_IA32 -DFLAC_HAS_NASM -DFLAC__SSE_OS -DFLAC__USE_3DNOW -DFLAC__NO_DLL -I. CCDV = @../ccdv CC = gcc diff --git a/FLAC/bitbuffer.c b/FLAC/bitbuffer.c index d31976a51..7eaab0ab6 100644 --- a/FLAC/bitbuffer.c +++ b/FLAC/bitbuffer.c @@ -1,2530 +1,2539 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#include /* for malloc() */ -#include /* for memcpy(), memset() */ -#include "private/bitbuffer.h" -#include "private/bitmath.h" -#include "private/crc.h" -#include "FLAC/assert.h" - -/* - * Along the way you will see two versions of some functions, selected - * by a FLAC__NO_MANUAL_INLINING macro. One is the simplified, more - * readable, and slow version, and the other is the same function - * where crucial parts have been manually inlined and are much faster. - * - */ - -/* - * This should be at least twice as large as the largest number of blurbs - * required to represent any 'number' (in any encoding) you are going to - * read. With FLAC this is on the order of maybe a few hundred bits. - * If the buffer is smaller than that, the decoder won't be able to read - * in a whole number that is in a variable length encoding (e.g. Rice). - * - * The number we are actually using here is based on what would be the - * approximate maximum size of a verbatim frame at the default block size, - * for CD audio (4096 sample * 4 bytes per sample), plus some wiggle room. - * 32kbytes sounds reasonable. For kicks we subtract out 64 bytes for any - * alignment or malloc overhead. - * - * Increase this number to decrease the number of read callbacks, at the - * expense of using more memory. Or decrease for the reverse effect, - * keeping in mind the limit from the first paragraph. - */ -static const unsigned FLAC__BITBUFFER_DEFAULT_CAPACITY = ((65536 - 64) * 8) / FLAC__BITS_PER_BLURB; /* blurbs */ - -#if FLAC__BITS_PER_BLURB == 8 -#define FLAC__BITS_PER_BLURB_LOG2 3 -#define FLAC__BYTES_PER_BLURB 1 -#define FLAC__BLURB_ALL_ONES ((FLAC__byte)0xff) -#define FLAC__BLURB_TOP_BIT_ONE ((FLAC__byte)0x80) -#define BLURB_BIT_TO_MASK(b) (((FLAC__blurb)'\x80') >> (b)) -#define CRC16_UPDATE_BLURB(bb, blurb, crc) FLAC__CRC16_UPDATE((blurb), (crc)); -#elif FLAC__BITS_PER_BLURB == 32 -#define FLAC__BITS_PER_BLURB_LOG2 5 -#define FLAC__BYTES_PER_BLURB 4 -#define FLAC__BLURB_ALL_ONES ((FLAC__uint32)0xffffffff) -#define FLAC__BLURB_TOP_BIT_ONE ((FLAC__uint32)0x80000000) -#define BLURB_BIT_TO_MASK(b) (((FLAC__blurb)0x80000000) >> (b)) -#define CRC16_UPDATE_BLURB(bb, blurb, crc) crc16_update_blurb((bb), (blurb)); -#else -/* ERROR, only sizes of 8 and 32 are supported */ -#endif - -#define FLAC__BLURBS_TO_BITS(blurbs) ((blurbs) << FLAC__BITS_PER_BLURB_LOG2) - -#ifdef min -#undef min -#endif -#define min(x,y) ((x)<(y)?(x):(y)) -#ifdef max -#undef max -#endif -#define max(x,y) ((x)>(y)?(x):(y)) - -/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ -#ifdef _MSC_VER -#define FLAC__U64L(x) x -#else -#define FLAC__U64L(x) x##LLU -#endif - -#ifndef FLaC__INLINE -#define FLaC__INLINE -#endif - -struct FLAC__BitBuffer { - FLAC__blurb *buffer; - unsigned capacity; /* in blurbs */ - unsigned blurbs, bits; - unsigned total_bits; /* must always == FLAC__BITS_PER_BLURB*blurbs+bits */ - unsigned consumed_blurbs, consumed_bits; - unsigned total_consumed_bits; /* must always == FLAC__BITS_PER_BLURB*consumed_blurbs+consumed_bits */ - FLAC__uint16 read_crc16; -#if FLAC__BITS_PER_BLURB == 32 - unsigned crc16_align; -#endif - FLAC__blurb save_head, save_tail; -}; - -#if FLAC__BITS_PER_BLURB == 32 -static void crc16_update_blurb(FLAC__BitBuffer *bb, FLAC__blurb blurb) -{ - if(bb->crc16_align == 0) { - FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); - FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); - FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); - FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); - } - else if(bb->crc16_align == 8) { - FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); - FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); - FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); - } - else if(bb->crc16_align == 16) { - FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); - FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); - } - else if(bb->crc16_align == 24) { - FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); - } - bb->crc16_align = 0; -} -#endif - -/* - * WATCHOUT: The current implentation is not friendly to shrinking, i.e. it - * does not shift left what is consumed, it just chops off the end, whether - * there is unconsumed data there or not. This is OK because currently we - * never shrink the buffer, but if this ever changes, we'll have to do some - * fixups here. - */ -static FLAC__bool bitbuffer_resize_(FLAC__BitBuffer *bb, unsigned new_capacity) -{ - FLAC__blurb *new_buffer; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - if(bb->capacity == new_capacity) - return true; - - new_buffer = (FLAC__blurb*)calloc(new_capacity, sizeof(FLAC__blurb)); - if(new_buffer == 0) - return false; - memcpy(new_buffer, bb->buffer, sizeof(FLAC__blurb)*min(bb->blurbs+(bb->bits?1:0), new_capacity)); - if(new_capacity < bb->blurbs+(bb->bits?1:0)) { - bb->blurbs = new_capacity; - bb->bits = 0; - bb->total_bits = FLAC__BLURBS_TO_BITS(new_capacity); - } - if(new_capacity < bb->consumed_blurbs+(bb->consumed_bits?1:0)) { - bb->consumed_blurbs = new_capacity; - bb->consumed_bits = 0; - bb->total_consumed_bits = FLAC__BLURBS_TO_BITS(new_capacity); - } - free(bb->buffer); /* we've already asserted above that (0 != bb->buffer) */ - bb->buffer = new_buffer; - bb->capacity = new_capacity; - return true; -} - -static FLAC__bool bitbuffer_grow_(FLAC__BitBuffer *bb, unsigned min_blurbs_to_add) -{ - unsigned new_capacity; - - FLAC__ASSERT(min_blurbs_to_add > 0); - - new_capacity = max(bb->capacity * 2, bb->capacity + min_blurbs_to_add); - return bitbuffer_resize_(bb, new_capacity); -} - -static FLAC__bool bitbuffer_ensure_size_(FLAC__BitBuffer *bb, unsigned bits_to_add) -{ - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - if(FLAC__BLURBS_TO_BITS(bb->capacity) < bb->total_bits + bits_to_add) - return bitbuffer_grow_(bb, (bits_to_add >> FLAC__BITS_PER_BLURB_LOG2) + 2); - else - return true; -} - -static FLAC__bool bitbuffer_read_from_client_(FLAC__BitBuffer *bb, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - unsigned bytes; - FLAC__byte *target; - - /* first shift the unconsumed buffer data toward the front as much as possible */ - if(bb->total_consumed_bits >= FLAC__BITS_PER_BLURB) { - unsigned l = 0, r = bb->consumed_blurbs, r_end = bb->blurbs + (bb->bits? 1:0); - for( ; r < r_end; l++, r++) - bb->buffer[l] = bb->buffer[r]; - for( ; l < r_end; l++) - bb->buffer[l] = 0; - bb->blurbs -= bb->consumed_blurbs; - bb->total_bits -= FLAC__BLURBS_TO_BITS(bb->consumed_blurbs); - bb->consumed_blurbs = 0; - bb->total_consumed_bits = bb->consumed_bits; - } - - /* grow if we need to */ - if(bb->capacity <= 1) { - if(!bitbuffer_resize_(bb, 16)) - return false; - } - - /* set the target for reading, taking into account blurb alignment */ -#if FLAC__BITS_PER_BLURB == 8 - /* blurb == byte, so no gyrations necessary: */ - target = bb->buffer + bb->blurbs; - bytes = bb->capacity - bb->blurbs; -#elif FLAC__BITS_PER_BLURB == 32 - /* @@@ WATCHOUT: code currently only works for big-endian: */ - FLAC__ASSERT((bb->bits & 7) == 0); - target = (FLAC__byte*)(bb->buffer + bb->blurbs) + (bb->bits >> 3); - bytes = ((bb->capacity - bb->blurbs) << 2) - (bb->bits >> 3); /* i.e. (bb->capacity - bb->blurbs) * FLAC__BYTES_PER_BLURB - (bb->bits / 8) */ -#else - FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ -#endif - - /* finally, read in some data */ - if(!read_callback(target, &bytes, client_data)) - return false; - - /* now we have to handle partial blurb cases: */ -#if FLAC__BITS_PER_BLURB == 8 - /* blurb == byte, so no gyrations necessary: */ - bb->blurbs += bytes; - bb->total_bits += FLAC__BLURBS_TO_BITS(bytes); -#elif FLAC__BITS_PER_BLURB == 32 - /* @@@ WATCHOUT: code currently only works for big-endian: */ - { - const unsigned aligned_bytes = (bb->bits >> 3) + bytes; - bb->blurbs += (aligned_bytes >> 2); /* i.e. aligned_bytes / FLAC__BYTES_PER_BLURB */ - bb->bits = (aligned_bytes & 3u) << 3; /* i.e. (aligned_bytes % FLAC__BYTES_PER_BLURB) * 8 */ - bb->total_bits += (bytes << 3); - } -#else - FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ -#endif - return true; -} - -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ - -FLAC__BitBuffer *FLAC__bitbuffer_new() -{ - FLAC__BitBuffer *bb = (FLAC__BitBuffer*)calloc(1, sizeof(FLAC__BitBuffer)); - - /* calloc() implies: - memset(bb, 0, sizeof(FLAC__BitBuffer)); - bb->buffer = 0; - bb->capacity = 0; - bb->blurbs = bb->bits = bb->total_bits = 0; - bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; - */ - return bb; -} - -void FLAC__bitbuffer_delete(FLAC__BitBuffer *bb) -{ - FLAC__ASSERT(0 != bb); - - FLAC__bitbuffer_free(bb); - free(bb); -} - -/*********************************************************************** - * - * Public class methods - * - ***********************************************************************/ - -FLAC__bool FLAC__bitbuffer_init(FLAC__BitBuffer *bb) -{ - FLAC__ASSERT(0 != bb); - - bb->buffer = 0; - bb->capacity = 0; - bb->blurbs = bb->bits = bb->total_bits = 0; - bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; - - return FLAC__bitbuffer_clear(bb); -} - -FLAC__bool FLAC__bitbuffer_init_from(FLAC__BitBuffer *bb, const FLAC__byte buffer[], unsigned bytes) -{ - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(bytes > 0); - - if(!FLAC__bitbuffer_init(bb)) - return false; - - if(!bitbuffer_ensure_size_(bb, bytes << 3)) - return false; - - FLAC__ASSERT(0 != buffer); - /* @@@ WATCHOUT: code currently only works for 8-bits-per-blurb inclusive-or big-endian: */ - memcpy((FLAC__byte*)bb->buffer, buffer, sizeof(FLAC__byte)*bytes); - bb->blurbs = bytes / FLAC__BYTES_PER_BLURB; - bb->bits = (bytes % FLAC__BYTES_PER_BLURB) << 3; - bb->total_bits = bytes << 3; - return true; -} - -FLAC__bool FLAC__bitbuffer_concatenate_aligned(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src) -{ - unsigned bits_to_add = src->total_bits - src->total_consumed_bits; - - FLAC__ASSERT(0 != dest); - FLAC__ASSERT(0 != src); - - if(bits_to_add == 0) - return true; - if(dest->bits != src->consumed_bits) - return false; - if(!bitbuffer_ensure_size_(dest, bits_to_add)) - return false; - if(dest->bits == 0) { - memcpy(dest->buffer+dest->blurbs, src->buffer+src->consumed_blurbs, sizeof(FLAC__blurb)*(src->blurbs-src->consumed_blurbs + ((src->bits)? 1:0))); - } - else if(dest->bits + bits_to_add > FLAC__BITS_PER_BLURB) { - dest->buffer[dest->blurbs] <<= (FLAC__BITS_PER_BLURB - dest->bits); - dest->buffer[dest->blurbs] |= (src->buffer[src->consumed_blurbs] & ((1u << (FLAC__BITS_PER_BLURB-dest->bits)) - 1)); - memcpy(dest->buffer+dest->blurbs+1, src->buffer+src->consumed_blurbs+1, sizeof(FLAC__blurb)*(src->blurbs-src->consumed_blurbs-1 + ((src->bits)? 1:0))); - } - else { - dest->buffer[dest->blurbs] <<= bits_to_add; - dest->buffer[dest->blurbs] |= (src->buffer[src->consumed_blurbs] & ((1u << bits_to_add) - 1)); - } - dest->bits = src->bits; - dest->total_bits += bits_to_add; - dest->blurbs = dest->total_bits / FLAC__BITS_PER_BLURB; - - return true; -} - -void FLAC__bitbuffer_free(FLAC__BitBuffer *bb) -{ - FLAC__ASSERT(0 != bb); - - if(0 != bb->buffer) - free(bb->buffer); - bb->buffer = 0; - bb->capacity = 0; - bb->blurbs = bb->bits = bb->total_bits = 0; - bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; -} - -FLAC__bool FLAC__bitbuffer_clear(FLAC__BitBuffer *bb) -{ - if(bb->buffer == 0) { - bb->capacity = FLAC__BITBUFFER_DEFAULT_CAPACITY; - bb->buffer = (FLAC__blurb*)calloc(bb->capacity, sizeof(FLAC__blurb)); - if(bb->buffer == 0) - return false; - } - else { - memset(bb->buffer, 0, bb->blurbs + (bb->bits?1:0)); - } - bb->blurbs = bb->bits = bb->total_bits = 0; - bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; - return true; -} - -FLAC__bool FLAC__bitbuffer_clone(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src) -{ - FLAC__ASSERT(0 != dest); - FLAC__ASSERT(0 != dest->buffer); - FLAC__ASSERT(0 != src); - FLAC__ASSERT(0 != src->buffer); - - if(dest->capacity < src->capacity) - if(!bitbuffer_resize_(dest, src->capacity)) - return false; - memcpy(dest->buffer, src->buffer, sizeof(FLAC__blurb)*min(src->capacity, src->blurbs+1)); - dest->blurbs = src->blurbs; - dest->bits = src->bits; - dest->total_bits = src->total_bits; - dest->consumed_blurbs = src->consumed_blurbs; - dest->consumed_bits = src->consumed_bits; - dest->total_consumed_bits = src->total_consumed_bits; - dest->read_crc16 = src->read_crc16; - return true; -} - -void FLAC__bitbuffer_reset_read_crc16(FLAC__BitBuffer *bb, FLAC__uint16 seed) -{ - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT((bb->consumed_bits & 7) == 0); - - bb->read_crc16 = seed; -#if FLAC__BITS_PER_BLURB == 8 - /* no need to do anything */ -#elif FLAC__BITS_PER_BLURB == 32 - bb->crc16_align = bb->consumed_bits; -#else - FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ -#endif -} - -FLAC__uint16 FLAC__bitbuffer_get_read_crc16(FLAC__BitBuffer *bb) -{ - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT((bb->bits & 7) == 0); - FLAC__ASSERT((bb->consumed_bits & 7) == 0); - -#if FLAC__BITS_PER_BLURB == 8 - /* no need to do anything */ -#elif FLAC__BITS_PER_BLURB == 32 - /*@@@ BUG: even though this probably can't happen with FLAC, need to fix the case where we are called here for the very first blurb and crc16_align is > 0 */ - if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { - if(bb->consumed_bits == 8) { - const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; - FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); - } - else if(bb->consumed_bits == 16) { - const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; - FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); - FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); - } - else if(bb->consumed_bits == 24) { - const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; - FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); - FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); - FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); - } - } - else { - if(bb->consumed_bits == 8) { - const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; - FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16); - } - else if(bb->consumed_bits == 16) { - const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; - FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16); - FLAC__CRC16_UPDATE((blurb >> (bb->bits-16)) & 0xff, bb->read_crc16); - } - else if(bb->consumed_bits == 24) { - const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; - FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16); - FLAC__CRC16_UPDATE((blurb >> (bb->bits-16)) & 0xff, bb->read_crc16); - FLAC__CRC16_UPDATE((blurb >> (bb->bits-24)) & 0xff, bb->read_crc16); - } - } - bb->crc16_align = bb->consumed_bits; -#else - FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ -#endif - return bb->read_crc16; -} - -FLAC__uint16 FLAC__bitbuffer_get_write_crc16(const FLAC__BitBuffer *bb) -{ - FLAC__ASSERT((bb->bits & 7) == 0); /* assert that we're byte-aligned */ - -#if FLAC__BITS_PER_BLURB == 8 - return FLAC__crc16(bb->buffer, bb->blurbs); -#elif FLAC__BITS_PER_BLURB == 32 - /* @@@ WATCHOUT: code currently only works for big-endian: */ - return FLAC__crc16((FLAC__byte*)(bb->buffer), (bb->blurbs * FLAC__BYTES_PER_BLURB) + (bb->bits >> 3)); -#else - FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ -#endif -} - -FLAC__byte FLAC__bitbuffer_get_write_crc8(const FLAC__BitBuffer *bb) -{ - FLAC__ASSERT(0 != bb); - FLAC__ASSERT((bb->bits & 7) == 0); /* assert that we're byte-aligned */ - FLAC__ASSERT(bb->buffer[0] == 0xff); /* MAGIC NUMBER for the first byte of the sync code */ -#if FLAC__BITS_PER_BLURB == 8 - return FLAC__crc8(bb->buffer, bb->blurbs); -#elif FLAC__BITS_PER_BLURB == 32 - /* @@@ WATCHOUT: code currently only works for big-endian: */ - return FLAC__crc8((FLAC__byte*)(bb->buffer), (bb->blurbs * FLAC__BYTES_PER_BLURB) + (bb->bits >> 3)); -#else - FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ -#endif -} - -FLAC__bool FLAC__bitbuffer_is_byte_aligned(const FLAC__BitBuffer *bb) -{ - return ((bb->bits & 7) == 0); -} - -FLAC__bool FLAC__bitbuffer_is_consumed_byte_aligned(const FLAC__BitBuffer *bb) -{ - return ((bb->consumed_bits & 7) == 0); -} - -unsigned FLAC__bitbuffer_bits_left_for_byte_alignment(const FLAC__BitBuffer *bb) -{ - return 8 - (bb->consumed_bits & 7); -} - -unsigned FLAC__bitbuffer_get_input_bytes_unconsumed(const FLAC__BitBuffer *bb) -{ - FLAC__ASSERT((bb->consumed_bits & 7) == 0 && (bb->bits & 7) == 0); - return (bb->total_bits - bb->total_consumed_bits) >> 3; -} - -void FLAC__bitbuffer_get_buffer(FLAC__BitBuffer *bb, const FLAC__byte **buffer, unsigned *bytes) -{ - FLAC__ASSERT((bb->consumed_bits & 7) == 0 && (bb->bits & 7) == 0); -#if FLAC__BITS_PER_BLURB == 8 - *buffer = bb->buffer + bb->consumed_blurbs; - *bytes = bb->blurbs - bb->consumed_blurbs; -#elif FLAC__BITS_PER_BLURB == 32 - /* @@@ WATCHOUT: code currently only works for big-endian: */ - *buffer = (FLAC__byte*)(bb->buffer + bb->consumed_blurbs) + (bb->consumed_bits >> 3); - *bytes = (bb->total_bits - bb->total_consumed_bits) >> 3; -#else - FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ -#endif -} - -void FLAC__bitbuffer_release_buffer(FLAC__BitBuffer *bb) -{ -#if FLAC__BITS_PER_BLURB == 8 - (void)bb; -#elif FLAC__BITS_PER_BLURB == 32 - /* @@@ WATCHOUT: code currently only works for big-endian: */ - (void)bb; -#else - FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ -#endif -} - -FLAC__bool FLAC__bitbuffer_write_zeroes(FLAC__BitBuffer *bb, unsigned bits) -{ - unsigned n; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - if(bits == 0) - return true; - if(!bitbuffer_ensure_size_(bb, bits)) - return false; - bb->total_bits += bits; - while(bits > 0) { - n = min(FLAC__BITS_PER_BLURB - bb->bits, bits); - bb->buffer[bb->blurbs] <<= n; - bits -= n; - bb->bits += n; - if(bb->bits == FLAC__BITS_PER_BLURB) { - bb->blurbs++; - bb->bits = 0; - } - } - return true; -} - -FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_raw_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val, unsigned bits) -{ - unsigned n, k; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - FLAC__ASSERT(bits <= 32); - if(bits == 0) - return true; - /* inline the size check so we don't incure a function call unnecessarily */ - if(FLAC__BLURBS_TO_BITS(bb->capacity) < bb->total_bits + bits) { - if(!bitbuffer_ensure_size_(bb, bits)) - return false; - } - - /* zero-out unused bits; WATCHOUT: other code relies on this, so this needs to stay */ - if(bits < 32) /* @@@ gcc seems to require this because the following line causes incorrect results when bits==32; investigate */ - val &= (~(0xffffffff << bits)); /* zero-out unused bits */ - - bb->total_bits += bits; - while(bits > 0) { - n = FLAC__BITS_PER_BLURB - bb->bits; - if(n == FLAC__BITS_PER_BLURB) { /* i.e. bb->bits == 0 */ - if(bits < FLAC__BITS_PER_BLURB) { - bb->buffer[bb->blurbs] = (FLAC__blurb)val; - bb->bits = bits; - break; - } - else if(bits == FLAC__BITS_PER_BLURB) { - bb->buffer[bb->blurbs++] = (FLAC__blurb)val; - break; - } - else { - k = bits - FLAC__BITS_PER_BLURB; - bb->buffer[bb->blurbs++] = (FLAC__blurb)(val >> k); - /* we know k < 32 so no need to protect against the gcc bug mentioned above */ - val &= (~(0xffffffff << k)); - bits -= FLAC__BITS_PER_BLURB; - } - } - else if(bits <= n) { - bb->buffer[bb->blurbs] <<= bits; - bb->buffer[bb->blurbs] |= val; - if(bits == n) { - bb->blurbs++; - bb->bits = 0; - } - else - bb->bits += bits; - break; - } - else { - k = bits - n; - bb->buffer[bb->blurbs] <<= n; - bb->buffer[bb->blurbs] |= (val >> k); - /* we know n > 0 so k < 32 so no need to protect against the gcc bug mentioned above */ - val &= (~(0xffffffff << k)); - bits -= n; - bb->blurbs++; - bb->bits = 0; - } - } - - return true; -} - -FLAC__bool FLAC__bitbuffer_write_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 val, unsigned bits) -{ - return FLAC__bitbuffer_write_raw_uint32(bb, (FLAC__uint32)val, bits); -} - -FLAC__bool FLAC__bitbuffer_write_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 val, unsigned bits) -{ - static const FLAC__uint64 mask[] = { - 0, - FLAC__U64L(0x0000000000000001), FLAC__U64L(0x0000000000000003), FLAC__U64L(0x0000000000000007), FLAC__U64L(0x000000000000000F), - FLAC__U64L(0x000000000000001F), FLAC__U64L(0x000000000000003F), FLAC__U64L(0x000000000000007F), FLAC__U64L(0x00000000000000FF), - FLAC__U64L(0x00000000000001FF), FLAC__U64L(0x00000000000003FF), FLAC__U64L(0x00000000000007FF), FLAC__U64L(0x0000000000000FFF), - FLAC__U64L(0x0000000000001FFF), FLAC__U64L(0x0000000000003FFF), FLAC__U64L(0x0000000000007FFF), FLAC__U64L(0x000000000000FFFF), - FLAC__U64L(0x000000000001FFFF), FLAC__U64L(0x000000000003FFFF), FLAC__U64L(0x000000000007FFFF), FLAC__U64L(0x00000000000FFFFF), - FLAC__U64L(0x00000000001FFFFF), FLAC__U64L(0x00000000003FFFFF), FLAC__U64L(0x00000000007FFFFF), FLAC__U64L(0x0000000000FFFFFF), - FLAC__U64L(0x0000000001FFFFFF), FLAC__U64L(0x0000000003FFFFFF), FLAC__U64L(0x0000000007FFFFFF), FLAC__U64L(0x000000000FFFFFFF), - FLAC__U64L(0x000000001FFFFFFF), FLAC__U64L(0x000000003FFFFFFF), FLAC__U64L(0x000000007FFFFFFF), FLAC__U64L(0x00000000FFFFFFFF), - FLAC__U64L(0x00000001FFFFFFFF), FLAC__U64L(0x00000003FFFFFFFF), FLAC__U64L(0x00000007FFFFFFFF), FLAC__U64L(0x0000000FFFFFFFFF), - FLAC__U64L(0x0000001FFFFFFFFF), FLAC__U64L(0x0000003FFFFFFFFF), FLAC__U64L(0x0000007FFFFFFFFF), FLAC__U64L(0x000000FFFFFFFFFF), - FLAC__U64L(0x000001FFFFFFFFFF), FLAC__U64L(0x000003FFFFFFFFFF), FLAC__U64L(0x000007FFFFFFFFFF), FLAC__U64L(0x00000FFFFFFFFFFF), - FLAC__U64L(0x00001FFFFFFFFFFF), FLAC__U64L(0x00003FFFFFFFFFFF), FLAC__U64L(0x00007FFFFFFFFFFF), FLAC__U64L(0x0000FFFFFFFFFFFF), - FLAC__U64L(0x0001FFFFFFFFFFFF), FLAC__U64L(0x0003FFFFFFFFFFFF), FLAC__U64L(0x0007FFFFFFFFFFFF), FLAC__U64L(0x000FFFFFFFFFFFFF), - FLAC__U64L(0x001FFFFFFFFFFFFF), FLAC__U64L(0x003FFFFFFFFFFFFF), FLAC__U64L(0x007FFFFFFFFFFFFF), FLAC__U64L(0x00FFFFFFFFFFFFFF), - FLAC__U64L(0x01FFFFFFFFFFFFFF), FLAC__U64L(0x03FFFFFFFFFFFFFF), FLAC__U64L(0x07FFFFFFFFFFFFFF), FLAC__U64L(0x0FFFFFFFFFFFFFFF), - FLAC__U64L(0x1FFFFFFFFFFFFFFF), FLAC__U64L(0x3FFFFFFFFFFFFFFF), FLAC__U64L(0x7FFFFFFFFFFFFFFF), FLAC__U64L(0xFFFFFFFFFFFFFFFF) - }; - unsigned n, k; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - FLAC__ASSERT(bits <= 64); - if(bits == 0) - return true; - if(!bitbuffer_ensure_size_(bb, bits)) - return false; - val &= mask[bits]; - bb->total_bits += bits; - while(bits > 0) { - if(bb->bits == 0) { - if(bits < FLAC__BITS_PER_BLURB) { - bb->buffer[bb->blurbs] = (FLAC__blurb)val; - bb->bits = bits; - break; - } - else if(bits == FLAC__BITS_PER_BLURB) { - bb->buffer[bb->blurbs++] = (FLAC__blurb)val; - break; - } - else { - k = bits - FLAC__BITS_PER_BLURB; - bb->buffer[bb->blurbs++] = (FLAC__blurb)(val >> k); - /* we know k < 64 so no need to protect against the gcc bug mentioned above */ - val &= (~(FLAC__U64L(0xffffffffffffffff) << k)); - bits -= FLAC__BITS_PER_BLURB; - } - } - else { - n = min(FLAC__BITS_PER_BLURB - bb->bits, bits); - k = bits - n; - bb->buffer[bb->blurbs] <<= n; - bb->buffer[bb->blurbs] |= (val >> k); - /* we know n > 0 so k < 64 so no need to protect against the gcc bug mentioned above */ - val &= (~(FLAC__U64L(0xffffffffffffffff) << k)); - bits -= n; - bb->bits += n; - if(bb->bits == FLAC__BITS_PER_BLURB) { - bb->blurbs++; - bb->bits = 0; - } - } - } - - return true; -} - -#if 0 /* UNUSED */ -FLAC__bool FLAC__bitbuffer_write_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 val, unsigned bits) -{ - return FLAC__bitbuffer_write_raw_uint64(bb, (FLAC__uint64)val, bits); -} -#endif - -FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_raw_uint32_little_endian(FLAC__BitBuffer *bb, FLAC__uint32 val) -{ - /* this doesn't need to be that fast as currently it is only used for vorbis comments */ - - /* NOTE: we rely on the fact that FLAC__bitbuffer_write_raw_uint32() masks out the unused bits */ - if(!FLAC__bitbuffer_write_raw_uint32(bb, val, 8)) - return false; - if(!FLAC__bitbuffer_write_raw_uint32(bb, val>>8, 8)) - return false; - if(!FLAC__bitbuffer_write_raw_uint32(bb, val>>16, 8)) - return false; - if(!FLAC__bitbuffer_write_raw_uint32(bb, val>>24, 8)) - return false; - - return true; -} - -FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_byte_block(FLAC__BitBuffer *bb, const FLAC__byte vals[], unsigned nvals) -{ - unsigned i; - - /* this could be faster but currently we don't need it to be */ - for(i = 0; i < nvals; i++) { - if(!FLAC__bitbuffer_write_raw_uint32(bb, (FLAC__uint32)(vals[i]), 8)) - return false; - } - - return true; -} - -FLAC__bool FLAC__bitbuffer_write_unary_unsigned(FLAC__BitBuffer *bb, unsigned val) -{ - if(val < 32) - return FLAC__bitbuffer_write_raw_uint32(bb, 1, ++val); - else if(val < 64) - return FLAC__bitbuffer_write_raw_uint64(bb, 1, ++val); - else { - if(!FLAC__bitbuffer_write_zeroes(bb, val)) - return false; - return FLAC__bitbuffer_write_raw_uint32(bb, 1, 1); - } -} - -unsigned FLAC__bitbuffer_rice_bits(int val, unsigned parameter) -{ - unsigned msbs, uval; - - /* fold signed to unsigned */ - if(val < 0) - /* equivalent to - * (unsigned)(((--val) << 1) - 1); - * but without the overflow problem at MININT - */ - uval = (unsigned)(((-(++val)) << 1) + 1); - else - uval = (unsigned)(val << 1); - - msbs = uval >> parameter; - - return 1 + parameter + msbs; -} - -#if 0 /* UNUSED */ -unsigned FLAC__bitbuffer_golomb_bits_signed(int val, unsigned parameter) -{ - unsigned bits, msbs, uval; - unsigned k; - - FLAC__ASSERT(parameter > 0); - - /* fold signed to unsigned */ - if(val < 0) - /* equivalent to - * (unsigned)(((--val) << 1) - 1); - * but without the overflow problem at MININT - */ - uval = (unsigned)(((-(++val)) << 1) + 1); - else - uval = (unsigned)(val << 1); - - k = FLAC__bitmath_ilog2(parameter); - if(parameter == 1u<> k; - bits = 1 + k + msbs; - } - else { - unsigned q, r, d; - - d = (1 << (k+1)) - parameter; - q = uval / parameter; - r = uval - (q * parameter); - - bits = 1 + q + k; - if(r >= d) - bits++; - } - return bits; -} - -unsigned FLAC__bitbuffer_golomb_bits_unsigned(unsigned uval, unsigned parameter) -{ - unsigned bits, msbs; - unsigned k; - - FLAC__ASSERT(parameter > 0); - - k = FLAC__bitmath_ilog2(parameter); - if(parameter == 1u<> k; - bits = 1 + k + msbs; - } - else { - unsigned q, r, d; - - d = (1 << (k+1)) - parameter; - q = uval / parameter; - r = uval - (q * parameter); - - bits = 1 + q + k; - if(r >= d) - bits++; - } - return bits; -} -#endif /* UNUSED */ - -#ifdef FLAC__SYMMETRIC_RICE -FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter) -{ - unsigned total_bits, interesting_bits, msbs; - FLAC__uint32 pattern; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(parameter <= 31); - - /* init pattern with the unary end bit and the sign bit */ - if(val < 0) { - pattern = 3; - val = -val; - } - else - pattern = 2; - - msbs = val >> parameter; - interesting_bits = 2 + parameter; - total_bits = interesting_bits + msbs; - pattern <<= parameter; - pattern |= (val & ((1<buffer); - FLAC__ASSERT(parameter <= 31); - - *overflow = false; - - /* init pattern with the unary end bit and the sign bit */ - if(val < 0) { - pattern = 3; - val = -val; - } - else - pattern = 2; - - msbs = val >> parameter; - interesting_bits = 2 + parameter; - total_bits = interesting_bits + msbs; - pattern <<= parameter; - pattern |= (val & ((1< max_bits) { - *overflow = true; - return true; - } - else { - /* write the unary MSBs */ - if(!FLAC__bitbuffer_write_zeroes(bb, msbs)) - return false; - /* write the unary end bit, the sign bit, and binary LSBs */ - if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, interesting_bits)) - return false; - } - return true; -} -#endif /* UNUSED */ - -FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_escape(FLAC__BitBuffer *bb, int val, unsigned parameter) -{ - unsigned total_bits, val_bits; - FLAC__uint32 pattern; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(parameter <= 31); - - val_bits = FLAC__bitmath_silog2(val); - total_bits = 2 + parameter + 5 + val_bits; - - if(total_bits <= 32) { - pattern = 3; - pattern <<= (parameter + 5); - pattern |= val_bits; - pattern <<= val_bits; - pattern |= (val & ((1 << val_bits) - 1)); - if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, total_bits)) - return false; - } - else { - /* write the '-0' escape code first */ - if(!FLAC__bitbuffer_write_raw_uint32(bb, 3u << parameter, 2+parameter)) - return false; - /* write the length */ - if(!FLAC__bitbuffer_write_raw_uint32(bb, val_bits, 5)) - return false; - /* write the value */ - if(!FLAC__bitbuffer_write_raw_int32(bb, val, val_bits)) - return false; - } - return true; -} -#endif /* ifdef FLAC__SYMMETRIC_RICE */ - -FLAC__bool FLAC__bitbuffer_write_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter) -{ - unsigned total_bits, interesting_bits, msbs, uval; - FLAC__uint32 pattern; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(parameter <= 30); - - /* fold signed to unsigned */ - if(val < 0) - /* equivalent to - * (unsigned)(((--val) << 1) - 1); - * but without the overflow problem at MININT - */ - uval = (unsigned)(((-(++val)) << 1) + 1); - else - uval = (unsigned)(val << 1); - - msbs = uval >> parameter; - interesting_bits = 1 + parameter; - total_bits = interesting_bits + msbs; - pattern = 1 << parameter; /* the unary end bit */ - pattern |= (uval & ((1<buffer); - FLAC__ASSERT(parameter <= 30); - - *overflow = false; - - /* fold signed to unsigned */ - if(val < 0) - /* equivalent to - * (unsigned)(((--val) << 1) - 1); - * but without the overflow problem at MININT - */ - uval = (unsigned)(((-(++val)) << 1) + 1); - else - uval = (unsigned)(val << 1); - - msbs = uval >> parameter; - interesting_bits = 1 + parameter; - total_bits = interesting_bits + msbs; - pattern = 1 << parameter; /* the unary end bit */ - pattern |= (uval & ((1< max_bits) { - *overflow = true; - return true; - } - else { - /* write the unary MSBs */ - if(!FLAC__bitbuffer_write_zeroes(bb, msbs)) - return false; - /* write the unary end bit and binary LSBs */ - if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, interesting_bits)) - return false; - } - return true; -} -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -FLAC__bool FLAC__bitbuffer_write_golomb_signed(FLAC__BitBuffer *bb, int val, unsigned parameter) -{ - unsigned total_bits, msbs, uval; - unsigned k; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(parameter > 0); - - /* fold signed to unsigned */ - if(val < 0) - /* equivalent to - * (unsigned)(((--val) << 1) - 1); - * but without the overflow problem at MININT - */ - uval = (unsigned)(((-(++val)) << 1) + 1); - else - uval = (unsigned)(val << 1); - - k = FLAC__bitmath_ilog2(parameter); - if(parameter == 1u<> k; - total_bits = 1 + k + msbs; - pattern = 1 << k; /* the unary end bit */ - pattern |= (uval & ((1u<= d) { - if(!FLAC__bitbuffer_write_raw_uint32(bb, r+d, k+1)) - return false; - } - else { - if(!FLAC__bitbuffer_write_raw_uint32(bb, r, k)) - return false; - } - } - return true; -} - -FLAC__bool FLAC__bitbuffer_write_golomb_unsigned(FLAC__BitBuffer *bb, unsigned uval, unsigned parameter) -{ - unsigned total_bits, msbs; - unsigned k; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(parameter > 0); - - k = FLAC__bitmath_ilog2(parameter); - if(parameter == 1u<> k; - total_bits = 1 + k + msbs; - pattern = 1 << k; /* the unary end bit */ - pattern |= (uval & ((1u<= d) { - if(!FLAC__bitbuffer_write_raw_uint32(bb, r+d, k+1)) - return false; - } - else { - if(!FLAC__bitbuffer_write_raw_uint32(bb, r, k)) - return false; - } - } - return true; -} -#endif /* UNUSED */ - -FLAC__bool FLAC__bitbuffer_write_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val) -{ - FLAC__bool ok = 1; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - FLAC__ASSERT(!(val & 0x80000000)); /* this version only handles 31 bits */ - - if(val < 0x80) { - return FLAC__bitbuffer_write_raw_uint32(bb, val, 8); - } - else if(val < 0x800) { - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xC0 | (val>>6), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); - } - else if(val < 0x10000) { - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xE0 | (val>>12), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); - } - else if(val < 0x200000) { - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF0 | (val>>18), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); - } - else if(val < 0x4000000) { - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF8 | (val>>24), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>18)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); - } - else { - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFC | (val>>30), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>24)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>18)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); - } - - return ok; -} - -FLAC__bool FLAC__bitbuffer_write_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 val) -{ - FLAC__bool ok = 1; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - FLAC__ASSERT(!(val & FLAC__U64L(0xFFFFFFF000000000))); /* this version only handles 36 bits */ - - if(val < 0x80) { - return FLAC__bitbuffer_write_raw_uint32(bb, (FLAC__uint32)val, 8); - } - else if(val < 0x800) { - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xC0 | (FLAC__uint32)(val>>6), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); - } - else if(val < 0x10000) { - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xE0 | (FLAC__uint32)(val>>12), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); - } - else if(val < 0x200000) { - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF0 | (FLAC__uint32)(val>>18), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); - } - else if(val < 0x4000000) { - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF8 | (FLAC__uint32)(val>>24), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); - } - else if(val < 0x80000000) { - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFC | (FLAC__uint32)(val>>30), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); - } - else { - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFE, 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>30)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); - ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); - } - - return ok; -} - -FLAC__bool FLAC__bitbuffer_zero_pad_to_byte_boundary(FLAC__BitBuffer *bb) -{ - /* 0-pad to byte boundary */ - if(bb->bits & 7u) - return FLAC__bitbuffer_write_zeroes(bb, 8 - (bb->bits & 7u)); - else - return true; -} - -FLAC__bool FLAC__bitbuffer_peek_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - /* to avoid a drastic speed penalty we don't: - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(bb->bits == 0); - */ - - while(1) { - if(bb->total_consumed_bits < bb->total_bits) { - *val = (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; - return true; - } - else { - if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) - return false; - } - } -} - -FLAC__bool FLAC__bitbuffer_read_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - /* to avoid a drastic speed penalty we don't: - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(bb->bits == 0); - */ - - while(1) { - if(bb->total_consumed_bits < bb->total_bits) { - *val = (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; - bb->consumed_bits++; - if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - bb->consumed_bits = 0; - } - bb->total_consumed_bits++; - return true; - } - else { - if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) - return false; - } - } -} - -FLAC__bool FLAC__bitbuffer_read_bit_to_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - /* to avoid a drastic speed penalty we don't: - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(bb->bits == 0); - */ - - while(1) { - if(bb->total_consumed_bits < bb->total_bits) { - *val <<= 1; - *val |= (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; - bb->consumed_bits++; - if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - bb->consumed_bits = 0; - } - bb->total_consumed_bits++; - return true; - } - else { - if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) - return false; - } - } -} - -FLAC__bool FLAC__bitbuffer_read_bit_to_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - /* to avoid a drastic speed penalty we don't: - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(bb->bits == 0); - */ - - while(1) { - if(bb->total_consumed_bits < bb->total_bits) { - *val <<= 1; - *val |= (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; - bb->consumed_bits++; - if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - bb->consumed_bits = 0; - } - bb->total_consumed_bits++; - return true; - } - else { - if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) - return false; - } - } -} - -FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_raw_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -#ifdef FLAC__NO_MANUAL_INLINING -{ - unsigned i; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - FLAC__ASSERT(bits <= 32); - - *val = 0; - for(i = 0; i < bits; i++) { - if(!FLAC__bitbuffer_read_bit_to_uint32(bb, val, read_callback, client_data)) - return false; - } - return true; -} -#else -{ - unsigned i, bits_ = bits; - FLAC__uint32 v = 0; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - FLAC__ASSERT(bits <= 32); - FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); - - if(bits == 0) { - *val = 0; - return true; - } - - while(bb->total_consumed_bits + bits > bb->total_bits) { - if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) - return false; - } -#if FLAC__BITS_PER_BLURB > 8 - if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ -#endif - if(bb->consumed_bits) { - i = FLAC__BITS_PER_BLURB - bb->consumed_bits; - if(i <= bits_) { - v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); - bits_ -= i; - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - bb->consumed_bits = 0; - /* we hold off updating bb->total_consumed_bits until the end */ - } - else { - *val = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)) >> (i-bits_); - bb->consumed_bits += bits_; - bb->total_consumed_bits += bits_; - return true; - } - } -#if FLAC__BITS_PER_BLURB == 32 - /* note that we know bits_ cannot be > 32 because of previous assertions */ - if(bits_ == FLAC__BITS_PER_BLURB) { - v = bb->buffer[bb->consumed_blurbs]; - CRC16_UPDATE_BLURB(bb, v, bb->read_crc16); - bb->consumed_blurbs++; - /* bb->consumed_bits is already 0 */ - bb->total_consumed_bits += bits; - *val = v; - return true; - } -#else - while(bits_ >= FLAC__BITS_PER_BLURB) { - v <<= FLAC__BITS_PER_BLURB; - v |= bb->buffer[bb->consumed_blurbs]; - bits_ -= FLAC__BITS_PER_BLURB; - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - /* bb->consumed_bits is already 0 */ - /* we hold off updating bb->total_consumed_bits until the end */ - } -#endif - if(bits_ > 0) { - v <<= bits_; - v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); - bb->consumed_bits = bits_; - /* we hold off updating bb->total_consumed_bits until the end */ - } - bb->total_consumed_bits += bits; - *val = v; -#if FLAC__BITS_PER_BLURB > 8 - } - else { - *val = 0; - for(i = 0; i < bits; i++) { - if(!FLAC__bitbuffer_read_bit_to_uint32(bb, val, read_callback, client_data)) - return false; - } - } -#endif - return true; -} -#endif - -FLAC__bool FLAC__bitbuffer_read_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -#ifdef FLAC__NO_MANUAL_INLINING -{ - unsigned i; - FLAC__uint32 v; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - FLAC__ASSERT(bits <= 32); - - if(bits == 0) { - *val = 0; - return true; - } - - v = 0; - for(i = 0; i < bits; i++) { - if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &v, read_callback, client_data)) - return false; - } - - /* fix the sign */ - i = 32 - bits; - if(i) { - v <<= i; - *val = (FLAC__int32)v; - *val >>= i; - } - else - *val = (FLAC__int32)v; - - return true; -} -#else -{ - unsigned i, bits_ = bits; - FLAC__uint32 v = 0; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - FLAC__ASSERT(bits <= 32); - FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); - - if(bits == 0) { - *val = 0; - return true; - } - - while(bb->total_consumed_bits + bits > bb->total_bits) { - if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) - return false; - } -#if FLAC__BITS_PER_BLURB > 8 - if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ -#endif - if(bb->consumed_bits) { - i = FLAC__BITS_PER_BLURB - bb->consumed_bits; - if(i <= bits_) { - v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); - bits_ -= i; - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - bb->consumed_bits = 0; - /* we hold off updating bb->total_consumed_bits until the end */ - } - else { - /* bits_ must be < FLAC__BITS_PER_BLURB-1 if we get to here */ - v = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)); - v <<= (32-i); - *val = (FLAC__int32)v; - *val >>= (32-bits_); - bb->consumed_bits += bits_; - bb->total_consumed_bits += bits_; - return true; - } - } -#if FLAC__BITS_PER_BLURB == 32 - /* note that we know bits_ cannot be > 32 because of previous assertions */ - if(bits_ == FLAC__BITS_PER_BLURB) { - v = bb->buffer[bb->consumed_blurbs]; - bits_ = 0; - CRC16_UPDATE_BLURB(bb, v, bb->read_crc16); - bb->consumed_blurbs++; - /* bb->consumed_bits is already 0 */ - /* we hold off updating bb->total_consumed_bits until the end */ - } -#else - while(bits_ >= FLAC__BITS_PER_BLURB) { - v <<= FLAC__BITS_PER_BLURB; - v |= bb->buffer[bb->consumed_blurbs]; - bits_ -= FLAC__BITS_PER_BLURB; - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - /* bb->consumed_bits is already 0 */ - /* we hold off updating bb->total_consumed_bits until the end */ - } -#endif - if(bits_ > 0) { - v <<= bits_; - v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); - bb->consumed_bits = bits_; - /* we hold off updating bb->total_consumed_bits until the end */ - } - bb->total_consumed_bits += bits; -#if FLAC__BITS_PER_BLURB > 8 - } - else { - for(i = 0; i < bits; i++) { - if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &v, read_callback, client_data)) - return false; - } - } -#endif - - /* fix the sign */ - i = 32 - bits; - if(i) { - v <<= i; - *val = (FLAC__int32)v; - *val >>= i; - } - else - *val = (FLAC__int32)v; - - return true; -} -#endif - -FLAC__bool FLAC__bitbuffer_read_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -#ifdef FLAC__NO_MANUAL_INLINING -{ - unsigned i; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - FLAC__ASSERT(bits <= 64); - - *val = 0; - for(i = 0; i < bits; i++) { - if(!FLAC__bitbuffer_read_bit_to_uint64(bb, val, read_callback, client_data)) - return false; - } - return true; -} -#else -{ - unsigned i, bits_ = bits; - FLAC__uint64 v = 0; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - FLAC__ASSERT(bits <= 64); - FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); - - if(bits == 0) { - *val = 0; - return true; - } - - while(bb->total_consumed_bits + bits > bb->total_bits) { - if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) - return false; - } -#if FLAC__BITS_PER_BLURB > 8 - if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ -#endif - if(bb->consumed_bits) { - i = FLAC__BITS_PER_BLURB - bb->consumed_bits; - if(i <= bits_) { - v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); - bits_ -= i; - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - bb->consumed_bits = 0; - /* we hold off updating bb->total_consumed_bits until the end */ - } - else { - *val = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)) >> (i-bits_); - bb->consumed_bits += bits_; - bb->total_consumed_bits += bits_; - return true; - } - } - while(bits_ >= FLAC__BITS_PER_BLURB) { - v <<= FLAC__BITS_PER_BLURB; - v |= bb->buffer[bb->consumed_blurbs]; - bits_ -= FLAC__BITS_PER_BLURB; - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - /* bb->consumed_bits is already 0 */ - /* we hold off updating bb->total_consumed_bits until the end */ - } - if(bits_ > 0) { - v <<= bits_; - v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); - bb->consumed_bits = bits_; - /* we hold off updating bb->total_consumed_bits until the end */ - } - bb->total_consumed_bits += bits; - *val = v; -#if FLAC__BITS_PER_BLURB > 8 - } - else { - *val = 0; - for(i = 0; i < bits; i++) { - if(!FLAC__bitbuffer_read_bit_to_uint64(bb, val, read_callback, client_data)) - return false; - } - } -#endif - return true; -} -#endif - -#if 0 /* UNUSED */ -FLAC__bool FLAC__bitbuffer_read_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -#ifdef FLAC__NO_MANUAL_INLINING -{ - unsigned i; - FLAC__uint64 v; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - FLAC__ASSERT(bits <= 64); - - v = 0; - for(i = 0; i < bits; i++) { - if(!FLAC__bitbuffer_read_bit_to_uint64(bb, &v, read_callback, client_data)) - return false; - } - /* fix the sign */ - i = 64 - bits; - if(i) { - v <<= i; - *val = (FLAC__int64)v; - *val >>= i; - } - else - *val = (FLAC__int64)v; - - return true; -} -#else -{ - unsigned i, bits_ = bits; - FLAC__uint64 v = 0; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - FLAC__ASSERT(bits <= 64); - FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); - - if(bits == 0) { - *val = 0; - return true; - } - - while(bb->total_consumed_bits + bits > bb->total_bits) { - if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) - return false; - } -#if FLAC__BITS_PER_BLURB > 8 - if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ -#endif - if(bb->consumed_bits) { - i = FLAC__BITS_PER_BLURB - bb->consumed_bits; - if(i <= bits_) { - v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); - bits_ -= i; - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - bb->consumed_bits = 0; - /* we hold off updating bb->total_consumed_bits until the end */ - } - else { - /* bits_ must be < FLAC__BITS_PER_BLURB-1 if we get to here */ - v = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)); - v <<= (64-i); - *val = (FLAC__int64)v; - *val >>= (64-bits_); - bb->consumed_bits += bits_; - bb->total_consumed_bits += bits_; - return true; - } - } - while(bits_ >= FLAC__BITS_PER_BLURB) { - v <<= FLAC__BITS_PER_BLURB; - v |= bb->buffer[bb->consumed_blurbs]; - bits_ -= FLAC__BITS_PER_BLURB; - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - /* bb->consumed_bits is already 0 */ - /* we hold off updating bb->total_consumed_bits until the end */ - } - if(bits_ > 0) { - v <<= bits_; - v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); - bb->consumed_bits = bits_; - /* we hold off updating bb->total_consumed_bits until the end */ - } - bb->total_consumed_bits += bits; -#if FLAC__BITS_PER_BLURB > 8 - } - else { - for(i = 0; i < bits; i++) { - if(!FLAC__bitbuffer_read_bit_to_uint64(bb, &v, read_callback, client_data)) - return false; - } - } -#endif - - /* fix the sign */ - i = 64 - bits; - if(i) { - v <<= i; - *val = (FLAC__int64)v; - *val >>= i; - } - else - *val = (FLAC__int64)v; - - return true; -} -#endif -#endif - -FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_raw_uint32_little_endian(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - FLAC__uint32 x8, x32 = 0; - - /* this doesn't need to be that fast as currently it is only used for vorbis comments */ - - if(!FLAC__bitbuffer_read_raw_uint32(bb, &x32, 8, read_callback, client_data)) - return false; - - if(!FLAC__bitbuffer_read_raw_uint32(bb, &x8, 8, read_callback, client_data)) - return false; - x32 |= (x8 << 8); - - if(!FLAC__bitbuffer_read_raw_uint32(bb, &x8, 8, read_callback, client_data)) - return false; - x32 |= (x8 << 16); - - if(!FLAC__bitbuffer_read_raw_uint32(bb, &x8, 8, read_callback, client_data)) - return false; - x32 |= (x8 << 24); - - *val = x32; - return true; -} - -FLAC__bool FLAC__bitbuffer_skip_bits_no_crc(FLAC__BitBuffer *bb, unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - /* - * @@@ a slightly faster implementation is possible but - * probably not that useful since this is only called a - * couple of times in the metadata readers. - */ - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - if(bits > 0) { - const unsigned n = bb->consumed_bits & 7; - unsigned m; - FLAC__uint32 x; - - if(n != 0) { - m = min(8-n, bits); - if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, m, read_callback, client_data)) - return false; - bits -= m; - } - m = bits / 8; - if(m > 0) { - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(bb, 0, m, read_callback, client_data)) - return false; - bits %= 8; - } - if(bits > 0) { - if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, bits, read_callback, client_data)) - return false; - } - } - - return true; -} - -FLAC__bool FLAC__bitbuffer_read_byte_block_aligned_no_crc(FLAC__BitBuffer *bb, FLAC__byte *val, unsigned nvals, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(bb)); - FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(bb)); -#if FLAC__BITS_PER_BLURB == 8 - while(nvals > 0) { - unsigned chunk = min(nvals, bb->blurbs - bb->consumed_blurbs); - if(chunk == 0) { - if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) - return false; - } - else { - if(0 != val) { - memcpy(val, bb->buffer + bb->consumed_blurbs, FLAC__BYTES_PER_BLURB * chunk); - val += FLAC__BYTES_PER_BLURB * chunk; - } - nvals -= chunk; - bb->consumed_blurbs += chunk; - bb->total_consumed_bits = (bb->consumed_blurbs << FLAC__BITS_PER_BLURB_LOG2); - } - } -#else - @@@ need to write this still - FLAC__ASSERT(0); -#endif - - return true; -} - -FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_unary_unsigned(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -#ifdef FLAC__NO_MANUAL_INLINING -{ - unsigned bit, val_ = 0; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - while(1) { - if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data)) - return false; - if(bit) - break; - else - val_++; - } - *val = val_; - return true; -} -#else -{ - unsigned i, val_ = 0; - unsigned total_blurbs_ = (bb->total_bits + (FLAC__BITS_PER_BLURB-1)) / FLAC__BITS_PER_BLURB; - FLAC__blurb b; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - -#if FLAC__BITS_PER_BLURB > 8 - if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ -#endif - if(bb->consumed_bits) { - b = bb->buffer[bb->consumed_blurbs] << bb->consumed_bits; - if(b) { - for(i = 0; !(b & FLAC__BLURB_TOP_BIT_ONE); i++) - b <<= 1; - *val = i; - i++; - bb->consumed_bits += i; - bb->total_consumed_bits += i; - if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - bb->consumed_bits = 0; - } - return true; - } - else { - val_ = FLAC__BITS_PER_BLURB - bb->consumed_bits; - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - bb->consumed_bits = 0; - bb->total_consumed_bits += val_; - } - } - while(1) { - if(bb->consumed_blurbs >= total_blurbs_) { - if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) - return false; - total_blurbs_ = (bb->total_bits + (FLAC__BITS_PER_BLURB-1)) / FLAC__BITS_PER_BLURB; - } - b = bb->buffer[bb->consumed_blurbs]; - if(b) { - for(i = 0; !(b & FLAC__BLURB_TOP_BIT_ONE); i++) - b <<= 1; - val_ += i; - i++; - bb->consumed_bits = i; - *val = val_; - if(i == FLAC__BITS_PER_BLURB) { - CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); - bb->consumed_blurbs++; - bb->consumed_bits = 0; - } - bb->total_consumed_bits += i; - return true; - } - else { - val_ += FLAC__BITS_PER_BLURB; - CRC16_UPDATE_BLURB(bb, 0, bb->read_crc16); - bb->consumed_blurbs++; - /* bb->consumed_bits is already 0 */ - bb->total_consumed_bits += FLAC__BITS_PER_BLURB; - } - } -#if FLAC__BITS_PER_BLURB > 8 - } - else { - while(1) { - if(!FLAC__bitbuffer_read_bit(bb, &i, read_callback, client_data)) - return false; - if(i) - break; - else - val_++; - } - *val = val_; - return true; - } -#endif -} -#endif - -#ifdef FLAC__SYMMETRIC_RICE -FLAC__bool FLAC__bitbuffer_read_symmetric_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - FLAC__uint32 sign = 0, lsbs = 0, msbs = 0; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(parameter <= 31); - - /* read the unary MSBs and end bit */ - if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) - return false; - - /* read the sign bit */ - if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &sign, read_callback, client_data)) - return false; - - /* read the binary LSBs */ - if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, parameter, read_callback, client_data)) - return false; - - /* compose the value */ - *val = (msbs << parameter) | lsbs; - if(sign) - *val = -(*val); - - return true; -} -#endif /* ifdef FLAC__SYMMETRIC_RICE */ - -FLAC__bool FLAC__bitbuffer_read_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - FLAC__uint32 lsbs = 0, msbs = 0; - unsigned uval; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(parameter <= 31); - - /* read the unary MSBs and end bit */ - if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) - return false; - - /* read the binary LSBs */ - if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, parameter, read_callback, client_data)) - return false; - - /* compose the value */ - uval = (msbs << parameter) | lsbs; - if(uval & 1) - *val = -((int)(uval >> 1)) - 1; - else - *val = (int)(uval >> 1); - - return true; -} - -FLAC__bool FLAC__bitbuffer_read_rice_signed_block(FLAC__BitBuffer *bb, int vals[], unsigned nvals, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - const FLAC__blurb *buffer = bb->buffer; - - unsigned i, j, val_i = 0; - unsigned cbits = 0, uval = 0, msbs = 0, lsbs_left = 0; - FLAC__blurb blurb, save_blurb; - unsigned state = 0; /* 0 = getting unary MSBs, 1 = getting binary LSBs */ - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - FLAC__ASSERT(parameter <= 31); - - if(nvals == 0) - return true; - - i = bb->consumed_blurbs; - /* - * We unroll the main loop to take care of partially consumed blurbs here. - */ - if(bb->consumed_bits > 0) { - save_blurb = blurb = buffer[i]; - cbits = bb->consumed_bits; - blurb <<= cbits; - - while(1) { - if(state == 0) { - if(blurb) { - for(j = 0; !(blurb & FLAC__BLURB_TOP_BIT_ONE); j++) - blurb <<= 1; - msbs += j; - - /* dispose of the unary end bit */ - blurb <<= 1; - j++; - cbits += j; - - uval = 0; - lsbs_left = parameter; - state++; - if(cbits == FLAC__BITS_PER_BLURB) { - cbits = 0; - CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); - break; - } - } - else { - msbs += FLAC__BITS_PER_BLURB - cbits; - cbits = 0; - CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); - break; - } - } - else { - const unsigned available_bits = FLAC__BITS_PER_BLURB - cbits; - if(lsbs_left >= available_bits) { - uval <<= available_bits; - uval |= (blurb >> cbits); - cbits = 0; - CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); - - if(lsbs_left == available_bits) { - /* compose the value */ - uval |= (msbs << parameter); - if(uval & 1) - vals[val_i++] = -((int)(uval >> 1)) - 1; - else - vals[val_i++] = (int)(uval >> 1); - if(val_i == nvals) - break; - - msbs = 0; - state = 0; - } - - lsbs_left -= available_bits; - break; - } - else { - uval <<= lsbs_left; - uval |= (blurb >> (FLAC__BITS_PER_BLURB - lsbs_left)); - blurb <<= lsbs_left; - cbits += lsbs_left; - - /* compose the value */ - uval |= (msbs << parameter); - if(uval & 1) - vals[val_i++] = -((int)(uval >> 1)) - 1; - else - vals[val_i++] = (int)(uval >> 1); - if(val_i == nvals) { - /* back up one if we exited the for loop because we read all nvals but the end came in the middle of a blurb */ - i--; - break; - } - - msbs = 0; - state = 0; - } - } - } - i++; - - bb->consumed_blurbs = i; - bb->consumed_bits = cbits; - bb->total_consumed_bits = (i << FLAC__BITS_PER_BLURB_LOG2) | cbits; - } - - /* - * Now that we are blurb-aligned the logic is slightly simpler - */ - while(val_i < nvals) { - for( ; i < bb->blurbs && val_i < nvals; i++) { - save_blurb = blurb = buffer[i]; - cbits = 0; - while(1) { - if(state == 0) { - if(blurb) { - for(j = 0; !(blurb & FLAC__BLURB_TOP_BIT_ONE); j++) - blurb <<= 1; - msbs += j; - - /* dispose of the unary end bit */ - blurb <<= 1; - j++; - cbits += j; - - uval = 0; - lsbs_left = parameter; - state++; - if(cbits == FLAC__BITS_PER_BLURB) { - cbits = 0; - CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); - break; - } - } - else { - msbs += FLAC__BITS_PER_BLURB - cbits; - cbits = 0; - CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); - break; - } - } - else { - const unsigned available_bits = FLAC__BITS_PER_BLURB - cbits; - if(lsbs_left >= available_bits) { - uval <<= available_bits; - uval |= (blurb >> cbits); - cbits = 0; - CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); - - if(lsbs_left == available_bits) { - /* compose the value */ - uval |= (msbs << parameter); - if(uval & 1) - vals[val_i++] = -((int)(uval >> 1)) - 1; - else - vals[val_i++] = (int)(uval >> 1); - if(val_i == nvals) - break; - - msbs = 0; - state = 0; - } - - lsbs_left -= available_bits; - break; - } - else { - uval <<= lsbs_left; - uval |= (blurb >> (FLAC__BITS_PER_BLURB - lsbs_left)); - blurb <<= lsbs_left; - cbits += lsbs_left; - - /* compose the value */ - uval |= (msbs << parameter); - if(uval & 1) - vals[val_i++] = -((int)(uval >> 1)) - 1; - else - vals[val_i++] = (int)(uval >> 1); - if(val_i == nvals) { - /* back up one if we exited the for loop because we read all nvals but the end came in the middle of a blurb */ - i--; - break; - } - - msbs = 0; - state = 0; - } - } - } - } - bb->consumed_blurbs = i; - bb->consumed_bits = cbits; - bb->total_consumed_bits = (i << FLAC__BITS_PER_BLURB_LOG2) | cbits; - if(val_i < nvals) { - if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) - return false; - /* these must be zero because we can only get here if we got to the end of the buffer */ - FLAC__ASSERT(bb->consumed_blurbs == 0); - FLAC__ASSERT(bb->consumed_bits == 0); - i = 0; - } - } - - return true; -} - -#if 0 /* UNUSED */ -FLAC__bool FLAC__bitbuffer_read_golomb_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - FLAC__uint32 lsbs = 0, msbs = 0; - unsigned bit, uval, k; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - k = FLAC__bitmath_ilog2(parameter); - - /* read the unary MSBs and end bit */ - if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) - return false; - - /* read the binary LSBs */ - if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, k, read_callback, client_data)) - return false; - - if(parameter == 1u<= d) { - if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data)) - return false; - lsbs <<= 1; - lsbs |= bit; - lsbs -= d; - } - /* compose the value */ - uval = msbs * parameter + lsbs; - } - - /* unfold unsigned to signed */ - if(uval & 1) - *val = -((int)(uval >> 1)) - 1; - else - *val = (int)(uval >> 1); - - return true; -} - -FLAC__bool FLAC__bitbuffer_read_golomb_unsigned(FLAC__BitBuffer *bb, unsigned *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) -{ - FLAC__uint32 lsbs, msbs = 0; - unsigned bit, k; - - FLAC__ASSERT(0 != bb); - FLAC__ASSERT(0 != bb->buffer); - - k = FLAC__bitmath_ilog2(parameter); - - /* read the unary MSBs and end bit */ - if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) - return false; - - /* read the binary LSBs */ - if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, k, read_callback, client_data)) - return false; - - if(parameter == 1u<= d) { - if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data)) - return false; - lsbs <<= 1; - lsbs |= bit; - lsbs -= d; - } - /* compose the value */ - *val = msbs * parameter + lsbs; - } - - return true; -} -#endif /* UNUSED */ - -/* on return, if *val == 0xffffffff then the utf-8 sequence was invalid, but the return value will be true */ -FLAC__bool FLAC__bitbuffer_read_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen) -{ - FLAC__uint32 v = 0; - FLAC__uint32 x; - unsigned i; - - if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) - return false; - if(raw) - raw[(*rawlen)++] = (FLAC__byte)x; - if(!(x & 0x80)) { /* 0xxxxxxx */ - v = x; - i = 0; - } - else if(x & 0xC0 && !(x & 0x20)) { /* 110xxxxx */ - v = x & 0x1F; - i = 1; - } - else if(x & 0xE0 && !(x & 0x10)) { /* 1110xxxx */ - v = x & 0x0F; - i = 2; - } - else if(x & 0xF0 && !(x & 0x08)) { /* 11110xxx */ - v = x & 0x07; - i = 3; - } - else if(x & 0xF8 && !(x & 0x04)) { /* 111110xx */ - v = x & 0x03; - i = 4; - } - else if(x & 0xFC && !(x & 0x02)) { /* 1111110x */ - v = x & 0x01; - i = 5; - } - else { - *val = 0xffffffff; - return true; - } - for( ; i; i--) { - if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) - return false; - if(raw) - raw[(*rawlen)++] = (FLAC__byte)x; - if(!(x & 0x80) || (x & 0x40)) { /* 10xxxxxx */ - *val = 0xffffffff; - return true; - } - v <<= 6; - v |= (x & 0x3F); - } - *val = v; - return true; -} - -/* on return, if *val == 0xffffffffffffffff then the utf-8 sequence was invalid, but the return value will be true */ -FLAC__bool FLAC__bitbuffer_read_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen) -{ - FLAC__uint64 v = 0; - FLAC__uint32 x; - unsigned i; - - if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) - return false; - if(raw) - raw[(*rawlen)++] = (FLAC__byte)x; - if(!(x & 0x80)) { /* 0xxxxxxx */ - v = x; - i = 0; - } - else if(x & 0xC0 && !(x & 0x20)) { /* 110xxxxx */ - v = x & 0x1F; - i = 1; - } - else if(x & 0xE0 && !(x & 0x10)) { /* 1110xxxx */ - v = x & 0x0F; - i = 2; - } - else if(x & 0xF0 && !(x & 0x08)) { /* 11110xxx */ - v = x & 0x07; - i = 3; - } - else if(x & 0xF8 && !(x & 0x04)) { /* 111110xx */ - v = x & 0x03; - i = 4; - } - else if(x & 0xFC && !(x & 0x02)) { /* 1111110x */ - v = x & 0x01; - i = 5; - } - else if(x & 0xFE && !(x & 0x01)) { /* 11111110 */ - v = 0; - i = 6; - } - else { - *val = FLAC__U64L(0xffffffffffffffff); - return true; - } - for( ; i; i--) { - if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) - return false; - if(raw) - raw[(*rawlen)++] = (FLAC__byte)x; - if(!(x & 0x80) || (x & 0x40)) { /* 10xxxxxx */ - *val = FLAC__U64L(0xffffffffffffffff); - return true; - } - v <<= 6; - v |= (x & 0x3F); - } - *val = v; - return true; -} - -void FLAC__bitbuffer_dump(const FLAC__BitBuffer *bb, FILE *out) -{ - unsigned i, j; - if(bb == 0) { - fprintf(out, "bitbuffer is NULL\n"); - } - else { - fprintf(out, "bitbuffer: capacity=%u blurbs=%u bits=%u total_bits=%u consumed: blurbs=%u, bits=%u, total_bits=%u\n", bb->capacity, bb->blurbs, bb->bits, bb->total_bits, bb->consumed_blurbs, bb->consumed_bits, bb->total_consumed_bits); - - for(i = 0; i < bb->blurbs; i++) { - fprintf(out, "%08X: ", i); - for(j = 0; j < FLAC__BITS_PER_BLURB; j++) - if(i*FLAC__BITS_PER_BLURB+j < bb->total_consumed_bits) - fprintf(out, "."); - else - fprintf(out, "%01u", bb->buffer[i] & (1 << (FLAC__BITS_PER_BLURB-j-1)) ? 1:0); - fprintf(out, "\n"); - } - if(bb->bits > 0) { - fprintf(out, "%08X: ", i); - for(j = 0; j < bb->bits; j++) - if(i*FLAC__BITS_PER_BLURB+j < bb->total_consumed_bits) - fprintf(out, "."); - else - fprintf(out, "%01u", bb->buffer[i] & (1 << (bb->bits-j-1)) ? 1:0); - fprintf(out, "\n"); - } - } -} +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#include /* for malloc() */ +#include /* for memcpy(), memset() */ +#include "private/bitbuffer.h" +#include "private/bitmath.h" +#include "private/crc.h" +#include "FLAC/assert.h" + +/* + * Along the way you will see two versions of some functions, selected + * by a FLAC__NO_MANUAL_INLINING macro. One is the simplified, more + * readable, and slow version, and the other is the same function + * where crucial parts have been manually inlined and are much faster. + * + */ + +/* + * Some optimization strategies are slower with older versions of MSVC + */ +#if defined _MSC_VER && _MSC_VER <= 1200 +#define FLAC__OLD_MSVC_FLAVOR +#endif + +/* + * This should be at least twice as large as the largest number of blurbs + * required to represent any 'number' (in any encoding) you are going to + * read. With FLAC this is on the order of maybe a few hundred bits. + * If the buffer is smaller than that, the decoder won't be able to read + * in a whole number that is in a variable length encoding (e.g. Rice). + * + * The number we are actually using here is based on what would be the + * approximate maximum size of a verbatim frame at the default block size, + * for CD audio (4096 sample * 4 bytes per sample), plus some wiggle room. + * 32kbytes sounds reasonable. For kicks we subtract out 64 bytes for any + * alignment or malloc overhead. + * + * Increase this number to decrease the number of read callbacks, at the + * expense of using more memory. Or decrease for the reverse effect, + * keeping in mind the limit from the first paragraph. + */ +static const unsigned FLAC__BITBUFFER_DEFAULT_CAPACITY = ((65536 - 64) * 8) / FLAC__BITS_PER_BLURB; /* blurbs */ + +#ifndef FLAC__OLD_MSVC_FLAVOR +static const unsigned char byte_to_unary_table[] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +#endif + +#if FLAC__BITS_PER_BLURB == 8 +#define FLAC__BITS_PER_BLURB_LOG2 3 +#define FLAC__BYTES_PER_BLURB 1 +#define FLAC__BLURB_ALL_ONES ((FLAC__byte)0xff) +#define FLAC__BLURB_TOP_BIT_ONE ((FLAC__byte)0x80) +#define BLURB_BIT_TO_MASK(b) (((FLAC__blurb)'\x80') >> (b)) +#define CRC16_UPDATE_BLURB(bb, blurb, crc) FLAC__CRC16_UPDATE((blurb), (crc)); +#ifndef FLAC__OLD_MSVC_FLAVOR +#define FLAC__ALIGNED_BLURB_UNARY(blurb) (byte_to_unary_table[blurb]) +#endif +#elif FLAC__BITS_PER_BLURB == 32 +#define FLAC__BITS_PER_BLURB_LOG2 5 +#define FLAC__BYTES_PER_BLURB 4 +#define FLAC__BLURB_ALL_ONES ((FLAC__uint32)0xffffffff) +#define FLAC__BLURB_TOP_BIT_ONE ((FLAC__uint32)0x80000000) +#define BLURB_BIT_TO_MASK(b) (((FLAC__blurb)0x80000000) >> (b)) +#define CRC16_UPDATE_BLURB(bb, blurb, crc) crc16_update_blurb((bb), (blurb)); +#ifndef FLAC__OLD_MSVC_FLAVOR +#define FLAC__ALIGNED_BLURB_UNARY(blurb) ((blurb) <= 0xff ? byte_to_unary_table[blurb] + 24 : ((blurb) <= 0xffff ? byte_to_unary_table[(blurb) >> 8] + 16 : ((blurb) <= 0xffffff ? byte_to_unary_table[(blurb) >> 16] + 8 : byte_to_unary_table[(blurb) >> 24]))) +#endif +#else +/* ERROR, only sizes of 8 and 32 are supported */ +#endif + +#define FLAC__BLURBS_TO_BITS(blurbs) ((blurbs) << FLAC__BITS_PER_BLURB_LOG2) + +#ifdef min +#undef min +#endif +#define min(x,y) ((x)<(y)?(x):(y)) +#ifdef max +#undef max +#endif +#define max(x,y) ((x)>(y)?(x):(y)) + +/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ +#ifdef _MSC_VER +#define FLAC__U64L(x) x +#else +#define FLAC__U64L(x) x##LLU +#endif + +#ifndef FLaC__INLINE +#define FLaC__INLINE +#endif + +struct FLAC__BitBuffer { + FLAC__blurb *buffer; + unsigned capacity; /* in blurbs */ + unsigned blurbs, bits; + unsigned total_bits; /* must always == FLAC__BITS_PER_BLURB*blurbs+bits */ + unsigned consumed_blurbs, consumed_bits; + unsigned total_consumed_bits; /* must always == FLAC__BITS_PER_BLURB*consumed_blurbs+consumed_bits */ + FLAC__uint16 read_crc16; +#if FLAC__BITS_PER_BLURB == 32 + unsigned crc16_align; +#endif + FLAC__blurb save_head, save_tail; +}; + +#if FLAC__BITS_PER_BLURB == 32 +static void crc16_update_blurb(FLAC__BitBuffer *bb, FLAC__blurb blurb) +{ + if(bb->crc16_align == 0) { + FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); + } + else if(bb->crc16_align == 8) { + FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); + } + else if(bb->crc16_align == 16) { + FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); + } + else if(bb->crc16_align == 24) { + FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); + } + bb->crc16_align = 0; +} +#endif + +/* + * WATCHOUT: The current implentation is not friendly to shrinking, i.e. it + * does not shift left what is consumed, it just chops off the end, whether + * there is unconsumed data there or not. This is OK because currently we + * never shrink the buffer, but if this ever changes, we'll have to do some + * fixups here. + */ +static FLAC__bool bitbuffer_resize_(FLAC__BitBuffer *bb, unsigned new_capacity) +{ + FLAC__blurb *new_buffer; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + if(bb->capacity == new_capacity) + return true; + + new_buffer = (FLAC__blurb*)calloc(new_capacity, sizeof(FLAC__blurb)); + if(new_buffer == 0) + return false; + memcpy(new_buffer, bb->buffer, sizeof(FLAC__blurb)*min(bb->blurbs+(bb->bits?1:0), new_capacity)); + if(new_capacity < bb->blurbs+(bb->bits?1:0)) { + bb->blurbs = new_capacity; + bb->bits = 0; + bb->total_bits = FLAC__BLURBS_TO_BITS(new_capacity); + } + if(new_capacity < bb->consumed_blurbs+(bb->consumed_bits?1:0)) { + bb->consumed_blurbs = new_capacity; + bb->consumed_bits = 0; + bb->total_consumed_bits = FLAC__BLURBS_TO_BITS(new_capacity); + } + free(bb->buffer); /* we've already asserted above that (0 != bb->buffer) */ + bb->buffer = new_buffer; + bb->capacity = new_capacity; + return true; +} + +static FLAC__bool bitbuffer_grow_(FLAC__BitBuffer *bb, unsigned min_blurbs_to_add) +{ + unsigned new_capacity; + + FLAC__ASSERT(min_blurbs_to_add > 0); + + new_capacity = max(bb->capacity * 2, bb->capacity + min_blurbs_to_add); + return bitbuffer_resize_(bb, new_capacity); +} + +static FLAC__bool bitbuffer_ensure_size_(FLAC__BitBuffer *bb, unsigned bits_to_add) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + if(FLAC__BLURBS_TO_BITS(bb->capacity) < bb->total_bits + bits_to_add) + return bitbuffer_grow_(bb, (bits_to_add >> FLAC__BITS_PER_BLURB_LOG2) + 2); + else + return true; +} + +static FLAC__bool bitbuffer_read_from_client_(FLAC__BitBuffer *bb, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + unsigned bytes; + FLAC__byte *target; + + /* first shift the unconsumed buffer data toward the front as much as possible */ + if(bb->total_consumed_bits >= FLAC__BITS_PER_BLURB) { +#if FLAC__BITS_PER_BLURB == 8 + /* + * memset and memcpy are usually implemented in assembly language + * by the system libc, and they can be much faster + */ + const unsigned r_end = bb->blurbs + (bb->bits? 1:0); + const unsigned r = bb->consumed_blurbs, l = r_end - r; + memmove(&bb->buffer[0], &bb->buffer[r], l); + memset(&bb->buffer[l], 0, r); +#elif FLAC__BITS_PER_BLURB == 32 + /* still needs optimization */ + const unsigned r_end = bb->blurbs + (bb->bits? 1:0); + unsigned l = 0, r = bb->consumed_blurbs; + for( ; r < r_end; l++, r++) + bb->buffer[l] = bb->buffer[r]; + for( ; l < r_end; l++) + bb->buffer[l] = 0; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif /* FLAC__BITS_PER_BLURB == 32 or 8 */ + + bb->blurbs -= bb->consumed_blurbs; + bb->total_bits -= FLAC__BLURBS_TO_BITS(bb->consumed_blurbs); + bb->consumed_blurbs = 0; + bb->total_consumed_bits = bb->consumed_bits; + } + + /* grow if we need to */ + if(bb->capacity <= 1) { + if(!bitbuffer_resize_(bb, 16)) + return false; + } + + /* set the target for reading, taking into account blurb alignment */ +#if FLAC__BITS_PER_BLURB == 8 + /* blurb == byte, so no gyrations necessary: */ + target = bb->buffer + bb->blurbs; + bytes = bb->capacity - bb->blurbs; +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + FLAC__ASSERT((bb->bits & 7) == 0); + target = (FLAC__byte*)(bb->buffer + bb->blurbs) + (bb->bits >> 3); + bytes = ((bb->capacity - bb->blurbs) << 2) - (bb->bits >> 3); /* i.e. (bb->capacity - bb->blurbs) * FLAC__BYTES_PER_BLURB - (bb->bits / 8) */ +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif + + /* finally, read in some data */ + if(!read_callback(target, &bytes, client_data)) + return false; + + /* now we have to handle partial blurb cases: */ +#if FLAC__BITS_PER_BLURB == 8 + /* blurb == byte, so no gyrations necessary: */ + bb->blurbs += bytes; + bb->total_bits += FLAC__BLURBS_TO_BITS(bytes); +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + { + const unsigned aligned_bytes = (bb->bits >> 3) + bytes; + bb->blurbs += (aligned_bytes >> 2); /* i.e. aligned_bytes / FLAC__BYTES_PER_BLURB */ + bb->bits = (aligned_bytes & 3u) << 3; /* i.e. (aligned_bytes % FLAC__BYTES_PER_BLURB) * 8 */ + bb->total_bits += (bytes << 3); + } +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif + return true; +} + +/*********************************************************************** + * + * Class constructor/destructor + * + ***********************************************************************/ + +FLAC__BitBuffer *FLAC__bitbuffer_new() +{ + FLAC__BitBuffer *bb = (FLAC__BitBuffer*)calloc(1, sizeof(FLAC__BitBuffer)); + + /* calloc() implies: + memset(bb, 0, sizeof(FLAC__BitBuffer)); + bb->buffer = 0; + bb->capacity = 0; + bb->blurbs = bb->bits = bb->total_bits = 0; + bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; + */ + return bb; +} + +void FLAC__bitbuffer_delete(FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + + FLAC__bitbuffer_free(bb); + free(bb); +} + +/*********************************************************************** + * + * Public class methods + * + ***********************************************************************/ + +FLAC__bool FLAC__bitbuffer_init(FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + + bb->buffer = 0; + bb->capacity = 0; + bb->blurbs = bb->bits = bb->total_bits = 0; + bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; + + return FLAC__bitbuffer_clear(bb); +} + +FLAC__bool FLAC__bitbuffer_init_from(FLAC__BitBuffer *bb, const FLAC__byte buffer[], unsigned bytes) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(bytes > 0); + + if(!FLAC__bitbuffer_init(bb)) + return false; + + if(!bitbuffer_ensure_size_(bb, bytes << 3)) + return false; + + FLAC__ASSERT(0 != buffer); + /* @@@ WATCHOUT: code currently only works for 8-bits-per-blurb inclusive-or big-endian: */ + memcpy((FLAC__byte*)bb->buffer, buffer, sizeof(FLAC__byte)*bytes); + bb->blurbs = bytes / FLAC__BYTES_PER_BLURB; + bb->bits = (bytes % FLAC__BYTES_PER_BLURB) << 3; + bb->total_bits = bytes << 3; + return true; +} + +FLAC__bool FLAC__bitbuffer_concatenate_aligned(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src) +{ + unsigned bits_to_add = src->total_bits - src->total_consumed_bits; + + FLAC__ASSERT(0 != dest); + FLAC__ASSERT(0 != src); + + if(bits_to_add == 0) + return true; + if(dest->bits != src->consumed_bits) + return false; + if(!bitbuffer_ensure_size_(dest, bits_to_add)) + return false; + if(dest->bits == 0) { + memcpy(dest->buffer+dest->blurbs, src->buffer+src->consumed_blurbs, sizeof(FLAC__blurb)*(src->blurbs-src->consumed_blurbs + ((src->bits)? 1:0))); + } + else if(dest->bits + bits_to_add > FLAC__BITS_PER_BLURB) { + dest->buffer[dest->blurbs] <<= (FLAC__BITS_PER_BLURB - dest->bits); + dest->buffer[dest->blurbs] |= (src->buffer[src->consumed_blurbs] & ((1u << (FLAC__BITS_PER_BLURB-dest->bits)) - 1)); + memcpy(dest->buffer+dest->blurbs+1, src->buffer+src->consumed_blurbs+1, sizeof(FLAC__blurb)*(src->blurbs-src->consumed_blurbs-1 + ((src->bits)? 1:0))); + } + else { + dest->buffer[dest->blurbs] <<= bits_to_add; + dest->buffer[dest->blurbs] |= (src->buffer[src->consumed_blurbs] & ((1u << bits_to_add) - 1)); + } + dest->bits = src->bits; + dest->total_bits += bits_to_add; + dest->blurbs = dest->total_bits / FLAC__BITS_PER_BLURB; + + return true; +} + +void FLAC__bitbuffer_free(FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + + if(0 != bb->buffer) + free(bb->buffer); + bb->buffer = 0; + bb->capacity = 0; + bb->blurbs = bb->bits = bb->total_bits = 0; + bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; +} + +FLAC__bool FLAC__bitbuffer_clear(FLAC__BitBuffer *bb) +{ + if(bb->buffer == 0) { + bb->capacity = FLAC__BITBUFFER_DEFAULT_CAPACITY; + bb->buffer = (FLAC__blurb*)calloc(bb->capacity, sizeof(FLAC__blurb)); + if(bb->buffer == 0) + return false; + } + else { + memset(bb->buffer, 0, bb->blurbs + (bb->bits?1:0)); + } + bb->blurbs = bb->bits = bb->total_bits = 0; + bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; + return true; +} + +FLAC__bool FLAC__bitbuffer_clone(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src) +{ + FLAC__ASSERT(0 != dest); + FLAC__ASSERT(0 != dest->buffer); + FLAC__ASSERT(0 != src); + FLAC__ASSERT(0 != src->buffer); + + if(dest->capacity < src->capacity) + if(!bitbuffer_resize_(dest, src->capacity)) + return false; + memcpy(dest->buffer, src->buffer, sizeof(FLAC__blurb)*min(src->capacity, src->blurbs+1)); + dest->blurbs = src->blurbs; + dest->bits = src->bits; + dest->total_bits = src->total_bits; + dest->consumed_blurbs = src->consumed_blurbs; + dest->consumed_bits = src->consumed_bits; + dest->total_consumed_bits = src->total_consumed_bits; + dest->read_crc16 = src->read_crc16; + return true; +} + +void FLAC__bitbuffer_reset_read_crc16(FLAC__BitBuffer *bb, FLAC__uint16 seed) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT((bb->consumed_bits & 7) == 0); + + bb->read_crc16 = seed; +#if FLAC__BITS_PER_BLURB == 8 + /* no need to do anything */ +#elif FLAC__BITS_PER_BLURB == 32 + bb->crc16_align = bb->consumed_bits; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +FLAC__uint16 FLAC__bitbuffer_get_read_crc16(FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT((bb->bits & 7) == 0); + FLAC__ASSERT((bb->consumed_bits & 7) == 0); + +#if FLAC__BITS_PER_BLURB == 8 + /* no need to do anything */ +#elif FLAC__BITS_PER_BLURB == 32 + /*@@@ BUG: even though this probably can't happen with FLAC, need to fix the case where we are called here for the very first blurb and crc16_align is > 0 */ + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { + if(bb->consumed_bits == 8) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); + } + else if(bb->consumed_bits == 16) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); + } + else if(bb->consumed_bits == 24) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); + } + } + else { + if(bb->consumed_bits == 8) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16); + } + else if(bb->consumed_bits == 16) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> (bb->bits-16)) & 0xff, bb->read_crc16); + } + else if(bb->consumed_bits == 24) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> (bb->bits-16)) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> (bb->bits-24)) & 0xff, bb->read_crc16); + } + } + bb->crc16_align = bb->consumed_bits; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif + return bb->read_crc16; +} + +FLAC__uint16 FLAC__bitbuffer_get_write_crc16(const FLAC__BitBuffer *bb) +{ + FLAC__ASSERT((bb->bits & 7) == 0); /* assert that we're byte-aligned */ + +#if FLAC__BITS_PER_BLURB == 8 + return FLAC__crc16(bb->buffer, bb->blurbs); +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + return FLAC__crc16((FLAC__byte*)(bb->buffer), (bb->blurbs * FLAC__BYTES_PER_BLURB) + (bb->bits >> 3)); +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +FLAC__byte FLAC__bitbuffer_get_write_crc8(const FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT((bb->bits & 7) == 0); /* assert that we're byte-aligned */ + FLAC__ASSERT(bb->buffer[0] == 0xff); /* MAGIC NUMBER for the first byte of the sync code */ +#if FLAC__BITS_PER_BLURB == 8 + return FLAC__crc8(bb->buffer, bb->blurbs); +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + return FLAC__crc8((FLAC__byte*)(bb->buffer), (bb->blurbs * FLAC__BYTES_PER_BLURB) + (bb->bits >> 3)); +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +FLAC__bool FLAC__bitbuffer_is_byte_aligned(const FLAC__BitBuffer *bb) +{ + return ((bb->bits & 7) == 0); +} + +FLAC__bool FLAC__bitbuffer_is_consumed_byte_aligned(const FLAC__BitBuffer *bb) +{ + return ((bb->consumed_bits & 7) == 0); +} + +unsigned FLAC__bitbuffer_bits_left_for_byte_alignment(const FLAC__BitBuffer *bb) +{ + return 8 - (bb->consumed_bits & 7); +} + +unsigned FLAC__bitbuffer_get_input_bytes_unconsumed(const FLAC__BitBuffer *bb) +{ + FLAC__ASSERT((bb->consumed_bits & 7) == 0 && (bb->bits & 7) == 0); + return (bb->total_bits - bb->total_consumed_bits) >> 3; +} + +void FLAC__bitbuffer_get_buffer(FLAC__BitBuffer *bb, const FLAC__byte **buffer, unsigned *bytes) +{ + FLAC__ASSERT((bb->consumed_bits & 7) == 0 && (bb->bits & 7) == 0); +#if FLAC__BITS_PER_BLURB == 8 + *buffer = bb->buffer + bb->consumed_blurbs; + *bytes = bb->blurbs - bb->consumed_blurbs; +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + *buffer = (FLAC__byte*)(bb->buffer + bb->consumed_blurbs) + (bb->consumed_bits >> 3); + *bytes = (bb->total_bits - bb->total_consumed_bits) >> 3; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +void FLAC__bitbuffer_release_buffer(FLAC__BitBuffer *bb) +{ +#if FLAC__BITS_PER_BLURB == 8 + (void)bb; +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + (void)bb; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +FLAC__bool FLAC__bitbuffer_write_zeroes(FLAC__BitBuffer *bb, unsigned bits) +{ + unsigned n; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + if(bits == 0) + return true; + if(!bitbuffer_ensure_size_(bb, bits)) + return false; + bb->total_bits += bits; + while(bits > 0) { + n = min(FLAC__BITS_PER_BLURB - bb->bits, bits); + bb->buffer[bb->blurbs] <<= n; + bits -= n; + bb->bits += n; + if(bb->bits == FLAC__BITS_PER_BLURB) { + bb->blurbs++; + bb->bits = 0; + } + } + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_raw_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val, unsigned bits) +{ + unsigned n, k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + if(bits == 0) + return true; + /* inline the size check so we don't incure a function call unnecessarily */ + if(FLAC__BLURBS_TO_BITS(bb->capacity) < bb->total_bits + bits) { + if(!bitbuffer_ensure_size_(bb, bits)) + return false; + } + + /* zero-out unused bits; WATCHOUT: other code relies on this, so this needs to stay */ + if(bits < 32) /* @@@ gcc seems to require this because the following line causes incorrect results when bits==32; investigate */ + val &= (~(0xffffffff << bits)); /* zero-out unused bits */ + + bb->total_bits += bits; + while(bits > 0) { + n = FLAC__BITS_PER_BLURB - bb->bits; + if(n == FLAC__BITS_PER_BLURB) { /* i.e. bb->bits == 0 */ + if(bits < FLAC__BITS_PER_BLURB) { + bb->buffer[bb->blurbs] = (FLAC__blurb)val; + bb->bits = bits; + break; + } + else if(bits == FLAC__BITS_PER_BLURB) { + bb->buffer[bb->blurbs++] = (FLAC__blurb)val; + break; + } + else { + k = bits - FLAC__BITS_PER_BLURB; + bb->buffer[bb->blurbs++] = (FLAC__blurb)(val >> k); + /* we know k < 32 so no need to protect against the gcc bug mentioned above */ + val &= (~(0xffffffff << k)); + bits -= FLAC__BITS_PER_BLURB; + } + } + else if(bits <= n) { + bb->buffer[bb->blurbs] <<= bits; + bb->buffer[bb->blurbs] |= val; + if(bits == n) { + bb->blurbs++; + bb->bits = 0; + } + else + bb->bits += bits; + break; + } + else { + k = bits - n; + bb->buffer[bb->blurbs] <<= n; + bb->buffer[bb->blurbs] |= (val >> k); + /* we know n > 0 so k < 32 so no need to protect against the gcc bug mentioned above */ + val &= (~(0xffffffff << k)); + bits -= n; + bb->blurbs++; + bb->bits = 0; + } + } + + return true; +} + +FLAC__bool FLAC__bitbuffer_write_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 val, unsigned bits) +{ + return FLAC__bitbuffer_write_raw_uint32(bb, (FLAC__uint32)val, bits); +} + +FLAC__bool FLAC__bitbuffer_write_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 val, unsigned bits) +{ + static const FLAC__uint64 mask[] = { + 0, + FLAC__U64L(0x0000000000000001), FLAC__U64L(0x0000000000000003), FLAC__U64L(0x0000000000000007), FLAC__U64L(0x000000000000000F), + FLAC__U64L(0x000000000000001F), FLAC__U64L(0x000000000000003F), FLAC__U64L(0x000000000000007F), FLAC__U64L(0x00000000000000FF), + FLAC__U64L(0x00000000000001FF), FLAC__U64L(0x00000000000003FF), FLAC__U64L(0x00000000000007FF), FLAC__U64L(0x0000000000000FFF), + FLAC__U64L(0x0000000000001FFF), FLAC__U64L(0x0000000000003FFF), FLAC__U64L(0x0000000000007FFF), FLAC__U64L(0x000000000000FFFF), + FLAC__U64L(0x000000000001FFFF), FLAC__U64L(0x000000000003FFFF), FLAC__U64L(0x000000000007FFFF), FLAC__U64L(0x00000000000FFFFF), + FLAC__U64L(0x00000000001FFFFF), FLAC__U64L(0x00000000003FFFFF), FLAC__U64L(0x00000000007FFFFF), FLAC__U64L(0x0000000000FFFFFF), + FLAC__U64L(0x0000000001FFFFFF), FLAC__U64L(0x0000000003FFFFFF), FLAC__U64L(0x0000000007FFFFFF), FLAC__U64L(0x000000000FFFFFFF), + FLAC__U64L(0x000000001FFFFFFF), FLAC__U64L(0x000000003FFFFFFF), FLAC__U64L(0x000000007FFFFFFF), FLAC__U64L(0x00000000FFFFFFFF), + FLAC__U64L(0x00000001FFFFFFFF), FLAC__U64L(0x00000003FFFFFFFF), FLAC__U64L(0x00000007FFFFFFFF), FLAC__U64L(0x0000000FFFFFFFFF), + FLAC__U64L(0x0000001FFFFFFFFF), FLAC__U64L(0x0000003FFFFFFFFF), FLAC__U64L(0x0000007FFFFFFFFF), FLAC__U64L(0x000000FFFFFFFFFF), + FLAC__U64L(0x000001FFFFFFFFFF), FLAC__U64L(0x000003FFFFFFFFFF), FLAC__U64L(0x000007FFFFFFFFFF), FLAC__U64L(0x00000FFFFFFFFFFF), + FLAC__U64L(0x00001FFFFFFFFFFF), FLAC__U64L(0x00003FFFFFFFFFFF), FLAC__U64L(0x00007FFFFFFFFFFF), FLAC__U64L(0x0000FFFFFFFFFFFF), + FLAC__U64L(0x0001FFFFFFFFFFFF), FLAC__U64L(0x0003FFFFFFFFFFFF), FLAC__U64L(0x0007FFFFFFFFFFFF), FLAC__U64L(0x000FFFFFFFFFFFFF), + FLAC__U64L(0x001FFFFFFFFFFFFF), FLAC__U64L(0x003FFFFFFFFFFFFF), FLAC__U64L(0x007FFFFFFFFFFFFF), FLAC__U64L(0x00FFFFFFFFFFFFFF), + FLAC__U64L(0x01FFFFFFFFFFFFFF), FLAC__U64L(0x03FFFFFFFFFFFFFF), FLAC__U64L(0x07FFFFFFFFFFFFFF), FLAC__U64L(0x0FFFFFFFFFFFFFFF), + FLAC__U64L(0x1FFFFFFFFFFFFFFF), FLAC__U64L(0x3FFFFFFFFFFFFFFF), FLAC__U64L(0x7FFFFFFFFFFFFFFF), FLAC__U64L(0xFFFFFFFFFFFFFFFF) + }; + unsigned n, k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + if(bits == 0) + return true; + if(!bitbuffer_ensure_size_(bb, bits)) + return false; + val &= mask[bits]; + bb->total_bits += bits; + while(bits > 0) { + if(bb->bits == 0) { + if(bits < FLAC__BITS_PER_BLURB) { + bb->buffer[bb->blurbs] = (FLAC__blurb)val; + bb->bits = bits; + break; + } + else if(bits == FLAC__BITS_PER_BLURB) { + bb->buffer[bb->blurbs++] = (FLAC__blurb)val; + break; + } + else { + k = bits - FLAC__BITS_PER_BLURB; + bb->buffer[bb->blurbs++] = (FLAC__blurb)(val >> k); + /* we know k < 64 so no need to protect against the gcc bug mentioned above */ + val &= (~(FLAC__U64L(0xffffffffffffffff) << k)); + bits -= FLAC__BITS_PER_BLURB; + } + } + else { + n = min(FLAC__BITS_PER_BLURB - bb->bits, bits); + k = bits - n; + bb->buffer[bb->blurbs] <<= n; + bb->buffer[bb->blurbs] |= (val >> k); + /* we know n > 0 so k < 64 so no need to protect against the gcc bug mentioned above */ + val &= (~(FLAC__U64L(0xffffffffffffffff) << k)); + bits -= n; + bb->bits += n; + if(bb->bits == FLAC__BITS_PER_BLURB) { + bb->blurbs++; + bb->bits = 0; + } + } + } + + return true; +} + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_write_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 val, unsigned bits) +{ + return FLAC__bitbuffer_write_raw_uint64(bb, (FLAC__uint64)val, bits); +} +#endif + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_raw_uint32_little_endian(FLAC__BitBuffer *bb, FLAC__uint32 val) +{ + /* this doesn't need to be that fast as currently it is only used for vorbis comments */ + + /* NOTE: we rely on the fact that FLAC__bitbuffer_write_raw_uint32() masks out the unused bits */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, val, 8)) + return false; + if(!FLAC__bitbuffer_write_raw_uint32(bb, val>>8, 8)) + return false; + if(!FLAC__bitbuffer_write_raw_uint32(bb, val>>16, 8)) + return false; + if(!FLAC__bitbuffer_write_raw_uint32(bb, val>>24, 8)) + return false; + + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_byte_block(FLAC__BitBuffer *bb, const FLAC__byte vals[], unsigned nvals) +{ + unsigned i; + + /* this could be faster but currently we don't need it to be */ + for(i = 0; i < nvals; i++) { + if(!FLAC__bitbuffer_write_raw_uint32(bb, (FLAC__uint32)(vals[i]), 8)) + return false; + } + + return true; +} + +FLAC__bool FLAC__bitbuffer_write_unary_unsigned(FLAC__BitBuffer *bb, unsigned val) +{ + if(val < 32) + return FLAC__bitbuffer_write_raw_uint32(bb, 1, ++val); + else if(val < 64) + return FLAC__bitbuffer_write_raw_uint64(bb, 1, ++val); + else { + if(!FLAC__bitbuffer_write_zeroes(bb, val)) + return false; + return FLAC__bitbuffer_write_raw_uint32(bb, 1, 1); + } +} + +unsigned FLAC__bitbuffer_rice_bits(int val, unsigned parameter) +{ + unsigned msbs, uval; + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + msbs = uval >> parameter; + + return 1 + parameter + msbs; +} + +#if 0 /* UNUSED */ +unsigned FLAC__bitbuffer_golomb_bits_signed(int val, unsigned parameter) +{ + unsigned bits, msbs, uval; + unsigned k; + + FLAC__ASSERT(parameter > 0); + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + k = FLAC__bitmath_ilog2(parameter); + if(parameter == 1u<> k; + bits = 1 + k + msbs; + } + else { + unsigned q, r, d; + + d = (1 << (k+1)) - parameter; + q = uval / parameter; + r = uval - (q * parameter); + + bits = 1 + q + k; + if(r >= d) + bits++; + } + return bits; +} + +unsigned FLAC__bitbuffer_golomb_bits_unsigned(unsigned uval, unsigned parameter) +{ + unsigned bits, msbs; + unsigned k; + + FLAC__ASSERT(parameter > 0); + + k = FLAC__bitmath_ilog2(parameter); + if(parameter == 1u<> k; + bits = 1 + k + msbs; + } + else { + unsigned q, r, d; + + d = (1 << (k+1)) - parameter; + q = uval / parameter; + r = uval - (q * parameter); + + bits = 1 + q + k; + if(r >= d) + bits++; + } + return bits; +} +#endif /* UNUSED */ + +FLAC__bool FLAC__bitbuffer_write_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter) +{ + unsigned total_bits, interesting_bits, msbs, uval; + FLAC__uint32 pattern; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 30); + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + msbs = uval >> parameter; + interesting_bits = 1 + parameter; + total_bits = interesting_bits + msbs; + pattern = 1 << parameter; /* the unary end bit */ + pattern |= (uval & ((1<buffer); + FLAC__ASSERT(parameter <= 30); + + *overflow = false; + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + msbs = uval >> parameter; + interesting_bits = 1 + parameter; + total_bits = interesting_bits + msbs; + pattern = 1 << parameter; /* the unary end bit */ + pattern |= (uval & ((1< max_bits) { + *overflow = true; + return true; + } + else { + /* write the unary MSBs */ + if(!FLAC__bitbuffer_write_zeroes(bb, msbs)) + return false; + /* write the unary end bit and binary LSBs */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, interesting_bits)) + return false; + } + return true; +} +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_write_golomb_signed(FLAC__BitBuffer *bb, int val, unsigned parameter) +{ + unsigned total_bits, msbs, uval; + unsigned k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter > 0); + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + k = FLAC__bitmath_ilog2(parameter); + if(parameter == 1u<> k; + total_bits = 1 + k + msbs; + pattern = 1 << k; /* the unary end bit */ + pattern |= (uval & ((1u<= d) { + if(!FLAC__bitbuffer_write_raw_uint32(bb, r+d, k+1)) + return false; + } + else { + if(!FLAC__bitbuffer_write_raw_uint32(bb, r, k)) + return false; + } + } + return true; +} + +FLAC__bool FLAC__bitbuffer_write_golomb_unsigned(FLAC__BitBuffer *bb, unsigned uval, unsigned parameter) +{ + unsigned total_bits, msbs; + unsigned k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter > 0); + + k = FLAC__bitmath_ilog2(parameter); + if(parameter == 1u<> k; + total_bits = 1 + k + msbs; + pattern = 1 << k; /* the unary end bit */ + pattern |= (uval & ((1u<= d) { + if(!FLAC__bitbuffer_write_raw_uint32(bb, r+d, k+1)) + return false; + } + else { + if(!FLAC__bitbuffer_write_raw_uint32(bb, r, k)) + return false; + } + } + return true; +} +#endif /* UNUSED */ + +FLAC__bool FLAC__bitbuffer_write_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val) +{ + FLAC__bool ok = 1; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(!(val & 0x80000000)); /* this version only handles 31 bits */ + + if(val < 0x80) { + return FLAC__bitbuffer_write_raw_uint32(bb, val, 8); + } + else if(val < 0x800) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xC0 | (val>>6), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + else if(val < 0x10000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xE0 | (val>>12), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + else if(val < 0x200000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF0 | (val>>18), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + else if(val < 0x4000000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF8 | (val>>24), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + else { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFC | (val>>30), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>24)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + + return ok; +} + +FLAC__bool FLAC__bitbuffer_write_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 val) +{ + FLAC__bool ok = 1; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(!(val & FLAC__U64L(0xFFFFFFF000000000))); /* this version only handles 36 bits */ + + if(val < 0x80) { + return FLAC__bitbuffer_write_raw_uint32(bb, (FLAC__uint32)val, 8); + } + else if(val < 0x800) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xC0 | (FLAC__uint32)(val>>6), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x10000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xE0 | (FLAC__uint32)(val>>12), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x200000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF0 | (FLAC__uint32)(val>>18), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x4000000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF8 | (FLAC__uint32)(val>>24), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x80000000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFC | (FLAC__uint32)(val>>30), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFE, 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>30)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + + return ok; +} + +FLAC__bool FLAC__bitbuffer_zero_pad_to_byte_boundary(FLAC__BitBuffer *bb) +{ + /* 0-pad to byte boundary */ + if(bb->bits & 7u) + return FLAC__bitbuffer_write_zeroes(bb, 8 - (bb->bits & 7u)); + else + return true; +} + +FLAC__bool FLAC__bitbuffer_peek_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* to avoid a drastic speed penalty we don't: + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(bb->bits == 0); + */ + + while(1) { + if(bb->total_consumed_bits < bb->total_bits) { + *val = (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; + return true; + } + else { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + } +} + +FLAC__bool FLAC__bitbuffer_read_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* to avoid a drastic speed penalty we don't: + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(bb->bits == 0); + */ + + while(1) { + if(bb->total_consumed_bits < bb->total_bits) { + *val = (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; + bb->consumed_bits++; + if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + bb->total_consumed_bits++; + return true; + } + else { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + } +} + +FLAC__bool FLAC__bitbuffer_read_bit_to_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* to avoid a drastic speed penalty we don't: + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(bb->bits == 0); + */ + + while(1) { + if(bb->total_consumed_bits < bb->total_bits) { + *val <<= 1; + *val |= (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; + bb->consumed_bits++; + if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + bb->total_consumed_bits++; + return true; + } + else { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + } +} + +FLAC__bool FLAC__bitbuffer_read_bit_to_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* to avoid a drastic speed penalty we don't: + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(bb->bits == 0); + */ + + while(1) { + if(bb->total_consumed_bits < bb->total_bits) { + *val <<= 1; + *val |= (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; + bb->consumed_bits++; + if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + bb->total_consumed_bits++; + return true; + } + else { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + } +} + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_raw_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned i; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + + *val = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, val, read_callback, client_data)) + return false; + } + return true; +} +#else +{ + unsigned i, bits_ = bits; + FLAC__uint32 v = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); + + if(bits == 0) { + *val = 0; + return true; + } + + while(bb->total_consumed_bits + bits > bb->total_bits) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + i = FLAC__BITS_PER_BLURB - bb->consumed_bits; + if(i <= bits_) { + v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); + bits_ -= i; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + /* we hold off updating bb->total_consumed_bits until the end */ + } + else { + *val = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)) >> (i-bits_); + bb->consumed_bits += bits_; + bb->total_consumed_bits += bits_; + return true; + } + } +#if FLAC__BITS_PER_BLURB == 32 + /* note that we know bits_ cannot be > 32 because of previous assertions */ + if(bits_ == FLAC__BITS_PER_BLURB) { + v = bb->buffer[bb->consumed_blurbs]; + CRC16_UPDATE_BLURB(bb, v, bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + bb->total_consumed_bits += bits; + *val = v; + return true; + } +#else + while(bits_ >= FLAC__BITS_PER_BLURB) { + v <<= FLAC__BITS_PER_BLURB; + v |= bb->buffer[bb->consumed_blurbs]; + bits_ -= FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } +#endif + if(bits_ > 0) { + v <<= bits_; + v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); + bb->consumed_bits = bits_; + /* we hold off updating bb->total_consumed_bits until the end */ + } + bb->total_consumed_bits += bits; + *val = v; +#if FLAC__BITS_PER_BLURB > 8 + } + else { + *val = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, val, read_callback, client_data)) + return false; + } + } +#endif + return true; +} +#endif + +FLAC__bool FLAC__bitbuffer_read_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned i; + FLAC__uint32 v; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + + if(bits == 0) { + *val = 0; + return true; + } + + v = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &v, read_callback, client_data)) + return false; + } + + /* fix the sign */ + i = 32 - bits; + if(i) { + v <<= i; + *val = (FLAC__int32)v; + *val >>= i; + } + else + *val = (FLAC__int32)v; + + return true; +} +#else +{ + unsigned i, bits_ = bits; + FLAC__uint32 v = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); + + if(bits == 0) { + *val = 0; + return true; + } + + while(bb->total_consumed_bits + bits > bb->total_bits) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + i = FLAC__BITS_PER_BLURB - bb->consumed_bits; + if(i <= bits_) { + v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); + bits_ -= i; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + /* we hold off updating bb->total_consumed_bits until the end */ + } + else { + /* bits_ must be < FLAC__BITS_PER_BLURB-1 if we get to here */ + v = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)); + v <<= (32-i); + *val = (FLAC__int32)v; + *val >>= (32-bits_); + bb->consumed_bits += bits_; + bb->total_consumed_bits += bits_; + return true; + } + } +#if FLAC__BITS_PER_BLURB == 32 + /* note that we know bits_ cannot be > 32 because of previous assertions */ + if(bits_ == FLAC__BITS_PER_BLURB) { + v = bb->buffer[bb->consumed_blurbs]; + bits_ = 0; + CRC16_UPDATE_BLURB(bb, v, bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } +#else + while(bits_ >= FLAC__BITS_PER_BLURB) { + v <<= FLAC__BITS_PER_BLURB; + v |= bb->buffer[bb->consumed_blurbs]; + bits_ -= FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } +#endif + if(bits_ > 0) { + v <<= bits_; + v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); + bb->consumed_bits = bits_; + /* we hold off updating bb->total_consumed_bits until the end */ + } + bb->total_consumed_bits += bits; +#if FLAC__BITS_PER_BLURB > 8 + } + else { + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &v, read_callback, client_data)) + return false; + } + } +#endif + + /* fix the sign */ + i = 32 - bits; + if(i) { + v <<= i; + *val = (FLAC__int32)v; + *val >>= i; + } + else + *val = (FLAC__int32)v; + + return true; +} +#endif + +FLAC__bool FLAC__bitbuffer_read_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned i; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + + *val = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint64(bb, val, read_callback, client_data)) + return false; + } + return true; +} +#else +{ + unsigned i, bits_ = bits; + FLAC__uint64 v = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); + + if(bits == 0) { + *val = 0; + return true; + } + + while(bb->total_consumed_bits + bits > bb->total_bits) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + i = FLAC__BITS_PER_BLURB - bb->consumed_bits; + if(i <= bits_) { + v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); + bits_ -= i; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + /* we hold off updating bb->total_consumed_bits until the end */ + } + else { + *val = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)) >> (i-bits_); + bb->consumed_bits += bits_; + bb->total_consumed_bits += bits_; + return true; + } + } + while(bits_ >= FLAC__BITS_PER_BLURB) { + v <<= FLAC__BITS_PER_BLURB; + v |= bb->buffer[bb->consumed_blurbs]; + bits_ -= FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } + if(bits_ > 0) { + v <<= bits_; + v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); + bb->consumed_bits = bits_; + /* we hold off updating bb->total_consumed_bits until the end */ + } + bb->total_consumed_bits += bits; + *val = v; +#if FLAC__BITS_PER_BLURB > 8 + } + else { + *val = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint64(bb, val, read_callback, client_data)) + return false; + } + } +#endif + return true; +} +#endif + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_read_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned i; + FLAC__uint64 v; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + + v = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint64(bb, &v, read_callback, client_data)) + return false; + } + /* fix the sign */ + i = 64 - bits; + if(i) { + v <<= i; + *val = (FLAC__int64)v; + *val >>= i; + } + else + *val = (FLAC__int64)v; + + return true; +} +#else +{ + unsigned i, bits_ = bits; + FLAC__uint64 v = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); + + if(bits == 0) { + *val = 0; + return true; + } + + while(bb->total_consumed_bits + bits > bb->total_bits) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + i = FLAC__BITS_PER_BLURB - bb->consumed_bits; + if(i <= bits_) { + v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); + bits_ -= i; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + /* we hold off updating bb->total_consumed_bits until the end */ + } + else { + /* bits_ must be < FLAC__BITS_PER_BLURB-1 if we get to here */ + v = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)); + v <<= (64-i); + *val = (FLAC__int64)v; + *val >>= (64-bits_); + bb->consumed_bits += bits_; + bb->total_consumed_bits += bits_; + return true; + } + } + while(bits_ >= FLAC__BITS_PER_BLURB) { + v <<= FLAC__BITS_PER_BLURB; + v |= bb->buffer[bb->consumed_blurbs]; + bits_ -= FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } + if(bits_ > 0) { + v <<= bits_; + v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); + bb->consumed_bits = bits_; + /* we hold off updating bb->total_consumed_bits until the end */ + } + bb->total_consumed_bits += bits; +#if FLAC__BITS_PER_BLURB > 8 + } + else { + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint64(bb, &v, read_callback, client_data)) + return false; + } + } +#endif + + /* fix the sign */ + i = 64 - bits; + if(i) { + v <<= i; + *val = (FLAC__int64)v; + *val >>= i; + } + else + *val = (FLAC__int64)v; + + return true; +} +#endif +#endif + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_raw_uint32_little_endian(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 x8, x32 = 0; + + /* this doesn't need to be that fast as currently it is only used for vorbis comments */ + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x32, 8, read_callback, client_data)) + return false; + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x8, 8, read_callback, client_data)) + return false; + x32 |= (x8 << 8); + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x8, 8, read_callback, client_data)) + return false; + x32 |= (x8 << 16); + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x8, 8, read_callback, client_data)) + return false; + x32 |= (x8 << 24); + + *val = x32; + return true; +} + +FLAC__bool FLAC__bitbuffer_skip_bits_no_crc(FLAC__BitBuffer *bb, unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* + * @@@ a slightly faster implementation is possible but + * probably not that useful since this is only called a + * couple of times in the metadata readers. + */ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + if(bits > 0) { + const unsigned n = bb->consumed_bits & 7; + unsigned m; + FLAC__uint32 x; + + if(n != 0) { + m = min(8-n, bits); + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, m, read_callback, client_data)) + return false; + bits -= m; + } + m = bits / 8; + if(m > 0) { + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(bb, 0, m, read_callback, client_data)) + return false; + bits %= 8; + } + if(bits > 0) { + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, bits, read_callback, client_data)) + return false; + } + } + + return true; +} + +FLAC__bool FLAC__bitbuffer_read_byte_block_aligned_no_crc(FLAC__BitBuffer *bb, FLAC__byte *val, unsigned nvals, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(bb)); + FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(bb)); +#if FLAC__BITS_PER_BLURB == 8 + while(nvals > 0) { + unsigned chunk = min(nvals, bb->blurbs - bb->consumed_blurbs); + if(chunk == 0) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + else { + if(0 != val) { + memcpy(val, bb->buffer + bb->consumed_blurbs, FLAC__BYTES_PER_BLURB * chunk); + val += FLAC__BYTES_PER_BLURB * chunk; + } + nvals -= chunk; + bb->consumed_blurbs += chunk; + bb->total_consumed_bits = (bb->consumed_blurbs << FLAC__BITS_PER_BLURB_LOG2); + } + } +#else + @@@ need to write this still + FLAC__ASSERT(0); +#endif + + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_unary_unsigned(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned bit, val_ = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + while(1) { + if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data)) + return false; + if(bit) + break; + else + val_++; + } + *val = val_; + return true; +} +#else +{ + unsigned i, val_ = 0; + unsigned total_blurbs_ = (bb->total_bits + (FLAC__BITS_PER_BLURB-1)) / FLAC__BITS_PER_BLURB; + FLAC__blurb b; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + b = bb->buffer[bb->consumed_blurbs] << bb->consumed_bits; + if(b) { + for(i = 0; !(b & FLAC__BLURB_TOP_BIT_ONE); i++) + b <<= 1; + *val = i; + i++; + bb->consumed_bits += i; + bb->total_consumed_bits += i; + if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + return true; + } + else { + val_ = FLAC__BITS_PER_BLURB - bb->consumed_bits; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + bb->total_consumed_bits += val_; + } + } + while(1) { + if(bb->consumed_blurbs >= total_blurbs_) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + total_blurbs_ = (bb->total_bits + (FLAC__BITS_PER_BLURB-1)) / FLAC__BITS_PER_BLURB; + } + b = bb->buffer[bb->consumed_blurbs]; + if(b) { + for(i = 0; !(b & FLAC__BLURB_TOP_BIT_ONE); i++) + b <<= 1; + val_ += i; + i++; + bb->consumed_bits = i; + *val = val_; + if(i == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + bb->total_consumed_bits += i; + return true; + } + else { + val_ += FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, 0, bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + bb->total_consumed_bits += FLAC__BITS_PER_BLURB; + } + } +#if FLAC__BITS_PER_BLURB > 8 + } + else { + while(1) { + if(!FLAC__bitbuffer_read_bit(bb, &i, read_callback, client_data)) + return false; + if(i) + break; + else + val_++; + } + *val = val_; + return true; + } +#endif +} +#endif + +FLAC__bool FLAC__bitbuffer_read_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 lsbs = 0, msbs = 0; + unsigned uval; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, parameter, read_callback, client_data)) + return false; + + /* compose the value */ + uval = (msbs << parameter) | lsbs; + if(uval & 1) + *val = -((int)(uval >> 1)) - 1; + else + *val = (int)(uval >> 1); + + return true; +} + +FLAC__bool FLAC__bitbuffer_read_rice_signed_block(FLAC__BitBuffer *bb, int vals[], unsigned nvals, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__OLD_MSVC_FLAVOR +{ + const FLAC__blurb *buffer = bb->buffer; + + unsigned i, j, val_i = 0; + unsigned cbits = 0, uval = 0, msbs = 0, lsbs_left = 0; + FLAC__blurb blurb, save_blurb; + unsigned state = 0; /* 0 = getting unary MSBs, 1 = getting binary LSBs */ + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + if(nvals == 0) + return true; + + i = bb->consumed_blurbs; + /* + * We unroll the main loop to take care of partially consumed blurbs here. + */ + if(bb->consumed_bits > 0) { + save_blurb = blurb = buffer[i]; + cbits = bb->consumed_bits; + blurb <<= cbits; + + while(1) { + if(state == 0) { + if(blurb) { + for(j = 0; !(blurb & FLAC__BLURB_TOP_BIT_ONE); j++) + blurb <<= 1; + msbs += j; + + /* dispose of the unary end bit */ + blurb <<= 1; + j++; + cbits += j; + + uval = 0; + lsbs_left = parameter; + state++; + if(cbits == FLAC__BITS_PER_BLURB) { + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + msbs += FLAC__BITS_PER_BLURB - cbits; + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + const unsigned available_bits = FLAC__BITS_PER_BLURB - cbits; + if(lsbs_left >= available_bits) { + uval <<= available_bits; + uval |= (blurb >> cbits); + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + + if(lsbs_left == available_bits) { + /* compose the value */ + uval |= (msbs << parameter); + if(uval & 1) + vals[val_i++] = -((int)(uval >> 1)) - 1; + else + vals[val_i++] = (int)(uval >> 1); + if(val_i == nvals) + break; + + msbs = 0; + state = 0; + } + + lsbs_left -= available_bits; + break; + } + else { + uval <<= lsbs_left; + uval |= (blurb >> (FLAC__BITS_PER_BLURB - lsbs_left)); + blurb <<= lsbs_left; + cbits += lsbs_left; + + /* compose the value */ + uval |= (msbs << parameter); + if(uval & 1) + vals[val_i++] = -((int)(uval >> 1)) - 1; + else + vals[val_i++] = (int)(uval >> 1); + if(val_i == nvals) { + /* back up one if we exited the for loop because we read all nvals but the end came in the middle of a blurb */ + i--; + break; + } + + msbs = 0; + state = 0; + } + } + } + i++; + + bb->consumed_blurbs = i; + bb->consumed_bits = cbits; + bb->total_consumed_bits = (i << FLAC__BITS_PER_BLURB_LOG2) | cbits; + } + + /* + * Now that we are blurb-aligned the logic is slightly simpler + */ + while(val_i < nvals) { + for( ; i < bb->blurbs && val_i < nvals; i++) { + save_blurb = blurb = buffer[i]; + cbits = 0; + while(1) { + if(state == 0) { + if(blurb) { + for(j = 0; !(blurb & FLAC__BLURB_TOP_BIT_ONE); j++) + blurb <<= 1; + msbs += j; + + /* dispose of the unary end bit */ + blurb <<= 1; + j++; + cbits += j; + + uval = 0; + lsbs_left = parameter; + state++; + if(cbits == FLAC__BITS_PER_BLURB) { + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + msbs += FLAC__BITS_PER_BLURB - cbits; + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + const unsigned available_bits = FLAC__BITS_PER_BLURB - cbits; + if(lsbs_left >= available_bits) { + uval <<= available_bits; + uval |= (blurb >> cbits); + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + + if(lsbs_left == available_bits) { + /* compose the value */ + uval |= (msbs << parameter); + if(uval & 1) + vals[val_i++] = -((int)(uval >> 1)) - 1; + else + vals[val_i++] = (int)(uval >> 1); + if(val_i == nvals) + break; + + msbs = 0; + state = 0; + } + + lsbs_left -= available_bits; + break; + } + else { + uval <<= lsbs_left; + uval |= (blurb >> (FLAC__BITS_PER_BLURB - lsbs_left)); + blurb <<= lsbs_left; + cbits += lsbs_left; + + /* compose the value */ + uval |= (msbs << parameter); + if(uval & 1) + vals[val_i++] = -((int)(uval >> 1)) - 1; + else + vals[val_i++] = (int)(uval >> 1); + if(val_i == nvals) { + /* back up one if we exited the for loop because we read all nvals but the end came in the middle of a blurb */ + i--; + break; + } + + msbs = 0; + state = 0; + } + } + } + } + bb->consumed_blurbs = i; + bb->consumed_bits = cbits; + bb->total_consumed_bits = (i << FLAC__BITS_PER_BLURB_LOG2) | cbits; + if(val_i < nvals) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + /* these must be zero because we can only get here if we got to the end of the buffer */ + FLAC__ASSERT(bb->consumed_blurbs == 0); + FLAC__ASSERT(bb->consumed_bits == 0); + i = 0; + } + } + + return true; +} +#else +{ + const FLAC__blurb *buffer = bb->buffer; + + unsigned i, j, val_i = nvals; + unsigned cbits = 0, uval = 0, msbs = 0, lsbs_left = 0; + FLAC__blurb blurb, save_blurb; + unsigned state = 0; /* 0 = getting unary MSBs, 1 = getting binary LSBs */ + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + if(nvals == 0) + return true; + + cbits = bb->consumed_bits; + i = bb->consumed_blurbs; + while(val_i != 0) { + for( ; i < bb->blurbs; i++) { + blurb = (save_blurb = buffer[i]) << cbits; + while(1) { + if(state == 0) { + if(blurb) { + j = FLAC__ALIGNED_BLURB_UNARY(blurb); + msbs += j; + j++; + cbits += j; + + uval = 0; + lsbs_left = parameter; + state++; + if(cbits == FLAC__BITS_PER_BLURB) { + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + blurb <<= j; + } + else { + msbs += FLAC__BITS_PER_BLURB - cbits; + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + const unsigned available_bits = FLAC__BITS_PER_BLURB - cbits; + if(lsbs_left >= available_bits) { + uval <<= available_bits; + uval |= (blurb >> cbits); + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + + if(lsbs_left == available_bits) { + /* compose the value */ + uval |= (msbs << parameter); + *vals = (int)(uval >> 1 ^ -(int)(uval & 1)); + --val_i; + if(val_i == 0) { + i++; + goto break2; + } + ++vals; + + msbs = 0; + state = 0; + } + + lsbs_left -= available_bits; + break; + } + else { + cbits += lsbs_left; + uval <<= lsbs_left; + uval |= (blurb >> (FLAC__BITS_PER_BLURB - lsbs_left)); + blurb <<= lsbs_left; + + /* compose the value */ + uval |= (msbs << parameter); + *vals = (int)(uval >> 1 ^ -(int)(uval & 1)); + --val_i; + if(val_i == 0) + goto break2; + ++vals; + + msbs = 0; + state = 0; + } + } + } + } +break2: + bb->consumed_blurbs = i; + bb->consumed_bits = cbits; + bb->total_consumed_bits = (i << FLAC__BITS_PER_BLURB_LOG2) | cbits; + if(val_i != 0) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + /* these must be zero because we can only get here if we got to the end of the buffer */ + FLAC__ASSERT(bb->consumed_blurbs == 0); + FLAC__ASSERT(bb->consumed_bits == 0); + i = 0; + } + } + + return true; +} +#endif + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_read_golomb_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 lsbs = 0, msbs = 0; + unsigned bit, uval, k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + k = FLAC__bitmath_ilog2(parameter); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, k, read_callback, client_data)) + return false; + + if(parameter == 1u<= d) { + if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data)) + return false; + lsbs <<= 1; + lsbs |= bit; + lsbs -= d; + } + /* compose the value */ + uval = msbs * parameter + lsbs; + } + + /* unfold unsigned to signed */ + if(uval & 1) + *val = -((int)(uval >> 1)) - 1; + else + *val = (int)(uval >> 1); + + return true; +} + +FLAC__bool FLAC__bitbuffer_read_golomb_unsigned(FLAC__BitBuffer *bb, unsigned *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 lsbs, msbs = 0; + unsigned bit, k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + k = FLAC__bitmath_ilog2(parameter); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, k, read_callback, client_data)) + return false; + + if(parameter == 1u<= d) { + if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data)) + return false; + lsbs <<= 1; + lsbs |= bit; + lsbs -= d; + } + /* compose the value */ + *val = msbs * parameter + lsbs; + } + + return true; +} +#endif /* UNUSED */ + +/* on return, if *val == 0xffffffff then the utf-8 sequence was invalid, but the return value will be true */ +FLAC__bool FLAC__bitbuffer_read_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen) +{ + FLAC__uint32 v = 0; + FLAC__uint32 x; + unsigned i; + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) + return false; + if(raw) + raw[(*rawlen)++] = (FLAC__byte)x; + if(!(x & 0x80)) { /* 0xxxxxxx */ + v = x; + i = 0; + } + else if(x & 0xC0 && !(x & 0x20)) { /* 110xxxxx */ + v = x & 0x1F; + i = 1; + } + else if(x & 0xE0 && !(x & 0x10)) { /* 1110xxxx */ + v = x & 0x0F; + i = 2; + } + else if(x & 0xF0 && !(x & 0x08)) { /* 11110xxx */ + v = x & 0x07; + i = 3; + } + else if(x & 0xF8 && !(x & 0x04)) { /* 111110xx */ + v = x & 0x03; + i = 4; + } + else if(x & 0xFC && !(x & 0x02)) { /* 1111110x */ + v = x & 0x01; + i = 5; + } + else { + *val = 0xffffffff; + return true; + } + for( ; i; i--) { + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) + return false; + if(raw) + raw[(*rawlen)++] = (FLAC__byte)x; + if(!(x & 0x80) || (x & 0x40)) { /* 10xxxxxx */ + *val = 0xffffffff; + return true; + } + v <<= 6; + v |= (x & 0x3F); + } + *val = v; + return true; +} + +/* on return, if *val == 0xffffffffffffffff then the utf-8 sequence was invalid, but the return value will be true */ +FLAC__bool FLAC__bitbuffer_read_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen) +{ + FLAC__uint64 v = 0; + FLAC__uint32 x; + unsigned i; + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) + return false; + if(raw) + raw[(*rawlen)++] = (FLAC__byte)x; + if(!(x & 0x80)) { /* 0xxxxxxx */ + v = x; + i = 0; + } + else if(x & 0xC0 && !(x & 0x20)) { /* 110xxxxx */ + v = x & 0x1F; + i = 1; + } + else if(x & 0xE0 && !(x & 0x10)) { /* 1110xxxx */ + v = x & 0x0F; + i = 2; + } + else if(x & 0xF0 && !(x & 0x08)) { /* 11110xxx */ + v = x & 0x07; + i = 3; + } + else if(x & 0xF8 && !(x & 0x04)) { /* 111110xx */ + v = x & 0x03; + i = 4; + } + else if(x & 0xFC && !(x & 0x02)) { /* 1111110x */ + v = x & 0x01; + i = 5; + } + else if(x & 0xFE && !(x & 0x01)) { /* 11111110 */ + v = 0; + i = 6; + } + else { + *val = FLAC__U64L(0xffffffffffffffff); + return true; + } + for( ; i; i--) { + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) + return false; + if(raw) + raw[(*rawlen)++] = (FLAC__byte)x; + if(!(x & 0x80) || (x & 0x40)) { /* 10xxxxxx */ + *val = FLAC__U64L(0xffffffffffffffff); + return true; + } + v <<= 6; + v |= (x & 0x3F); + } + *val = v; + return true; +} + +void FLAC__bitbuffer_dump(const FLAC__BitBuffer *bb, FILE *out) +{ + unsigned i, j; + if(bb == 0) { + fprintf(out, "bitbuffer is NULL\n"); + } + else { + fprintf(out, "bitbuffer: capacity=%u blurbs=%u bits=%u total_bits=%u consumed: blurbs=%u, bits=%u, total_bits=%u\n", bb->capacity, bb->blurbs, bb->bits, bb->total_bits, bb->consumed_blurbs, bb->consumed_bits, bb->total_consumed_bits); + + for(i = 0; i < bb->blurbs; i++) { + fprintf(out, "%08X: ", i); + for(j = 0; j < FLAC__BITS_PER_BLURB; j++) + if(i*FLAC__BITS_PER_BLURB+j < bb->total_consumed_bits) + fprintf(out, "."); + else + fprintf(out, "%01u", bb->buffer[i] & (1 << (FLAC__BITS_PER_BLURB-j-1)) ? 1:0); + fprintf(out, "\n"); + } + if(bb->bits > 0) { + fprintf(out, "%08X: ", i); + for(j = 0; j < bb->bits; j++) + if(i*FLAC__BITS_PER_BLURB+j < bb->total_consumed_bits) + fprintf(out, "."); + else + fprintf(out, "%01u", bb->buffer[i] & (1 << (bb->bits-j-1)) ? 1:0); + fprintf(out, "\n"); + } + } +} diff --git a/FLAC/bitmath.c b/FLAC/bitmath.c index 5ace20b9f..e63ef1175 100644 --- a/FLAC/bitmath.c +++ b/FLAC/bitmath.c @@ -1,136 +1,145 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#include "private/bitmath.h" -#include "FLAC/assert.h" - -/* An example of what FLAC__bitmath_ilog2() computes: - * - * ilog2( 0) = assertion failure - * ilog2( 1) = 0 - * ilog2( 2) = 1 - * ilog2( 3) = 1 - * ilog2( 4) = 2 - * ilog2( 5) = 2 - * ilog2( 6) = 2 - * ilog2( 7) = 2 - * ilog2( 8) = 3 - * ilog2( 9) = 3 - * ilog2(10) = 3 - * ilog2(11) = 3 - * ilog2(12) = 3 - * ilog2(13) = 3 - * ilog2(14) = 3 - * ilog2(15) = 3 - * ilog2(16) = 4 - * ilog2(17) = 4 - * ilog2(18) = 4 - */ -unsigned FLAC__bitmath_ilog2(unsigned v) -{ - unsigned l = 0; - FLAC__ASSERT(v > 0); - while(v >>= 1) - l++; - return l; -} - -/* An example of what FLAC__bitmath_silog2() computes: - * - * silog2(-10) = 5 - * silog2(- 9) = 5 - * silog2(- 8) = 4 - * silog2(- 7) = 4 - * silog2(- 6) = 4 - * silog2(- 5) = 4 - * silog2(- 4) = 3 - * silog2(- 3) = 3 - * silog2(- 2) = 2 - * silog2(- 1) = 2 - * silog2( 0) = 0 - * silog2( 1) = 2 - * silog2( 2) = 3 - * silog2( 3) = 3 - * silog2( 4) = 4 - * silog2( 5) = 4 - * silog2( 6) = 4 - * silog2( 7) = 4 - * silog2( 8) = 5 - * silog2( 9) = 5 - * silog2( 10) = 5 - */ -unsigned FLAC__bitmath_silog2(int v) -{ - while(1) { - if(v == 0) { - return 0; - } - else if(v > 0) { - unsigned l = 0; - while(v) { - l++; - v >>= 1; - } - return l+1; - } - else if(v == -1) { - return 2; - } - else { - v++; - v = -v; - } - } -} - -unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v) -{ - while(1) { - if(v == 0) { - return 0; - } - else if(v > 0) { - unsigned l = 0; - while(v) { - l++; - v >>= 1; - } - return l+1; - } - else if(v == -1) { - return 2; - } - else { - v++; - v = -v; - } - } -} +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#include "private/bitmath.h" +#include "FLAC/assert.h" + +/* An example of what FLAC__bitmath_ilog2() computes: + * + * ilog2( 0) = assertion failure + * ilog2( 1) = 0 + * ilog2( 2) = 1 + * ilog2( 3) = 1 + * ilog2( 4) = 2 + * ilog2( 5) = 2 + * ilog2( 6) = 2 + * ilog2( 7) = 2 + * ilog2( 8) = 3 + * ilog2( 9) = 3 + * ilog2(10) = 3 + * ilog2(11) = 3 + * ilog2(12) = 3 + * ilog2(13) = 3 + * ilog2(14) = 3 + * ilog2(15) = 3 + * ilog2(16) = 4 + * ilog2(17) = 4 + * ilog2(18) = 4 + */ +unsigned FLAC__bitmath_ilog2(FLAC__uint32 v) +{ + unsigned l = 0; + FLAC__ASSERT(v > 0); + while(v >>= 1) + l++; + return l; +} + +unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v) +{ + unsigned l = 0; + FLAC__ASSERT(v > 0); + while(v >>= 1) + l++; + return l; +} + +/* An example of what FLAC__bitmath_silog2() computes: + * + * silog2(-10) = 5 + * silog2(- 9) = 5 + * silog2(- 8) = 4 + * silog2(- 7) = 4 + * silog2(- 6) = 4 + * silog2(- 5) = 4 + * silog2(- 4) = 3 + * silog2(- 3) = 3 + * silog2(- 2) = 2 + * silog2(- 1) = 2 + * silog2( 0) = 0 + * silog2( 1) = 2 + * silog2( 2) = 3 + * silog2( 3) = 3 + * silog2( 4) = 4 + * silog2( 5) = 4 + * silog2( 6) = 4 + * silog2( 7) = 4 + * silog2( 8) = 5 + * silog2( 9) = 5 + * silog2( 10) = 5 + */ +unsigned FLAC__bitmath_silog2(int v) +{ + while(1) { + if(v == 0) { + return 0; + } + else if(v > 0) { + unsigned l = 0; + while(v) { + l++; + v >>= 1; + } + return l+1; + } + else if(v == -1) { + return 2; + } + else { + v++; + v = -v; + } + } +} + +unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v) +{ + while(1) { + if(v == 0) { + return 0; + } + else if(v > 0) { + unsigned l = 0; + while(v) { + l++; + v >>= 1; + } + return l+1; + } + else if(v == -1) { + return 2; + } + else { + v++; + v = -v; + } + } +} diff --git a/FLAC/cpu.c b/FLAC/cpu.c index 63ce05e09..225bf4fad 100644 --- a/FLAC/cpu.c +++ b/FLAC/cpu.c @@ -1,117 +1,193 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#include "private/cpu.h" -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#if defined FLAC__CPU_PPC -#if !defined FLAC__NO_ASM -#if defined __APPLE__ && defined __MACH__ -#include -#endif /* __APPLE__ && __MACH__ */ -#endif /* FLAC__NO_ASM */ -#endif /* FLAC__CPU_PPC */ - -const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV = 0x00008000; -const unsigned FLAC__CPUINFO_IA32_CPUID_MMX = 0x00800000; -const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR = 0x01000000; -const unsigned FLAC__CPUINFO_IA32_CPUID_SSE = 0x02000000; -const unsigned FLAC__CPUINFO_IA32_CPUID_SSE2 = 0x04000000; - -const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW = 0x80000000; -const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW = 0x40000000; -const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX = 0x00400000; - - -void FLAC__cpu_info(FLAC__CPUInfo *info) -{ -#ifdef FLAC__CPU_IA32 - info->type = FLAC__CPUINFO_TYPE_IA32; -#if !defined FLAC__NO_ASM && defined FLAC__HAS_NASM - info->use_asm = true; - { - unsigned cpuid = FLAC__cpu_info_asm_ia32(); - info->data.ia32.cmov = (cpuid & FLAC__CPUINFO_IA32_CPUID_CMOV)? true : false; - info->data.ia32.mmx = (cpuid & FLAC__CPUINFO_IA32_CPUID_MMX)? true : false; - info->data.ia32.fxsr = (cpuid & FLAC__CPUINFO_IA32_CPUID_FXSR)? true : false; - info->data.ia32.sse = (cpuid & FLAC__CPUINFO_IA32_CPUID_SSE)? true : false; - info->data.ia32.sse2 = (cpuid & FLAC__CPUINFO_IA32_CPUID_SSE2)? true : false; - -#ifndef FLAC__SSE_OS - info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = false; -#endif - -#ifdef FLAC__USE_3DNOW - cpuid = FLAC__cpu_info_extended_amd_asm_ia32(); - info->data.ia32._3dnow = (cpuid & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW)? true : false; - info->data.ia32.ext3dnow = (cpuid & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW)? true : false; - info->data.ia32.extmmx = (cpuid & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX)? true : false; -#else - info->data.ia32._3dnow = info->data.ia32.ext3dnow = info->data.ia32.extmmx = false; -#endif - } -#else - info->use_asm = false; -#endif -#elif defined FLAC__CPU_PPC - info->type = FLAC__CPUINFO_TYPE_PPC; -#if !defined FLAC__NO_ASM - info->use_asm = true; -#ifdef FLAC__USE_ALTIVEC -#if defined __APPLE__ && defined __MACH__ - { - int selectors[2] = { CTL_HW, HW_VECTORUNIT }; - int result = 0; - size_t length = sizeof(result); - int error = sysctl(selectors, 2, &result, &length, 0, 0); - - info->data.ppc.altivec = error==0 ? result!=0 : 0; - } -#else /* __APPLE__ && __MACH__ */ - /* don't know of any other thread-safe way to check */ - info->data.ppc.altivec = 0; -#endif /* __APPLE__ && __MACH__ */ -#else /* FLAC__USE_ALTIVEC */ - info->data.ppc.altivec = 0; -#endif /* FLAC__USE_ALTIVEC */ -#else /* FLAC__NO_ASM */ - info->use_asm = false; -#endif /* FLAC__NO_ASM */ -#else - info->type = FLAC__CPUINFO_TYPE_UNKNOWN; - info->use_asm = false; -#endif -} +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#include "private/cpu.h" +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if defined FLAC__CPU_PPC +# if !defined FLAC__NO_ASM +# if defined FLAC__SYS_DARWIN +# include +# include +# include +# include +# include +# ifndef CPU_SUBTYPE_POWERPC_970 +# define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100) +# endif +# else /* FLAC__SYS_DARWIN */ + +# ifdef __FreeBSD__ +# include +# include +# endif + +# include +# include + +static sigjmp_buf jmpbuf; +static volatile sig_atomic_t canjump = 0; + +static void sigill_handler (int sig) +{ + if (!canjump) { + signal (sig, SIG_DFL); + raise (sig); + } + canjump = 0; + siglongjmp (jmpbuf, 1); +} +# endif /* FLAC__SYS_DARWIN */ +# endif /* FLAC__NO_ASM */ +#endif /* FLAC__CPU_PPC */ + +const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV = 0x00008000; +const unsigned FLAC__CPUINFO_IA32_CPUID_MMX = 0x00800000; +const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR = 0x01000000; +const unsigned FLAC__CPUINFO_IA32_CPUID_SSE = 0x02000000; +const unsigned FLAC__CPUINFO_IA32_CPUID_SSE2 = 0x04000000; + +const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW = 0x80000000; +const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW = 0x40000000; +const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX = 0x00400000; + + +void FLAC__cpu_info(FLAC__CPUInfo *info) +{ +#ifdef FLAC__CPU_IA32 + info->type = FLAC__CPUINFO_TYPE_IA32; +#if !defined FLAC__NO_ASM && defined FLAC__HAS_NASM + info->use_asm = true; + { + unsigned cpuid = FLAC__cpu_info_asm_ia32(); + info->data.ia32.cmov = (cpuid & FLAC__CPUINFO_IA32_CPUID_CMOV)? true : false; + info->data.ia32.mmx = (cpuid & FLAC__CPUINFO_IA32_CPUID_MMX)? true : false; + info->data.ia32.fxsr = (cpuid & FLAC__CPUINFO_IA32_CPUID_FXSR)? true : false; + info->data.ia32.sse = (cpuid & FLAC__CPUINFO_IA32_CPUID_SSE)? true : false; + info->data.ia32.sse2 = (cpuid & FLAC__CPUINFO_IA32_CPUID_SSE2)? true : false; + +#ifndef FLAC__SSE_OS + info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = false; +#elif defined(__FreeBSD__) + /* on FreeBSD we can double-check via sysctl whether the OS supports SSE */ + { + int sse; + size_t len = sizeof(sse); + if (sysctlbyname("hw.instruction_sse", &sse, &len, NULL, 0) || !sse) + info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = false; + } +#endif + +#ifdef FLAC__USE_3DNOW + cpuid = FLAC__cpu_info_extended_amd_asm_ia32(); + info->data.ia32._3dnow = (cpuid & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW)? true : false; + info->data.ia32.ext3dnow = (cpuid & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW)? true : false; + info->data.ia32.extmmx = (cpuid & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX)? true : false; +#else + info->data.ia32._3dnow = info->data.ia32.ext3dnow = info->data.ia32.extmmx = false; +#endif + } +#else + info->use_asm = false; +#endif +#elif defined FLAC__CPU_PPC + info->type = FLAC__CPUINFO_TYPE_PPC; +#if !defined FLAC__NO_ASM + info->use_asm = true; +#ifdef FLAC__USE_ALTIVEC +#if defined FLAC__SYS_DARWIN + { + int selectors[2] = { CTL_HW, HW_VECTORUNIT }; + int result = 0; + size_t length = sizeof(result); + int error = sysctl(selectors, 2, &result, &length, 0, 0); + + info->data.ppc.altivec = error==0 ? result!=0 : 0; + } + { + host_basic_info_data_t hostInfo; + mach_msg_type_number_t infoCount; + + infoCount = HOST_BASIC_INFO_COUNT; + host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount); + + info->data.ppc.ppc64 = (hostInfo.cpu_type == CPU_TYPE_POWERPC) && (hostInfo.cpu_subtype == CPU_SUBTYPE_POWERPC_970); + } +#else /* FLAC__SYS_DARWIN */ + { + /* no Darwin, do it the brute-force way */ + /* this is borrowed from MPlayer from the libmpeg2 library */ + info->data.ppc.altivec = 0; + info->data.ppc.ppc64 = 0; + + signal (SIGILL, sigill_handler); + if (!sigsetjmp (jmpbuf, 1)) { + canjump = 1; + + asm volatile ( + "mtspr 256, %0\n\t" + "vand %%v0, %%v0, %%v0" + : + : "r" (-1) + ); + + info->data.ppc.altivec = 1; + } + canjump = 0; + if (!sigsetjmp (jmpbuf, 1)) { + int x = 0; + canjump = 1; + + /* PPC64 hardware implements the cntlzd instruction */ + asm volatile ("cntlzd %0, %1" : "=r" (x) : "r" (x) ); + + info->data.ppc.ppc64 = 1; + } + signal (SIGILL, SIG_DFL); + } +#endif /* FLAC__SYS_DARWIN */ +#else /* FLAC__USE_ALTIVEC */ + info->data.ppc.altivec = 0; + info->data.ppc.ppc64 = 0; +#endif /* FLAC__USE_ALTIVEC */ +#else /* FLAC__NO_ASM */ + info->use_asm = false; +#endif /* FLAC__NO_ASM */ +#else + info->type = FLAC__CPUINFO_TYPE_UNKNOWN; + info->use_asm = false; +#endif +} diff --git a/FLAC/crc.c b/FLAC/crc.c index f453f8c7a..49274eab8 100644 --- a/FLAC/crc.c +++ b/FLAC/crc.c @@ -1,149 +1,149 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#include "private/crc.h" - -/* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */ - -FLAC__byte const FLAC__crc8_table[256] = { - 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, - 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, - 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, - 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, - 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, - 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, - 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, - 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, - 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, - 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, - 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, - 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, - 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, - 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, - 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, - 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, - 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, - 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, - 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, - 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, - 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, - 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, - 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, - 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, - 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, - 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, - 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, - 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, - 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, - 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, - 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, - 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 -}; - -/* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */ - -FLAC__uint16 FLAC__crc16_table[256] = { - 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, - 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, - 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, - 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, - 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, - 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, - 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, - 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, - 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, - 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, - 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, - 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, - 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, - 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, - 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, - 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, - 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, - 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, - 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, - 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, - 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, - 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, - 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, - 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, - 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, - 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, - 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, - 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, - 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, - 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, - 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, - 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 -}; - - -void FLAC__crc8_update(const FLAC__byte data, FLAC__uint8 *crc) -{ - *crc = FLAC__crc8_table[*crc ^ data]; -} - -void FLAC__crc8_update_block(const FLAC__byte *data, unsigned len, FLAC__uint8 *crc) -{ - while(len--) - *crc = FLAC__crc8_table[*crc ^ *data++]; -} - -FLAC__uint8 FLAC__crc8(const FLAC__byte *data, unsigned len) -{ - FLAC__uint8 crc = 0; - - while(len--) - crc = FLAC__crc8_table[crc ^ *data++]; - - return crc; -} - -void FLAC__crc16_update(const FLAC__byte data, FLAC__uint16 *crc) -{ - *crc = (*crc<<8) ^ FLAC__crc16_table[(*crc>>8) ^ data]; -} - -void FLAC__crc16_update_block(const FLAC__byte *data, unsigned len, FLAC__uint16 *crc) -{ - while(len--) - *crc = (*crc<<8) ^ FLAC__crc16_table[(*crc>>8) ^ *data++]; -} - -FLAC__uint16 FLAC__crc16(const FLAC__byte *data, unsigned len) -{ - FLAC__uint16 crc = 0; - - while(len--) - crc = (crc<<8) ^ FLAC__crc16_table[(crc>>8) ^ *data++]; - - return crc; -} +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#include "private/crc.h" + +/* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */ + +FLAC__byte const FLAC__crc8_table[256] = { + 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, + 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, + 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, + 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, + 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, + 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, + 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, + 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, + 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, + 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, + 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, + 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, + 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, + 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, + 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, + 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, + 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, + 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, + 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, + 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, + 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, + 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, + 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, + 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, + 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, + 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, + 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, + 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, + 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, + 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, + 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, + 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 +}; + +/* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */ + +FLAC__uint16 FLAC__crc16_table[256] = { + 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, + 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, + 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, + 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, + 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, + 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, + 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, + 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, + 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, + 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, + 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, + 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, + 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, + 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, + 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, + 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, + 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, + 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, + 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 +}; + + +void FLAC__crc8_update(const FLAC__byte data, FLAC__uint8 *crc) +{ + *crc = FLAC__crc8_table[*crc ^ data]; +} + +void FLAC__crc8_update_block(const FLAC__byte *data, unsigned len, FLAC__uint8 *crc) +{ + while(len--) + *crc = FLAC__crc8_table[*crc ^ *data++]; +} + +FLAC__uint8 FLAC__crc8(const FLAC__byte *data, unsigned len) +{ + FLAC__uint8 crc = 0; + + while(len--) + crc = FLAC__crc8_table[crc ^ *data++]; + + return crc; +} + +void FLAC__crc16_update(const FLAC__byte data, FLAC__uint16 *crc) +{ + *crc = (*crc<<8) ^ FLAC__crc16_table[(*crc>>8) ^ data]; +} + +void FLAC__crc16_update_block(const FLAC__byte *data, unsigned len, FLAC__uint16 *crc) +{ + while(len--) + *crc = (*crc<<8) ^ FLAC__crc16_table[(*crc>>8) ^ *data++]; +} + +FLAC__uint16 FLAC__crc16(const FLAC__byte *data, unsigned len) +{ + FLAC__uint16 crc = 0; + + while(len--) + crc = (crc<<8) ^ FLAC__crc16_table[(crc>>8) ^ *data++]; + + return crc; +} diff --git a/FLAC/fixed.c b/FLAC/fixed.c index bf88461a6..6824e9371 100644 --- a/FLAC/fixed.c +++ b/FLAC/fixed.c @@ -1,231 +1,422 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#include -#include "private/fixed.h" -#include "FLAC/assert.h" - -#ifndef M_LN2 -/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ -#define M_LN2 0.69314718055994530942 -#endif - -#ifdef min -#undef min -#endif -#define min(x,y) ((x) < (y)? (x) : (y)) - -#ifdef local_abs -#undef local_abs -#endif -#define local_abs(x) ((unsigned)((x)<0? -(x) : (x))) - -unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) -{ - 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; - unsigned i, order; - - for(i = 0; i < data_len; i++) { - error = data[i] ; total_error_0 += local_abs(error); save = error; - error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error; - error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error; - error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error; - error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save; - } - - if(total_error_0 < min(min(min(total_error_1, total_error_2), total_error_3), total_error_4)) - order = 0; - else if(total_error_1 < min(min(total_error_2, total_error_3), total_error_4)) - order = 1; - else if(total_error_2 < min(total_error_3, total_error_4)) - order = 2; - else if(total_error_3 < total_error_4) - order = 3; - else - order = 4; - - /* Estimate the expected number of bits per residual signal sample. */ - /* 'total_error*' is linearly related to the variance of the residual */ - /* signal, so we use it directly to compute E(|x|) */ - FLAC__ASSERT(data_len > 0 || total_error_0 == 0); - FLAC__ASSERT(data_len > 0 || total_error_1 == 0); - FLAC__ASSERT(data_len > 0 || total_error_2 == 0); - FLAC__ASSERT(data_len > 0 || total_error_3 == 0); - FLAC__ASSERT(data_len > 0 || total_error_4 == 0); - residual_bits_per_sample[0] = (FLAC__real)((total_error_0 > 0) ? log(M_LN2 * (double)total_error_0 / (double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[1] = (FLAC__real)((total_error_1 > 0) ? log(M_LN2 * (double)total_error_1 / (double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[2] = (FLAC__real)((total_error_2 > 0) ? log(M_LN2 * (double)total_error_2 / (double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[3] = (FLAC__real)((total_error_3 > 0) ? log(M_LN2 * (double)total_error_3 / (double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[4] = (FLAC__real)((total_error_4 > 0) ? log(M_LN2 * (double)total_error_4 / (double)data_len) / M_LN2 : 0.0); - - return order; -} - -unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) -{ - 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; - unsigned i, order; - - for(i = 0; i < data_len; i++) { - error = data[i] ; total_error_0 += local_abs(error); save = error; - error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error; - error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error; - error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error; - error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save; - } - - if(total_error_0 < min(min(min(total_error_1, total_error_2), total_error_3), total_error_4)) - order = 0; - else if(total_error_1 < min(min(total_error_2, total_error_3), total_error_4)) - order = 1; - else if(total_error_2 < min(total_error_3, total_error_4)) - order = 2; - else if(total_error_3 < total_error_4) - order = 3; - else - order = 4; - - /* Estimate the expected number of bits per residual signal sample. */ - /* 'total_error*' is linearly related to the variance of the residual */ - /* signal, so we use it directly to compute E(|x|) */ - FLAC__ASSERT(data_len > 0 || total_error_0 == 0); - FLAC__ASSERT(data_len > 0 || total_error_1 == 0); - FLAC__ASSERT(data_len > 0 || total_error_2 == 0); - FLAC__ASSERT(data_len > 0 || total_error_3 == 0); - FLAC__ASSERT(data_len > 0 || total_error_4 == 0); -#if defined _MSC_VER || defined __MINGW32__ - /* with VC++ you have to spoon feed it the casting */ - residual_bits_per_sample[0] = (FLAC__real)((total_error_0 > 0) ? log(M_LN2 * (double)(FLAC__int64)total_error_0 / (double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[1] = (FLAC__real)((total_error_1 > 0) ? log(M_LN2 * (double)(FLAC__int64)total_error_1 / (double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[2] = (FLAC__real)((total_error_2 > 0) ? log(M_LN2 * (double)(FLAC__int64)total_error_2 / (double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[3] = (FLAC__real)((total_error_3 > 0) ? log(M_LN2 * (double)(FLAC__int64)total_error_3 / (double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[4] = (FLAC__real)((total_error_4 > 0) ? log(M_LN2 * (double)(FLAC__int64)total_error_4 / (double)data_len) / M_LN2 : 0.0); -#else - residual_bits_per_sample[0] = (FLAC__real)((total_error_0 > 0) ? log(M_LN2 * (double)total_error_0 / (double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[1] = (FLAC__real)((total_error_1 > 0) ? log(M_LN2 * (double)total_error_1 / (double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[2] = (FLAC__real)((total_error_2 > 0) ? log(M_LN2 * (double)total_error_2 / (double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[3] = (FLAC__real)((total_error_3 > 0) ? log(M_LN2 * (double)total_error_3 / (double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[4] = (FLAC__real)((total_error_4 > 0) ? log(M_LN2 * (double)total_error_4 / (double)data_len) / M_LN2 : 0.0); -#endif - - return order; -} - -void FLAC__fixed_compute_residual(const FLAC__int32 data[], unsigned data_len, unsigned 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++) { - /* == data[i] - 2*data[i-1] + data[i-2] */ - residual[i] = data[i] - (data[i-1] << 1) + data[i-2]; - } - break; - case 3: - for(i = 0; i < idata_len; i++) { - /* == data[i] - 3*data[i-1] + 3*data[i-2] - data[i-3] */ - residual[i] = data[i] - (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) - data[i-3]; - } - break; - case 4: - for(i = 0; i < idata_len; i++) { - /* == data[i] - 4*data[i-1] + 6*data[i-2] - 4*data[i-3] + data[i-4] */ - residual[i] = data[i] - ((data[i-1]+data[i-3])<<2) + ((data[i-2]<<2) + (data[i-2]<<1)) + data[i-4]; - } - break; - default: - FLAC__ASSERT(0); - } -} - -void FLAC__fixed_restore_signal(const FLAC__int32 residual[], unsigned data_len, unsigned order, FLAC__int32 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] = residual[i] + data[i-1]; - } - break; - case 2: - for(i = 0; i < idata_len; i++) { - /* == residual[i] + 2*data[i-1] - data[i-2] */ - data[i] = residual[i] + (data[i-1]<<1) - data[i-2]; - } - break; - case 3: - for(i = 0; i < idata_len; i++) { - /* residual[i] + 3*data[i-1] - 3*data[i-2]) + data[i-3] */ - data[i] = residual[i] + (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) + data[i-3]; - } - break; - case 4: - for(i = 0; i < idata_len; i++) { - /* == residual[i] + 4*data[i-1] - 6*data[i-2] + 4*data[i-3] - data[i-4] */ - data[i] = residual[i] + ((data[i-1]+data[i-3])<<2) - ((data[i-2]<<2) + (data[i-2]<<1)) - data[i-4]; - } - break; - default: - FLAC__ASSERT(0); - } -} +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#include +#include "private/bitmath.h" +#include "private/fixed.h" +#include "FLAC/assert.h" + +#ifndef M_LN2 +/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ +#define M_LN2 0.69314718055994530942 +#endif + +#ifdef min +#undef min +#endif +#define min(x,y) ((x) < (y)? (x) : (y)) + +#ifdef local_abs +#undef local_abs +#endif +#define local_abs(x) ((unsigned)((x)<0? -(x) : (x))) + +#ifdef FLAC__INTEGER_ONLY_LIBRARY +/* rbps stands for residual bits per sample + * + * (ln(2) * err) + * rbps = log (-----------) + * 2 ( n ) + */ +static FLAC__fixedpoint local__compute_rbps_integerized(FLAC__uint32 err, FLAC__uint32 n) +{ + FLAC__uint32 rbps; + unsigned bits; /* the number of bits required to represent a number */ + int fracbits; /* the number of bits of rbps that comprise the fractional part */ + + FLAC__ASSERT(sizeof(rbps) == sizeof(FLAC__fixedpoint)); + FLAC__ASSERT(err > 0); + FLAC__ASSERT(n > 0); + + FLAC__ASSERT(n <= FLAC__MAX_BLOCK_SIZE); + if(err <= n) + return 0; + /* + * The above two things tell us 1) n fits in 16 bits; 2) err/n > 1. + * These allow us later to know we won't lose too much precision in the + * fixed-point division (err< 0); + bits = FLAC__bitmath_ilog2(err)+1; + if(bits > 16) { + err >>= (bits-16); + fracbits -= (bits-16); + } + rbps = (FLAC__uint32)err; + + /* Multiply by fixed-point version of ln(2), with 16 fractional bits */ + rbps *= FLAC__FP_LN2; + fracbits += 16; + FLAC__ASSERT(fracbits >= 0); + + /* FLAC__fixedpoint_log2 requires fracbits%4 to be 0 */ + { + const int f = fracbits & 3; + if(f) { + rbps >>= f; + fracbits -= f; + } + } + + rbps = FLAC__fixedpoint_log2(rbps, fracbits, (unsigned)(-1)); + + if(rbps == 0) + return 0; + + /* + * The return value must have 16 fractional bits. Since the whole part + * of the base-2 log of a 32 bit number must fit in 5 bits, and fracbits + * must be >= -3, these assertion allows us to be able to shift rbps + * left if necessary to get 16 fracbits without losing any bits of the + * whole part of rbps. + * + * There is a slight chance due to accumulated error that the whole part + * will require 6 bits, so we use 6 in the assertion. Really though as + * long as it fits in 13 bits (32 - (16 - (-3))) we are fine. + */ + FLAC__ASSERT((int)FLAC__bitmath_ilog2(rbps)+1 <= fracbits + 6); + FLAC__ASSERT(fracbits >= -3); + + /* now shift the decimal point into place */ + if(fracbits < 16) + return rbps << (16-fracbits); + else if(fracbits > 16) + return rbps >> (fracbits-16); + else + return rbps; +} + +static FLAC__fixedpoint local__compute_rbps_wide_integerized(FLAC__uint64 err, FLAC__uint32 n) +{ + FLAC__uint32 rbps; + unsigned bits; /* the number of bits required to represent a number */ + int fracbits; /* the number of bits of rbps that comprise the fractional part */ + + FLAC__ASSERT(sizeof(rbps) == sizeof(FLAC__fixedpoint)); + FLAC__ASSERT(err > 0); + FLAC__ASSERT(n > 0); + + FLAC__ASSERT(n <= FLAC__MAX_BLOCK_SIZE); + if(err <= n) + return 0; + /* + * The above two things tell us 1) n fits in 16 bits; 2) err/n > 1. + * These allow us later to know we won't lose too much precision in the + * fixed-point division (err< 0); + bits = FLAC__bitmath_ilog2_wide(err)+1; + if(bits > 16) { + err >>= (bits-16); + fracbits -= (bits-16); + } + rbps = (FLAC__uint32)err; + + /* Multiply by fixed-point version of ln(2), with 16 fractional bits */ + rbps *= FLAC__FP_LN2; + fracbits += 16; + FLAC__ASSERT(fracbits >= 0); + + /* FLAC__fixedpoint_log2 requires fracbits%4 to be 0 */ + { + const int f = fracbits & 3; + if(f) { + rbps >>= f; + fracbits -= f; + } + } + + rbps = FLAC__fixedpoint_log2(rbps, fracbits, (unsigned)(-1)); + + if(rbps == 0) + return 0; + + /* + * The return value must have 16 fractional bits. Since the whole part + * of the base-2 log of a 32 bit number must fit in 5 bits, and fracbits + * must be >= -3, these assertion allows us to be able to shift rbps + * left if necessary to get 16 fracbits without losing any bits of the + * whole part of rbps. + * + * There is a slight chance due to accumulated error that the whole part + * will require 6 bits, so we use 6 in the assertion. Really though as + * long as it fits in 13 bits (32 - (16 - (-3))) we are fine. + */ + FLAC__ASSERT((int)FLAC__bitmath_ilog2(rbps)+1 <= fracbits + 6); + FLAC__ASSERT(fracbits >= -3); + + /* now shift the decimal point into place */ + if(fracbits < 16) + return rbps << (16-fracbits); + else if(fracbits > 16) + return rbps >> (fracbits-16); + else + return rbps; +} +#endif + +#ifndef FLAC__INTEGER_ONLY_LIBRARY +unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +#else +unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned 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; + FLAC__uint32 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0; + unsigned i, order; + + for(i = 0; i < data_len; i++) { + error = data[i] ; total_error_0 += local_abs(error); save = error; + error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error; + error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error; + error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error; + error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save; + } + + if(total_error_0 < min(min(min(total_error_1, total_error_2), total_error_3), total_error_4)) + order = 0; + else if(total_error_1 < min(min(total_error_2, total_error_3), total_error_4)) + order = 1; + else if(total_error_2 < min(total_error_3, total_error_4)) + order = 2; + else if(total_error_3 < total_error_4) + order = 3; + else + order = 4; + + /* Estimate the expected number of bits per residual signal sample. */ + /* 'total_error*' is linearly related to the variance of the residual */ + /* signal, so we use it directly to compute E(|x|) */ + FLAC__ASSERT(data_len > 0 || total_error_0 == 0); + FLAC__ASSERT(data_len > 0 || total_error_1 == 0); + FLAC__ASSERT(data_len > 0 || total_error_2 == 0); + FLAC__ASSERT(data_len > 0 || total_error_3 == 0); + FLAC__ASSERT(data_len > 0 || total_error_4 == 0); +#ifndef FLAC__INTEGER_ONLY_LIBRARY + residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0); +#else + residual_bits_per_sample[0] = (total_error_0 > 0) ? local__compute_rbps_integerized(total_error_0, data_len) : 0; + residual_bits_per_sample[1] = (total_error_1 > 0) ? local__compute_rbps_integerized(total_error_1, data_len) : 0; + residual_bits_per_sample[2] = (total_error_2 > 0) ? local__compute_rbps_integerized(total_error_2, data_len) : 0; + residual_bits_per_sample[3] = (total_error_3 > 0) ? local__compute_rbps_integerized(total_error_3, data_len) : 0; + residual_bits_per_sample[4] = (total_error_4 > 0) ? local__compute_rbps_integerized(total_error_4, data_len) : 0; +#endif + + return order; +} + +#ifndef FLAC__INTEGER_ONLY_LIBRARY +unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +#else +unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned 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; + unsigned i, order; + + for(i = 0; i < data_len; i++) { + error = data[i] ; total_error_0 += local_abs(error); save = error; + error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error; + error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error; + error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error; + error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save; + } + + if(total_error_0 < min(min(min(total_error_1, total_error_2), total_error_3), total_error_4)) + order = 0; + else if(total_error_1 < min(min(total_error_2, total_error_3), total_error_4)) + order = 1; + else if(total_error_2 < min(total_error_3, total_error_4)) + order = 2; + else if(total_error_3 < total_error_4) + order = 3; + else + order = 4; + + /* Estimate the expected number of bits per residual signal sample. */ + /* 'total_error*' is linearly related to the variance of the residual */ + /* signal, so we use it directly to compute E(|x|) */ + FLAC__ASSERT(data_len > 0 || total_error_0 == 0); + FLAC__ASSERT(data_len > 0 || total_error_1 == 0); + FLAC__ASSERT(data_len > 0 || total_error_2 == 0); + FLAC__ASSERT(data_len > 0 || total_error_3 == 0); + FLAC__ASSERT(data_len > 0 || total_error_4 == 0); +#ifndef FLAC__INTEGER_ONLY_LIBRARY +#if defined _MSC_VER || defined __MINGW32__ + /* with MSVC you have to spoon feed it the casting */ + residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0); +#else + residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0); +#endif +#else + residual_bits_per_sample[0] = (total_error_0 > 0) ? local__compute_rbps_wide_integerized(total_error_0, data_len) : 0; + residual_bits_per_sample[1] = (total_error_1 > 0) ? local__compute_rbps_wide_integerized(total_error_1, data_len) : 0; + residual_bits_per_sample[2] = (total_error_2 > 0) ? local__compute_rbps_wide_integerized(total_error_2, data_len) : 0; + residual_bits_per_sample[3] = (total_error_3 > 0) ? local__compute_rbps_wide_integerized(total_error_3, data_len) : 0; + residual_bits_per_sample[4] = (total_error_4 > 0) ? local__compute_rbps_wide_integerized(total_error_4, data_len) : 0; +#endif + + return order; +} + +void FLAC__fixed_compute_residual(const FLAC__int32 data[], unsigned data_len, unsigned 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++) { + /* == data[i] - 2*data[i-1] + data[i-2] */ + residual[i] = data[i] - (data[i-1] << 1) + data[i-2]; + } + break; + case 3: + for(i = 0; i < idata_len; i++) { + /* == data[i] - 3*data[i-1] + 3*data[i-2] - data[i-3] */ + residual[i] = data[i] - (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) - data[i-3]; + } + break; + case 4: + for(i = 0; i < idata_len; i++) { + /* == data[i] - 4*data[i-1] + 6*data[i-2] - 4*data[i-3] + data[i-4] */ + residual[i] = data[i] - ((data[i-1]+data[i-3])<<2) + ((data[i-2]<<2) + (data[i-2]<<1)) + data[i-4]; + } + break; + default: + FLAC__ASSERT(0); + } +} + +void FLAC__fixed_restore_signal(const FLAC__int32 residual[], unsigned data_len, unsigned order, FLAC__int32 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] = residual[i] + data[i-1]; + } + break; + case 2: + for(i = 0; i < idata_len; i++) { + /* == residual[i] + 2*data[i-1] - data[i-2] */ + data[i] = residual[i] + (data[i-1]<<1) - data[i-2]; + } + break; + case 3: + for(i = 0; i < idata_len; i++) { + /* residual[i] + 3*data[i-1] - 3*data[i-2]) + data[i-3] */ + data[i] = residual[i] + (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) + data[i-3]; + } + break; + case 4: + for(i = 0; i < idata_len; i++) { + /* == residual[i] + 4*data[i-1] - 6*data[i-2] + 4*data[i-3] - data[i-4] */ + data[i] = residual[i] + ((data[i-1]+data[i-3])<<2) - ((data[i-2]<<2) + (data[i-2]<<1)) - data[i-4]; + } + break; + default: + FLAC__ASSERT(0); + } +} diff --git a/FLAC/format.c b/FLAC/format.c index de07a0b2b..c55572462 100644 --- a/FLAC/format.c +++ b/FLAC/format.c @@ -1,403 +1,513 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#include -#include /* for qsort() */ -#include "FLAC/assert.h" -#include "FLAC/format.h" -#include "private/format.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef min -#undef min -#endif -#define min(a,b) ((a)<(b)?(a):(b)) - -/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ -#ifdef _MSC_VER -#define FLAC__U64L(x) x -#else -#define FLAC__U64L(x) x##LLU -#endif - -/* VERSION should come from configure */ -FLAC_API const char *FLAC__VERSION_STRING = "1.1.1"; - -#if defined _MSC_VER || defined __MINW32__ -/* yet one more hack because of MSVC6: */ -FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.1.1 20041001"; -#else -FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20041001"; -#endif - -FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' }; -FLAC_API const unsigned FLAC__STREAM_SYNC = 0x664C6143; -FLAC_API const unsigned FLAC__STREAM_SYNC_LEN = 32; /* bits */; - -FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN = 16; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN = 16; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN = 24; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN = 24; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN = 20; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN = 3; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN = 5; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN = 36; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN = 128; /* bits */ - -FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN = 32; /* bits */ - -FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN = 64; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN = 64; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN = 16; /* bits */ - -FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER = FLAC__U64L(0xffffffffffffffff); - -FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN = 32; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN = 32; /* bits */ - -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN = 64; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN = 8; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN = 3*8; /* bits */ - -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN = 64; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN = 8; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN = 12*8; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN = 1; /* bit */ -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN = 1; /* bit */ -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN = 6+13*8; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN = 8; /* bits */ - -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN = 128*8; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN = 64; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN = 1; /* bit */ -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN = 7+258*8; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* bits */ - -FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */ -FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */ - -FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC = 0x3ffe; -FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN = 14; /* bits */ -FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN = 2; /* bits */ -FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN = 4; /* bits */ -FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN = 4; /* bits */ -FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN = 4; /* bits */ -FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN = 3; /* bits */ -FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN = 1; /* bits */ -FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN = 8; /* bits */ - -FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN = 16; /* bits */ - -FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN = 2; /* bits */ -FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN = 4; /* bits */ -FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN = 4; /* bits */ -FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN = 5; /* bits */ - -FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER = 15; /* == (1< FLAC__MAX_SAMPLE_RATE || - ( - sample_rate >= (1u << 16) && - !(sample_rate % 1000 == 0 || sample_rate % 10 == 0) - ) - ) { - return false; - } - else - return true; -} - -FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table) -{ - unsigned i; - FLAC__uint64 prev_sample_number = 0; - FLAC__bool got_prev = false; - - FLAC__ASSERT(0 != seek_table); - - for(i = 0; i < seek_table->num_points; i++) { - if(got_prev) { - if( - seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && - seek_table->points[i].sample_number <= prev_sample_number - ) - return false; - } - prev_sample_number = seek_table->points[i].sample_number; - got_prev = true; - } - - return true; -} - -/* used as the sort predicate for qsort() */ -static int seekpoint_compare_(const FLAC__StreamMetadata_SeekPoint *l, const FLAC__StreamMetadata_SeekPoint *r) -{ - /* we don't just 'return l->sample_number - r->sample_number' since the result (FLAC__int64) might overflow an 'int' */ - if(l->sample_number == r->sample_number) - return 0; - else if(l->sample_number < r->sample_number) - return -1; - else - return 1; -} - -FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table) -{ - unsigned i, j; - FLAC__bool first; - - FLAC__ASSERT(0 != seek_table); - - /* sort the seekpoints */ - qsort(seek_table->points, seek_table->num_points, sizeof(FLAC__StreamMetadata_SeekPoint), (int (*)(const void *, const void *))seekpoint_compare_); - - /* uniquify the seekpoints */ - first = true; - for(i = j = 0; i < seek_table->num_points; i++) { - if(seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) { - if(!first) { - if(seek_table->points[i].sample_number == seek_table->points[j-1].sample_number) - continue; - } - } - first = false; - seek_table->points[j++] = seek_table->points[i]; - } - - for(i = j; i < seek_table->num_points; i++) { - seek_table->points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; - seek_table->points[i].stream_offset = 0; - seek_table->points[i].frame_samples = 0; - } - - return j; -} - -FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation) -{ - unsigned i, j; - - if(check_cd_da_subset) { - if(cue_sheet->lead_in < 2 * 44100) { - if(violation) *violation = "CD-DA cue sheet must have a lead-in length of at least 2 seconds"; - return false; - } - if(cue_sheet->lead_in % 588 != 0) { - if(violation) *violation = "CD-DA cue sheet lead-in length must be evenly divisible by 588 samples"; - return false; - } - } - - if(cue_sheet->num_tracks == 0) { - if(violation) *violation = "cue sheet must have at least one track (the lead-out)"; - return false; - } - - if(check_cd_da_subset && cue_sheet->tracks[cue_sheet->num_tracks-1].number != 170) { - if(violation) *violation = "CD-DA cue sheet must have a lead-out track number 170 (0xAA)"; - return false; - } - - for(i = 0; i < cue_sheet->num_tracks; i++) { - if(cue_sheet->tracks[i].number == 0) { - if(violation) *violation = "cue sheet may not have a track number 0"; - return false; - } - - if(check_cd_da_subset) { - if(!((cue_sheet->tracks[i].number >= 1 && cue_sheet->tracks[i].number <= 99) || cue_sheet->tracks[i].number == 170)) { - if(violation) *violation = "CD-DA cue sheet track number must be 1-99 or 170"; - return false; - } - } - - if(check_cd_da_subset && cue_sheet->tracks[i].offset % 588 != 0) { - if(violation) *violation = "CD-DA cue sheet track offset must be evenly divisible by 588 samples"; - return false; - } - - if(i < cue_sheet->num_tracks - 1) { - if(cue_sheet->tracks[i].num_indices == 0) { - if(violation) *violation = "cue sheet track must have at least one index point"; - return false; - } - - if(cue_sheet->tracks[i].indices[0].number > 1) { - if(violation) *violation = "cue sheet track's first index number must be 0 or 1"; - return false; - } - } - - for(j = 0; j < cue_sheet->tracks[i].num_indices; j++) { - if(check_cd_da_subset && cue_sheet->tracks[i].indices[j].offset % 588 != 0) { - if(violation) *violation = "CD-DA cue sheet track index offset must be evenly divisible by 588 samples"; - return false; - } - - if(j > 0) { - if(cue_sheet->tracks[i].indices[j].number != cue_sheet->tracks[i].indices[j-1].number + 1) { - if(violation) *violation = "cue sheet track index numbers must increase by 1"; - return false; - } - } - } - } - - return true; -} - -/* - * These routines are private to libFLAC - */ -unsigned FLAC__format_get_max_rice_partition_order(unsigned blocksize, unsigned predictor_order) -{ - return - FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order( - FLAC__format_get_max_rice_partition_order_from_blocksize(blocksize), - blocksize, - predictor_order - ); -} - -unsigned FLAC__format_get_max_rice_partition_order_from_blocksize(unsigned blocksize) -{ - unsigned max_rice_partition_order = 0; - while(!(blocksize & 1)) { - max_rice_partition_order++; - blocksize >>= 1; - } - return min(FLAC__MAX_RICE_PARTITION_ORDER, max_rice_partition_order); -} - -unsigned FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(unsigned limit, unsigned blocksize, unsigned predictor_order) -{ - unsigned max_rice_partition_order = limit; - - while(max_rice_partition_order > 0 && (blocksize >> max_rice_partition_order) <= predictor_order) - max_rice_partition_order--; - - FLAC__ASSERT( - (max_rice_partition_order == 0 && blocksize >= predictor_order) || - (max_rice_partition_order > 0 && blocksize >> max_rice_partition_order > predictor_order) - ); - - return max_rice_partition_order; -} - -void FLAC__format_entropy_coding_method_partitioned_rice_contents_init(FLAC__EntropyCodingMethod_PartitionedRiceContents *object) -{ - FLAC__ASSERT(0 != object); - - object->parameters = 0; - object->raw_bits = 0; - object->capacity_by_order = 0; -} - -void FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(FLAC__EntropyCodingMethod_PartitionedRiceContents *object) -{ - FLAC__ASSERT(0 != object); - - if(0 != object->parameters) - free(object->parameters); - if(0 != object->raw_bits) - free(object->raw_bits); - FLAC__format_entropy_coding_method_partitioned_rice_contents_init(object); -} - -FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(FLAC__EntropyCodingMethod_PartitionedRiceContents *object, unsigned max_partition_order) -{ - FLAC__ASSERT(0 != object); - - FLAC__ASSERT(object->capacity_by_order > 0 || (0 == object->parameters && 0 == object->raw_bits)); - - if(object->capacity_by_order < max_partition_order) { - if(0 == (object->parameters = (unsigned*)realloc(object->parameters, sizeof(unsigned)*(1 << max_partition_order)))) - return false; - if(0 == (object->raw_bits = (unsigned*)realloc(object->raw_bits, sizeof(unsigned)*(1 << max_partition_order)))) - return false; - object->capacity_by_order = max_partition_order; - } - - return true; -} +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#include +#include /* for qsort() */ +#include "FLAC/assert.h" +#include "FLAC/format.h" +#include "private/format.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef min +#undef min +#endif +#define min(a,b) ((a)<(b)?(a):(b)) + +/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ +#ifdef _MSC_VER +#define FLAC__U64L(x) x +#else +#define FLAC__U64L(x) x##LLU +#endif + +/* VERSION should come from configure */ +FLAC_API const char *FLAC__VERSION_STRING = "1.1.2"; + +#if defined _MSC_VER || defined __MINW32__ +/* yet one more hack because of MSVC6: */ +FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.1.2 20050205"; +#else +FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20050205"; +#endif + +FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' }; +FLAC_API const unsigned FLAC__STREAM_SYNC = 0x664C6143; +FLAC_API const unsigned FLAC__STREAM_SYNC_LEN = 32; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN = 16; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN = 16; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN = 24; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN = 24; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN = 20; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN = 3; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN = 5; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN = 36; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN = 128; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN = 32; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN = 64; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN = 64; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN = 16; /* bits */ + +FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER = FLAC__U64L(0xffffffffffffffff); + +FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN = 32; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN = 32; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN = 64; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN = 8; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN = 3*8; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN = 64; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN = 8; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN = 12*8; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN = 1; /* bit */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN = 1; /* bit */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN = 6+13*8; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN = 8; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN = 128*8; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN = 64; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN = 1; /* bit */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN = 7+258*8; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */ + +FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC = 0x3ffe; +FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN = 14; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN = 2; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN = 4; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN = 4; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN = 4; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN = 3; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN = 1; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN = 8; /* bits */ + +FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN = 16; /* bits */ + +FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN = 2; /* bits */ +FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN = 4; /* bits */ +FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN = 4; /* bits */ +FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN = 5; /* bits */ + +FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER = 15; /* == (1< FLAC__MAX_SAMPLE_RATE || + ( + sample_rate >= (1u << 16) && + !(sample_rate % 1000 == 0 || sample_rate % 10 == 0) + ) + ) { + return false; + } + else + return true; +} + +FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table) +{ + unsigned i; + FLAC__uint64 prev_sample_number = 0; + FLAC__bool got_prev = false; + + FLAC__ASSERT(0 != seek_table); + + for(i = 0; i < seek_table->num_points; i++) { + if(got_prev) { + if( + seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && + seek_table->points[i].sample_number <= prev_sample_number + ) + return false; + } + prev_sample_number = seek_table->points[i].sample_number; + got_prev = true; + } + + return true; +} + +/* used as the sort predicate for qsort() */ +static int seekpoint_compare_(const FLAC__StreamMetadata_SeekPoint *l, const FLAC__StreamMetadata_SeekPoint *r) +{ + /* we don't just 'return l->sample_number - r->sample_number' since the result (FLAC__int64) might overflow an 'int' */ + if(l->sample_number == r->sample_number) + return 0; + else if(l->sample_number < r->sample_number) + return -1; + else + return 1; +} + +FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table) +{ + unsigned i, j; + FLAC__bool first; + + FLAC__ASSERT(0 != seek_table); + + /* sort the seekpoints */ + qsort(seek_table->points, seek_table->num_points, sizeof(FLAC__StreamMetadata_SeekPoint), (int (*)(const void *, const void *))seekpoint_compare_); + + /* uniquify the seekpoints */ + first = true; + for(i = j = 0; i < seek_table->num_points; i++) { + if(seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) { + if(!first) { + if(seek_table->points[i].sample_number == seek_table->points[j-1].sample_number) + continue; + } + } + first = false; + seek_table->points[j++] = seek_table->points[i]; + } + + for(i = j; i < seek_table->num_points; i++) { + seek_table->points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; + seek_table->points[i].stream_offset = 0; + seek_table->points[i].frame_samples = 0; + } + + return j; +} + +/* + * also disallows non-shortest-form encodings, c.f. + * http://www.unicode.org/versions/corrigendum1.html + * and a more clear explanation at the end of this section: + * http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + */ +static __inline unsigned utf8len_(const FLAC__byte *utf8) +{ + FLAC__ASSERT(0 != utf8); + if ((utf8[0] & 0x80) == 0) { + return 1; + } + else if ((utf8[0] & 0xE0) == 0xC0 && (utf8[1] & 0xC0) == 0x80) { + if ((utf8[0] & 0xFE) == 0xC0) /* overlong sequence check */ + return 0; + return 2; + } + else if ((utf8[0] & 0xF0) == 0xE0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80) { + if (utf8[0] == 0xE0 && (utf8[1] & 0xE0) == 0x80) /* overlong sequence check */ + return 0; + /* illegal surrogates check (U+D800...U+DFFF and U+FFFE...U+FFFF) */ + if (utf8[0] == 0xED && (utf8[1] & 0xE0) == 0xA0) /* D800-DFFF */ + return 0; + if (utf8[0] == 0xEF && utf8[1] == 0xBF && (utf8[2] & 0xFE) == 0xBE) /* FFFE-FFFF */ + return 0; + return 3; + } + else if ((utf8[0] & 0xF8) == 0xF0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80) { + if (utf8[0] == 0xF0 && (utf8[1] & 0xF0) == 0x80) /* overlong sequence check */ + return 0; + return 4; + } + else if ((utf8[0] & 0xFC) == 0xF8 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80 && (utf8[4] & 0xC0) == 0x80) { + if (utf8[0] == 0xF8 && (utf8[1] & 0xF8) == 0x80) /* overlong sequence check */ + return 0; + return 5; + } + else if ((utf8[0] & 0xFE) == 0xFC && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80 && (utf8[4] & 0xC0) == 0x80 && (utf8[5] & 0xC0) == 0x80) { + if (utf8[0] == 0xFC && (utf8[1] & 0xFC) == 0x80) /* overlong sequence check */ + return 0; + return 6; + } + else { + return 0; + } +} + +FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_name_is_legal(const char *name) +{ + char c; + for(c = *name; c; c = *(++name)) + if(c < 0x20 || c == 0x3d || c > 0x7d) + return false; + return true; +} + +FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, unsigned length) +{ + if(length == (unsigned)(-1)) { + while(*value) { + unsigned n = utf8len_(value); + if(n == 0) + return false; + value += n; + } + } + else { + const FLAC__byte *end = value + length; + while(value < end) { + unsigned n = utf8len_(value); + if(n == 0) + return false; + value += n; + } + if(value != end) + return false; + } + return true; +} + +FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, unsigned length) +{ + const FLAC__byte *s, *end; + + for(s = entry, end = s + length; s < end && *s != '='; s++) { + if(*s < 0x20 || *s > 0x7D) + return false; + } + if(s == end) + return false; + + s++; /* skip '=' */ + + while(s < end) { + unsigned n = utf8len_(s); + if(n == 0) + return false; + s += n; + } + if(s != end) + return false; + + return true; +} + +FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation) +{ + unsigned i, j; + + if(check_cd_da_subset) { + if(cue_sheet->lead_in < 2 * 44100) { + if(violation) *violation = "CD-DA cue sheet must have a lead-in length of at least 2 seconds"; + return false; + } + if(cue_sheet->lead_in % 588 != 0) { + if(violation) *violation = "CD-DA cue sheet lead-in length must be evenly divisible by 588 samples"; + return false; + } + } + + if(cue_sheet->num_tracks == 0) { + if(violation) *violation = "cue sheet must have at least one track (the lead-out)"; + return false; + } + + if(check_cd_da_subset && cue_sheet->tracks[cue_sheet->num_tracks-1].number != 170) { + if(violation) *violation = "CD-DA cue sheet must have a lead-out track number 170 (0xAA)"; + return false; + } + + for(i = 0; i < cue_sheet->num_tracks; i++) { + if(cue_sheet->tracks[i].number == 0) { + if(violation) *violation = "cue sheet may not have a track number 0"; + return false; + } + + if(check_cd_da_subset) { + if(!((cue_sheet->tracks[i].number >= 1 && cue_sheet->tracks[i].number <= 99) || cue_sheet->tracks[i].number == 170)) { + if(violation) *violation = "CD-DA cue sheet track number must be 1-99 or 170"; + return false; + } + } + + if(check_cd_da_subset && cue_sheet->tracks[i].offset % 588 != 0) { + if(violation) { + if(i == cue_sheet->num_tracks-1) /* the lead-out track... */ + *violation = "CD-DA cue sheet lead-out offset must be evenly divisible by 588 samples"; + else + *violation = "CD-DA cue sheet track offset must be evenly divisible by 588 samples"; + } + return false; + } + + if(i < cue_sheet->num_tracks - 1) { + if(cue_sheet->tracks[i].num_indices == 0) { + if(violation) *violation = "cue sheet track must have at least one index point"; + return false; + } + + if(cue_sheet->tracks[i].indices[0].number > 1) { + if(violation) *violation = "cue sheet track's first index number must be 0 or 1"; + return false; + } + } + + for(j = 0; j < cue_sheet->tracks[i].num_indices; j++) { + if(check_cd_da_subset && cue_sheet->tracks[i].indices[j].offset % 588 != 0) { + if(violation) *violation = "CD-DA cue sheet track index offset must be evenly divisible by 588 samples"; + return false; + } + + if(j > 0) { + if(cue_sheet->tracks[i].indices[j].number != cue_sheet->tracks[i].indices[j-1].number + 1) { + if(violation) *violation = "cue sheet track index numbers must increase by 1"; + return false; + } + } + } + } + + return true; +} + +/* + * These routines are private to libFLAC + */ +unsigned FLAC__format_get_max_rice_partition_order(unsigned blocksize, unsigned predictor_order) +{ + return + FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order( + FLAC__format_get_max_rice_partition_order_from_blocksize(blocksize), + blocksize, + predictor_order + ); +} + +unsigned FLAC__format_get_max_rice_partition_order_from_blocksize(unsigned blocksize) +{ + unsigned max_rice_partition_order = 0; + while(!(blocksize & 1)) { + max_rice_partition_order++; + blocksize >>= 1; + } + return min(FLAC__MAX_RICE_PARTITION_ORDER, max_rice_partition_order); +} + +unsigned FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(unsigned limit, unsigned blocksize, unsigned predictor_order) +{ + unsigned max_rice_partition_order = limit; + + while(max_rice_partition_order > 0 && (blocksize >> max_rice_partition_order) <= predictor_order) + max_rice_partition_order--; + + FLAC__ASSERT( + (max_rice_partition_order == 0 && blocksize >= predictor_order) || + (max_rice_partition_order > 0 && blocksize >> max_rice_partition_order > predictor_order) + ); + + return max_rice_partition_order; +} + +void FLAC__format_entropy_coding_method_partitioned_rice_contents_init(FLAC__EntropyCodingMethod_PartitionedRiceContents *object) +{ + FLAC__ASSERT(0 != object); + + object->parameters = 0; + object->raw_bits = 0; + object->capacity_by_order = 0; +} + +void FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(FLAC__EntropyCodingMethod_PartitionedRiceContents *object) +{ + FLAC__ASSERT(0 != object); + + if(0 != object->parameters) + free(object->parameters); + if(0 != object->raw_bits) + free(object->raw_bits); + FLAC__format_entropy_coding_method_partitioned_rice_contents_init(object); +} + +FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(FLAC__EntropyCodingMethod_PartitionedRiceContents *object, unsigned max_partition_order) +{ + FLAC__ASSERT(0 != object); + + FLAC__ASSERT(object->capacity_by_order > 0 || (0 == object->parameters && 0 == object->raw_bits)); + + if(object->capacity_by_order < max_partition_order) { + if(0 == (object->parameters = (unsigned*)realloc(object->parameters, sizeof(unsigned)*(1 << max_partition_order)))) + return false; + if(0 == (object->raw_bits = (unsigned*)realloc(object->raw_bits, sizeof(unsigned)*(1 << max_partition_order)))) + return false; + object->capacity_by_order = max_partition_order; + } + + return true; +} diff --git a/FLAC/ia32/cpu_asm.nasm b/FLAC/ia32/cpu_asm.nasm index 570aec344..b3165c3f5 100644 --- a/FLAC/ia32/cpu_asm.nasm +++ b/FLAC/ia32/cpu_asm.nasm @@ -1,5 +1,5 @@ ; libFLAC - Free Lossless Audio Codec library -; Copyright (C) 2001,2002,2003 Josh Coalson +; Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions diff --git a/FLAC/ia32/fixed_asm.nasm b/FLAC/ia32/fixed_asm.nasm index 9e93928e4..c7ba38fc5 100644 --- a/FLAC/ia32/fixed_asm.nasm +++ b/FLAC/ia32/fixed_asm.nasm @@ -1,5 +1,5 @@ ; libFLAC - Free Lossless Audio Codec library -; Copyright (C) 2001,2002,2003 Josh Coalson +; Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions @@ -38,7 +38,7 @@ cglobal FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov ; ********************************************************************** ; -; unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +; unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 *data, unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) ; { ; FLAC__int32 last_error_0 = data[-1]; ; FLAC__int32 last_error_1 = data[-1] - data[-2]; @@ -67,11 +67,11 @@ cglobal FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov ; else ; order = 4; ; -; residual_bits_per_sample[0] = (FLAC__real)((data_len > 0 && total_error_0 > 0) ? log(M_LN2 * (double)total_error_0 / (double)data_len) / M_LN2 : 0.0); -; residual_bits_per_sample[1] = (FLAC__real)((data_len > 0 && total_error_1 > 0) ? log(M_LN2 * (double)total_error_1 / (double)data_len) / M_LN2 : 0.0); -; residual_bits_per_sample[2] = (FLAC__real)((data_len > 0 && total_error_2 > 0) ? log(M_LN2 * (double)total_error_2 / (double)data_len) / M_LN2 : 0.0); -; residual_bits_per_sample[3] = (FLAC__real)((data_len > 0 && total_error_3 > 0) ? log(M_LN2 * (double)total_error_3 / (double)data_len) / M_LN2 : 0.0); -; residual_bits_per_sample[4] = (FLAC__real)((data_len > 0 && total_error_4 > 0) ? log(M_LN2 * (double)total_error_4 / (double)data_len) / M_LN2 : 0.0); +; residual_bits_per_sample[0] = (FLAC__float)((data_len > 0 && total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0); +; residual_bits_per_sample[1] = (FLAC__float)((data_len > 0 && total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0); +; residual_bits_per_sample[2] = (FLAC__float)((data_len > 0 && total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0); +; residual_bits_per_sample[3] = (FLAC__float)((data_len > 0 && total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0); +; residual_bits_per_sample[4] = (FLAC__float)((data_len > 0 && total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0); ; ; return order; ; } @@ -196,11 +196,11 @@ cident FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov movd ebx, mm0 ; ebx = total_error_0 emms - ; residual_bits_per_sample[0] = (FLAC__real)((data_len > 0 && total_error_0 > 0) ? log(M_LN2 * (double)total_error_0 / (double)data_len) / M_LN2 : 0.0); - ; residual_bits_per_sample[1] = (FLAC__real)((data_len > 0 && total_error_1 > 0) ? log(M_LN2 * (double)total_error_1 / (double)data_len) / M_LN2 : 0.0); - ; residual_bits_per_sample[2] = (FLAC__real)((data_len > 0 && total_error_2 > 0) ? log(M_LN2 * (double)total_error_2 / (double)data_len) / M_LN2 : 0.0); - ; residual_bits_per_sample[3] = (FLAC__real)((data_len > 0 && total_error_3 > 0) ? log(M_LN2 * (double)total_error_3 / (double)data_len) / M_LN2 : 0.0); - ; residual_bits_per_sample[4] = (FLAC__real)((data_len > 0 && total_error_4 > 0) ? log(M_LN2 * (double)total_error_4 / (double)data_len) / M_LN2 : 0.0); + ; residual_bits_per_sample[0] = (FLAC__float)((data_len > 0 && total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0); + ; residual_bits_per_sample[1] = (FLAC__float)((data_len > 0 && total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0); + ; residual_bits_per_sample[2] = (FLAC__float)((data_len > 0 && total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0); + ; residual_bits_per_sample[3] = (FLAC__float)((data_len > 0 && total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0); + ; residual_bits_per_sample[4] = (FLAC__float)((data_len > 0 && total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0); xor eax, eax fild dword [esp + 40] ; ST = data_len (NOTE: assumes data_len is <2gigs) .rbps_0: diff --git a/FLAC/ia32/lpc_asm.nasm b/FLAC/ia32/lpc_asm.nasm index 4eb104b96..16e36d388 100644 --- a/FLAC/ia32/lpc_asm.nasm +++ b/FLAC/ia32/lpc_asm.nasm @@ -1,5 +1,5 @@ ; libFLAC - Free Lossless Audio Codec library -; Copyright (C) 2001,2002,2003 Josh Coalson +; Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions @@ -736,7 +736,7 @@ cident FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow pop ebp ret -;void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 data[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]) +;void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]) ; ; for(i = 0; i < data_len; i++) { ; sum = 0; diff --git a/FLAC/ia32/nasm.h b/FLAC/ia32/nasm.h index 00aecef3a..5951fb00a 100644 --- a/FLAC/ia32/nasm.h +++ b/FLAC/ia32/nasm.h @@ -1,5 +1,5 @@ ; libFLAC - Free Lossless Audio Codec library -; Copyright (C) 2001,2002,2003 Josh Coalson +; Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions diff --git a/FLAC/lpc.c b/FLAC/lpc.c index 275b707a3..38e0d00d0 100644 --- a/FLAC/lpc.c +++ b/FLAC/lpc.c @@ -1,423 +1,430 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#include -#include "FLAC/assert.h" -#include "FLAC/format.h" -#include "private/bitmath.h" -#include "private/lpc.h" -#if defined DEBUG || defined FLAC__OVERFLOW_DETECT || defined FLAC__OVERFLOW_DETECT_VERBOSE -#include -#endif - -#ifndef M_LN2 -/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ -#define M_LN2 0.69314718055994530942 -#endif - -void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]) -{ - /* a readable, but slower, version */ -#if 0 - FLAC__real d; - unsigned i; - - FLAC__ASSERT(lag > 0); - FLAC__ASSERT(lag <= data_len); - - while(lag--) { - for(i = lag, d = 0.0; i < data_len; i++) - d += data[i] * data[i - lag]; - autoc[lag] = d; - } -#endif - - /* - * this version tends to run faster because of better data locality - * ('data_len' is usually much larger than 'lag') - */ - FLAC__real d; - unsigned sample, coeff; - const unsigned limit = data_len - lag; - - FLAC__ASSERT(lag > 0); - FLAC__ASSERT(lag <= data_len); - - for(coeff = 0; coeff < lag; coeff++) - autoc[coeff] = 0.0; - for(sample = 0; sample <= limit; sample++) { - d = data[sample]; - for(coeff = 0; coeff < lag; coeff++) - autoc[coeff] += d * data[sample+coeff]; - } - for(; sample < data_len; sample++) { - d = data[sample]; - for(coeff = 0; coeff < data_len - sample; coeff++) - autoc[coeff] += d * data[sample+coeff]; - } -} - -void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], unsigned max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], FLAC__real error[]) -{ - unsigned i, j; - double r, err, ref[FLAC__MAX_LPC_ORDER], lpc[FLAC__MAX_LPC_ORDER]; - - FLAC__ASSERT(0 < max_order); - FLAC__ASSERT(max_order <= FLAC__MAX_LPC_ORDER); - FLAC__ASSERT(autoc[0] != 0.0); - - err = autoc[0]; - - for(i = 0; i < max_order; i++) { - /* Sum up this iteration's reflection coefficient. */ - r = -autoc[i+1]; - for(j = 0; j < i; j++) - r -= lpc[j] * autoc[i-j]; - ref[i] = (r/=err); - - /* Update LPC coefficients and total error. */ - lpc[i]=r; - for(j = 0; j < (i>>1); j++) { - double tmp = lpc[j]; - lpc[j] += r * lpc[i-1-j]; - lpc[i-1-j] += r * tmp; - } - if(i & 1) - lpc[j] += lpc[j] * r; - - err *= (1.0 - r * r); - - /* save this order */ - for(j = 0; j <= i; j++) - lp_coeff[i][j] = (FLAC__real)(-lpc[j]); /* negate FIR filter coeff to get predictor coeff */ - error[i] = (FLAC__real)err; - } -} - -int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order, unsigned precision, FLAC__int32 qlp_coeff[], int *shift) -{ - unsigned i; - double d, cmax = -1e32; - FLAC__int32 qmax, qmin; - const int max_shiftlimit = (1 << (FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN-1)) - 1; - const int min_shiftlimit = -max_shiftlimit - 1; - - FLAC__ASSERT(precision > 0); - FLAC__ASSERT(precision >= FLAC__MIN_QLP_COEFF_PRECISION); - - /* drop one bit for the sign; from here on out we consider only |lp_coeff[i]| */ - precision--; - qmax = 1 << precision; - qmin = -qmax; - qmax--; - - for(i = 0; i < order; i++) { - if(lp_coeff[i] == 0.0) - continue; - d = fabs(lp_coeff[i]); - if(d > cmax) - cmax = d; - } -redo_it: - if(cmax <= 0.0) { - /* => coefficients are all 0, which means our constant-detect didn't work */ - return 2; - } - else { - int log2cmax; - - (void)frexp(cmax, &log2cmax); - log2cmax--; - *shift = (int)precision - log2cmax - 1; - - if(*shift < min_shiftlimit || *shift > max_shiftlimit) { -#if 0 - /*@@@ this does not seem to help at all, but was not extensively tested either: */ - if(*shift > max_shiftlimit) - *shift = max_shiftlimit; - else -#endif - return 1; - } - } - - if(*shift >= 0) { - for(i = 0; i < order; i++) { - qlp_coeff[i] = (FLAC__int32)floor((double)lp_coeff[i] * (double)(1 << *shift)); - - /* double-check the result */ - if(qlp_coeff[i] > qmax || qlp_coeff[i] < qmin) { -#ifdef FLAC__OVERFLOW_DETECT - fprintf(stderr,"FLAC__lpc_quantize_coefficients: compensating for overflow, qlp_coeff[%u]=%d, lp_coeff[%u]=%f, cmax=%f, precision=%u, shift=%d, q=%f, f(q)=%f\n", i, qlp_coeff[i], i, lp_coeff[i], cmax, precision, *shift, (double)lp_coeff[i] * (double)(1 << *shift), floor((double)lp_coeff[i] * (double)(1 << *shift))); -#endif - cmax *= 2.0; - goto redo_it; - } - } - } - else { /* (*shift < 0) */ - const int nshift = -(*shift); -#ifdef DEBUG - fprintf(stderr,"FLAC__lpc_quantize_coefficients: negative shift = %d\n", *shift); -#endif - for(i = 0; i < order; i++) { - qlp_coeff[i] = (FLAC__int32)floor((double)lp_coeff[i] / (double)(1 << nshift)); - - /* double-check the result */ - if(qlp_coeff[i] > qmax || qlp_coeff[i] < qmin) { -#ifdef FLAC__OVERFLOW_DETECT - fprintf(stderr,"FLAC__lpc_quantize_coefficients: compensating for overflow, qlp_coeff[%u]=%d, lp_coeff[%u]=%f, cmax=%f, precision=%u, shift=%d, q=%f, f(q)=%f\n", i, qlp_coeff[i], i, lp_coeff[i], cmax, precision, *shift, (double)lp_coeff[i] / (double)(1 << nshift), floor((double)lp_coeff[i] / (double)(1 << nshift))); -#endif - cmax *= 2.0; - goto redo_it; - } - } - } - - return 0; -} - -void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 data[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]) -{ -#ifdef FLAC__OVERFLOW_DETECT - FLAC__int64 sumo; -#endif - unsigned i, j; - FLAC__int32 sum; - const FLAC__int32 *history; - -#ifdef FLAC__OVERFLOW_DETECT_VERBOSE - fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); - for(i=0;i 0); - - for(i = 0; i < data_len; i++) { -#ifdef FLAC__OVERFLOW_DETECT - sumo = 0; -#endif - sum = 0; - history = data; - for(j = 0; j < order; j++) { - sum += qlp_coeff[j] * (*(--history)); -#ifdef FLAC__OVERFLOW_DETECT - sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history); -#if defined _MSC_VER - if(sumo > 2147483647I64 || sumo < -2147483648I64) - fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%I64d\n",i,j,qlp_coeff[j],*history,sumo); -#else - if(sumo > 2147483647ll || sumo < -2147483648ll) - fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%lld\n",i,j,qlp_coeff[j],*history,sumo); -#endif -#endif - } - *(residual++) = *(data++) - (sum >> lp_quantization); - } - - /* Here's a slower but clearer version: - for(i = 0; i < data_len; i++) { - sum = 0; - for(j = 0; j < order; j++) - sum += qlp_coeff[j] * data[i-j-1]; - residual[i] = data[i] - (sum >> lp_quantization); - } - */ -} - -void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 data[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]) -{ - unsigned i, j; - FLAC__int64 sum; - const FLAC__int32 *history; - -#ifdef FLAC__OVERFLOW_DETECT_VERBOSE - fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); - for(i=0;i 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_wide(sum >> lp_quantization) > 32) { - fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, sum=%lld\n", i, sum >> lp_quantization); - break; - } - if(FLAC__bitmath_silog2_wide((FLAC__int64)(*data) - (sum >> lp_quantization)) > 32) { - fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=%lld, residual=%lld\n", i, *data, sum >> lp_quantization, (FLAC__int64)(*data) - (sum >> lp_quantization)); - break; - } -#endif - *(residual++) = *(data++) - (FLAC__int32)(sum >> lp_quantization); - } -} - -void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]) -{ -#ifdef FLAC__OVERFLOW_DETECT - FLAC__int64 sumo; -#endif - unsigned i, j; - FLAC__int32 sum; - const FLAC__int32 *history; - -#ifdef FLAC__OVERFLOW_DETECT_VERBOSE - fprintf(stderr,"FLAC__lpc_restore_signal: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); - for(i=0;i 0); - - for(i = 0; i < data_len; i++) { -#ifdef FLAC__OVERFLOW_DETECT - sumo = 0; -#endif - sum = 0; - history = data; - for(j = 0; j < order; j++) { - sum += qlp_coeff[j] * (*(--history)); -#ifdef FLAC__OVERFLOW_DETECT - sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history); -#if defined _MSC_VER - if(sumo > 2147483647I64 || sumo < -2147483648I64) - fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%I64d\n",i,j,qlp_coeff[j],*history,sumo); -#else - if(sumo > 2147483647ll || sumo < -2147483648ll) - fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%lld\n",i,j,qlp_coeff[j],*history,sumo); -#endif -#endif - } - *(data++) = *(residual++) + (sum >> lp_quantization); - } - - /* Here's a slower but clearer version: - for(i = 0; i < data_len; i++) { - sum = 0; - for(j = 0; j < order; j++) - sum += qlp_coeff[j] * data[i-j-1]; - data[i] = residual[i] + (sum >> lp_quantization); - } - */ -} - -void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]) -{ - unsigned i, j; - FLAC__int64 sum; - const FLAC__int32 *history; - -#ifdef FLAC__OVERFLOW_DETECT_VERBOSE - fprintf(stderr,"FLAC__lpc_restore_signal_wide: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); - for(i=0;i 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_wide(sum >> lp_quantization) > 32) { - fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, sum=%lld\n", i, sum >> lp_quantization); - break; - } - if(FLAC__bitmath_silog2_wide((FLAC__int64)(*residual) + (sum >> lp_quantization)) > 32) { - fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=%lld, data=%lld\n", i, *residual, sum >> lp_quantization, (FLAC__int64)(*residual) + (sum >> lp_quantization)); - break; - } -#endif - *(data++) = *(residual++) + (FLAC__int32)(sum >> lp_quantization); - } -} - -FLAC__real FLAC__lpc_compute_expected_bits_per_residual_sample(FLAC__real lpc_error, unsigned total_samples) -{ - double error_scale; - - FLAC__ASSERT(total_samples > 0); - - error_scale = 0.5 * M_LN2 * M_LN2 / (FLAC__real)total_samples; - - return FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(lpc_error, error_scale); -} - -FLAC__real FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(FLAC__real lpc_error, double error_scale) -{ - if(lpc_error > 0.0) { - FLAC__real bps = (FLAC__real)((double)0.5 * log(error_scale * lpc_error) / M_LN2); - if(bps >= 0.0) - return bps; - else - return 0.0; - } - else if(lpc_error < 0.0) { /* error should not be negative but can happen due to inadequate float resolution */ - return (FLAC__real)1e32; - } - else { - return 0.0; - } -} - -unsigned FLAC__lpc_compute_best_order(const FLAC__real lpc_error[], unsigned max_order, unsigned total_samples, unsigned bits_per_signal_sample) -{ - unsigned order, best_order; - FLAC__real best_bits, tmp_bits; - double error_scale; - - FLAC__ASSERT(max_order > 0); - FLAC__ASSERT(total_samples > 0); - - error_scale = 0.5 * M_LN2 * M_LN2 / (FLAC__real)total_samples; - - best_order = 0; - best_bits = FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(lpc_error[0], error_scale) * (FLAC__real)total_samples; - - for(order = 1; order < max_order; order++) { - tmp_bits = FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(lpc_error[order], error_scale) * (FLAC__real)(total_samples - order) + (FLAC__real)(order * bits_per_signal_sample); - if(tmp_bits < best_bits) { - best_order = order; - best_bits = tmp_bits; - } - } - - return best_order+1; /* +1 since index of lpc_error[] is order-1 */ -} +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#include +#include "FLAC/assert.h" +#include "FLAC/format.h" +#include "private/bitmath.h" +#include "private/lpc.h" +#if defined DEBUG || defined FLAC__OVERFLOW_DETECT || defined FLAC__OVERFLOW_DETECT_VERBOSE +#include +#endif + +#ifndef FLAC__INTEGER_ONLY_LIBRARY + +#ifndef M_LN2 +/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ +#define M_LN2 0.69314718055994530942 +#endif + +void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]) +{ + /* a readable, but slower, version */ +#if 0 + FLAC__real d; + unsigned i; + + FLAC__ASSERT(lag > 0); + FLAC__ASSERT(lag <= data_len); + + while(lag--) { + for(i = lag, d = 0.0; i < data_len; i++) + d += data[i] * data[i - lag]; + autoc[lag] = d; + } +#endif + + /* + * this version tends to run faster because of better data locality + * ('data_len' is usually much larger than 'lag') + */ + FLAC__real d; + unsigned sample, coeff; + const unsigned limit = data_len - lag; + + FLAC__ASSERT(lag > 0); + FLAC__ASSERT(lag <= data_len); + + for(coeff = 0; coeff < lag; coeff++) + autoc[coeff] = 0.0; + for(sample = 0; sample <= limit; sample++) { + d = data[sample]; + for(coeff = 0; coeff < lag; coeff++) + autoc[coeff] += d * data[sample+coeff]; + } + for(; sample < data_len; sample++) { + d = data[sample]; + for(coeff = 0; coeff < data_len - sample; coeff++) + autoc[coeff] += d * data[sample+coeff]; + } +} + +void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], unsigned max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], FLAC__double error[]) +{ + unsigned i, j; + FLAC__double r, err, ref[FLAC__MAX_LPC_ORDER], lpc[FLAC__MAX_LPC_ORDER]; + + FLAC__ASSERT(0 < max_order); + FLAC__ASSERT(max_order <= FLAC__MAX_LPC_ORDER); + FLAC__ASSERT(autoc[0] != 0.0); + + err = autoc[0]; + + for(i = 0; i < max_order; i++) { + /* Sum up this iteration's reflection coefficient. */ + r = -autoc[i+1]; + for(j = 0; j < i; j++) + r -= lpc[j] * autoc[i-j]; + ref[i] = (r/=err); + + /* Update LPC coefficients and total error. */ + lpc[i]=r; + for(j = 0; j < (i>>1); j++) { + FLAC__double tmp = lpc[j]; + lpc[j] += r * lpc[i-1-j]; + lpc[i-1-j] += r * tmp; + } + if(i & 1) + lpc[j] += lpc[j] * r; + + err *= (1.0 - r * r); + + /* save this order */ + for(j = 0; j <= i; j++) + lp_coeff[i][j] = (FLAC__real)(-lpc[j]); /* negate FIR filter coeff to get predictor coeff */ + error[i] = err; + } +} + +int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order, unsigned precision, FLAC__int32 qlp_coeff[], int *shift) +{ + unsigned i; + FLAC__double d, cmax = -1e32; + FLAC__int32 qmax, qmin; + const int max_shiftlimit = (1 << (FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN-1)) - 1; + const int min_shiftlimit = -max_shiftlimit - 1; + + FLAC__ASSERT(precision > 0); + FLAC__ASSERT(precision >= FLAC__MIN_QLP_COEFF_PRECISION); + + /* drop one bit for the sign; from here on out we consider only |lp_coeff[i]| */ + precision--; + qmax = 1 << precision; + qmin = -qmax; + qmax--; + + for(i = 0; i < order; i++) { + if(lp_coeff[i] == 0.0) + continue; + d = fabs(lp_coeff[i]); + if(d > cmax) + cmax = d; + } +redo_it: + if(cmax <= 0.0) { + /* => coefficients are all 0, which means our constant-detect didn't work */ + return 2; + } + else { + int log2cmax; + + (void)frexp(cmax, &log2cmax); + log2cmax--; + *shift = (int)precision - log2cmax - 1; + + if(*shift < min_shiftlimit || *shift > max_shiftlimit) { +#if 0 + /*@@@ this does not seem to help at all, but was not extensively tested either: */ + if(*shift > max_shiftlimit) + *shift = max_shiftlimit; + else +#endif + return 1; + } + } + + if(*shift >= 0) { + for(i = 0; i < order; i++) { + qlp_coeff[i] = (FLAC__int32)floor((FLAC__double)lp_coeff[i] * (FLAC__double)(1 << *shift)); + + /* double-check the result */ + if(qlp_coeff[i] > qmax || qlp_coeff[i] < qmin) { +#ifdef FLAC__OVERFLOW_DETECT + fprintf(stderr,"FLAC__lpc_quantize_coefficients: compensating for overflow, qlp_coeff[%u]=%d, lp_coeff[%u]=%f, cmax=%f, precision=%u, shift=%d, q=%f, f(q)=%f\n", i, qlp_coeff[i], i, lp_coeff[i], cmax, precision, *shift, (FLAC__double)lp_coeff[i] * (FLAC__double)(1 << *shift), floor((FLAC__double)lp_coeff[i] * (FLAC__double)(1 << *shift))); +#endif + cmax *= 2.0; + goto redo_it; + } + } + } + else { /* (*shift < 0) */ + const int nshift = -(*shift); +#ifdef DEBUG + fprintf(stderr,"FLAC__lpc_quantize_coefficients: negative shift = %d\n", *shift); +#endif + for(i = 0; i < order; i++) { + qlp_coeff[i] = (FLAC__int32)floor((FLAC__double)lp_coeff[i] / (FLAC__double)(1 << nshift)); + + /* double-check the result */ + if(qlp_coeff[i] > qmax || qlp_coeff[i] < qmin) { +#ifdef FLAC__OVERFLOW_DETECT + fprintf(stderr,"FLAC__lpc_quantize_coefficients: compensating for overflow, qlp_coeff[%u]=%d, lp_coeff[%u]=%f, cmax=%f, precision=%u, shift=%d, q=%f, f(q)=%f\n", i, qlp_coeff[i], i, lp_coeff[i], cmax, precision, *shift, (FLAC__double)lp_coeff[i] / (FLAC__double)(1 << nshift), floor((FLAC__double)lp_coeff[i] / (FLAC__double)(1 << nshift))); +#endif + cmax *= 2.0; + goto redo_it; + } + } + } + + return 0; +} + +void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]) +{ +#ifdef FLAC__OVERFLOW_DETECT + FLAC__int64 sumo; +#endif + unsigned i, j; + FLAC__int32 sum; + const FLAC__int32 *history; + +#ifdef FLAC__OVERFLOW_DETECT_VERBOSE + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); + for(i=0;i 0); + + for(i = 0; i < data_len; i++) { +#ifdef FLAC__OVERFLOW_DETECT + sumo = 0; +#endif + sum = 0; + history = data; + for(j = 0; j < order; j++) { + sum += qlp_coeff[j] * (*(--history)); +#ifdef FLAC__OVERFLOW_DETECT + sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history); +#if defined _MSC_VER + if(sumo > 2147483647I64 || sumo < -2147483648I64) + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%I64d\n",i,j,qlp_coeff[j],*history,sumo); +#else + if(sumo > 2147483647ll || sumo < -2147483648ll) + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%lld\n",i,j,qlp_coeff[j],*history,sumo); +#endif +#endif + } + *(residual++) = *(data++) - (sum >> lp_quantization); + } + + /* Here's a slower but clearer version: + for(i = 0; i < data_len; i++) { + sum = 0; + for(j = 0; j < order; j++) + sum += qlp_coeff[j] * data[i-j-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + */ +} + +void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]) +{ + unsigned i, j; + FLAC__int64 sum; + const FLAC__int32 *history; + +#ifdef FLAC__OVERFLOW_DETECT_VERBOSE + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); + for(i=0;i 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_wide(sum >> lp_quantization) > 32) { + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, sum=%lld\n", i, sum >> lp_quantization); + break; + } + if(FLAC__bitmath_silog2_wide((FLAC__int64)(*data) - (sum >> lp_quantization)) > 32) { + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=%lld, residual=%lld\n", i, *data, sum >> lp_quantization, (FLAC__int64)(*data) - (sum >> lp_quantization)); + break; + } +#endif + *(residual++) = *(data++) - (FLAC__int32)(sum >> lp_quantization); + } +} + +#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ + +void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]) +{ +#ifdef FLAC__OVERFLOW_DETECT + FLAC__int64 sumo; +#endif + unsigned i, j; + FLAC__int32 sum; + const FLAC__int32 *history; + +#ifdef FLAC__OVERFLOW_DETECT_VERBOSE + fprintf(stderr,"FLAC__lpc_restore_signal: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); + for(i=0;i 0); + + for(i = 0; i < data_len; i++) { +#ifdef FLAC__OVERFLOW_DETECT + sumo = 0; +#endif + sum = 0; + history = data; + for(j = 0; j < order; j++) { + sum += qlp_coeff[j] * (*(--history)); +#ifdef FLAC__OVERFLOW_DETECT + sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history); +#if defined _MSC_VER + if(sumo > 2147483647I64 || sumo < -2147483648I64) + fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%I64d\n",i,j,qlp_coeff[j],*history,sumo); +#else + if(sumo > 2147483647ll || sumo < -2147483648ll) + fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%lld\n",i,j,qlp_coeff[j],*history,sumo); +#endif +#endif + } + *(data++) = *(residual++) + (sum >> lp_quantization); + } + + /* Here's a slower but clearer version: + for(i = 0; i < data_len; i++) { + sum = 0; + for(j = 0; j < order; j++) + sum += qlp_coeff[j] * data[i-j-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + */ +} + +void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]) +{ + unsigned i, j; + FLAC__int64 sum; + const FLAC__int32 *history; + +#ifdef FLAC__OVERFLOW_DETECT_VERBOSE + fprintf(stderr,"FLAC__lpc_restore_signal_wide: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); + for(i=0;i 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_wide(sum >> lp_quantization) > 32) { + fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, sum=%lld\n", i, sum >> lp_quantization); + break; + } + if(FLAC__bitmath_silog2_wide((FLAC__int64)(*residual) + (sum >> lp_quantization)) > 32) { + fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=%lld, data=%lld\n", i, *residual, sum >> lp_quantization, (FLAC__int64)(*residual) + (sum >> lp_quantization)); + break; + } +#endif + *(data++) = *(residual++) + (FLAC__int32)(sum >> lp_quantization); + } +} + +#ifndef FLAC__INTEGER_ONLY_LIBRARY + +FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample(FLAC__double lpc_error, unsigned total_samples) +{ + FLAC__double error_scale; + + FLAC__ASSERT(total_samples > 0); + + error_scale = 0.5 * M_LN2 * M_LN2 / (FLAC__double)total_samples; + + return FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(lpc_error, error_scale); +} + +FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(FLAC__double lpc_error, FLAC__double error_scale) +{ + if(lpc_error > 0.0) { + FLAC__double bps = (FLAC__double)0.5 * log(error_scale * lpc_error) / M_LN2; + if(bps >= 0.0) + return bps; + else + return 0.0; + } + else if(lpc_error < 0.0) { /* error should not be negative but can happen due to inadequate floating-point resolution */ + return 1e32; + } + else { + return 0.0; + } +} + +unsigned FLAC__lpc_compute_best_order(const FLAC__double lpc_error[], unsigned max_order, unsigned total_samples, unsigned bits_per_signal_sample) +{ + unsigned order, best_order; + FLAC__double best_bits, tmp_bits, error_scale; + + FLAC__ASSERT(max_order > 0); + FLAC__ASSERT(total_samples > 0); + + error_scale = 0.5 * M_LN2 * M_LN2 / (FLAC__double)total_samples; + + best_order = 0; + best_bits = FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(lpc_error[0], error_scale) * (FLAC__double)total_samples; + + for(order = 1; order < max_order; order++) { + tmp_bits = FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(lpc_error[order], error_scale) * (FLAC__double)(total_samples - order) + (FLAC__double)(order * bits_per_signal_sample); + if(tmp_bits < best_bits) { + best_order = order; + best_bits = tmp_bits; + } + } + + return best_order+1; /* +1 since index of lpc_error[] is order-1 */ +} + +#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ diff --git a/FLAC/memory.c b/FLAC/memory.c index a332f7275..fcdf58ca5 100644 --- a/FLAC/memory.c +++ b/FLAC/memory.c @@ -1,169 +1,188 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#include "private/memory.h" -#include "FLAC/assert.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address) -{ - void *x; - - FLAC__ASSERT(0 != aligned_address); - -#ifdef FLAC__ALIGN_MALLOC_DATA - /* align on 32-byte (256-bit) boundary */ - x = malloc(bytes+31); - *aligned_address = (void*)(((unsigned)x + 31) & -32); -#else - x = malloc(bytes); - *aligned_address = x; -#endif - return x; -} - -FLAC__bool FLAC__memory_alloc_aligned_int32_array(unsigned elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer) -{ - union { void *v; FLAC__int32 *i; } pa; - FLAC__int32 *pu; /* aligned pointer, unaligned pointer */ - - FLAC__ASSERT(elements > 0); - FLAC__ASSERT(0 != unaligned_pointer); - FLAC__ASSERT(0 != aligned_pointer); - FLAC__ASSERT(unaligned_pointer != aligned_pointer); - - pu = (FLAC__int32*)FLAC__memory_alloc_aligned(sizeof(FLAC__int32) * elements, &pa.v); - if(0 == pu) { - return false; - } - else { - if(*unaligned_pointer != 0) - free(*unaligned_pointer); - *unaligned_pointer = pu; - *aligned_pointer = pa.i; - return true; - } -} - -FLAC__bool FLAC__memory_alloc_aligned_uint32_array(unsigned elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer) -{ - union { void *v; FLAC__uint32 *i; } pa; - FLAC__uint32 *pu; /* aligned pointer, unaligned pointer */ - - FLAC__ASSERT(elements > 0); - FLAC__ASSERT(0 != unaligned_pointer); - FLAC__ASSERT(0 != aligned_pointer); - FLAC__ASSERT(unaligned_pointer != aligned_pointer); - - pu = (FLAC__uint32*)FLAC__memory_alloc_aligned(sizeof(FLAC__uint32) * elements, &pa.v); - if(0 == pu) { - return false; - } - else { - if(*unaligned_pointer != 0) - free(*unaligned_pointer); - *unaligned_pointer = pu; - *aligned_pointer = pa.i; - return true; - } -} - -FLAC__bool FLAC__memory_alloc_aligned_uint64_array(unsigned elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer) -{ - union { void *v; FLAC__uint64 *i; } pa; - FLAC__uint64 *pu; /* aligned pointer, unaligned pointer */ - - FLAC__ASSERT(elements > 0); - FLAC__ASSERT(0 != unaligned_pointer); - FLAC__ASSERT(0 != aligned_pointer); - FLAC__ASSERT(unaligned_pointer != aligned_pointer); - - pu = (FLAC__uint64*)FLAC__memory_alloc_aligned(sizeof(FLAC__uint64) * elements, &pa.v); - if(0 == pu) { - return false; - } - else { - if(*unaligned_pointer != 0) - free(*unaligned_pointer); - *unaligned_pointer = pu; - *aligned_pointer = pa.i; - return true; - } -} - -FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(unsigned elements, unsigned **unaligned_pointer, unsigned **aligned_pointer) -{ - union { void *v; unsigned *i; } pa; - unsigned *pu; /* aligned pointer, unaligned pointer */ - - FLAC__ASSERT(elements > 0); - FLAC__ASSERT(0 != unaligned_pointer); - FLAC__ASSERT(0 != aligned_pointer); - FLAC__ASSERT(unaligned_pointer != aligned_pointer); - - pu = (unsigned*)FLAC__memory_alloc_aligned(sizeof(unsigned) * elements, &pa.v); - if(0 == pu) { - return false; - } - else { - if(*unaligned_pointer != 0) - free(*unaligned_pointer); - *unaligned_pointer = pu; - *aligned_pointer = pa.i; - return true; - } -} - -FLAC__bool FLAC__memory_alloc_aligned_real_array(unsigned elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer) -{ - union { void *v; FLAC__real *r; } pa; - FLAC__real *pu; /* aligned pointer, unaligned pointer */ - - FLAC__ASSERT(elements > 0); - FLAC__ASSERT(0 != unaligned_pointer); - FLAC__ASSERT(0 != aligned_pointer); - FLAC__ASSERT(unaligned_pointer != aligned_pointer); - - pu = (FLAC__real*)FLAC__memory_alloc_aligned(sizeof(FLAC__real) * elements, &pa.v); - if(0 == pu) { - return false; - } - else { - if(*unaligned_pointer != 0) - free(*unaligned_pointer); - *unaligned_pointer = pu; - *aligned_pointer = pa.r; - return true; - } -} +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#include "private/memory.h" +#include "FLAC/assert.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address) +{ + void *x; + + FLAC__ASSERT(0 != aligned_address); + +#ifdef FLAC__ALIGN_MALLOC_DATA + /* align on 32-byte (256-bit) boundary */ + x = malloc(bytes+31); + *aligned_address = (void*)(((unsigned)x + 31) & -32); +#else + x = malloc(bytes); + *aligned_address = x; +#endif + return x; +} + +FLAC__bool FLAC__memory_alloc_aligned_int32_array(unsigned elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer) +{ + FLAC__int32 *pu; /* unaligned pointer */ + union { /* union needed to comply with C99 pointer aliasing rules */ + FLAC__int32 *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); + + pu = (FLAC__int32*)FLAC__memory_alloc_aligned(sizeof(FLAC__int32) * 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_uint32_array(unsigned elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer) +{ + 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); + + pu = (FLAC__uint32*)FLAC__memory_alloc_aligned(sizeof(FLAC__uint32) * elements, &u.pv); + if(0 == pu) { + return false; + } + else { + if(*unaligned_pointer != 0) + free(*unaligned_pointer); + *unaligned_pointer = pu; + *aligned_pointer = u.pa; + return true; + } +} + +FLAC__bool FLAC__memory_alloc_aligned_uint64_array(unsigned elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer) +{ + FLAC__uint64 *pu; /* unaligned pointer */ + union { /* union needed to comply with C99 pointer aliasing rules */ + FLAC__uint64 *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); + + pu = (FLAC__uint64*)FLAC__memory_alloc_aligned(sizeof(FLAC__uint64) * 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_unsigned_array(unsigned elements, unsigned **unaligned_pointer, unsigned **aligned_pointer) +{ + unsigned *pu; /* unaligned pointer */ + union { /* union needed to comply with C99 pointer aliasing rules */ + unsigned *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); + + pu = (unsigned*)FLAC__memory_alloc_aligned(sizeof(unsigned) * 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; + } +} + +#ifndef FLAC__INTEGER_ONLY_LIBRARY + +FLAC__bool FLAC__memory_alloc_aligned_real_array(unsigned elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer) +{ + FLAC__real *pu; /* unaligned pointer */ + union { /* union needed to comply with C99 pointer aliasing rules */ + FLAC__real *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); + + pu = (FLAC__real*)FLAC__memory_alloc_aligned(sizeof(FLAC__real) * 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; + } +} + +#endif diff --git a/FLAC/private/bitbuffer.h b/FLAC/private/bitbuffer.h index fc6928037..0923df895 100644 --- a/FLAC/private/bitbuffer.h +++ b/FLAC/private/bitbuffer.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003 Josh Coalson + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -105,13 +105,6 @@ unsigned FLAC__bitbuffer_rice_bits(int val, unsigned parameter); unsigned FLAC__bitbuffer_golomb_bits_signed(int val, unsigned parameter); unsigned FLAC__bitbuffer_golomb_bits_unsigned(unsigned val, unsigned parameter); #endif -#ifdef FLAC__SYMMETRIC_RICE -FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter); -#if 0 /* UNUSED */ -FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_guarded(FLAC__BitBuffer *bb, int val, unsigned parameter, unsigned max_bits, FLAC__bool *overflow); -#endif -FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_escape(FLAC__BitBuffer *bb, int val, unsigned parameter); -#endif FLAC__bool FLAC__bitbuffer_write_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter); #if 0 /* UNUSED */ FLAC__bool FLAC__bitbuffer_write_rice_signed_guarded(FLAC__BitBuffer *bb, int val, unsigned parameter, unsigned max_bits, FLAC__bool *overflow); @@ -143,9 +136,6 @@ FLAC__bool FLAC__bitbuffer_read_raw_uint32_little_endian(FLAC__BitBuffer *bb, FL FLAC__bool FLAC__bitbuffer_skip_bits_no_crc(FLAC__BitBuffer *bb, unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); /* WATCHOUT: does not CRC the skipped data! */ /*@@@@ add to unit tests */ FLAC__bool FLAC__bitbuffer_read_byte_block_aligned_no_crc(FLAC__BitBuffer *bb, FLAC__byte *val, unsigned nvals, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); /* val may be 0 to skip bytes instead of reading them */ /* WATCHOUT: does not CRC the read data! */ FLAC__bool FLAC__bitbuffer_read_unary_unsigned(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); -#ifdef FLAC__SYMMETRIC_RICE -FLAC__bool FLAC__bitbuffer_read_symmetric_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); -#endif FLAC__bool FLAC__bitbuffer_read_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); FLAC__bool FLAC__bitbuffer_read_rice_signed_block(FLAC__BitBuffer *bb, int vals[], unsigned nvals, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data); #if 0 /* UNUSED */ diff --git a/FLAC/private/bitmath.h b/FLAC/private/bitmath.h index 74220ae59..980ee29ab 100644 --- a/FLAC/private/bitmath.h +++ b/FLAC/private/bitmath.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2001,2002,2003 Josh Coalson + * Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,7 +34,8 @@ #include "FLAC/ordinals.h" -unsigned FLAC__bitmath_ilog2(unsigned v); +unsigned FLAC__bitmath_ilog2(FLAC__uint32 v); +unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v); unsigned FLAC__bitmath_silog2(int v); unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v); diff --git a/FLAC/private/cpu.h b/FLAC/private/cpu.h index c7f7bd205..acd4615d8 100644 --- a/FLAC/private/cpu.h +++ b/FLAC/private/cpu.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2001,2002,2003 Josh Coalson + * Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,6 +40,7 @@ typedef enum { FLAC__CPUINFO_TYPE_IA32, + FLAC__CPUINFO_TYPE_PPC, FLAC__CPUINFO_TYPE_UNKNOWN } FLAC__CPUInfo_Type; @@ -54,6 +55,11 @@ typedef struct { FLAC__bool extmmx; } FLAC__CPUInfo_IA32; +typedef struct { + FLAC__bool altivec; + FLAC__bool ppc64; +} FLAC__CPUInfo_PPC; + extern const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV; extern const unsigned FLAC__CPUINFO_IA32_CPUID_MMX; extern const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR; @@ -69,6 +75,7 @@ typedef struct { FLAC__CPUInfo_Type type; union { FLAC__CPUInfo_IA32 ia32; + FLAC__CPUInfo_PPC ppc; } data; } FLAC__CPUInfo; diff --git a/FLAC/private/crc.h b/FLAC/private/crc.h index 2656c7b03..083cbcf51 100644 --- a/FLAC/private/crc.h +++ b/FLAC/private/crc.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003 Josh Coalson + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/FLAC/private/fixed.h b/FLAC/private/fixed.h index e2728e00a..de35b6d67 100644 --- a/FLAC/private/fixed.h +++ b/FLAC/private/fixed.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003 Josh Coalson + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,12 +32,13 @@ #ifndef FLAC__PRIVATE__FIXED_H #define FLAC__PRIVATE__FIXED_H -#include "FLAC/format.h" - #ifdef HAVE_CONFIG_H #include #endif +#include "private/float.h" +#include "FLAC/format.h" + /* * FLAC__fixed_compute_best_predictor() * -------------------------------------------------------------------- @@ -50,15 +51,20 @@ * IN data_len * OUT residual_bits_per_sample[0,FLAC__MAX_FIXED_ORDER] */ -unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); -#ifndef FLAC__NO_ASM -#ifdef FLAC__CPU_IA32 -#ifdef FLAC__HAS_NASM -unsigned FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov(const FLAC__int32 data[], unsigned data_len, FLAC__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +#ifndef FLAC__INTEGER_ONLY_LIBRARY +unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +# ifndef FLAC__NO_ASM +# ifdef FLAC__CPU_IA32 +# ifdef FLAC__HAS_NASM +unsigned FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +# endif +# endif +# endif +unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +#else +unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); #endif -#endif -#endif -unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); /* * FLAC__fixed_compute_residual() diff --git a/FLAC/private/format.h b/FLAC/private/format.h index 691cfc2f5..62eb8cb18 100644 --- a/FLAC/private/format.h +++ b/FLAC/private/format.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003 Josh Coalson + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/FLAC/private/lpc.h b/FLAC/private/lpc.h index 801f7c5f9..79781add9 100644 --- a/FLAC/private/lpc.h +++ b/FLAC/private/lpc.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003 Josh Coalson + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,12 +32,15 @@ #ifndef FLAC__PRIVATE__LPC_H #define FLAC__PRIVATE__LPC_H -#include "FLAC/format.h" - #ifdef HAVE_CONFIG_H #include #endif +#include "private/float.h" +#include "FLAC/format.h" + +#ifndef FLAC__INTEGER_ONLY_LIBRARY + /* * FLAC__lpc_compute_autocorrelation() * -------------------------------------------------------------------- @@ -52,15 +55,15 @@ */ void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); #ifndef FLAC__NO_ASM -#ifdef FLAC__CPU_IA32 -#ifdef FLAC__HAS_NASM +# ifdef FLAC__CPU_IA32 +# ifdef FLAC__HAS_NASM void FLAC__lpc_compute_autocorrelation_asm_ia32(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); void FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); -#endif -#endif +# endif +# endif #endif /* @@ -81,7 +84,7 @@ void FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow(const FLAC__real data[], u * 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[], unsigned max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], FLAC__real error[]); +void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], unsigned max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], FLAC__double error[]); /* * FLAC__lpc_quantize_coefficients() @@ -118,17 +121,19 @@ int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order, * IN lp_quantization quantization of LP coefficients in bits * OUT residual[0,data_len-1] residual signal */ -void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 data[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); -void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 data[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); #ifndef FLAC__NO_ASM -#ifdef FLAC__CPU_IA32 -#ifdef FLAC__HAS_NASM -void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32(const FLAC__int32 data[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); -void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx(const FLAC__int32 data[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); -#endif -#endif +# ifdef FLAC__CPU_IA32 +# ifdef FLAC__HAS_NASM +void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +# endif +# endif #endif +#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ + /* * FLAC__lpc_restore_signal() * -------------------------------------------------------------------- @@ -147,13 +152,18 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx(const FLAC__i void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); #ifndef FLAC__NO_ASM -#ifdef FLAC__CPU_IA32 -#ifdef FLAC__HAS_NASM +# ifdef FLAC__CPU_IA32 +# ifdef FLAC__HAS_NASM void FLAC__lpc_restore_signal_asm_ia32(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); void FLAC__lpc_restore_signal_asm_ia32_mmx(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); -#endif -#endif -#endif +# endif /* FLAC__HAS_NASM */ +# elif defined FLAC__CPU_PPC +void FLAC__lpc_restore_signal_asm_ppc_altivec_16(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); +void FLAC__lpc_restore_signal_asm_ppc_altivec_16_order8(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); +# endif/* FLAC__CPU_IA32 || FLAC__CPU_PPC */ +#endif /* FLAC__NO_ASM */ + +#ifndef FLAC__INTEGER_ONLY_LIBRARY /* * FLAC__lpc_compute_expected_bits_per_residual_sample() @@ -165,8 +175,8 @@ void FLAC__lpc_restore_signal_asm_ia32_mmx(const FLAC__int32 residual[], unsigne * IN total_samples > 0 # of samples in residual signal * RETURN expected bits per sample */ -FLAC__real FLAC__lpc_compute_expected_bits_per_residual_sample(FLAC__real lpc_error, unsigned total_samples); -FLAC__real FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(FLAC__real lpc_error, double error_scale); +FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample(FLAC__double lpc_error, unsigned total_samples); +FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(FLAC__double lpc_error, FLAC__double error_scale); /* * FLAC__lpc_compute_best_order() @@ -180,6 +190,8 @@ FLAC__real FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale( * IN bits_per_signal_sample # of bits per sample in the original signal * RETURN [1,max_order] best order */ -unsigned FLAC__lpc_compute_best_order(const FLAC__real lpc_error[], unsigned max_order, unsigned total_samples, unsigned bits_per_signal_sample); +unsigned FLAC__lpc_compute_best_order(const FLAC__double lpc_error[], unsigned max_order, unsigned total_samples, unsigned bits_per_signal_sample); + +#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ #endif diff --git a/FLAC/private/memory.h b/FLAC/private/memory.h index 0445ba018..c985a72fb 100644 --- a/FLAC/private/memory.h +++ b/FLAC/private/memory.h @@ -1,49 +1,56 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#ifndef FLAC__PRIVATE__MEMORY_H -#define FLAC__PRIVATE__MEMORY_H - -#include /* for size_t */ - -#include "FLAC/ordinals.h" /* for FLAC__bool */ - -/* Returns the unaligned address returned by malloc. - * Use free() on this address to deallocate. - */ -void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address); -FLAC__bool FLAC__memory_alloc_aligned_int32_array(unsigned elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer); -FLAC__bool FLAC__memory_alloc_aligned_uint32_array(unsigned elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer); -FLAC__bool FLAC__memory_alloc_aligned_uint64_array(unsigned elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer); -FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(unsigned elements, unsigned **unaligned_pointer, unsigned **aligned_pointer); -FLAC__bool FLAC__memory_alloc_aligned_real_array(unsigned elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer); - -#endif +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#ifndef FLAC__PRIVATE__MEMORY_H +#define FLAC__PRIVATE__MEMORY_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include /* for size_t */ + +#include "private/float.h" +#include "FLAC/ordinals.h" /* for FLAC__bool */ + +/* Returns the unaligned address returned by malloc. + * Use free() on this address to deallocate. + */ +void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address); +FLAC__bool FLAC__memory_alloc_aligned_int32_array(unsigned elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer); +FLAC__bool FLAC__memory_alloc_aligned_uint32_array(unsigned elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer); +FLAC__bool FLAC__memory_alloc_aligned_uint64_array(unsigned elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer); +FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(unsigned elements, unsigned **unaligned_pointer, unsigned **aligned_pointer); +#ifndef FLAC__INTEGER_ONLY_LIBRARY +FLAC__bool FLAC__memory_alloc_aligned_real_array(unsigned elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer); +#endif + +#endif diff --git a/FLAC/protected/stream_decoder.h b/FLAC/protected/stream_decoder.h index bc274677b..8cc1e6bdf 100644 --- a/FLAC/protected/stream_decoder.h +++ b/FLAC/protected/stream_decoder.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003 Josh Coalson + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/FLAC/stream_decoder.c b/FLAC/stream_decoder.c index 4b1c5776f..25fdfb00b 100644 --- a/FLAC/stream_decoder.c +++ b/FLAC/stream_decoder.c @@ -1,2112 +1,2153 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000,2001,2002,2003,2004 Josh Coalson - * - * 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. - */ - -#include -#include /* for malloc() */ -#include /* for memset/memcpy() */ -#include "FLAC/assert.h" -#include "protected/stream_decoder.h" -#include "private/bitbuffer.h" -#include "private/bitmath.h" -#include "private/cpu.h" -#include "private/crc.h" -#include "private/fixed.h" -#include "private/format.h" -#include "private/lpc.h" -#include "private/memory.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef max -#undef max -#endif -#define max(a,b) ((a)>(b)?(a):(b)) - -/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ -#ifdef _MSC_VER -#define FLAC__U64L(x) x -#else -#define FLAC__U64L(x) x##LLU -#endif - -/*********************************************************************** - * - * Private static data - * - ***********************************************************************/ - -static FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' }; - -/*********************************************************************** - * - * Private class method prototypes - * - ***********************************************************************/ - -static void set_defaults_(FLAC__StreamDecoder *decoder); -static FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels); -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); -static FLAC__bool read_metadata_streaminfo_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length); -static FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length); -static FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj); -static FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj); -static FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder); -static FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder); -static FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FLAC__bool do_full_decode); -static FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder); -static FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode); -static FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode); -static FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode); -static FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode); -static FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode); -static FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigned predictor_order, unsigned partition_order, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, FLAC__int32 *residual); -static FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder); -static FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_data); - -/*********************************************************************** - * - * Private class data - * - ***********************************************************************/ - -typedef struct FLAC__StreamDecoderPrivate { - FLAC__StreamDecoderReadCallback read_callback; - 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[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); - /* generic 64-bit datapath: */ - void (*local_lpc_restore_signal_64bit)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned 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[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned 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), AND order <= 8: */ - void (*local_lpc_restore_signal_16bit_order8)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); - void *client_data; - FLAC__BitBuffer *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__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents[FLAC__MAX_CHANNELS]; - unsigned output_capacity, output_channels; - FLAC__uint32 last_frame_number; - FLAC__uint64 samples_decoded; - FLAC__bool has_stream_info, has_seek_table; - FLAC__StreamMetadata stream_info; - FLAC__StreamMetadata seek_table; - FLAC__bool metadata_filter[128]; /* MAGIC number 128 == total number of metadata block types == 1 << 7 */ - FLAC__byte *metadata_filter_ids; - unsigned 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 */ - FLAC__int32 *residual_unaligned[FLAC__MAX_CHANNELS]; -} FLAC__StreamDecoderPrivate; - -/*********************************************************************** - * - * Public static class data - * - ***********************************************************************/ - -FLAC_API const char * const FLAC__StreamDecoderStateString[] = { - "FLAC__STREAM_DECODER_SEARCH_FOR_METADATA", - "FLAC__STREAM_DECODER_READ_METADATA", - "FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC", - "FLAC__STREAM_DECODER_READ_FRAME", - "FLAC__STREAM_DECODER_END_OF_STREAM", - "FLAC__STREAM_DECODER_ABORTED", - "FLAC__STREAM_DECODER_UNPARSEABLE_STREAM", - "FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR", - "FLAC__STREAM_DECODER_ALREADY_INITIALIZED", - "FLAC__STREAM_DECODER_INVALID_CALLBACK", - "FLAC__STREAM_DECODER_UNINITIALIZED" -}; - -FLAC_API const char * const FLAC__StreamDecoderReadStatusString[] = { - "FLAC__STREAM_DECODER_READ_STATUS_CONTINUE", - "FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM", - "FLAC__STREAM_DECODER_READ_STATUS_ABORT" -}; - -FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[] = { - "FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE", - "FLAC__STREAM_DECODER_WRITE_STATUS_ABORT" -}; - -FLAC_API const char * const FLAC__StreamDecoderErrorStatusString[] = { - "FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC", - "FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER", - "FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH" -}; - -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ -FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new() -{ - FLAC__StreamDecoder *decoder; - unsigned i; - - FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */ - - decoder = (FLAC__StreamDecoder*)calloc(1, sizeof(FLAC__StreamDecoder)); - if(decoder == 0) { - return 0; - } - - decoder->protected_ = (FLAC__StreamDecoderProtected*)calloc(1, sizeof(FLAC__StreamDecoderProtected)); - if(decoder->protected_ == 0) { - free(decoder); - return 0; - } - - decoder->private_ = (FLAC__StreamDecoderPrivate*)calloc(1, sizeof(FLAC__StreamDecoderPrivate)); - if(decoder->private_ == 0) { - free(decoder->protected_); - free(decoder); - return 0; - } - - decoder->private_->input = FLAC__bitbuffer_new(); - if(decoder->private_->input == 0) { - free(decoder->private_); - free(decoder->protected_); - free(decoder); - return 0; - } - - decoder->private_->metadata_filter_ids_capacity = 16; - if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)malloc((FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) * decoder->private_->metadata_filter_ids_capacity))) { - FLAC__bitbuffer_delete(decoder->private_->input); - free(decoder->private_); - free(decoder->protected_); - free(decoder); - return 0; - } - - for(i = 0; i < FLAC__MAX_CHANNELS; i++) { - decoder->private_->output[i] = 0; - decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0; - } - - decoder->private_->output_capacity = 0; - decoder->private_->output_channels = 0; - decoder->private_->has_seek_table = false; - - for(i = 0; i < FLAC__MAX_CHANNELS; i++) - FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&decoder->private_->partitioned_rice_contents[i]); - - set_defaults_(decoder); - - decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED; - - return decoder; -} - -FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder) -{ - unsigned i; - - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->private_->input); - - FLAC__stream_decoder_finish(decoder); - - if(0 != decoder->private_->metadata_filter_ids) - free(decoder->private_->metadata_filter_ids); - - FLAC__bitbuffer_delete(decoder->private_->input); - - for(i = 0; i < FLAC__MAX_CHANNELS; i++) - FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&decoder->private_->partitioned_rice_contents[i]); - - free(decoder->private_); - free(decoder->protected_); - free(decoder); -} - -/*********************************************************************** - * - * Public class methods - * - ***********************************************************************/ - -FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - - if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return decoder->protected_->state = FLAC__STREAM_DECODER_ALREADY_INITIALIZED; - - if(0 == decoder->private_->read_callback || 0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback) - return decoder->protected_->state = FLAC__STREAM_DECODER_INVALID_CALLBACK; - - if(!FLAC__bitbuffer_init(decoder->private_->input)) - return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - - decoder->private_->last_frame_number = 0; - decoder->private_->samples_decoded = 0; - decoder->private_->has_stream_info = false; - decoder->private_->cached = false; - - /* - * 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; - decoder->private_->local_lpc_restore_signal_16bit_order8 = 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 - if(decoder->private_->cpuinfo.data.ia32.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; - decoder->private_->local_lpc_restore_signal_16bit_order8 = 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; - decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ia32; - } -#endif -#elif defined FLAC__CPU_PPC - FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_PPC); - if(decoder->private_->cpuinfo.data.ppc.altivec) { - decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ppc_altivec_16; - decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ppc_altivec_16_order8; - } -#endif - } -#endif - - if(!FLAC__stream_decoder_reset(decoder)) - return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - - return decoder->protected_->state; -} - -FLAC_API void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder) -{ - unsigned i; - FLAC__ASSERT(0 != decoder); - if(decoder->protected_->state == FLAC__STREAM_DECODER_UNINITIALIZED) - return; - if(0 != decoder->private_->seek_table.data.seek_table.points) { - free(decoder->private_->seek_table.data.seek_table.points); - decoder->private_->seek_table.data.seek_table.points = 0; - decoder->private_->has_seek_table = false; - } - FLAC__bitbuffer_free(decoder->private_->input); - for(i = 0; i < FLAC__MAX_CHANNELS; i++) { - /* WATCHOUT: - * FLAC__lpc_restore_signal_asm_ia32_mmx() requires that the - * output arrays have a buffer of up to 3 zeroes in front - * (at negative indices) for alignment purposes; we use 4 - * to keep the data well-aligned. - */ - if(0 != decoder->private_->output[i]) { - free(decoder->private_->output[i]-4); - decoder->private_->output[i] = 0; - } - if(0 != decoder->private_->residual_unaligned[i]) { - free(decoder->private_->residual_unaligned[i]); - decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0; - } - } - decoder->private_->output_capacity = 0; - decoder->private_->output_channels = 0; - - set_defaults_(decoder); - - decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_set_read_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->read_callback = value; - return true; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_set_write_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderWriteCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->write_callback = value; - return true; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderMetadataCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->metadata_callback = value; - return true; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_set_error_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->error_callback = value; - return true; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_set_client_data(FLAC__StreamDecoder *decoder, void *value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->client_data = value; - return true; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond(FLAC__StreamDecoder *decoder, FLAC__MetadataType type) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT((unsigned)type <= FLAC__MAX_METADATA_TYPE_CODE); - /* double protection */ - if((unsigned)type > FLAC__MAX_METADATA_TYPE_CODE) - return false; - if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->metadata_filter[type] = true; - if(type == FLAC__METADATA_TYPE_APPLICATION) - decoder->private_->metadata_filter_ids_count = 0; - return true; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != id); - if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return false; - - if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_APPLICATION]) - return true; - - FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids); - - if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) { - if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)realloc(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity * 2))) - return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - decoder->private_->metadata_filter_ids_capacity *= 2; - } - - memcpy(decoder->private_->metadata_filter_ids + decoder->private_->metadata_filter_ids_count * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8)); - decoder->private_->metadata_filter_ids_count++; - - return true; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_all(FLAC__StreamDecoder *decoder) -{ - unsigned i; - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return false; - for(i = 0; i < sizeof(decoder->private_->metadata_filter) / sizeof(decoder->private_->metadata_filter[0]); i++) - decoder->private_->metadata_filter[i] = true; - decoder->private_->metadata_filter_ids_count = 0; - return true; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore(FLAC__StreamDecoder *decoder, FLAC__MetadataType type) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT((unsigned)type <= FLAC__MAX_METADATA_TYPE_CODE); - /* double protection */ - if((unsigned)type > FLAC__MAX_METADATA_TYPE_CODE) - return false; - if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->metadata_filter[type] = false; - if(type == FLAC__METADATA_TYPE_APPLICATION) - decoder->private_->metadata_filter_ids_count = 0; - return true; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != id); - if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return false; - - if(!decoder->private_->metadata_filter[FLAC__METADATA_TYPE_APPLICATION]) - return true; - - FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids); - - if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) { - if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)realloc(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity * 2))) - return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - decoder->private_->metadata_filter_ids_capacity *= 2; - } - - memcpy(decoder->private_->metadata_filter_ids + decoder->private_->metadata_filter_ids_count * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8)); - decoder->private_->metadata_filter_ids_count++; - - return true; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_all(FLAC__StreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return false; - memset(decoder->private_->metadata_filter, 0, sizeof(decoder->private_->metadata_filter)); - decoder->private_->metadata_filter_ids_count = 0; - return true; -} - -FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__StreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - return decoder->protected_->state; -} - -FLAC_API const char *FLAC__stream_decoder_get_resolved_state_string(const FLAC__StreamDecoder *decoder) -{ - return FLAC__StreamDecoderStateString[decoder->protected_->state]; -} - -FLAC_API unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - return decoder->protected_->channels; -} - -FLAC_API FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(const FLAC__StreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - return decoder->protected_->channel_assignment; -} - -FLAC_API unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - return decoder->protected_->bits_per_sample; -} - -FLAC_API unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - return decoder->protected_->sample_rate; -} - -FLAC_API unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - return decoder->protected_->blocksize; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - - if(!FLAC__bitbuffer_clear(decoder->private_->input)) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - - return true; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - - if(!FLAC__stream_decoder_flush(decoder)) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA; - - decoder->private_->samples_decoded = 0; - - return true; -} - -FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *decoder) -{ - FLAC__bool got_a_frame; - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - - while(1) { - switch(decoder->protected_->state) { - case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: - if(!find_metadata_(decoder)) - return false; /* above function sets the status for us */ - break; - case FLAC__STREAM_DECODER_READ_METADATA: - if(!read_metadata_(decoder)) - return false; /* above function sets the status for us */ - else - return true; - case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: - if(!frame_sync_(decoder)) - return true; /* above function sets the status for us */ - break; - case FLAC__STREAM_DECODER_READ_FRAME: - if(!read_frame_(decoder, &got_a_frame, /*do_full_decode=*/true)) - return false; /* above function sets the status for us */ - if(got_a_frame) - return true; /* above function sets the status for us */ - break; - case FLAC__STREAM_DECODER_END_OF_STREAM: - case FLAC__STREAM_DECODER_ABORTED: - return true; - default: - FLAC__ASSERT(0); - return false; - } - } -} - -FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_metadata(FLAC__StreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - - while(1) { - switch(decoder->protected_->state) { - case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: - if(!find_metadata_(decoder)) - return false; /* above function sets the status for us */ - break; - case FLAC__STREAM_DECODER_READ_METADATA: - if(!read_metadata_(decoder)) - return false; /* above function sets the status for us */ - break; - case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: - case FLAC__STREAM_DECODER_READ_FRAME: - case FLAC__STREAM_DECODER_END_OF_STREAM: - case FLAC__STREAM_DECODER_ABORTED: - return true; - default: - FLAC__ASSERT(0); - return false; - } - } -} - -FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder) -{ - FLAC__bool dummy; - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - - while(1) { - switch(decoder->protected_->state) { - case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: - if(!find_metadata_(decoder)) - return false; /* above function sets the status for us */ - break; - case FLAC__STREAM_DECODER_READ_METADATA: - if(!read_metadata_(decoder)) - return false; /* above function sets the status for us */ - break; - case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: - if(!frame_sync_(decoder)) - return true; /* above function sets the status for us */ - break; - case FLAC__STREAM_DECODER_READ_FRAME: - if(!read_frame_(decoder, &dummy, /*do_full_decode=*/true)) - return false; /* above function sets the status for us */ - break; - case FLAC__STREAM_DECODER_END_OF_STREAM: - case FLAC__STREAM_DECODER_ABORTED: - return true; - default: - FLAC__ASSERT(0); - return false; - } - } -} - -FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder) -{ - FLAC__bool got_a_frame; - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - - while(1) { - switch(decoder->protected_->state) { - case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: - case FLAC__STREAM_DECODER_READ_METADATA: - return false; /* above function sets the status for us */ - case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: - if(!frame_sync_(decoder)) - return true; /* above function sets the status for us */ - break; - case FLAC__STREAM_DECODER_READ_FRAME: - if(!read_frame_(decoder, &got_a_frame, /*do_full_decode=*/false)) - return false; /* above function sets the status for us */ - if(got_a_frame) - return true; /* above function sets the status for us */ - break; - case FLAC__STREAM_DECODER_END_OF_STREAM: - case FLAC__STREAM_DECODER_ABORTED: - return true; - default: - FLAC__ASSERT(0); - return false; - } - } -} - -/*********************************************************************** - * - * Protected class methods - * - ***********************************************************************/ - -unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - return FLAC__bitbuffer_get_input_bytes_unconsumed(decoder->private_->input); -} - -/*********************************************************************** - * - * Private class methods - * - ***********************************************************************/ - -void set_defaults_(FLAC__StreamDecoder *decoder) -{ - decoder->private_->read_callback = 0; - decoder->private_->write_callback = 0; - decoder->private_->metadata_callback = 0; - decoder->private_->error_callback = 0; - decoder->private_->client_data = 0; - - memset(decoder->private_->metadata_filter, 0, sizeof(decoder->private_->metadata_filter)); - decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO] = true; - decoder->private_->metadata_filter_ids_count = 0; -} - -FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels) -{ - unsigned i; - FLAC__int32 *tmp; - - if(size <= decoder->private_->output_capacity && channels <= decoder->private_->output_channels) - return true; - - /* simply using realloc() is not practical because the number of channels may change mid-stream */ - - for(i = 0; i < FLAC__MAX_CHANNELS; i++) { - if(0 != decoder->private_->output[i]) { - free(decoder->private_->output[i]-4); - decoder->private_->output[i] = 0; - } - if(0 != decoder->private_->residual_unaligned[i]) { - free(decoder->private_->residual_unaligned[i]); - decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0; - } - } - - for(i = 0; i < channels; i++) { - /* WATCHOUT: - * FLAC__lpc_restore_signal_asm_ia32_mmx() requires that the - * output arrays have a buffer of up to 3 zeroes in front - * (at negative indices) for alignment purposes; we use 4 - * to keep the data well-aligned. - */ - tmp = (FLAC__int32*)malloc(sizeof(FLAC__int32)*(size+4)); - if(tmp == 0) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - memset(tmp, 0, sizeof(FLAC__int32)*4); - decoder->private_->output[i] = tmp + 4; - - /* WATCHOUT: - * minimum of quadword alignment for PPC vector optimizations is REQUIRED: - */ - if(!FLAC__memory_alloc_aligned_int32_array(size, &decoder->private_->residual_unaligned[i], &decoder->private_->residual[i])) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - } - - decoder->private_->output_capacity = size; - decoder->private_->output_channels = channels; - - return true; -} - -FLAC__bool has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id) -{ - unsigned i; - - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - - for(i = 0; i < decoder->private_->metadata_filter_ids_count; i++) - if(0 == memcmp(decoder->private_->metadata_filter_ids + i * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8))) - return true; - - return false; -} - -FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder) -{ - FLAC__uint32 x; - unsigned i, id; - FLAC__bool first = true; - - FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); - - for(i = id = 0; i < 4; ) { - if(decoder->private_->cached) { - x = (FLAC__uint32)decoder->private_->lookahead; - decoder->private_->cached = false; - } - else { - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - } - if(x == FLAC__STREAM_SYNC_STRING[i]) { - first = true; - i++; - id = 0; - continue; - } - if(x == ID3V2_TAG_[id]) { - id++; - i = 0; - if(id == 3) { - if(!skip_id3v2_tag_(decoder)) - return false; /* the read_callback_ sets the state for us */ - } - continue; - } - if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ - decoder->private_->header_warmup[0] = (FLAC__byte)x; - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - /* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */ - /* else we have to check if the second byte is the end of a sync code */ - if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ - decoder->private_->lookahead = (FLAC__byte)x; - decoder->private_->cached = true; - } - else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */ - decoder->private_->header_warmup[1] = (FLAC__byte)x; - decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME; - return true; - } - } - i = 0; - if(first) { - decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); - first = false; - } - } - - decoder->protected_->state = FLAC__STREAM_DECODER_READ_METADATA; - return true; -} - -FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) -{ - FLAC__bool is_last; - FLAC__uint32 i, x, type, length; - - FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); - - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_IS_LAST_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - is_last = x? true : false; - - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &type, FLAC__STREAM_METADATA_TYPE_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &length, FLAC__STREAM_METADATA_LENGTH_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - if(type == FLAC__METADATA_TYPE_STREAMINFO) { - if(!read_metadata_streaminfo_(decoder, is_last, length)) - return false; - - decoder->private_->has_stream_info = true; - if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO]) - decoder->private_->metadata_callback(decoder, &decoder->private_->stream_info, decoder->private_->client_data); - } - else if(type == FLAC__METADATA_TYPE_SEEKTABLE) { - if(!read_metadata_seektable_(decoder, is_last, length)) - return false; - - decoder->private_->has_seek_table = true; - if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_SEEKTABLE]) - decoder->private_->metadata_callback(decoder, &decoder->private_->seek_table, decoder->private_->client_data); - } - else { - FLAC__bool skip_it = !decoder->private_->metadata_filter[type]; - unsigned real_length = length; - FLAC__StreamMetadata block; - - block.is_last = is_last; - block.type = (FLAC__MetadataType)type; - block.length = length; - - if(type == FLAC__METADATA_TYPE_APPLICATION) { - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - real_length -= FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8; - - if(decoder->private_->metadata_filter_ids_count > 0 && has_id_filtered_(decoder, block.data.application.id)) - skip_it = !skip_it; - } - - if(skip_it) { - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, real_length, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - } - else { - switch(type) { - case FLAC__METADATA_TYPE_PADDING: - /* skip the padding bytes */ - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, real_length, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - break; - case FLAC__METADATA_TYPE_APPLICATION: - /* remember, we read the ID already */ - if(real_length > 0) { - if(0 == (block.data.application.data = (FLAC__byte*)malloc(real_length))) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.data, real_length, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - } - else - block.data.application.data = 0; - break; - case FLAC__METADATA_TYPE_VORBIS_COMMENT: - if(!read_metadata_vorbiscomment_(decoder, &block.data.vorbis_comment)) - return false; - break; - case FLAC__METADATA_TYPE_CUESHEET: - if(!read_metadata_cuesheet_(decoder, &block.data.cue_sheet)) - return false; - break; - case FLAC__METADATA_TYPE_STREAMINFO: - case FLAC__METADATA_TYPE_SEEKTABLE: - FLAC__ASSERT(0); - break; - default: - if(real_length > 0) { - if(0 == (block.data.unknown.data = (FLAC__byte*)malloc(real_length))) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.unknown.data, real_length, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - } - else - block.data.unknown.data = 0; - break; - } - decoder->private_->metadata_callback(decoder, &block, decoder->private_->client_data); - - /* now we have to free any malloc'ed data in the block */ - switch(type) { - case FLAC__METADATA_TYPE_PADDING: - break; - case FLAC__METADATA_TYPE_APPLICATION: - if(0 != block.data.application.data) - free(block.data.application.data); - break; - case FLAC__METADATA_TYPE_VORBIS_COMMENT: - if(0 != block.data.vorbis_comment.vendor_string.entry) - free(block.data.vorbis_comment.vendor_string.entry); - if(block.data.vorbis_comment.num_comments > 0) - for(i = 0; i < block.data.vorbis_comment.num_comments; i++) - if(0 != block.data.vorbis_comment.comments[i].entry) - free(block.data.vorbis_comment.comments[i].entry); - if(0 != block.data.vorbis_comment.comments) - free(block.data.vorbis_comment.comments); - break; - case FLAC__METADATA_TYPE_CUESHEET: - if(block.data.cue_sheet.num_tracks > 0) - 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); - if(0 != block.data.cue_sheet.tracks) - free(block.data.cue_sheet.tracks); - break; - case FLAC__METADATA_TYPE_STREAMINFO: - case FLAC__METADATA_TYPE_SEEKTABLE: - FLAC__ASSERT(0); - default: - if(0 != block.data.unknown.data) - free(block.data.unknown.data); - break; - } - } - } - - if(is_last) - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - - return true; -} - -FLAC__bool read_metadata_streaminfo_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length) -{ - FLAC__uint32 x; - unsigned bits, used_bits = 0; - - FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); - - decoder->private_->stream_info.type = FLAC__METADATA_TYPE_STREAMINFO; - decoder->private_->stream_info.is_last = is_last; - decoder->private_->stream_info.length = length; - - bits = FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN; - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, bits, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - decoder->private_->stream_info.data.stream_info.min_blocksize = x; - used_bits += bits; - - bits = FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN; - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - decoder->private_->stream_info.data.stream_info.max_blocksize = x; - used_bits += bits; - - bits = FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN; - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - decoder->private_->stream_info.data.stream_info.min_framesize = x; - used_bits += bits; - - bits = FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN; - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - decoder->private_->stream_info.data.stream_info.max_framesize = x; - used_bits += bits; - - bits = FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN; - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - decoder->private_->stream_info.data.stream_info.sample_rate = x; - used_bits += bits; - - bits = FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN; - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - decoder->private_->stream_info.data.stream_info.channels = x+1; - used_bits += bits; - - bits = FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN; - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - decoder->private_->stream_info.data.stream_info.bits_per_sample = x+1; - used_bits += bits; - - bits = FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN; - if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &decoder->private_->stream_info.data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - used_bits += bits; - - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, decoder->private_->stream_info.data.stream_info.md5sum, 16, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - used_bits += 16*8; - - /* skip the rest of the block */ - FLAC__ASSERT(used_bits % 8 == 0); - length -= (used_bits / 8); - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, length, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - return true; -} - -FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length) -{ - FLAC__uint32 i, x; - FLAC__uint64 xx; - - FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); - - decoder->private_->seek_table.type = FLAC__METADATA_TYPE_SEEKTABLE; - decoder->private_->seek_table.is_last = is_last; - decoder->private_->seek_table.length = length; - - decoder->private_->seek_table.data.seek_table.num_points = length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; - - /* use realloc since we may pass through here several times (e.g. after seeking) */ - if(0 == (decoder->private_->seek_table.data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)realloc(decoder->private_->seek_table.data.seek_table.points, decoder->private_->seek_table.data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint)))) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - for(i = 0; i < decoder->private_->seek_table.data.seek_table.num_points; i++) { - if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - decoder->private_->seek_table.data.seek_table.points[i].sample_number = xx; - - if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - decoder->private_->seek_table.data.seek_table.points[i].stream_offset = xx; - - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - decoder->private_->seek_table.data.seek_table.points[i].frame_samples = x; - } - length -= (decoder->private_->seek_table.data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH); - /* if there is a partial point left, skip over it */ - if(length > 0) { - /*@@@ do an error_callback() here? there's an argument for either way */ - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, length, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - } - - return true; -} - -FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj) -{ - FLAC__uint32 i; - - FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); - - /* read vendor string */ - FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); - if(!FLAC__bitbuffer_read_raw_uint32_little_endian(decoder->private_->input, &obj->vendor_string.length, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - if(obj->vendor_string.length > 0) { - if(0 == (obj->vendor_string.entry = (FLAC__byte*)malloc(obj->vendor_string.length))) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, obj->vendor_string.entry, obj->vendor_string.length, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - } - else - obj->vendor_string.entry = 0; - - /* read num comments */ - FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN == 32); - if(!FLAC__bitbuffer_read_raw_uint32_little_endian(decoder->private_->input, &obj->num_comments, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - /* read comments */ - if(obj->num_comments > 0) { - if(0 == (obj->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)malloc(obj->num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - for(i = 0; i < obj->num_comments; i++) { - FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); - if(!FLAC__bitbuffer_read_raw_uint32_little_endian(decoder->private_->input, &obj->comments[i].length, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - if(obj->comments[i].length > 0) { - if(0 == (obj->comments[i].entry = (FLAC__byte*)malloc(obj->comments[i].length))) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, obj->comments[i].entry, obj->comments[i].length, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - } - else - obj->comments[i].entry = 0; - } - } - else { - obj->comments = 0; - } - - return true; -} - -FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj) -{ - FLAC__uint32 i, j, x; - - FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); - - memset(obj, 0, sizeof(FLAC__StreamMetadata_CueSheet)); - - FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)obj->media_catalog_number, FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN/8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &obj->lead_in, FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - obj->is_cd = x? true : false; - - if(!FLAC__bitbuffer_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - obj->num_tracks = x; - - if(obj->num_tracks > 0) { - if(0 == (obj->tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc(obj->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - for(i = 0; i < obj->num_tracks; i++) { - FLAC__StreamMetadata_CueSheet_Track *track = &obj->tracks[i]; - if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &track->offset, FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - track->number = (FLAC__byte)x; - - FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)track->isrc, FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN/8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - track->type = x; - - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - track->pre_emphasis = x; - - if(!FLAC__bitbuffer_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - track->num_indices = (FLAC__byte)x; - - if(track->num_indices > 0) { - if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)calloc(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - for(j = 0; j < track->num_indices; j++) { - FLAC__StreamMetadata_CueSheet_Index *index = &track->indices[j]; - if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &index->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - index->number = (FLAC__byte)x; - - if(!FLAC__bitbuffer_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - } - } - } - } - - return true; -} - -FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder) -{ - FLAC__uint32 x; - unsigned i, skip; - - /* skip the version and flags bytes */ - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 24, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - /* get the size (in bytes) to skip */ - skip = 0; - for(i = 0; i < 4; i++) { - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - skip <<= 7; - skip |= (x & 0x7f); - } - /* skip the rest of the tag */ - if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, skip, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - return true; -} - -FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder) -{ - FLAC__uint32 x; - FLAC__bool first = true; - - /* If we know the total number of samples in the stream, stop if we've read that many. */ - /* This will stop us, for example, from wasting time trying to sync on an ID3V1 tag. */ - if(decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.total_samples) { - if(decoder->private_->samples_decoded >= decoder->private_->stream_info.data.stream_info.total_samples) { - decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM; - return true; - } - } - - /* make sure we're byte aligned */ - if(!FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)) { - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__bitbuffer_bits_left_for_byte_alignment(decoder->private_->input), read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - } - - while(1) { - if(decoder->private_->cached) { - x = (FLAC__uint32)decoder->private_->lookahead; - decoder->private_->cached = false; - } - else { - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - } - if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ - decoder->private_->header_warmup[0] = (FLAC__byte)x; - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - /* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */ - /* else we have to check if the second byte is the end of a sync code */ - if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ - decoder->private_->lookahead = (FLAC__byte)x; - decoder->private_->cached = true; - } - else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */ - decoder->private_->header_warmup[1] = (FLAC__byte)x; - decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME; - return true; - } - } - if(first) { - decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); - first = false; - } - } - - return true; -} - -FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FLAC__bool do_full_decode) -{ - unsigned channel; - unsigned i; - FLAC__int32 mid, side, left, right; - FLAC__uint16 frame_crc; /* the one we calculate from the input stream */ - FLAC__uint32 x; - - *got_a_frame = false; - - /* init the CRC */ - frame_crc = 0; - FLAC__CRC16_UPDATE(decoder->private_->header_warmup[0], frame_crc); - FLAC__CRC16_UPDATE(decoder->private_->header_warmup[1], frame_crc); - FLAC__bitbuffer_reset_read_crc16(decoder->private_->input, frame_crc); - - if(!read_frame_header_(decoder)) - return false; - if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) - return true; - if(!allocate_output_(decoder, decoder->private_->frame.header.blocksize, decoder->private_->frame.header.channels)) - return false; - for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) { - /* - * first figure the correct bits-per-sample of the subframe - */ - unsigned bps = decoder->private_->frame.header.bits_per_sample; - switch(decoder->private_->frame.header.channel_assignment) { - case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: - /* no adjustment needed */ - break; - case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: - FLAC__ASSERT(decoder->private_->frame.header.channels == 2); - if(channel == 1) - bps++; - break; - case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE: - FLAC__ASSERT(decoder->private_->frame.header.channels == 2); - if(channel == 0) - bps++; - break; - case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE: - FLAC__ASSERT(decoder->private_->frame.header.channels == 2); - if(channel == 1) - bps++; - break; - default: - FLAC__ASSERT(0); - } - /* - * now read it - */ - if(!read_subframe_(decoder, channel, bps, do_full_decode)) - return false; - if(decoder->protected_->state != FLAC__STREAM_DECODER_READ_FRAME) { - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; - } - } - if(!read_zero_padding_(decoder)) - return false; - - /* - * Read the frame CRC-16 from the footer and check - */ - frame_crc = FLAC__bitbuffer_get_read_crc16(decoder->private_->input); - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__FRAME_FOOTER_CRC_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - if(frame_crc == (FLAC__uint16)x) { - 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++) { - mid = decoder->private_->output[0][i]; - side = decoder->private_->output[1][i]; - mid <<= 1; - if(side & 1) /* i.e. if 'side' is odd... */ - mid++; - left = mid + side; - right = mid - side; - decoder->private_->output[0][i] = left >> 1; - decoder->private_->output[1][i] = right >> 1; - } - break; - default: - FLAC__ASSERT(0); - break; - } - } - } - else { - /* Bad frame, emit error and zero the output signal */ - decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH, decoder->private_->client_data); - 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); - } - } - } - - *got_a_frame = true; - - /* 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; - - /* write it */ - if(do_full_decode) { - if(decoder->private_->write_callback(decoder, &decoder->private_->frame, (const FLAC__int32 * const *)decoder->private_->output, decoder->private_->client_data) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE) - return false; - } - - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; -} - -FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder) -{ - FLAC__uint32 x; - FLAC__uint64 xx; - unsigned i, blocksize_hint = 0, sample_rate_hint = 0; - FLAC__byte crc8, raw_header[16]; /* MAGIC NUMBER based on the maximum frame header size, including CRC */ - unsigned raw_header_len; - FLAC__bool is_unparseable = false; - const FLAC__bool is_known_variable_blocksize_stream = (decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.min_blocksize != decoder->private_->stream_info.data.stream_info.max_blocksize); - const FLAC__bool is_known_fixed_blocksize_stream = (decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.min_blocksize == decoder->private_->stream_info.data.stream_info.max_blocksize); - - FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); - - /* init the raw header with the saved bits from synchronization */ - raw_header[0] = decoder->private_->header_warmup[0]; - raw_header[1] = decoder->private_->header_warmup[1]; - raw_header_len = 2; - - /* - * check to make sure that the reserved bits are 0 - */ - if(raw_header[1] & 0x03) { /* MAGIC NUMBER */ - is_unparseable = true; - } - - /* - * Note that along the way as we read the header, we look for a sync - * code inside. If we find one it would indicate that our original - * sync was bad since there cannot be a sync code in a valid header. - */ - - /* - * read in the raw header as bytes so we can CRC it, and parse it on the way - */ - for(i = 0; i < 2; i++) { - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ - /* if we get here it means our original sync was erroneous since the sync code cannot appear in the header */ - decoder->private_->lookahead = (FLAC__byte)x; - decoder->private_->cached = true; - decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; - } - raw_header[raw_header_len++] = (FLAC__byte)x; - } - - switch(x = raw_header[2] >> 4) { - case 0: - if(is_known_fixed_blocksize_stream) - decoder->private_->frame.header.blocksize = decoder->private_->stream_info.data.stream_info.min_blocksize; - else - is_unparseable = true; - break; - case 1: - decoder->private_->frame.header.blocksize = 192; - break; - case 2: - case 3: - case 4: - case 5: - decoder->private_->frame.header.blocksize = 576 << (x-2); - break; - case 6: - case 7: - blocksize_hint = x; - break; - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - decoder->private_->frame.header.blocksize = 256 << (x-8); - break; - default: - FLAC__ASSERT(0); - break; - } - - switch(x = raw_header[2] & 0x0f) { - case 0: - if(decoder->private_->has_stream_info) - decoder->private_->frame.header.sample_rate = decoder->private_->stream_info.data.stream_info.sample_rate; - else - is_unparseable = true; - break; - case 1: - case 2: - case 3: - is_unparseable = true; - break; - case 4: - decoder->private_->frame.header.sample_rate = 8000; - break; - case 5: - decoder->private_->frame.header.sample_rate = 16000; - break; - case 6: - decoder->private_->frame.header.sample_rate = 22050; - break; - case 7: - decoder->private_->frame.header.sample_rate = 24000; - break; - case 8: - decoder->private_->frame.header.sample_rate = 32000; - break; - case 9: - decoder->private_->frame.header.sample_rate = 44100; - break; - case 10: - decoder->private_->frame.header.sample_rate = 48000; - break; - case 11: - decoder->private_->frame.header.sample_rate = 96000; - break; - case 12: - case 13: - case 14: - sample_rate_hint = x; - break; - case 15: - decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; - default: - FLAC__ASSERT(0); - } - - x = (unsigned)(raw_header[3] >> 4); - if(x & 8) { - decoder->private_->frame.header.channels = 2; - switch(x & 7) { - case 0: - decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE; - break; - case 1: - decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE; - break; - case 2: - decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_MID_SIDE; - break; - default: - is_unparseable = true; - break; - } - } - else { - decoder->private_->frame.header.channels = (unsigned)x + 1; - decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; - } - - switch(x = (unsigned)(raw_header[3] & 0x0e) >> 1) { - case 0: - if(decoder->private_->has_stream_info) - decoder->private_->frame.header.bits_per_sample = decoder->private_->stream_info.data.stream_info.bits_per_sample; - else - is_unparseable = true; - break; - case 1: - decoder->private_->frame.header.bits_per_sample = 8; - break; - case 2: - decoder->private_->frame.header.bits_per_sample = 12; - break; - case 4: - decoder->private_->frame.header.bits_per_sample = 16; - break; - case 5: - decoder->private_->frame.header.bits_per_sample = 20; - break; - case 6: - decoder->private_->frame.header.bits_per_sample = 24; - break; - case 3: - case 7: - is_unparseable = true; - break; - default: - FLAC__ASSERT(0); - break; - } - - if(raw_header[3] & 0x01) { /* this should be a zero padding bit */ - decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; - } - - if(blocksize_hint && is_known_variable_blocksize_stream) { - if(!FLAC__bitbuffer_read_utf8_uint64(decoder->private_->input, &xx, read_callback_, decoder, raw_header, &raw_header_len)) - return false; /* the read_callback_ sets the state for us */ - if(xx == FLAC__U64L(0xffffffffffffffff)) { /* i.e. non-UTF8 code... */ - decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */ - decoder->private_->cached = true; - decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; - } - decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER; - decoder->private_->frame.header.number.sample_number = xx; - } - else { - if(!FLAC__bitbuffer_read_utf8_uint32(decoder->private_->input, &x, read_callback_, decoder, raw_header, &raw_header_len)) - return false; /* the read_callback_ sets the state for us */ - if(x == 0xffffffff) { /* i.e. non-UTF8 code... */ - decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */ - decoder->private_->cached = true; - decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; - } - decoder->private_->last_frame_number = x; - decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER; - if(blocksize_hint) { - if(decoder->private_->has_stream_info) - decoder->private_->frame.header.number.sample_number = (FLAC__int64)decoder->private_->stream_info.data.stream_info.min_blocksize * (FLAC__int64)x; - else - is_unparseable = true; - } - else - decoder->private_->frame.header.number.sample_number = (FLAC__int64)decoder->private_->frame.header.blocksize * (FLAC__int64)x; - } - - if(blocksize_hint) { - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - raw_header[raw_header_len++] = (FLAC__byte)x; - if(blocksize_hint == 7) { - FLAC__uint32 _x; - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &_x, 8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - raw_header[raw_header_len++] = (FLAC__byte)_x; - x = (x << 8) | _x; - } - decoder->private_->frame.header.blocksize = x+1; - } - - if(sample_rate_hint) { - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - raw_header[raw_header_len++] = (FLAC__byte)x; - if(sample_rate_hint != 12) { - FLAC__uint32 _x; - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &_x, 8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - raw_header[raw_header_len++] = (FLAC__byte)_x; - x = (x << 8) | _x; - } - if(sample_rate_hint == 12) - decoder->private_->frame.header.sample_rate = x*1000; - else if(sample_rate_hint == 13) - decoder->private_->frame.header.sample_rate = x; - else - decoder->private_->frame.header.sample_rate = x*10; - } - - /* read the CRC-8 byte */ - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - crc8 = (FLAC__byte)x; - - if(FLAC__crc8(raw_header, raw_header_len) != crc8) { - decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; - } - - if(is_unparseable) { - decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; - return false; - } - - return true; -} - -FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode) -{ - FLAC__uint32 x; - FLAC__bool wasted_bits; - - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) /* MAGIC NUMBER */ - return false; /* the read_callback_ sets the state for us */ - - wasted_bits = (x & 1); - x &= 0xfe; - - if(wasted_bits) { - unsigned u; - if(!FLAC__bitbuffer_read_unary_unsigned(decoder->private_->input, &u, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - decoder->private_->frame.subframes[channel].wasted_bits = u+1; - bps -= decoder->private_->frame.subframes[channel].wasted_bits; - } - else - decoder->private_->frame.subframes[channel].wasted_bits = 0; - - /* - * Lots of magic numbers here - */ - if(x & 0x80) { - decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; - } - else if(x == 0) { - if(!read_subframe_constant_(decoder, channel, bps, do_full_decode)) - return false; - } - else if(x == 2) { - if(!read_subframe_verbatim_(decoder, channel, bps, do_full_decode)) - return false; - } - else if(x < 16) { - decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; - return false; - } - else if(x <= 24) { - if(!read_subframe_fixed_(decoder, channel, bps, (x>>1)&7, do_full_decode)) - return false; - } - else if(x < 64) { - decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; - return false; - } - else { - if(!read_subframe_lpc_(decoder, channel, bps, ((x>>1)&31)+1, do_full_decode)) - return false; - } - - if(wasted_bits && do_full_decode) { - unsigned i; - x = decoder->private_->frame.subframes[channel].wasted_bits; - for(i = 0; i < decoder->private_->frame.header.blocksize; i++) - decoder->private_->output[channel][i] <<= x; - } - - return true; -} - -FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode) -{ - FLAC__Subframe_Constant *subframe = &decoder->private_->frame.subframes[channel].data.constant; - FLAC__int32 x; - unsigned i; - FLAC__int32 *output = decoder->private_->output[channel]; - - decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_CONSTANT; - - if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &x, bps, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - - subframe->value = x; - - /* decode the subframe */ - if(do_full_decode) { - for(i = 0; i < decoder->private_->frame.header.blocksize; i++) - output[i] = x; - } - - return true; -} - -FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode) -{ - FLAC__Subframe_Fixed *subframe = &decoder->private_->frame.subframes[channel].data.fixed; - FLAC__int32 i32; - FLAC__uint32 u32; - unsigned u; - - decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_FIXED; - - subframe->residual = decoder->private_->residual[channel]; - subframe->order = order; - - /* read warm-up samples */ - for(u = 0; u < order; u++) { - if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, bps, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - subframe->warmup[u] = i32; - } - - /* read entropy coding method info */ - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - subframe->entropy_coding_method.type = (FLAC__EntropyCodingMethodType)u32; - switch(subframe->entropy_coding_method.type) { - case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - subframe->entropy_coding_method.data.partitioned_rice.order = u32; - subframe->entropy_coding_method.data.partitioned_rice.contents = &decoder->private_->partitioned_rice_contents[channel]; - break; - default: - decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; - return false; - } - - /* read residual */ - switch(subframe->entropy_coding_method.type) { - case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: - if(!read_residual_partitioned_rice_(decoder, order, subframe->entropy_coding_method.data.partitioned_rice.order, &decoder->private_->partitioned_rice_contents[channel], decoder->private_->residual[channel])) - return false; - break; - default: - FLAC__ASSERT(0); - } - - /* 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); - } - - return true; -} - -FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode) -{ - FLAC__Subframe_LPC *subframe = &decoder->private_->frame.subframes[channel].data.lpc; - FLAC__int32 i32; - FLAC__uint32 u32; - unsigned u; - - decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_LPC; - - subframe->residual = decoder->private_->residual[channel]; - subframe->order = order; - - /* read warm-up samples */ - for(u = 0; u < order; u++) { - if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, bps, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - subframe->warmup[u] = i32; - } - - /* read qlp coeff precision */ - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - if(u32 == (1u << FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN) - 1) { - decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; - } - subframe->qlp_coeff_precision = u32+1; - - /* read qlp shift */ - if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - subframe->quantization_level = i32; - - /* read quantized lp coefficiencts */ - for(u = 0; u < order; u++) { - if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, subframe->qlp_coeff_precision, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - subframe->qlp_coeff[u] = i32; - } - - /* read entropy coding method info */ - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - subframe->entropy_coding_method.type = (FLAC__EntropyCodingMethodType)u32; - switch(subframe->entropy_coding_method.type) { - case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - subframe->entropy_coding_method.data.partitioned_rice.order = u32; - subframe->entropy_coding_method.data.partitioned_rice.contents = &decoder->private_->partitioned_rice_contents[channel]; - break; - default: - decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; - return false; - } - - /* read residual */ - switch(subframe->entropy_coding_method.type) { - case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: - if(!read_residual_partitioned_rice_(decoder, order, subframe->entropy_coding_method.data.partitioned_rice.order, &decoder->private_->partitioned_rice_contents[channel], decoder->private_->residual[channel])) - return false; - break; - default: - FLAC__ASSERT(0); - } - - /* 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) { - if(order <= 8) - decoder->private_->local_lpc_restore_signal_16bit_order8(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_16bit(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); - } - - return true; -} - -FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned 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]; - unsigned i; - - decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_VERBATIM; - - subframe->data = residual; - - for(i = 0; i < decoder->private_->frame.header.blocksize; i++) { - if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &x, bps, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - residual[i] = x; - } - - /* decode the subframe */ - if(do_full_decode) - memcpy(decoder->private_->output[channel], subframe->data, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize); - - return true; -} - -FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigned predictor_order, unsigned partition_order, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, FLAC__int32 *residual) -{ - FLAC__uint32 rice_parameter; - int i; - unsigned partition, sample, u; - const unsigned partitions = 1u << partition_order; - const unsigned partition_samples = partition_order > 0? decoder->private_->frame.header.blocksize >> partition_order : decoder->private_->frame.header.blocksize - predictor_order; - - if(!FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order))) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - - sample = 0; - for(partition = 0; partition < partitions; partition++) { - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - partitioned_rice_contents->parameters[partition] = rice_parameter; - if(rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) { -#ifdef FLAC__SYMMETRIC_RICE - for(u = (partition_order == 0 || partition > 0)? 0 : predictor_order; u < partition_samples; u++, sample++) { - if(!FLAC__bitbuffer_read_symmetric_rice_signed(decoder->private_->input, &i, rice_parameter, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - residual[sample] = i; - } -#else - u = (partition_order == 0 || partition > 0)? partition_samples : partition_samples - predictor_order; - if(!FLAC__bitbuffer_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - sample += u; -#endif - } - else { - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - partitioned_rice_contents->raw_bits[partition] = rice_parameter; - for(u = (partition_order == 0 || partition > 0)? 0 : predictor_order; u < partition_samples; u++, sample++) { - if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i, rice_parameter, read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - residual[sample] = i; - } - } - } - - return true; -} - -FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder) -{ - if(!FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)) { - FLAC__uint32 zero = 0; - if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &zero, FLAC__bitbuffer_bits_left_for_byte_alignment(decoder->private_->input), read_callback_, decoder)) - return false; /* the read_callback_ sets the state for us */ - if(zero != 0) { - decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); - decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - } - } - return true; -} - -FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_data) -{ - FLAC__StreamDecoder *decoder = (FLAC__StreamDecoder *)client_data; - FLAC__StreamDecoderReadStatus status; - - status = decoder->private_->read_callback(decoder, buffer, bytes, decoder->private_->client_data); - if(status == FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM) - decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM; - else if(status == FLAC__STREAM_DECODER_READ_STATUS_ABORT) - decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED; - return status == FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; -} +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#include +#include /* for malloc() */ +#include /* for memset/memcpy() */ +#include "FLAC/assert.h" +#include "protected/stream_decoder.h" +#include "private/bitbuffer.h" +#include "private/bitmath.h" +#include "private/cpu.h" +#include "private/crc.h" +#include "private/fixed.h" +#include "private/format.h" +#include "private/lpc.h" +#include "private/memory.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef max +#undef max +#endif +#define max(a,b) ((a)>(b)?(a):(b)) + +/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ +#ifdef _MSC_VER +#define FLAC__U64L(x) x +#else +#define FLAC__U64L(x) x##LLU +#endif + +/*********************************************************************** + * + * Private static data + * + ***********************************************************************/ + +static FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' }; + +/*********************************************************************** + * + * Private class method prototypes + * + ***********************************************************************/ + +static void set_defaults_(FLAC__StreamDecoder *decoder); +static FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels); +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); +static FLAC__bool read_metadata_streaminfo_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length); +static FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length); +static FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj); +static FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj); +static FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder); +static FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder); +static FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FLAC__bool do_full_decode); +static FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder); +static FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode); +static FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode); +static FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode); +static FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode); +static FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode); +static FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigned predictor_order, unsigned partition_order, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, FLAC__int32 *residual); +static FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder); +static FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_data); + +/*********************************************************************** + * + * Private class data + * + ***********************************************************************/ + +typedef struct FLAC__StreamDecoderPrivate { + FLAC__StreamDecoderReadCallback read_callback; + 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[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); + /* generic 64-bit datapath: */ + void (*local_lpc_restore_signal_64bit)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned 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[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned 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), AND order <= 8: */ + void (*local_lpc_restore_signal_16bit_order8)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); + void *client_data; + FLAC__BitBuffer *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__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents[FLAC__MAX_CHANNELS]; + unsigned output_capacity, output_channels; + FLAC__uint32 last_frame_number; + FLAC__uint32 last_block_size; + FLAC__uint64 samples_decoded; + FLAC__bool has_stream_info, has_seek_table; + FLAC__StreamMetadata stream_info; + FLAC__StreamMetadata seek_table; + FLAC__bool metadata_filter[128]; /* MAGIC number 128 == total number of metadata block types == 1 << 7 */ + FLAC__byte *metadata_filter_ids; + unsigned 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 */ + FLAC__int32 *residual_unaligned[FLAC__MAX_CHANNELS]; +} FLAC__StreamDecoderPrivate; + +/*********************************************************************** + * + * Public static class data + * + ***********************************************************************/ + +FLAC_API const char * const FLAC__StreamDecoderStateString[] = { + "FLAC__STREAM_DECODER_SEARCH_FOR_METADATA", + "FLAC__STREAM_DECODER_READ_METADATA", + "FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC", + "FLAC__STREAM_DECODER_READ_FRAME", + "FLAC__STREAM_DECODER_END_OF_STREAM", + "FLAC__STREAM_DECODER_ABORTED", + "FLAC__STREAM_DECODER_UNPARSEABLE_STREAM", + "FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR", + "FLAC__STREAM_DECODER_ALREADY_INITIALIZED", + "FLAC__STREAM_DECODER_INVALID_CALLBACK", + "FLAC__STREAM_DECODER_UNINITIALIZED" +}; + +FLAC_API const char * const FLAC__StreamDecoderReadStatusString[] = { + "FLAC__STREAM_DECODER_READ_STATUS_CONTINUE", + "FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM", + "FLAC__STREAM_DECODER_READ_STATUS_ABORT" +}; + +FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[] = { + "FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE", + "FLAC__STREAM_DECODER_WRITE_STATUS_ABORT" +}; + +FLAC_API const char * const FLAC__StreamDecoderErrorStatusString[] = { + "FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC", + "FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER", + "FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH" +}; + +/*********************************************************************** + * + * Class constructor/destructor + * + ***********************************************************************/ +FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new() +{ + FLAC__StreamDecoder *decoder; + unsigned i; + + FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */ + + decoder = (FLAC__StreamDecoder*)calloc(1, sizeof(FLAC__StreamDecoder)); + if(decoder == 0) { + return 0; + } + + decoder->protected_ = (FLAC__StreamDecoderProtected*)calloc(1, sizeof(FLAC__StreamDecoderProtected)); + if(decoder->protected_ == 0) { + free(decoder); + return 0; + } + + decoder->private_ = (FLAC__StreamDecoderPrivate*)calloc(1, sizeof(FLAC__StreamDecoderPrivate)); + if(decoder->private_ == 0) { + free(decoder->protected_); + free(decoder); + return 0; + } + + decoder->private_->input = FLAC__bitbuffer_new(); + if(decoder->private_->input == 0) { + free(decoder->private_); + free(decoder->protected_); + free(decoder); + return 0; + } + + decoder->private_->metadata_filter_ids_capacity = 16; + if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)malloc((FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) * decoder->private_->metadata_filter_ids_capacity))) { + FLAC__bitbuffer_delete(decoder->private_->input); + free(decoder->private_); + free(decoder->protected_); + free(decoder); + return 0; + } + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) { + decoder->private_->output[i] = 0; + decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0; + } + + decoder->private_->output_capacity = 0; + decoder->private_->output_channels = 0; + decoder->private_->has_seek_table = false; + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) + FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&decoder->private_->partitioned_rice_contents[i]); + + set_defaults_(decoder); + + decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED; + + return decoder; +} + +FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder) +{ + unsigned i; + + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->private_->input); + + FLAC__stream_decoder_finish(decoder); + + if(0 != decoder->private_->metadata_filter_ids) + free(decoder->private_->metadata_filter_ids); + + FLAC__bitbuffer_delete(decoder->private_->input); + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) + FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&decoder->private_->partitioned_rice_contents[i]); + + free(decoder->private_); + free(decoder->protected_); + free(decoder); +} + +/*********************************************************************** + * + * Public class methods + * + ***********************************************************************/ + +FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return decoder->protected_->state = FLAC__STREAM_DECODER_ALREADY_INITIALIZED; + + if(0 == decoder->private_->read_callback || 0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback) + return decoder->protected_->state = FLAC__STREAM_DECODER_INVALID_CALLBACK; + + if(!FLAC__bitbuffer_init(decoder->private_->input)) + return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + + decoder->private_->last_frame_number = 0; + decoder->private_->last_block_size = 0; + decoder->private_->samples_decoded = 0; + decoder->private_->has_stream_info = false; + decoder->private_->cached = false; + + /* + * 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; + decoder->private_->local_lpc_restore_signal_16bit_order8 = 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 + if(decoder->private_->cpuinfo.data.ia32.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; + decoder->private_->local_lpc_restore_signal_16bit_order8 = 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; + decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ia32; + } +#endif +#elif defined FLAC__CPU_PPC + FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_PPC); + if(decoder->private_->cpuinfo.data.ppc.altivec) { + decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ppc_altivec_16; + decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ppc_altivec_16_order8; + } +#endif + } +#endif + + if(!FLAC__stream_decoder_reset(decoder)) + return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + + return decoder->protected_->state; +} + +FLAC_API void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder) +{ + unsigned i; + FLAC__ASSERT(0 != decoder); + if(decoder->protected_->state == FLAC__STREAM_DECODER_UNINITIALIZED) + return; + if(0 != decoder->private_->seek_table.data.seek_table.points) { + free(decoder->private_->seek_table.data.seek_table.points); + decoder->private_->seek_table.data.seek_table.points = 0; + decoder->private_->has_seek_table = false; + } + FLAC__bitbuffer_free(decoder->private_->input); + for(i = 0; i < FLAC__MAX_CHANNELS; i++) { + /* WATCHOUT: + * FLAC__lpc_restore_signal_asm_ia32_mmx() requires that the + * output arrays have a buffer of up to 3 zeroes in front + * (at negative indices) for alignment purposes; we use 4 + * to keep the data well-aligned. + */ + if(0 != decoder->private_->output[i]) { + free(decoder->private_->output[i]-4); + decoder->private_->output[i] = 0; + } + if(0 != decoder->private_->residual_unaligned[i]) { + free(decoder->private_->residual_unaligned[i]); + decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0; + } + } + decoder->private_->output_capacity = 0; + decoder->private_->output_channels = 0; + + set_defaults_(decoder); + + decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_read_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadCallback value) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + decoder->private_->read_callback = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_write_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderWriteCallback value) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + decoder->private_->write_callback = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderMetadataCallback value) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + decoder->private_->metadata_callback = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_error_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorCallback value) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + decoder->private_->error_callback = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_client_data(FLAC__StreamDecoder *decoder, void *value) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + decoder->private_->client_data = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond(FLAC__StreamDecoder *decoder, FLAC__MetadataType type) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + FLAC__ASSERT((unsigned)type <= FLAC__MAX_METADATA_TYPE_CODE); + /* double protection */ + if((unsigned)type > FLAC__MAX_METADATA_TYPE_CODE) + return false; + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + decoder->private_->metadata_filter[type] = true; + if(type == FLAC__METADATA_TYPE_APPLICATION) + decoder->private_->metadata_filter_ids_count = 0; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + FLAC__ASSERT(0 != id); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + + if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_APPLICATION]) + return true; + + FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids); + + if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) { + if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)realloc(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity * 2))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + decoder->private_->metadata_filter_ids_capacity *= 2; + } + + memcpy(decoder->private_->metadata_filter_ids + decoder->private_->metadata_filter_ids_count * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8)); + decoder->private_->metadata_filter_ids_count++; + + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_all(FLAC__StreamDecoder *decoder) +{ + unsigned i; + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + for(i = 0; i < sizeof(decoder->private_->metadata_filter) / sizeof(decoder->private_->metadata_filter[0]); i++) + decoder->private_->metadata_filter[i] = true; + decoder->private_->metadata_filter_ids_count = 0; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore(FLAC__StreamDecoder *decoder, FLAC__MetadataType type) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + FLAC__ASSERT((unsigned)type <= FLAC__MAX_METADATA_TYPE_CODE); + /* double protection */ + if((unsigned)type > FLAC__MAX_METADATA_TYPE_CODE) + return false; + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + decoder->private_->metadata_filter[type] = false; + if(type == FLAC__METADATA_TYPE_APPLICATION) + decoder->private_->metadata_filter_ids_count = 0; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + FLAC__ASSERT(0 != id); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + + if(!decoder->private_->metadata_filter[FLAC__METADATA_TYPE_APPLICATION]) + return true; + + FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids); + + if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) { + if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)realloc(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity * 2))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + decoder->private_->metadata_filter_ids_capacity *= 2; + } + + memcpy(decoder->private_->metadata_filter_ids + decoder->private_->metadata_filter_ids_count * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8)); + decoder->private_->metadata_filter_ids_count++; + + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_all(FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + memset(decoder->private_->metadata_filter, 0, sizeof(decoder->private_->metadata_filter)); + decoder->private_->metadata_filter_ids_count = 0; + return true; +} + +FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->state; +} + +FLAC_API const char *FLAC__stream_decoder_get_resolved_state_string(const FLAC__StreamDecoder *decoder) +{ + return FLAC__StreamDecoderStateString[decoder->protected_->state]; +} + +FLAC_API unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->channels; +} + +FLAC_API FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->channel_assignment; +} + +FLAC_API unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->bits_per_sample; +} + +FLAC_API unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->sample_rate; +} + +FLAC_API unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->blocksize; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + + if(!FLAC__bitbuffer_clear(decoder->private_->input)) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + decoder->private_->last_frame_number = 0; + decoder->private_->last_block_size = 0; + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + + if(!FLAC__stream_decoder_flush(decoder)) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA; + + decoder->private_->samples_decoded = 0; + + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *decoder) +{ + FLAC__bool got_a_frame; + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + + while(1) { + switch(decoder->protected_->state) { + case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: + if(!find_metadata_(decoder)) + return false; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_READ_METADATA: + if(!read_metadata_(decoder)) + return false; /* above function sets the status for us */ + else + return true; + case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: + if(!frame_sync_(decoder)) + return true; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_READ_FRAME: + if(!read_frame_(decoder, &got_a_frame, /*do_full_decode=*/true)) + return false; /* above function sets the status for us */ + if(got_a_frame) + return true; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_END_OF_STREAM: + case FLAC__STREAM_DECODER_ABORTED: + return true; + default: + FLAC__ASSERT(0); + return false; + } + } +} + +FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_metadata(FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + + while(1) { + switch(decoder->protected_->state) { + case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: + if(!find_metadata_(decoder)) + return false; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_READ_METADATA: + if(!read_metadata_(decoder)) + return false; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: + case FLAC__STREAM_DECODER_READ_FRAME: + case FLAC__STREAM_DECODER_END_OF_STREAM: + case FLAC__STREAM_DECODER_ABORTED: + return true; + default: + FLAC__ASSERT(0); + return false; + } + } +} + +FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder) +{ + FLAC__bool dummy; + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + + while(1) { + switch(decoder->protected_->state) { + case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: + if(!find_metadata_(decoder)) + return false; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_READ_METADATA: + if(!read_metadata_(decoder)) + return false; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: + if(!frame_sync_(decoder)) + return true; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_READ_FRAME: + if(!read_frame_(decoder, &dummy, /*do_full_decode=*/true)) + return false; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_END_OF_STREAM: + case FLAC__STREAM_DECODER_ABORTED: + return true; + default: + FLAC__ASSERT(0); + return false; + } + } +} + +FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder) +{ + FLAC__bool got_a_frame; + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + + while(1) { + switch(decoder->protected_->state) { + case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: + case FLAC__STREAM_DECODER_READ_METADATA: + return false; /* above function sets the status for us */ + case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: + if(!frame_sync_(decoder)) + return true; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_READ_FRAME: + if(!read_frame_(decoder, &got_a_frame, /*do_full_decode=*/false)) + return false; /* above function sets the status for us */ + if(got_a_frame) + return true; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_END_OF_STREAM: + case FLAC__STREAM_DECODER_ABORTED: + return true; + default: + FLAC__ASSERT(0); + return false; + } + } +} + +/*********************************************************************** + * + * Protected class methods + * + ***********************************************************************/ + +unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + return FLAC__bitbuffer_get_input_bytes_unconsumed(decoder->private_->input); +} + +/*********************************************************************** + * + * Private class methods + * + ***********************************************************************/ + +void set_defaults_(FLAC__StreamDecoder *decoder) +{ + decoder->private_->read_callback = 0; + decoder->private_->write_callback = 0; + decoder->private_->metadata_callback = 0; + decoder->private_->error_callback = 0; + decoder->private_->client_data = 0; + + memset(decoder->private_->metadata_filter, 0, sizeof(decoder->private_->metadata_filter)); + decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO] = true; + decoder->private_->metadata_filter_ids_count = 0; +} + +FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels) +{ + unsigned i; + FLAC__int32 *tmp; + + if(size <= decoder->private_->output_capacity && channels <= decoder->private_->output_channels) + return true; + + /* simply using realloc() is not practical because the number of channels may change mid-stream */ + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) { + if(0 != decoder->private_->output[i]) { + free(decoder->private_->output[i]-4); + decoder->private_->output[i] = 0; + } + if(0 != decoder->private_->residual_unaligned[i]) { + free(decoder->private_->residual_unaligned[i]); + decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0; + } + } + + for(i = 0; i < channels; i++) { + /* WATCHOUT: + * FLAC__lpc_restore_signal_asm_ia32_mmx() requires that the + * output arrays have a buffer of up to 3 zeroes in front + * (at negative indices) for alignment purposes; we use 4 + * to keep the data well-aligned. + */ + tmp = (FLAC__int32*)malloc(sizeof(FLAC__int32)*(size+4)); + if(tmp == 0) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + memset(tmp, 0, sizeof(FLAC__int32)*4); + decoder->private_->output[i] = tmp + 4; + + /* WATCHOUT: + * minimum of quadword alignment for PPC vector optimizations is REQUIRED: + */ + if(!FLAC__memory_alloc_aligned_int32_array(size, &decoder->private_->residual_unaligned[i], &decoder->private_->residual[i])) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + } + + decoder->private_->output_capacity = size; + decoder->private_->output_channels = channels; + + return true; +} + +FLAC__bool has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id) +{ + unsigned i; + + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + + for(i = 0; i < decoder->private_->metadata_filter_ids_count; i++) + if(0 == memcmp(decoder->private_->metadata_filter_ids + i * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8))) + return true; + + return false; +} + +FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder) +{ + FLAC__uint32 x; + unsigned i, id; + FLAC__bool first = true; + + FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); + + for(i = id = 0; i < 4; ) { + if(decoder->private_->cached) { + x = (FLAC__uint32)decoder->private_->lookahead; + decoder->private_->cached = false; + } + else { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + } + if(x == FLAC__STREAM_SYNC_STRING[i]) { + first = true; + i++; + id = 0; + continue; + } + if(x == ID3V2_TAG_[id]) { + id++; + i = 0; + if(id == 3) { + if(!skip_id3v2_tag_(decoder)) + return false; /* the read_callback_ sets the state for us */ + } + continue; + } + if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ + decoder->private_->header_warmup[0] = (FLAC__byte)x; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + /* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */ + /* else we have to check if the second byte is the end of a sync code */ + if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ + decoder->private_->lookahead = (FLAC__byte)x; + decoder->private_->cached = true; + } + else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */ + decoder->private_->header_warmup[1] = (FLAC__byte)x; + decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME; + return true; + } + } + i = 0; + if(first) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); + first = false; + } + } + + decoder->protected_->state = FLAC__STREAM_DECODER_READ_METADATA; + return true; +} + +FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) +{ + FLAC__bool is_last; + FLAC__uint32 i, x, type, length; + + FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_IS_LAST_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + is_last = x? true : false; + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &type, FLAC__STREAM_METADATA_TYPE_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &length, FLAC__STREAM_METADATA_LENGTH_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(type == FLAC__METADATA_TYPE_STREAMINFO) { + if(!read_metadata_streaminfo_(decoder, is_last, length)) + return false; + + decoder->private_->has_stream_info = true; + if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO]) + decoder->private_->metadata_callback(decoder, &decoder->private_->stream_info, decoder->private_->client_data); + } + else if(type == FLAC__METADATA_TYPE_SEEKTABLE) { + if(!read_metadata_seektable_(decoder, is_last, length)) + return false; + + decoder->private_->has_seek_table = true; + if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_SEEKTABLE]) + decoder->private_->metadata_callback(decoder, &decoder->private_->seek_table, decoder->private_->client_data); + } + else { + FLAC__bool skip_it = !decoder->private_->metadata_filter[type]; + unsigned real_length = length; + FLAC__StreamMetadata block; + + block.is_last = is_last; + block.type = (FLAC__MetadataType)type; + block.length = length; + + if(type == FLAC__METADATA_TYPE_APPLICATION) { + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + real_length -= FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8; + + if(decoder->private_->metadata_filter_ids_count > 0 && has_id_filtered_(decoder, block.data.application.id)) + skip_it = !skip_it; + } + + if(skip_it) { + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, real_length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + } + else { + switch(type) { + case FLAC__METADATA_TYPE_PADDING: + /* skip the padding bytes */ + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, real_length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + break; + case FLAC__METADATA_TYPE_APPLICATION: + /* remember, we read the ID already */ + if(real_length > 0) { + if(0 == (block.data.application.data = (FLAC__byte*)malloc(real_length))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.data, real_length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + } + else + block.data.application.data = 0; + break; + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + if(!read_metadata_vorbiscomment_(decoder, &block.data.vorbis_comment)) + return false; + break; + case FLAC__METADATA_TYPE_CUESHEET: + if(!read_metadata_cuesheet_(decoder, &block.data.cue_sheet)) + return false; + break; + case FLAC__METADATA_TYPE_STREAMINFO: + case FLAC__METADATA_TYPE_SEEKTABLE: + FLAC__ASSERT(0); + break; + default: + if(real_length > 0) { + if(0 == (block.data.unknown.data = (FLAC__byte*)malloc(real_length))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.unknown.data, real_length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + } + else + block.data.unknown.data = 0; + break; + } + decoder->private_->metadata_callback(decoder, &block, decoder->private_->client_data); + + /* now we have to free any malloc'ed data in the block */ + switch(type) { + case FLAC__METADATA_TYPE_PADDING: + break; + case FLAC__METADATA_TYPE_APPLICATION: + if(0 != block.data.application.data) + free(block.data.application.data); + break; + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + if(0 != block.data.vorbis_comment.vendor_string.entry) + free(block.data.vorbis_comment.vendor_string.entry); + if(block.data.vorbis_comment.num_comments > 0) + for(i = 0; i < block.data.vorbis_comment.num_comments; i++) + if(0 != block.data.vorbis_comment.comments[i].entry) + free(block.data.vorbis_comment.comments[i].entry); + if(0 != block.data.vorbis_comment.comments) + free(block.data.vorbis_comment.comments); + break; + case FLAC__METADATA_TYPE_CUESHEET: + if(block.data.cue_sheet.num_tracks > 0) + 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); + if(0 != block.data.cue_sheet.tracks) + free(block.data.cue_sheet.tracks); + break; + case FLAC__METADATA_TYPE_STREAMINFO: + case FLAC__METADATA_TYPE_SEEKTABLE: + FLAC__ASSERT(0); + default: + if(0 != block.data.unknown.data) + free(block.data.unknown.data); + break; + } + } + } + + if(is_last) + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + + return true; +} + +FLAC__bool read_metadata_streaminfo_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length) +{ + FLAC__uint32 x; + unsigned bits, used_bits = 0; + + FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); + + decoder->private_->stream_info.type = FLAC__METADATA_TYPE_STREAMINFO; + decoder->private_->stream_info.is_last = is_last; + decoder->private_->stream_info.length = length; + + bits = FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, bits, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.min_blocksize = x; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.max_blocksize = x; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.min_framesize = x; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.max_framesize = x; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.sample_rate = x; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.channels = x+1; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.bits_per_sample = x+1; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN; + if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &decoder->private_->stream_info.data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + used_bits += bits; + + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, decoder->private_->stream_info.data.stream_info.md5sum, 16, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + used_bits += 16*8; + + /* skip the rest of the block */ + FLAC__ASSERT(used_bits % 8 == 0); + length -= (used_bits / 8); + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + return true; +} + +FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length) +{ + FLAC__uint32 i, x; + FLAC__uint64 xx; + + FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); + + decoder->private_->seek_table.type = FLAC__METADATA_TYPE_SEEKTABLE; + decoder->private_->seek_table.is_last = is_last; + decoder->private_->seek_table.length = length; + + decoder->private_->seek_table.data.seek_table.num_points = length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; + + /* use realloc since we may pass through here several times (e.g. after seeking) */ + if(0 == (decoder->private_->seek_table.data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)realloc(decoder->private_->seek_table.data.seek_table.points, decoder->private_->seek_table.data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint)))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + for(i = 0; i < decoder->private_->seek_table.data.seek_table.num_points; i++) { + if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->seek_table.data.seek_table.points[i].sample_number = xx; + + if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->seek_table.data.seek_table.points[i].stream_offset = xx; + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->seek_table.data.seek_table.points[i].frame_samples = x; + } + length -= (decoder->private_->seek_table.data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH); + /* if there is a partial point left, skip over it */ + if(length > 0) { + /*@@@ do an error_callback() here? there's an argument for either way */ + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + } + + return true; +} + +FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj) +{ + FLAC__uint32 i; + + FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); + + /* read vendor string */ + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); + if(!FLAC__bitbuffer_read_raw_uint32_little_endian(decoder->private_->input, &obj->vendor_string.length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + if(obj->vendor_string.length > 0) { + if(0 == (obj->vendor_string.entry = (FLAC__byte*)malloc(obj->vendor_string.length+1))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, obj->vendor_string.entry, obj->vendor_string.length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + obj->vendor_string.entry[obj->vendor_string.length] = '\0'; + } + else + obj->vendor_string.entry = 0; + + /* read num comments */ + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN == 32); + if(!FLAC__bitbuffer_read_raw_uint32_little_endian(decoder->private_->input, &obj->num_comments, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + /* read comments */ + if(obj->num_comments > 0) { + if(0 == (obj->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)malloc(obj->num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + for(i = 0; i < obj->num_comments; i++) { + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); + if(!FLAC__bitbuffer_read_raw_uint32_little_endian(decoder->private_->input, &obj->comments[i].length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + if(obj->comments[i].length > 0) { + if(0 == (obj->comments[i].entry = (FLAC__byte*)malloc(obj->comments[i].length+1))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, obj->comments[i].entry, obj->comments[i].length, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + obj->comments[i].entry[obj->comments[i].length] = '\0'; + } + else + obj->comments[i].entry = 0; + } + } + else { + obj->comments = 0; + } + + return true; +} + +FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj) +{ + FLAC__uint32 i, j, x; + + FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); + + memset(obj, 0, sizeof(FLAC__StreamMetadata_CueSheet)); + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)obj->media_catalog_number, FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN/8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &obj->lead_in, FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + obj->is_cd = x? true : false; + + if(!FLAC__bitbuffer_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + obj->num_tracks = x; + + if(obj->num_tracks > 0) { + if(0 == (obj->tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc(obj->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + for(i = 0; i < obj->num_tracks; i++) { + FLAC__StreamMetadata_CueSheet_Track *track = &obj->tracks[i]; + if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &track->offset, FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + track->number = (FLAC__byte)x; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)track->isrc, FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN/8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + track->type = x; + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + track->pre_emphasis = x; + + if(!FLAC__bitbuffer_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + track->num_indices = (FLAC__byte)x; + + if(track->num_indices > 0) { + if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)calloc(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + for(j = 0; j < track->num_indices; j++) { + FLAC__StreamMetadata_CueSheet_Index *index = &track->indices[j]; + if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &index->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + index->number = (FLAC__byte)x; + + if(!FLAC__bitbuffer_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + } + } + } + } + + return true; +} + +FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder) +{ + FLAC__uint32 x; + unsigned i, skip; + + /* skip the version and flags bytes */ + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 24, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + /* get the size (in bytes) to skip */ + skip = 0; + for(i = 0; i < 4; i++) { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + skip <<= 7; + skip |= (x & 0x7f); + } + /* skip the rest of the tag */ + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, skip, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + return true; +} + +FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder) +{ + FLAC__uint32 x; + FLAC__bool first = true; + + /* If we know the total number of samples in the stream, stop if we've read that many. */ + /* This will stop us, for example, from wasting time trying to sync on an ID3V1 tag. */ + if(decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.total_samples) { + if(decoder->private_->samples_decoded >= decoder->private_->stream_info.data.stream_info.total_samples) { + decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM; + return true; + } + } + + /* make sure we're byte aligned */ + if(!FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)) { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__bitbuffer_bits_left_for_byte_alignment(decoder->private_->input), read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + } + + while(1) { + if(decoder->private_->cached) { + x = (FLAC__uint32)decoder->private_->lookahead; + decoder->private_->cached = false; + } + else { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + } + if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ + decoder->private_->header_warmup[0] = (FLAC__byte)x; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + /* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */ + /* else we have to check if the second byte is the end of a sync code */ + if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ + decoder->private_->lookahead = (FLAC__byte)x; + decoder->private_->cached = true; + } + else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */ + decoder->private_->header_warmup[1] = (FLAC__byte)x; + decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME; + return true; + } + } + if(first) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); + first = false; + } + } + + return true; +} + +FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FLAC__bool do_full_decode) +{ + unsigned channel; + unsigned i; + FLAC__int32 mid, side, left, right; + FLAC__uint16 frame_crc; /* the one we calculate from the input stream */ + FLAC__uint32 x; + + *got_a_frame = false; + + /* init the CRC */ + frame_crc = 0; + FLAC__CRC16_UPDATE(decoder->private_->header_warmup[0], frame_crc); + FLAC__CRC16_UPDATE(decoder->private_->header_warmup[1], frame_crc); + FLAC__bitbuffer_reset_read_crc16(decoder->private_->input, frame_crc); + + if(!read_frame_header_(decoder)) + return false; + if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) + return true; + if(!allocate_output_(decoder, decoder->private_->frame.header.blocksize, decoder->private_->frame.header.channels)) + return false; + for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) { + /* + * first figure the correct bits-per-sample of the subframe + */ + unsigned bps = decoder->private_->frame.header.bits_per_sample; + switch(decoder->private_->frame.header.channel_assignment) { + case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: + /* no adjustment needed */ + break; + case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: + FLAC__ASSERT(decoder->private_->frame.header.channels == 2); + if(channel == 1) + bps++; + break; + case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE: + FLAC__ASSERT(decoder->private_->frame.header.channels == 2); + if(channel == 0) + bps++; + break; + case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE: + FLAC__ASSERT(decoder->private_->frame.header.channels == 2); + if(channel == 1) + bps++; + break; + default: + FLAC__ASSERT(0); + } + /* + * now read it + */ + if(!read_subframe_(decoder, channel, bps, do_full_decode)) + return false; + if(decoder->protected_->state != FLAC__STREAM_DECODER_READ_FRAME) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + } + if(!read_zero_padding_(decoder)) + return false; + + /* + * Read the frame CRC-16 from the footer and check + */ + frame_crc = FLAC__bitbuffer_get_read_crc16(decoder->private_->input); + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__FRAME_FOOTER_CRC_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + if(frame_crc == (FLAC__uint16)x) { + 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++) { + mid = decoder->private_->output[0][i]; + side = decoder->private_->output[1][i]; + mid <<= 1; + if(side & 1) /* i.e. if 'side' is odd... */ + mid++; + left = mid + side; + right = mid - side; + decoder->private_->output[0][i] = left >> 1; + decoder->private_->output[1][i] = right >> 1; + } + break; + default: + FLAC__ASSERT(0); + break; + } + } + } + else { + /* Bad frame, emit error and zero the output signal */ + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH, decoder->private_->client_data); + 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); + } + } + } + + *got_a_frame = true; + + /* 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; + + /* write it */ + if(do_full_decode) { + if(decoder->private_->write_callback(decoder, &decoder->private_->frame, (const FLAC__int32 * const *)decoder->private_->output, decoder->private_->client_data) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE) + return false; + } + + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; +} + +FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder) +{ + FLAC__uint32 x; + FLAC__uint64 xx; + unsigned i, blocksize_hint = 0, sample_rate_hint = 0; + FLAC__byte crc8, raw_header[16]; /* MAGIC NUMBER based on the maximum frame header size, including CRC */ + unsigned raw_header_len; + FLAC__bool is_unparseable = false; + const FLAC__bool is_known_variable_blocksize_stream = (decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.min_blocksize != decoder->private_->stream_info.data.stream_info.max_blocksize); + const FLAC__bool is_known_fixed_blocksize_stream = (decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.min_blocksize == decoder->private_->stream_info.data.stream_info.max_blocksize); + + FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)); + + /* init the raw header with the saved bits from synchronization */ + raw_header[0] = decoder->private_->header_warmup[0]; + raw_header[1] = decoder->private_->header_warmup[1]; + raw_header_len = 2; + + /* + * check to make sure that the reserved bits are 0 + */ + if(raw_header[1] & 0x03) { /* MAGIC NUMBER */ + is_unparseable = true; + } + + /* + * Note that along the way as we read the header, we look for a sync + * code inside. If we find one it would indicate that our original + * sync was bad since there cannot be a sync code in a valid header. + */ + + /* + * read in the raw header as bytes so we can CRC it, and parse it on the way + */ + for(i = 0; i < 2; i++) { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ + /* if we get here it means our original sync was erroneous since the sync code cannot appear in the header */ + decoder->private_->lookahead = (FLAC__byte)x; + decoder->private_->cached = true; + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + raw_header[raw_header_len++] = (FLAC__byte)x; + } + + switch(x = raw_header[2] >> 4) { + case 0: + if(is_known_fixed_blocksize_stream) + decoder->private_->frame.header.blocksize = decoder->private_->stream_info.data.stream_info.min_blocksize; + else + is_unparseable = true; + break; + case 1: + decoder->private_->frame.header.blocksize = 192; + break; + case 2: + case 3: + case 4: + case 5: + decoder->private_->frame.header.blocksize = 576 << (x-2); + break; + case 6: + case 7: + blocksize_hint = x; + break; + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + decoder->private_->frame.header.blocksize = 256 << (x-8); + break; + default: + FLAC__ASSERT(0); + break; + } + + switch(x = raw_header[2] & 0x0f) { + case 0: + if(decoder->private_->has_stream_info) + decoder->private_->frame.header.sample_rate = decoder->private_->stream_info.data.stream_info.sample_rate; + else + is_unparseable = true; + break; + case 1: + case 2: + case 3: + is_unparseable = true; + break; + case 4: + decoder->private_->frame.header.sample_rate = 8000; + break; + case 5: + decoder->private_->frame.header.sample_rate = 16000; + break; + case 6: + decoder->private_->frame.header.sample_rate = 22050; + break; + case 7: + decoder->private_->frame.header.sample_rate = 24000; + break; + case 8: + decoder->private_->frame.header.sample_rate = 32000; + break; + case 9: + decoder->private_->frame.header.sample_rate = 44100; + break; + case 10: + decoder->private_->frame.header.sample_rate = 48000; + break; + case 11: + decoder->private_->frame.header.sample_rate = 96000; + break; + case 12: + case 13: + case 14: + sample_rate_hint = x; + break; + case 15: + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + default: + FLAC__ASSERT(0); + } + + x = (unsigned)(raw_header[3] >> 4); + if(x & 8) { + decoder->private_->frame.header.channels = 2; + switch(x & 7) { + case 0: + decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE; + break; + case 1: + decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE; + break; + case 2: + decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_MID_SIDE; + break; + default: + is_unparseable = true; + break; + } + } + else { + decoder->private_->frame.header.channels = (unsigned)x + 1; + decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; + } + + switch(x = (unsigned)(raw_header[3] & 0x0e) >> 1) { + case 0: + if(decoder->private_->has_stream_info) + decoder->private_->frame.header.bits_per_sample = decoder->private_->stream_info.data.stream_info.bits_per_sample; + else + is_unparseable = true; + break; + case 1: + decoder->private_->frame.header.bits_per_sample = 8; + break; + case 2: + decoder->private_->frame.header.bits_per_sample = 12; + break; + case 4: + decoder->private_->frame.header.bits_per_sample = 16; + break; + case 5: + decoder->private_->frame.header.bits_per_sample = 20; + break; + case 6: + decoder->private_->frame.header.bits_per_sample = 24; + break; + case 3: + case 7: + is_unparseable = true; + break; + default: + FLAC__ASSERT(0); + break; + } + + if(raw_header[3] & 0x01) { /* this should be a zero padding bit */ + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + + /* + * Now we get to the regrettable consequences of not knowing for sure + * whether we got a frame number or a sample number. There are no + * encoders that do variable-blocksize encoding so unless we know from + * the STREAMINFO that it is variable-blocksize we will assume it is + * fixed-blocksize. The trouble comes when we have no STREAMINFO; again + * we will guess that is fixed-blocksize. Where this can go wrong: 1) a + * variable-blocksize stream with no STREAMINFO; 2) a fixed-blocksize + * stream that was edited such that one or more frames before or + * including this one do not have the same number of samples as the + * STREAMINFO's min and max blocksize. + */ + if(is_known_variable_blocksize_stream) { + if(blocksize_hint) { + if(!FLAC__bitbuffer_read_utf8_uint64(decoder->private_->input, &xx, read_callback_, decoder, raw_header, &raw_header_len)) + return false; /* the read_callback_ sets the state for us */ + if(xx == FLAC__U64L(0xffffffffffffffff)) { /* i.e. non-UTF8 code... */ + decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */ + decoder->private_->cached = true; + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER; + decoder->private_->frame.header.number.sample_number = xx; + } + else + is_unparseable = true; + } + else { + if(!FLAC__bitbuffer_read_utf8_uint32(decoder->private_->input, &x, read_callback_, decoder, raw_header, &raw_header_len)) + return false; /* the read_callback_ sets the state for us */ + if(x == 0xffffffff) { /* i.e. non-UTF8 code... */ + decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */ + decoder->private_->cached = true; + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + decoder->private_->last_frame_number = x; + decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER; + if(decoder->private_->has_stream_info) { + FLAC__ASSERT(decoder->private_->stream_info.data.stream_info.min_blocksize == decoder->private_->stream_info.data.stream_info.max_blocksize); + decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->stream_info.data.stream_info.min_blocksize * (FLAC__uint64)x; + decoder->private_->last_block_size = decoder->private_->frame.header.blocksize; + } + else if(blocksize_hint) { + if(decoder->private_->last_block_size) + decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->last_block_size * (FLAC__uint64)x; + else + is_unparseable = true; + } + else { + decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->frame.header.blocksize * (FLAC__uint64)x; + decoder->private_->last_block_size = decoder->private_->frame.header.blocksize; + } + } + + if(blocksize_hint) { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + raw_header[raw_header_len++] = (FLAC__byte)x; + if(blocksize_hint == 7) { + FLAC__uint32 _x; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &_x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + raw_header[raw_header_len++] = (FLAC__byte)_x; + x = (x << 8) | _x; + } + decoder->private_->frame.header.blocksize = x+1; + } + + if(sample_rate_hint) { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + raw_header[raw_header_len++] = (FLAC__byte)x; + if(sample_rate_hint != 12) { + FLAC__uint32 _x; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &_x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + raw_header[raw_header_len++] = (FLAC__byte)_x; + x = (x << 8) | _x; + } + if(sample_rate_hint == 12) + decoder->private_->frame.header.sample_rate = x*1000; + else if(sample_rate_hint == 13) + decoder->private_->frame.header.sample_rate = x; + else + decoder->private_->frame.header.sample_rate = x*10; + } + + /* read the CRC-8 byte */ + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + crc8 = (FLAC__byte)x; + + if(FLAC__crc8(raw_header, raw_header_len) != crc8) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + + if(is_unparseable) { + decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; + return false; + } + + return true; +} + +FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode) +{ + FLAC__uint32 x; + FLAC__bool wasted_bits; + + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) /* MAGIC NUMBER */ + return false; /* the read_callback_ sets the state for us */ + + wasted_bits = (x & 1); + x &= 0xfe; + + if(wasted_bits) { + unsigned u; + if(!FLAC__bitbuffer_read_unary_unsigned(decoder->private_->input, &u, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + decoder->private_->frame.subframes[channel].wasted_bits = u+1; + bps -= decoder->private_->frame.subframes[channel].wasted_bits; + } + else + decoder->private_->frame.subframes[channel].wasted_bits = 0; + + /* + * Lots of magic numbers here + */ + if(x & 0x80) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + else if(x == 0) { + if(!read_subframe_constant_(decoder, channel, bps, do_full_decode)) + return false; + } + else if(x == 2) { + if(!read_subframe_verbatim_(decoder, channel, bps, do_full_decode)) + return false; + } + else if(x < 16) { + decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; + return false; + } + else if(x <= 24) { + if(!read_subframe_fixed_(decoder, channel, bps, (x>>1)&7, do_full_decode)) + return false; + } + else if(x < 64) { + decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; + return false; + } + else { + if(!read_subframe_lpc_(decoder, channel, bps, ((x>>1)&31)+1, do_full_decode)) + return false; + } + + if(wasted_bits && do_full_decode) { + unsigned i; + x = decoder->private_->frame.subframes[channel].wasted_bits; + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) + decoder->private_->output[channel][i] <<= x; + } + + return true; +} + +FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode) +{ + FLAC__Subframe_Constant *subframe = &decoder->private_->frame.subframes[channel].data.constant; + FLAC__int32 x; + unsigned i; + FLAC__int32 *output = decoder->private_->output[channel]; + + decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_CONSTANT; + + if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &x, bps, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + + subframe->value = x; + + /* decode the subframe */ + if(do_full_decode) { + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) + output[i] = x; + } + + return true; +} + +FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode) +{ + FLAC__Subframe_Fixed *subframe = &decoder->private_->frame.subframes[channel].data.fixed; + FLAC__int32 i32; + FLAC__uint32 u32; + unsigned u; + + decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_FIXED; + + subframe->residual = decoder->private_->residual[channel]; + subframe->order = order; + + /* read warm-up samples */ + for(u = 0; u < order; u++) { + if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, bps, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + subframe->warmup[u] = i32; + } + + /* read entropy coding method info */ + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + subframe->entropy_coding_method.type = (FLAC__EntropyCodingMethodType)u32; + switch(subframe->entropy_coding_method.type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + subframe->entropy_coding_method.data.partitioned_rice.order = u32; + subframe->entropy_coding_method.data.partitioned_rice.contents = &decoder->private_->partitioned_rice_contents[channel]; + break; + default: + decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; + return false; + } + + /* read residual */ + switch(subframe->entropy_coding_method.type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + if(!read_residual_partitioned_rice_(decoder, order, subframe->entropy_coding_method.data.partitioned_rice.order, &decoder->private_->partitioned_rice_contents[channel], decoder->private_->residual[channel])) + return false; + break; + default: + FLAC__ASSERT(0); + } + + /* 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); + } + + return true; +} + +FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode) +{ + FLAC__Subframe_LPC *subframe = &decoder->private_->frame.subframes[channel].data.lpc; + FLAC__int32 i32; + FLAC__uint32 u32; + unsigned u; + + decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_LPC; + + subframe->residual = decoder->private_->residual[channel]; + subframe->order = order; + + /* read warm-up samples */ + for(u = 0; u < order; u++) { + if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, bps, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + subframe->warmup[u] = i32; + } + + /* read qlp coeff precision */ + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + if(u32 == (1u << FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN) - 1) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + subframe->qlp_coeff_precision = u32+1; + + /* read qlp shift */ + if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + subframe->quantization_level = i32; + + /* read quantized lp coefficiencts */ + for(u = 0; u < order; u++) { + if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, subframe->qlp_coeff_precision, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + subframe->qlp_coeff[u] = i32; + } + + /* read entropy coding method info */ + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + subframe->entropy_coding_method.type = (FLAC__EntropyCodingMethodType)u32; + switch(subframe->entropy_coding_method.type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + subframe->entropy_coding_method.data.partitioned_rice.order = u32; + subframe->entropy_coding_method.data.partitioned_rice.contents = &decoder->private_->partitioned_rice_contents[channel]; + break; + default: + decoder->protected_->state = FLAC__STREAM_DECODER_UNPARSEABLE_STREAM; + return false; + } + + /* read residual */ + switch(subframe->entropy_coding_method.type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + if(!read_residual_partitioned_rice_(decoder, order, subframe->entropy_coding_method.data.partitioned_rice.order, &decoder->private_->partitioned_rice_contents[channel], decoder->private_->residual[channel])) + return false; + break; + default: + FLAC__ASSERT(0); + } + + /* 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) { + if(order <= 8) + decoder->private_->local_lpc_restore_signal_16bit_order8(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_16bit(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); + } + + return true; +} + +FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned 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]; + unsigned i; + + decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_VERBATIM; + + subframe->data = residual; + + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) { + if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &x, bps, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + residual[i] = x; + } + + /* decode the subframe */ + if(do_full_decode) + memcpy(decoder->private_->output[channel], subframe->data, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize); + + return true; +} + +FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigned predictor_order, unsigned partition_order, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, FLAC__int32 *residual) +{ + FLAC__uint32 rice_parameter; + int i; + unsigned partition, sample, u; + const unsigned partitions = 1u << partition_order; + const unsigned partition_samples = partition_order > 0? decoder->private_->frame.header.blocksize >> partition_order : decoder->private_->frame.header.blocksize - predictor_order; + + /* sanity checks */ + if(partition_order == 0) { + if(decoder->private_->frame.header.blocksize < predictor_order) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + } + else { + if(partition_samples < predictor_order) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + } + + if(!FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + + sample = 0; + for(partition = 0; partition < partitions; partition++) { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + partitioned_rice_contents->parameters[partition] = rice_parameter; + if(rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) { + u = (partition_order == 0 || partition > 0)? partition_samples : partition_samples - predictor_order; + if(!FLAC__bitbuffer_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + sample += u; + } + else { + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + partitioned_rice_contents->raw_bits[partition] = rice_parameter; + for(u = (partition_order == 0 || partition > 0)? 0 : predictor_order; u < partition_samples; u++, sample++) { + if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i, rice_parameter, read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + residual[sample] = i; + } + } + } + + return true; +} + +FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder) +{ + if(!FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)) { + FLAC__uint32 zero = 0; + if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &zero, FLAC__bitbuffer_bits_left_for_byte_alignment(decoder->private_->input), read_callback_, decoder)) + return false; /* the read_callback_ sets the state for us */ + if(zero != 0) { + decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + } + } + return true; +} + +FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_data) +{ + FLAC__StreamDecoder *decoder = (FLAC__StreamDecoder *)client_data; + FLAC__StreamDecoderReadStatus status; + + status = decoder->private_->read_callback(decoder, buffer, bytes, decoder->private_->client_data); + if(status == FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM) + decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM; + else if(status == FLAC__STREAM_DECODER_READ_STATUS_ABORT) + decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED; + return status == FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; +} diff --git a/FLAC/stream_decoder_pp.cpp b/FLAC/stream_decoder_pp.cpp index af1768887..10e15e0fa 100644 --- a/FLAC/stream_decoder_pp.cpp +++ b/FLAC/stream_decoder_pp.cpp @@ -1,222 +1,222 @@ -/* libFLAC++ - Free Lossless Audio Codec library - * Copyright (C) 2002,2003,2004 Josh Coalson - * - * 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. - */ - -#include "FLAC++/decoder.h" -#include "FLAC/assert.h" - -#ifdef _MSC_VER -// warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning) -#pragma warning ( disable : 4800 ) -#endif - -namespace FLAC { - namespace Decoder { - - Stream::Stream(): - decoder_(::FLAC__stream_decoder_new()) - { } - - Stream::~Stream() - { - if(0 != decoder_) { - ::FLAC__stream_decoder_finish(decoder_); - ::FLAC__stream_decoder_delete(decoder_); - } - } - - bool Stream::is_valid() const - { - return 0 != decoder_; - } - - bool Stream::set_metadata_respond(::FLAC__MetadataType type) - { - FLAC__ASSERT(is_valid()); - return (bool)::FLAC__stream_decoder_set_metadata_respond(decoder_, type); - } - - bool Stream::set_metadata_respond_application(const FLAC__byte id[4]) - { - FLAC__ASSERT(is_valid()); - return (bool)::FLAC__stream_decoder_set_metadata_respond_application(decoder_, id); - } - - bool Stream::set_metadata_respond_all() - { - FLAC__ASSERT(is_valid()); - return (bool)::FLAC__stream_decoder_set_metadata_respond_all(decoder_); - } - - bool Stream::set_metadata_ignore(::FLAC__MetadataType type) - { - FLAC__ASSERT(is_valid()); - return (bool)::FLAC__stream_decoder_set_metadata_ignore(decoder_, type); - } - - bool Stream::set_metadata_ignore_application(const FLAC__byte id[4]) - { - FLAC__ASSERT(is_valid()); - return (bool)::FLAC__stream_decoder_set_metadata_ignore_application(decoder_, id); - } - - bool Stream::set_metadata_ignore_all() - { - FLAC__ASSERT(is_valid()); - return (bool)::FLAC__stream_decoder_set_metadata_ignore_all(decoder_); - } - - Stream::State Stream::get_state() const - { - FLAC__ASSERT(is_valid()); - return State(::FLAC__stream_decoder_get_state(decoder_)); - } - - unsigned Stream::get_channels() const - { - FLAC__ASSERT(is_valid()); - return ::FLAC__stream_decoder_get_channels(decoder_); - } - - ::FLAC__ChannelAssignment Stream::get_channel_assignment() const - { - FLAC__ASSERT(is_valid()); - return ::FLAC__stream_decoder_get_channel_assignment(decoder_); - } - - unsigned Stream::get_bits_per_sample() const - { - FLAC__ASSERT(is_valid()); - return ::FLAC__stream_decoder_get_bits_per_sample(decoder_); - } - - unsigned Stream::get_sample_rate() const - { - FLAC__ASSERT(is_valid()); - return ::FLAC__stream_decoder_get_sample_rate(decoder_); - } - - unsigned Stream::get_blocksize() const - { - FLAC__ASSERT(is_valid()); - return ::FLAC__stream_decoder_get_blocksize(decoder_); - } - - Stream::State Stream::init() - { - FLAC__ASSERT(is_valid()); - ::FLAC__stream_decoder_set_read_callback(decoder_, read_callback_); - ::FLAC__stream_decoder_set_write_callback(decoder_, write_callback_); - ::FLAC__stream_decoder_set_metadata_callback(decoder_, metadata_callback_); - ::FLAC__stream_decoder_set_error_callback(decoder_, error_callback_); - ::FLAC__stream_decoder_set_client_data(decoder_, (void*)this); - return State(::FLAC__stream_decoder_init(decoder_)); - } - - void Stream::finish() - { - FLAC__ASSERT(is_valid()); - ::FLAC__stream_decoder_finish(decoder_); - } - - bool Stream::flush() - { - FLAC__ASSERT(is_valid()); - return (bool)::FLAC__stream_decoder_flush(decoder_); - } - - bool Stream::reset() - { - FLAC__ASSERT(is_valid()); - return (bool)::FLAC__stream_decoder_reset(decoder_); - } - - bool Stream::process_single() - { - FLAC__ASSERT(is_valid()); - return (bool)::FLAC__stream_decoder_process_single(decoder_); - } - - bool Stream::process_until_end_of_metadata() - { - FLAC__ASSERT(is_valid()); - return (bool)::FLAC__stream_decoder_process_until_end_of_metadata(decoder_); - } - - bool Stream::process_until_end_of_stream() - { - FLAC__ASSERT(is_valid()); - return (bool)::FLAC__stream_decoder_process_until_end_of_stream(decoder_); - } - - bool Stream::skip_single_frame() - { - FLAC__ASSERT(is_valid()); - return (bool)::FLAC__stream_decoder_skip_single_frame(decoder_); - } - - ::FLAC__StreamDecoderReadStatus Stream::read_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) - { - (void)decoder; - FLAC__ASSERT(0 != client_data); - Stream *instance = reinterpret_cast(client_data); - FLAC__ASSERT(0 != instance); - return instance->read_callback(buffer, bytes); - } - - ::FLAC__StreamDecoderWriteStatus Stream::write_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) - { - (void)decoder; - FLAC__ASSERT(0 != client_data); - Stream *instance = reinterpret_cast(client_data); - FLAC__ASSERT(0 != instance); - return instance->write_callback(frame, buffer); - } - - void Stream::metadata_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data) - { - (void)decoder; - FLAC__ASSERT(0 != client_data); - Stream *instance = reinterpret_cast(client_data); - FLAC__ASSERT(0 != instance); - instance->metadata_callback(metadata); - } - - void Stream::error_callback_(const ::FLAC__StreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data) - { - (void)decoder; - FLAC__ASSERT(0 != client_data); - Stream *instance = reinterpret_cast(client_data); - FLAC__ASSERT(0 != instance); - instance->error_callback(status); - } - - }; -}; +/* libFLAC++ - Free Lossless Audio Codec library + * Copyright (C) 2002,2003,2004,2005 Josh Coalson + * + * 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. + */ + +#include "FLAC++/decoder.h" +#include "FLAC/assert.h" + +#ifdef _MSC_VER +// warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning) +#pragma warning ( disable : 4800 ) +#endif + +namespace FLAC { + namespace Decoder { + + Stream::Stream(): + decoder_(::FLAC__stream_decoder_new()) + { } + + Stream::~Stream() + { + if(0 != decoder_) { + ::FLAC__stream_decoder_finish(decoder_); + ::FLAC__stream_decoder_delete(decoder_); + } + } + + bool Stream::is_valid() const + { + return 0 != decoder_; + } + + bool Stream::set_metadata_respond(::FLAC__MetadataType type) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_set_metadata_respond(decoder_, type); + } + + bool Stream::set_metadata_respond_application(const FLAC__byte id[4]) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_set_metadata_respond_application(decoder_, id); + } + + bool Stream::set_metadata_respond_all() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_set_metadata_respond_all(decoder_); + } + + bool Stream::set_metadata_ignore(::FLAC__MetadataType type) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_set_metadata_ignore(decoder_, type); + } + + bool Stream::set_metadata_ignore_application(const FLAC__byte id[4]) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_set_metadata_ignore_application(decoder_, id); + } + + bool Stream::set_metadata_ignore_all() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_set_metadata_ignore_all(decoder_); + } + + Stream::State Stream::get_state() const + { + FLAC__ASSERT(is_valid()); + return State(::FLAC__stream_decoder_get_state(decoder_)); + } + + unsigned Stream::get_channels() const + { + FLAC__ASSERT(is_valid()); + return ::FLAC__stream_decoder_get_channels(decoder_); + } + + ::FLAC__ChannelAssignment Stream::get_channel_assignment() const + { + FLAC__ASSERT(is_valid()); + return ::FLAC__stream_decoder_get_channel_assignment(decoder_); + } + + unsigned Stream::get_bits_per_sample() const + { + FLAC__ASSERT(is_valid()); + return ::FLAC__stream_decoder_get_bits_per_sample(decoder_); + } + + unsigned Stream::get_sample_rate() const + { + FLAC__ASSERT(is_valid()); + return ::FLAC__stream_decoder_get_sample_rate(decoder_); + } + + unsigned Stream::get_blocksize() const + { + FLAC__ASSERT(is_valid()); + return ::FLAC__stream_decoder_get_blocksize(decoder_); + } + + Stream::State Stream::init() + { + FLAC__ASSERT(is_valid()); + ::FLAC__stream_decoder_set_read_callback(decoder_, read_callback_); + ::FLAC__stream_decoder_set_write_callback(decoder_, write_callback_); + ::FLAC__stream_decoder_set_metadata_callback(decoder_, metadata_callback_); + ::FLAC__stream_decoder_set_error_callback(decoder_, error_callback_); + ::FLAC__stream_decoder_set_client_data(decoder_, (void*)this); + return State(::FLAC__stream_decoder_init(decoder_)); + } + + void Stream::finish() + { + FLAC__ASSERT(is_valid()); + ::FLAC__stream_decoder_finish(decoder_); + } + + bool Stream::flush() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_flush(decoder_); + } + + bool Stream::reset() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_reset(decoder_); + } + + bool Stream::process_single() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_process_single(decoder_); + } + + bool Stream::process_until_end_of_metadata() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_process_until_end_of_metadata(decoder_); + } + + bool Stream::process_until_end_of_stream() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_process_until_end_of_stream(decoder_); + } + + bool Stream::skip_single_frame() + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_decoder_skip_single_frame(decoder_); + } + + ::FLAC__StreamDecoderReadStatus Stream::read_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) + { + (void)decoder; + FLAC__ASSERT(0 != client_data); + Stream *instance = reinterpret_cast(client_data); + FLAC__ASSERT(0 != instance); + return instance->read_callback(buffer, bytes); + } + + ::FLAC__StreamDecoderWriteStatus Stream::write_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) + { + (void)decoder; + FLAC__ASSERT(0 != client_data); + Stream *instance = reinterpret_cast(client_data); + FLAC__ASSERT(0 != instance); + return instance->write_callback(frame, buffer); + } + + void Stream::metadata_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data) + { + (void)decoder; + FLAC__ASSERT(0 != client_data); + Stream *instance = reinterpret_cast(client_data); + FLAC__ASSERT(0 != instance); + instance->metadata_callback(metadata); + } + + void Stream::error_callback_(const ::FLAC__StreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data) + { + (void)decoder; + FLAC__ASSERT(0 != client_data); + Stream *instance = reinterpret_cast(client_data); + FLAC__ASSERT(0 != instance); + instance->error_callback(status); + } + + } +}