You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2022 lines
65 KiB
2022 lines
65 KiB
/*
|
|
* libfoxenflac -- Tiny FLAC Decoder Library
|
|
* Copyright (C) 2018-2022 Andreas Stöckel
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#include <foxen/flac.h>
|
|
|
|
#if 0
|
|
/* Set FX_FLAC_NO_CRC if you control the input data and already performed other
|
|
integrity checks. This makes the decoder significantly faster. */
|
|
#define FX_FLAC_NO_CRC
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
* CODE MERGED FROM OTHER LIBFOXEN PROJECTS *
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
* Copy of foxen/bitstream.h *
|
|
******************************************************************************/
|
|
|
|
/**
|
|
* Structure holding the current state of the bitstream reader.
|
|
*/
|
|
struct fx_bitstream {
|
|
/**
|
|
* 64 bit word from which the data is extracted.
|
|
*/
|
|
uint64_t buf;
|
|
|
|
/**
|
|
* Pointer at the source byte stream.
|
|
*/
|
|
uint8_t const *src;
|
|
|
|
/**
|
|
* Pointer at the end of the source byte stream.
|
|
*/
|
|
uint8_t const *src_end;
|
|
|
|
/**
|
|
* Position within the source byte stream in bits, i.e. the number of bits
|
|
* that have been consumed.
|
|
*/
|
|
uint8_t pos;
|
|
};
|
|
|
|
/**
|
|
* Typedef for the fx_bitstream struct.
|
|
*/
|
|
typedef struct fx_bitstream fx_bitstream_t;
|
|
|
|
/**
|
|
* Callback called whenever a fully byte has been consumed. This is useful for
|
|
* CRC calculations.
|
|
*/
|
|
typedef void (*fx_bitstream_byte_callback_t)(uint8_t byte, void *data);
|
|
|
|
/**
|
|
* Initializes the bitstream reader instance. Call fx_bitstream_set_source()
|
|
* to set the byte buffer from which the bitstream reader should read its
|
|
* data.
|
|
*
|
|
* @param reader is the bitstream reader instance that should be
|
|
* initialized.
|
|
*/
|
|
static inline void fx_bitstream_init(fx_bitstream_t *reader) {
|
|
reader->buf = 0U;
|
|
reader->pos = sizeof(reader->buf) * 8U;
|
|
reader->src = NULL;
|
|
reader->src_end = NULL;
|
|
}
|
|
|
|
/**
|
|
* Sets the backing source buffer for the bitstream. This function may only be
|
|
* called if the given pointer is a direct continuation of the previous data,
|
|
* i.e. are essentially set to reader->src.
|
|
*
|
|
* @param reader is the bitstream reader instance for which the source byte
|
|
* buffer should be set.
|
|
* @param src is a pointer at the source byte buffer.
|
|
* @param src_len is the length of the source byte buffer in bytes.
|
|
*/
|
|
static inline void fx_bitstream_set_source(fx_bitstream_t *reader,
|
|
const uint8_t *src,
|
|
uint32_t src_len);
|
|
|
|
/**
|
|
* Returns true if the corresponding read operation will be successful.
|
|
*
|
|
* @param reader is the bitstream reader instance from which the data should be
|
|
* read.
|
|
* @param n_bits is the number of bits that should be read from the bitstream
|
|
* reader. Must be in 1 <= n_bits <= 57.
|
|
* @return true if the number of available bits is smaller or equal to n_bits.
|
|
*/
|
|
static inline bool fx_bitstream_can_read(fx_bitstream_t *reader,
|
|
uint8_t n_bits) {
|
|
return (sizeof(reader->buf) * 8U) >= (n_bits + reader->pos);
|
|
}
|
|
|
|
/**
|
|
* Reads up to 64 bits from the input buffer in MSB order. Note that this
|
|
* function does not check whether the read operation returns valid data, so
|
|
* make sure to call fx_bitstream_can_read() before reading.
|
|
*
|
|
* @param reader is the bitstream reader instance from which the data should be
|
|
* read.
|
|
* @param n_bits is the number of bits that should be read. Must be in
|
|
* 1 <= n_bits <= 57.
|
|
* @return an integer corresponding the the specified number of bits.
|
|
*/
|
|
static inline uint64_t fx_bitstream_read_msb(fx_bitstream_t *reader,
|
|
uint8_t n_bits);
|
|
|
|
/**
|
|
* Reads up to 64 bits from the input buffer in MSB order. Note that this
|
|
* function does not check whether the read operation returns valid data, so
|
|
* make sure to call fx_bitstream_can_read() before reading.
|
|
*
|
|
* @param reader is the bitstream reader instance from which the data should be
|
|
* read.
|
|
* @param n_bits is the number of bits that should be read. Must be in
|
|
* 1 <= n_bits <= 57.
|
|
* @param callback is called whenever a full byte is consumed. Note that this
|
|
* includes a "virtual" set of zeros at the beginning of the bitstream.
|
|
* @param callback_data is a user-defined pointer passed to the byte callback.
|
|
* @return an integer corresponding the the specified number of bits.
|
|
*/
|
|
static inline uint64_t fx_bitstream_read_msb_ex(
|
|
fx_bitstream_t *reader, uint8_t n_bits,
|
|
fx_bitstream_byte_callback_t callback, void *callback_data);
|
|
|
|
/**
|
|
* Reads up to 64 bits from the input buffer in MSB order without advancing the
|
|
* buffer location. Note that this function does not check whether the read
|
|
* operation returns valid data, so make sure to call fx_bitstream_can_read()
|
|
* before reading.
|
|
*
|
|
* @param reader is the bitstream reader instance from which the data should be
|
|
* read.
|
|
* @param n_bits is the number of bits that should be read. Must be in
|
|
* 1 <= n_bits <= 57.
|
|
* @return an integer corresponding to the specified number of bits.
|
|
*/
|
|
static inline uint64_t fx_bitstream_peek_msb(fx_bitstream_t *reader,
|
|
uint8_t n_bits);
|
|
|
|
/**
|
|
* Combination of fx_bitstream_can_read and fx_bitstream_read_msb. Returns a
|
|
* negative value if the desired number of bits cannot be read from the source.
|
|
* If the given number of threads are available, returns the desired integer.
|
|
*
|
|
* @param reads is the bitstream reader instance from which the data should be
|
|
* read.
|
|
* @param n_bits is the number of bits that should be read. Must be in
|
|
* 1 <= n_bits <= 57.
|
|
* @return -1 if the desired number of bits is not available in the bitstream.
|
|
* Otherwise the integer corresponding to the specified number of bits is
|
|
* returned.
|
|
*/
|
|
static inline int64_t fx_bitstream_try_read_msb(fx_bitstream_t *reader,
|
|
uint8_t n_bits) {
|
|
return fx_bitstream_can_read(reader, n_bits)
|
|
? (int64_t)fx_bitstream_read_msb(reader, n_bits)
|
|
: -1;
|
|
}
|
|
|
|
/**
|
|
* Combination of fx_bitstream_can_read and fx_bitstream_read_msb. Returns a
|
|
* negative value if the desired number of bits cannot be read from the source.
|
|
* If the given number of threads are available, returns the desired integer.
|
|
*
|
|
* @param reads is the bitstream reader instance from which the data should be
|
|
* read.
|
|
* @param n_bits is the number of bits that should be read. Must be in
|
|
* 1 <= n_bits <= 57.
|
|
* @param callback is called whenever a full byte is consumed. Note that this
|
|
* includes a "virtual" set of zeros at the beginning of the bitstream.
|
|
* @param callback_data is a user-defined pointer passed to the byte callback.
|
|
* @return -1 if the desired number of bits is not available in the bitstream.
|
|
* Otherwise the integer corresponding to the specified number of bits is
|
|
* returned.
|
|
*/
|
|
static inline int64_t fx_bitstream_try_read_msb_ex(
|
|
fx_bitstream_t *reader, uint8_t n_bits,
|
|
fx_bitstream_byte_callback_t callback, void *callback_data) {
|
|
return fx_bitstream_can_read(reader, n_bits)
|
|
? (int64_t)fx_bitstream_read_msb_ex(reader, n_bits, callback,
|
|
callback_data)
|
|
: -1;
|
|
}
|
|
|
|
/**
|
|
* Combination of fx_bitstream_can_read and fx_bitstream_peek. Returns a
|
|
* negative value if the desired number of bits cannot be read from the source.
|
|
* If the given number of threads are available, returns the desired integer.
|
|
* In contrast to fx_bitstream_try_read_msb() this function does not advance
|
|
* the actual reader pointer.
|
|
*
|
|
* @param reads is the bitstream reader instance from which the data should be
|
|
* read.
|
|
* @param n_bits is the number of bits that should be read. Must be in
|
|
* 1 <= n_bits <= 57.
|
|
* @return -1 if the desired number of bits is not available in the bitstream.
|
|
* Otherwise the integer corresponding to the specified number of bits is
|
|
* returned.
|
|
*/
|
|
static inline int64_t fx_bitstream_try_peek_msb(fx_bitstream_t *reader,
|
|
uint8_t n_bits) {
|
|
return fx_bitstream_can_read(reader, n_bits)
|
|
? (int64_t)fx_bitstream_peek_msb(reader, n_bits)
|
|
: -1;
|
|
}
|
|
|
|
#define BUFSIZE (sizeof(((fx_bitstream_t *)NULL)->buf) * 8U)
|
|
|
|
static inline void _fx_bitstream_fill_buf(fx_bitstream_t *reader) {
|
|
while (reader->pos >= 8U && reader->src != reader->src_end) {
|
|
reader->buf = (reader->buf << 8U) | *(reader->src++);
|
|
reader->pos -= 8U;
|
|
}
|
|
}
|
|
|
|
static inline uint64_t _fx_bitstream_read_msb(
|
|
fx_bitstream_t *reader, uint8_t n_bits,
|
|
fx_bitstream_byte_callback_t callback, void *callback_data) {
|
|
assert((n_bits >= 1U) && (n_bits <= (BUFSIZE - 7U)));
|
|
|
|
/* Copy the current buffer content, skip already read bits */
|
|
uint64_t bits = reader->buf << reader->pos;
|
|
|
|
/* If the callback is specified, issue bytes that were read entirely */
|
|
const uint8_t pos_new = reader->pos + n_bits;
|
|
if (callback) {
|
|
const uint8_t i0 = reader->pos / 8U, i1 = pos_new / 8U;
|
|
uint64_t buf = reader->buf << (i0 * 8U);
|
|
for (uint8_t i = i0; i < i1; i++) {
|
|
uint8_t byte = buf >> (BUFSIZE - 8U);
|
|
callback(byte, callback_data);
|
|
buf = buf << 8U;
|
|
}
|
|
}
|
|
|
|
/* Advance the position */
|
|
reader->pos = pos_new;
|
|
|
|
/* Read new bytes from the byte stream */
|
|
_fx_bitstream_fill_buf(reader);
|
|
|
|
/* Mask out the "low" bits */
|
|
return bits >> (BUFSIZE - n_bits);
|
|
}
|
|
|
|
static inline void fx_bitstream_set_source(fx_bitstream_t *reader,
|
|
const uint8_t *src,
|
|
uint32_t src_len) {
|
|
reader->src = src;
|
|
reader->src_end = src + src_len;
|
|
_fx_bitstream_fill_buf(reader);
|
|
}
|
|
|
|
static inline uint64_t fx_bitstream_read_msb(fx_bitstream_t *reader,
|
|
uint8_t n_bits) {
|
|
return _fx_bitstream_read_msb(reader, n_bits, NULL, NULL);
|
|
}
|
|
|
|
static inline uint64_t fx_bitstream_read_msb_ex(
|
|
fx_bitstream_t *reader, uint8_t n_bits,
|
|
fx_bitstream_byte_callback_t callback, void *callback_data) {
|
|
return _fx_bitstream_read_msb(reader, n_bits, callback, callback_data);
|
|
}
|
|
|
|
static inline uint64_t fx_bitstream_peek_msb(fx_bitstream_t *reader,
|
|
uint8_t n_bits) {
|
|
assert((n_bits >= 1U) && (n_bits <= (BUFSIZE - 7U)));
|
|
return (reader->buf << reader->pos) >> (BUFSIZE - n_bits);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Copy of foxen/mem.h *
|
|
******************************************************************************/
|
|
|
|
/**
|
|
* Memory alignment for pointers internally used by Stanchion. Aligning memory
|
|
* and telling the compiler about it allows the compiler to perform better
|
|
* optimization. Furthermore, some platforms (WASM) do not allow unaligned
|
|
* memory access.
|
|
*/
|
|
#define FX_ALIGN 16
|
|
|
|
/**
|
|
* Macro telling the compiler that P is aligned with the specified alignment
|
|
* ALIGN.
|
|
*/
|
|
#define FX_ASSUME_ALIGNED_EX(P, ALIGN) P
|
|
#ifdef __GNUC__
|
|
#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ > 4)
|
|
#undef FX_ASSUME_ALIGNED_EX
|
|
#define FX_ASSUME_ALIGNED_EX(P, ALIGN) (__builtin_assume_aligned(P, ALIGN))
|
|
#endif /* (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ > 4) */
|
|
#endif /* __GNUC__ */
|
|
|
|
/**
|
|
* Macro telling the compiler that P is aligned with the alignment defined
|
|
* above.
|
|
*/
|
|
#define FX_ASSUME_ALIGNED(P) FX_ASSUME_ALIGNED_EX(P, FX_ALIGN)
|
|
|
|
/**
|
|
* Forces a pointer to have the specified alignment.
|
|
*/
|
|
#define FX_ALIGN_ADDR_EX(P, ALIGN) \
|
|
(FX_ASSUME_ALIGNED_EX( \
|
|
(void *)(((uintptr_t)(P) + ALIGN - 1) & (~(uintptr_t)(ALIGN - 1))), \
|
|
ALIGN))
|
|
|
|
/**
|
|
* Forces a pointer to have the alignment defined above.
|
|
*/
|
|
#define FX_ALIGN_ADDR(P) FX_ALIGN_ADDR_EX(P, FX_ALIGN)
|
|
|
|
/**
|
|
* Macro that fills the structure pointed at by P with zeros. See
|
|
* fx_mem_zero_aligned() regarding potential dangers.
|
|
*/
|
|
#define FX_MEM_ZERO_ALIGNED(P) \
|
|
do { \
|
|
fx_mem_zero_aligned(P, sizeof(*(P))); \
|
|
} while (0)
|
|
|
|
/**
|
|
* Call this first in a chain of fx_mem_update_size() calls. It will make sure
|
|
* that there is enough space to align the datastructure whenever the user
|
|
* provides a non-aligned target memory pointer.
|
|
*
|
|
* @param size is a pointer at a variable that holds the size of the object
|
|
* that we're describing. This function initializes this value to FX_ALIGN - 1.
|
|
* @return Always returns true to facilitate chaining with other fx_mem_*_size()
|
|
* functions.
|
|
*/
|
|
static inline bool fx_mem_init_size(uint32_t *size) {
|
|
*size = FX_ALIGN;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Function used to compute the total size of a datastructure consisting of
|
|
* multiple substructures. Calling this function updates the size of the outer
|
|
* datastructure by adding a substructure of size n_bytes. Assumes that the
|
|
* beginning of the substructure must be aligned to the given alignment.
|
|
*
|
|
* @param size is a pointer at the variable holding the size of the
|
|
* datastructure. This must always be a multiple of FX_ALIGN.
|
|
* @param n_bytes size of the sub-structure that should be added.
|
|
* @return zero if there was an overflow, one otherwise.
|
|
*/
|
|
static inline bool fx_mem_update_size_ex(uint32_t *size, uint32_t n_bytes,
|
|
uint32_t align) {
|
|
const uint32_t new_size = ((*size + n_bytes + align - 1) & (~(align - 1)));
|
|
if (new_size < *size) {
|
|
return false; /* error, there has been an overflow */
|
|
}
|
|
*size = new_size;
|
|
return true; /* success */
|
|
}
|
|
|
|
/**
|
|
* Function used to compute the total size of a datastructure consisting of
|
|
* multiple substructures. Calling this function updates the size of the outer
|
|
* datastructure by adding a substructure of size n_bytes. Assumes that the
|
|
* beginning of the substructure must be aligned to the default alignment.
|
|
*
|
|
* @param size is a pointer at the variable holding the size of the
|
|
* datastructure. This must always be a multiple of FX_ALIGN.
|
|
* @param n_bytes size of the sub-structure that should be added.
|
|
* @return zero if there was an overflow, one otherwise.
|
|
*/
|
|
static inline bool fx_mem_update_size(uint32_t *size, uint32_t n_bytes) {
|
|
return fx_mem_update_size_ex(size, n_bytes, FX_ALIGN);
|
|
}
|
|
|
|
/**
|
|
* Computes the aligned pointer pointing at the substructure of the given size
|
|
* for the specified alignment.
|
|
*
|
|
* @param mem pointer at the variable holding the pointer at the current
|
|
* pointer. The pointer is advanced by the given size after the return value is
|
|
* computed.
|
|
* @param size is the size of the substructure for which the pointer should be
|
|
* returned.
|
|
* @param align is the memory alignment to use.
|
|
* @return an aligned pointer pointing at the beginning of the substructure.
|
|
*/
|
|
static inline void *fx_mem_align_ex(void **mem, uint32_t size, uint32_t align) {
|
|
void *res = FX_ALIGN_ADDR_EX(*mem, align);
|
|
*mem = (void *)((uintptr_t)res + size);
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* Computes the default-aligned pointer pointing at the substructure of the
|
|
* given size.
|
|
*
|
|
* @param mem pointer at the variable holding the pointer at the current
|
|
* pointer. The pointer is advanced by the given size after the return value is
|
|
* computed.
|
|
* @param size is the size of the substructure for which the pointer should be
|
|
* returned.
|
|
* @return an aligned pointer pointing at the beginning of the substructure.
|
|
*/
|
|
static inline void *fx_mem_align(void **mem, uint32_t size) {
|
|
return fx_mem_align_ex(mem, size, FX_ALIGN);
|
|
}
|
|
|
|
/**
|
|
* Fills the given memory region with zeros. In contrast to memset(mem, 0, size)
|
|
* this assumes that the pointer is at least aligned at the FX_ALIGN boundary
|
|
* and that we can write multiples of FX_ALIGN bytes at once. This is
|
|
* potentially dangerous, so do not use this function if you don't know exactly
|
|
* what you're doing.
|
|
*
|
|
* @param mem is a pointer at the memory region that should be zeroed out. This
|
|
* pointer is assumed to be aligned.
|
|
* @param size is the size of the memory region that should be zeroed in bytes.
|
|
* This value is effectively rounded up to a multiple of FX_ALIGN
|
|
*/
|
|
static inline void fx_mem_zero_aligned(void *mem, uint32_t size) {
|
|
assert((((uintptr_t)mem) & (FX_ALIGN - 1)) == 0); /* mem must be aligned */
|
|
mem = FX_ASSUME_ALIGNED(mem);
|
|
for (uint32_t i = 0; i < (size + FX_ALIGN - 1) / FX_ALIGN; i++) {
|
|
((uint64_t *)mem)[2 * i + 0] = 0; /* If we're lucky, this loop is */
|
|
((uint64_t *)mem)[2 * i + 1] = 0; /* unrolled and vectorised. */
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* DATATYPES *
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
* Enums and constants defined in the FLAC format specifiction *
|
|
******************************************************************************/
|
|
|
|
/**
|
|
* Possible metadata block types.
|
|
*/
|
|
typedef enum {
|
|
META_TYPE_STREAMINFO = 0,
|
|
META_TYPE_PADDING = 1,
|
|
META_TYPE_APPLICATION = 2,
|
|
META_TYPE_SEEKTABLE = 3,
|
|
META_TYPE_VORBIS_COMMENT = 4,
|
|
META_TYPE_CUESHEET = 5,
|
|
META_TYPE_PICTURE = 6,
|
|
META_TYPE_INVALID = 127
|
|
} fx_flac_metadata_type_t;
|
|
|
|
typedef enum { BLK_FIXED = 0, BLK_VARIABLE = 1 } fx_flac_blocking_strategy_t;
|
|
|
|
typedef enum {
|
|
INDEPENDENT_MONO = 0,
|
|
INDEPENDENT_STEREO = 1,
|
|
INDEPENDENT_3C = 2,
|
|
INDEPENDENT_4C = 3,
|
|
INDEPENDENT_5C = 4,
|
|
INDEPENDENT_6C = 5,
|
|
INDEPENDENT_7C = 6,
|
|
INDEPENDENT_8C = 7,
|
|
LEFT_SIDE_STEREO = 8,
|
|
RIGHT_SIDE_STEREO = 9,
|
|
MID_SIDE_STEREO = 10,
|
|
} fx_flac_channel_assignment_t;
|
|
|
|
typedef enum {
|
|
BLK_SIZE_RESERVED = 0,
|
|
BLK_SIZE_192 = 1,
|
|
BLK_SIZE_576 = 2,
|
|
BLK_SIZE_1152 = 3,
|
|
BLK_SIZE_2304 = 4,
|
|
BLK_SIZE_4608 = 5,
|
|
BLK_SIZE_READ_8BIT = 6,
|
|
BLK_SIZE_READ_16BIT = 7,
|
|
BLK_SIZE_256 = 8,
|
|
BLK_SIZE_512 = 9,
|
|
BLK_SIZE_1024 = 10,
|
|
BLK_SIZE_2048 = 11,
|
|
BLK_SIZE_4096 = 12,
|
|
BLK_SIZE_8192 = 13,
|
|
BLK_SIZE_16384 = 14,
|
|
BLK_SIZE_32768 = 15
|
|
} fx_flac_block_size_t;
|
|
|
|
static const int32_t fx_flac_block_sizes_[] = {
|
|
-1, 192, 576, 1152, 2304, 4608, 0, 0,
|
|
256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
|
|
|
|
typedef enum {
|
|
FS_STREAMINFO = 0,
|
|
FS_88_2KHZ = 1,
|
|
FS_176_4KHZ = 2,
|
|
FS_192KHZ = 3,
|
|
FS_8KHZ = 4,
|
|
FS_16KHZ = 5,
|
|
FS_22_05KHZ = 6,
|
|
FS_24KHZ = 7,
|
|
FS_32KHZ = 8,
|
|
FS_44_1KHZ = 9,
|
|
FS_48KHZ = 10,
|
|
FS_96KHZ = 11,
|
|
FS_READ_8BIT_KHZ = 12,
|
|
FS_READ_16BIT_HZ = 13,
|
|
FS_READ_16BIT_DHZ = 14,
|
|
FS_INVALID = 15
|
|
} fx_flac_sample_rate_t;
|
|
|
|
static const int32_t fx_flac_sample_rates_[] = {
|
|
0, 88200, 176400, 192000, 8000, 16000, 22050, 24000,
|
|
32000, 44100, 48000, 96000, 0, 0, 0, -1};
|
|
|
|
typedef enum {
|
|
SS_STREAMINFO = 0,
|
|
SS_8BIT = 1,
|
|
SS_12BIT = 2,
|
|
SS_RESERVED_1 = 3,
|
|
SS_16BIT = 4,
|
|
SS_20BIT = 5,
|
|
SS_24BIT = 6,
|
|
SS_RESERVED_2 = 7
|
|
} fx_flac_sample_size_t;
|
|
|
|
static const int8_t fx_flac_sample_sizes_[] = {0, 8, 12, -1, 16, 20, 24, -1};
|
|
|
|
typedef enum {
|
|
SFT_CONSTANT,
|
|
SFT_VERBATIM,
|
|
SFT_FIXED,
|
|
SFT_LPC
|
|
} fx_flac_subframe_type_t;
|
|
|
|
typedef enum {
|
|
RES_RICE = 0,
|
|
RES_RICE2 = 1,
|
|
RES_RESERVED_1 = 2,
|
|
RES_RESERVED_2 = 3
|
|
} fx_flac_residual_method_t;
|
|
|
|
/******************************************************************************
|
|
* Structs defined in the flac format specification *
|
|
******************************************************************************/
|
|
|
|
/**
|
|
* Struc holding all the information stored in an individual block header.
|
|
*/
|
|
typedef struct {
|
|
/**
|
|
* Set to 1 if this metadata block is the last metadata block in the
|
|
* stream.
|
|
*/
|
|
bool is_last;
|
|
|
|
/**
|
|
* Type of the metadata block.
|
|
*/
|
|
fx_flac_metadata_type_t type;
|
|
|
|
/**
|
|
* Length of the metadata block in bytes.
|
|
*/
|
|
uint32_t length;
|
|
} fx_flac_metadata_t;
|
|
|
|
/**
|
|
* Data stored in the STREAMINFO header.
|
|
*/
|
|
typedef struct {
|
|
uint16_t min_block_size;
|
|
uint16_t max_block_size;
|
|
uint32_t min_frame_size;
|
|
uint32_t max_frame_size;
|
|
uint32_t sample_rate;
|
|
uint8_t n_channels;
|
|
uint8_t sample_size;
|
|
uint64_t n_samples;
|
|
uint8_t md5_sum[16];
|
|
} fx_flac_streaminfo_t;
|
|
|
|
/**
|
|
* Frame header prepended to each FLAC audio block.
|
|
*/
|
|
typedef struct {
|
|
fx_flac_blocking_strategy_t blocking_strategy;
|
|
fx_flac_block_size_t block_size_enum;
|
|
fx_flac_sample_rate_t sample_rate_enum;
|
|
fx_flac_channel_assignment_t channel_assignment;
|
|
fx_flac_sample_size_t sample_size_enum;
|
|
uint32_t block_size;
|
|
uint32_t sample_rate;
|
|
uint8_t channel_count;
|
|
uint8_t sample_size;
|
|
uint64_t sync_info;
|
|
uint8_t crc8;
|
|
} fx_flac_frame_header_t;
|
|
|
|
/**
|
|
* Header prepended to the channel-specific data of each FLAC audio block.
|
|
*/
|
|
typedef struct {
|
|
/**
|
|
* Specifies the method used to encode the data.
|
|
*/
|
|
fx_flac_subframe_type_t type;
|
|
|
|
/**
|
|
* Order of this frame.
|
|
*/
|
|
uint8_t order;
|
|
|
|
/**
|
|
* Number of bits the decoded result has to be shifted to the left.
|
|
*/
|
|
uint8_t wasted_bits;
|
|
|
|
/**
|
|
* Number of bits used to encode the linear predictor coefficients.
|
|
*/
|
|
uint8_t lpc_prec;
|
|
|
|
/**
|
|
* Shift applied to the coefficients.
|
|
*/
|
|
int8_t lpc_shift;
|
|
|
|
/**
|
|
* LPC coefficients. Number of used coefficients corresponds to the order.
|
|
*/
|
|
int32_t *lpc_coeffs;
|
|
|
|
/**
|
|
* Method used to code the residual. FLAC currently only supports RICE and
|
|
* RICE2.
|
|
*/
|
|
fx_flac_residual_method_t residual_method;
|
|
|
|
/**
|
|
* Number of partitions the signal is divided into.
|
|
*/
|
|
uint8_t rice_partition_order;
|
|
|
|
/**
|
|
* RICE parameter, i.e. the logarithm of the divisor.
|
|
*/
|
|
uint8_t rice_parameter;
|
|
|
|
} fx_flac_subframe_header_t;
|
|
|
|
/**
|
|
* Array containing the LPC coefficients for the fixed coding mode.
|
|
*/
|
|
static const int32_t _fx_flac_fixed_coeffs[5][4] = {
|
|
{0,0,0,0}, {1,0,0,0}, {2, -1, 0, 0}, {3, -3, 1, 0}, {4, -6, 4, -1}
|
|
};
|
|
|
|
/******************************************************************************
|
|
* Internal state machine enums *
|
|
******************************************************************************/
|
|
|
|
/**
|
|
* More fine-grained state descriptor used in the internal state machine.
|
|
*/
|
|
typedef enum {
|
|
FLAC_SYNC_INIT = 0,
|
|
FLAC_SYNC_F = 100,
|
|
FLAC_SYNC_L = 101,
|
|
FLAC_SYNC_A = 102,
|
|
FLAC_METADATA_HEADER = 200,
|
|
FLAC_METADATA_SKIP = 201,
|
|
FLAC_METADATA_SINFO = 202,
|
|
FLAC_FRAME_SYNC = 300,
|
|
FLAC_FRAME_HEADER = 400,
|
|
FLAC_FRAME_HEADER_SYNC_INFO = 401,
|
|
FLAC_FRAME_HEADER_AUX = 402,
|
|
FLAC_FRAME_HEADER_CRC = 403,
|
|
FLAC_SUBFRAME_HEADER = 500,
|
|
FLAC_SUBFRAME_CONSTANT = 502,
|
|
FLAC_SUBFRAME_FIXED = 503,
|
|
FLAC_SUBFRAME_FIXED_RESIDUAL = 504,
|
|
FLAC_SUBFRAME_LPC = 505,
|
|
FLAC_SUBFRAME_LPC_HEADER = 506,
|
|
FLAC_SUBFRAME_LPC_COEFFS = 507,
|
|
FLAC_SUBFRAME_LPC_RESIDUAL = 508,
|
|
FLAC_SUBFRAME_RICE_INIT = 509,
|
|
FLAC_SUBFRAME_RICE = 510,
|
|
FLAC_SUBFRAME_RICE_UNARY = 511,
|
|
FLAC_SUBFRAME_RICE_VERBATIM = 512,
|
|
FLAC_SUBFRAME_RICE_FINALIZE = 513,
|
|
FLAC_SUBFRAME_VERBATIM = 514,
|
|
FLAC_SUBFRAME_FINALIZE = 515
|
|
} fx_flac_private_state_t;
|
|
|
|
/******************************************************************************
|
|
* Internal structs *
|
|
******************************************************************************/
|
|
|
|
/**
|
|
* Private definition of the fx_flac structure.
|
|
*/
|
|
struct fx_flac {
|
|
/**
|
|
* Bitstream reader used to read individual bits from the input.
|
|
*/
|
|
fx_bitstream_t bitstream;
|
|
|
|
/**
|
|
* Current state of the decoder.
|
|
*/
|
|
fx_flac_state_t state;
|
|
|
|
/**
|
|
* Current private state of the decoder.
|
|
*/
|
|
fx_flac_private_state_t priv_state;
|
|
|
|
/**
|
|
* Number of bytes remaining to read for the current frame/block.
|
|
*/
|
|
uint32_t n_bytes_rem;
|
|
|
|
/**
|
|
* Maximum numbers of samples in a single block, per channel.
|
|
*/
|
|
uint16_t max_block_size;
|
|
|
|
/**
|
|
* Maximum number of channels supported by the decoder.
|
|
*/
|
|
uint8_t max_channels;
|
|
|
|
/**
|
|
* Current coefficient.
|
|
*/
|
|
uint8_t coef_cur;
|
|
|
|
/**
|
|
* Current rice partition.
|
|
*/
|
|
uint16_t partition_cur;
|
|
|
|
/**
|
|
* Current sample index in the current rice partition (decremented to zero).
|
|
*/
|
|
uint16_t partition_sample;
|
|
|
|
/**
|
|
* Current rice partition unary quotient counter.
|
|
*/
|
|
uint16_t rice_unary_counter;
|
|
|
|
/**
|
|
* Current channel. This is reset at frame boundaries.
|
|
*/
|
|
uint8_t chan_cur;
|
|
|
|
/**
|
|
* Pointer into the current block buffer.
|
|
*/
|
|
uint16_t blk_cur;
|
|
|
|
/**
|
|
* Variable holding the checksum computed when reading the frame_header.
|
|
*/
|
|
uint8_t crc8;
|
|
|
|
/**
|
|
* Variable holding the checksum of an entire frame. If this checksum does
|
|
* not match after decoding a frame, the entire frame is rejected.
|
|
*/
|
|
uint16_t crc16;
|
|
|
|
/**
|
|
* Flag indicating whether the current metadata block is the last metadata
|
|
* block.
|
|
*/
|
|
fx_flac_metadata_t *metadata;
|
|
|
|
/**
|
|
* Structure holding the current stream metadata.
|
|
*/
|
|
fx_flac_streaminfo_t *streaminfo;
|
|
|
|
/**
|
|
* Structure holding the frame header.
|
|
*/
|
|
fx_flac_frame_header_t *frame_header;
|
|
|
|
/**
|
|
* Structure holding the subframe header.
|
|
*/
|
|
fx_flac_subframe_header_t *subframe_header;
|
|
|
|
/**
|
|
* Buffer used for storing the LPC coefficients.
|
|
*/
|
|
int32_t *qbuf;
|
|
|
|
/**
|
|
* Structure holding the temporary/output buffers for each channel.
|
|
*/
|
|
int32_t *blkbuf[FLAC_MAX_CHANNEL_COUNT];
|
|
};
|
|
|
|
/******************************************************************************
|
|
* PRIVATE CODE *
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
* Initialization code utils *
|
|
******************************************************************************/
|
|
|
|
static bool _fx_flac_check_params(uint16_t max_block_size,
|
|
uint8_t max_channels) {
|
|
return (max_block_size > 0U) && (max_channels > 0U) &&
|
|
(max_channels <= FLAC_MAX_CHANNEL_COUNT);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* FLAC enum decoders *
|
|
******************************************************************************/
|
|
|
|
static bool _fx_flac_decode_block_size(fx_flac_block_size_t block_size_enum,
|
|
uint32_t *block_size) {
|
|
const int32_t bs = fx_flac_block_sizes_[(int)block_size_enum];
|
|
if (bs < 0) {
|
|
return false; /* Invalid */
|
|
} else if (bs > 0) {
|
|
*block_size = bs;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool _fx_flac_decode_sample_rate(fx_flac_sample_rate_t sample_rate_enum,
|
|
uint32_t *sample_rate) {
|
|
const int32_t fs = fx_flac_sample_rates_[(int)sample_rate_enum];
|
|
if (fs < 0) {
|
|
return false; /* Invalid */
|
|
} else if (fs > 0) {
|
|
*sample_rate = fs;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool _fx_flac_decode_sample_size(fx_flac_sample_size_t sample_size_enum,
|
|
uint8_t *sample_size) {
|
|
const int8_t ss = fx_flac_sample_sizes_[(int)sample_size_enum];
|
|
if (ss < 0) {
|
|
return false; /* Invalid */
|
|
} else if (ss > 0) {
|
|
*sample_size = ss;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns the number of channels encoded in the frame header.
|
|
*/
|
|
static bool _fx_flac_decode_channel_count(
|
|
fx_flac_channel_assignment_t channel_assignment, uint8_t *channel_count) {
|
|
*channel_count = (channel_assignment >= LEFT_SIDE_STEREO)
|
|
? 2U
|
|
: (uint8_t)channel_assignment + 1U;
|
|
return true;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Decoding functions *
|
|
******************************************************************************/
|
|
|
|
static inline void _fx_flac_post_process_left_side(int32_t *blk1, int32_t *blk2,
|
|
uint32_t blk_size) {
|
|
blk1 = (int32_t *)FX_ASSUME_ALIGNED(blk1);
|
|
blk2 = (int32_t *)FX_ASSUME_ALIGNED(blk2);
|
|
for (uint32_t i = 0U; i < blk_size; i++) {
|
|
blk2[i] = blk1[i] - blk2[i];
|
|
}
|
|
}
|
|
|
|
static inline void _fx_flac_post_process_right_side(int32_t *blk1,
|
|
int32_t *blk2,
|
|
uint32_t blk_size) {
|
|
blk1 = (int32_t *)FX_ASSUME_ALIGNED(blk1);
|
|
blk2 = (int32_t *)FX_ASSUME_ALIGNED(blk2);
|
|
for (uint32_t i = 0U; i < blk_size; i++) {
|
|
blk1[i] = blk1[i] + blk2[i];
|
|
}
|
|
}
|
|
|
|
static inline void _fx_flac_post_process_mid_side(int32_t *blk1, int32_t *blk2,
|
|
uint32_t blk_size) {
|
|
blk1 = (int32_t *)FX_ASSUME_ALIGNED(blk1);
|
|
blk2 = (int32_t *)FX_ASSUME_ALIGNED(blk2);
|
|
for (uint32_t i = 0U; i < blk_size; i++) {
|
|
/* Code libflac from stream_decoder.c */
|
|
int32_t mid = blk1[i];
|
|
int32_t side = blk2[i];
|
|
mid = ((uint32_t)mid) << 1;
|
|
mid |= (side & 1); /* Round correctly */
|
|
blk1[i] = (mid + side) >> 1;
|
|
blk2[i] = (mid - side) >> 1;
|
|
}
|
|
}
|
|
|
|
static inline void _fx_flac_restore_lpc_signal(int32_t *blk, uint32_t blk_size,
|
|
int32_t *lpc_coeffs,
|
|
uint8_t lpc_order,
|
|
int8_t lpc_shift) {
|
|
blk = (int32_t *)FX_ASSUME_ALIGNED(blk);
|
|
lpc_coeffs = (int32_t *)FX_ASSUME_ALIGNED(lpc_coeffs);
|
|
|
|
for (uint32_t i = lpc_order; i < blk_size; i++) {
|
|
int64_t accu = 0;
|
|
for (uint8_t j = 0; j < lpc_order; j++) {
|
|
accu += (int64_t)lpc_coeffs[j] * (int64_t)blk[i - j - 1];
|
|
}
|
|
blk[i] = blk[i] + (accu >> lpc_shift);
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Stream utility functions and macros *
|
|
******************************************************************************/
|
|
|
|
/* http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend */
|
|
#define SIGN_EXTEND(x, b) \
|
|
(int64_t)((x) ^ (1LU << ((b)-1U))) - (int64_t)(1LU << ((b)-1U))
|
|
|
|
#define ENSURE_BITS(n) \
|
|
if (!fx_bitstream_can_read(&inst->bitstream, n)) { \
|
|
return false; /* Need more data */ \
|
|
}
|
|
|
|
#define READ_BITS(n) \
|
|
(tmp_ = fx_bitstream_try_read_msb(&inst->bitstream, n)); \
|
|
if (tmp_ < 0) { \
|
|
return false; /* Need more data */ \
|
|
}
|
|
|
|
#define READ_BITS_FAST(n) (tmp_ = fx_bitstream_read_msb(&inst->bitstream, n));
|
|
|
|
#define PEEK_BITS(n) \
|
|
(tmp_ = fx_bitstream_try_peek_msb(&inst->bitstream, n)); \
|
|
if (tmp_ < 0) { \
|
|
return false; /* Need more data */ \
|
|
}
|
|
|
|
#define SYNC_BYTESTREAM() \
|
|
{ \
|
|
uint8_t n_ = inst->bitstream.pos & 0x07; \
|
|
if (n_) { \
|
|
READ_BITS(8U - n_); \
|
|
} \
|
|
}
|
|
|
|
#ifdef FX_FLAC_NO_CRC
|
|
|
|
/* Just alias the CRC versions of the READ macros to the read macros
|
|
themselves */
|
|
#define READ_BITS_CRC(n) READ_BITS(n)
|
|
#define READ_BITS_FAST_CRC(n) READ_BITS_FAST(n)
|
|
#define READ_BITS_DCRC(n) READ_BITS(n)
|
|
#define READ_BITS_FAST_DCRC(n) READ_BITS_FAST(n)
|
|
#define SYNC_BYTESTREAM_CRC() SYNC_BYTESTREAM()
|
|
|
|
#else /* FX_FLAC_NO_CRC */
|
|
|
|
/* Update the frame checksum while reading data */
|
|
|
|
#define READ_BITS_CRC(n) \
|
|
(tmp_ = fx_bitstream_try_read_msb_ex(&inst->bitstream, n, _fx_flac_crc16_, \
|
|
inst)); \
|
|
if (tmp_ < 0) { \
|
|
return false; /* Need more data */ \
|
|
}
|
|
|
|
#define READ_BITS_FAST_CRC(n) \
|
|
(tmp_ = fx_bitstream_read_msb_ex(&inst->bitstream, n, _fx_flac_crc16_, \
|
|
inst));
|
|
|
|
/* DCRC -> Dual CRC, update both the header and the frame checksum */
|
|
|
|
#define READ_BITS_DCRC(n) \
|
|
(tmp_ = fx_bitstream_try_read_msb_ex(&inst->bitstream, n, \
|
|
_fx_flac_double_crc_, inst)); \
|
|
if (tmp_ < 0) { \
|
|
return false; /* Need more data */ \
|
|
}
|
|
|
|
#define READ_BITS_FAST_DCRC(n) \
|
|
(tmp_ = fx_bitstream_read_msb_ex(&inst->bitstream, n, \
|
|
_fx_flac_double_crc_, inst));
|
|
|
|
#define SYNC_BYTESTREAM_CRC() \
|
|
{ \
|
|
uint8_t n_ = inst->bitstream.pos & 0x07; \
|
|
if (n_) { \
|
|
READ_BITS_CRC(8U - n_); \
|
|
} \
|
|
}
|
|
|
|
static const uint8_t fx_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};
|
|
|
|
static const uint16_t fx_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};
|
|
|
|
static inline void _fx_flac_crc8_(uint8_t byte, void *data) {
|
|
fx_flac_t *inst = (fx_flac_t *)FX_ASSUME_ALIGNED(data);
|
|
inst->crc8 = fx_flac_crc8_table_[inst->crc8 ^ byte];
|
|
}
|
|
|
|
static inline void _fx_flac_crc16_(uint8_t byte, void *data) {
|
|
fx_flac_t *inst = (fx_flac_t *)FX_ASSUME_ALIGNED(data);
|
|
const uint8_t i = ((inst->crc16 >> 8U) ^ byte) & 0xFF;
|
|
inst->crc16 = fx_flac_crc16_table_[i] ^ (inst->crc16 << 8U);
|
|
}
|
|
|
|
static inline void _fx_flac_double_crc_(uint8_t byte, void *data) {
|
|
_fx_flac_crc8_(byte, data);
|
|
_fx_flac_crc16_(byte, data);
|
|
}
|
|
#endif /* FX_FLAC_NO_CRC */
|
|
|
|
static bool _fx_flac_reader_utf8_coded_int(fx_flac_t *inst, uint8_t max_n,
|
|
uint64_t *tar) {
|
|
int64_t tmp_; /* Used by the READ_BITS macro */
|
|
|
|
ENSURE_BITS(max_n * 8U);
|
|
/* Read the first byte */
|
|
uint8_t v = READ_BITS_FAST_DCRC(8U);
|
|
|
|
/* Count the number of ones in the first byte */
|
|
uint8_t n_ones = 0U;
|
|
while (v & 0x80U) {
|
|
v = v << 1U;
|
|
n_ones++;
|
|
}
|
|
|
|
/* Abort if the number of bytes to read is larger than max_n */
|
|
if (n_ones > max_n) {
|
|
inst->priv_state = FLAC_FRAME_SYNC; /* Invalid header */
|
|
return true;
|
|
}
|
|
|
|
/* Shift v back and store in var */
|
|
*tar = (v >> n_ones);
|
|
|
|
/* Read all continuation bytes */
|
|
for (uint8_t i = 1U; i < n_ones; i++) {
|
|
v = READ_BITS_FAST_DCRC(8U);
|
|
/* Abort if continuation byte doesn't start with correct sequence */
|
|
if ((v & 0xC0U) != 0x80) {
|
|
inst->priv_state = FLAC_FRAME_SYNC; /* Invalid header */
|
|
return true;
|
|
}
|
|
*tar = ((*tar) << 6U) | (v & 0x3F);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Private decoder state machine *
|
|
******************************************************************************/
|
|
|
|
/*
|
|
* Note: the boolean return value of these functions indicates whether they
|
|
* rand out of data -- true indicates that there is still enough data left,
|
|
* false indicates that the outer state machine should return to the user code
|
|
* to read more data. The return value does NOT indicate success/failure. This
|
|
* is what inst->state == FLAC_ERR is for.
|
|
*/
|
|
|
|
static bool _fx_flac_handle_err(fx_flac_t *inst) {
|
|
/* TODO: Add flags to fx_flac_t which control this behaviour */
|
|
|
|
/* If an error happens while searching for metadata, this is fatal. */
|
|
if (inst->state < FLAC_END_OF_METADATA) {
|
|
inst->state = FLAC_ERR;
|
|
return false;
|
|
}
|
|
|
|
/* Otherwise just try to re-synchronise with the stream by searching for the
|
|
next frame */
|
|
inst->state = FLAC_SEARCH_FRAME;
|
|
inst->priv_state = FLAC_FRAME_SYNC;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Statemachine used to search the beginning of the stream. This (for example)
|
|
* skips IDv3 tags prepended to the file.
|
|
*/
|
|
static bool _fx_flac_process_init(fx_flac_t *inst) {
|
|
int64_t tmp_; /* Used by the READ_BITS macro */
|
|
/* Search for the 'fLaC' sync word */
|
|
uint8_t byte = READ_BITS(8);
|
|
switch (inst->priv_state) {
|
|
case FLAC_SYNC_INIT:
|
|
if (byte == 'f') {
|
|
inst->priv_state = FLAC_SYNC_F;
|
|
}
|
|
break;
|
|
case FLAC_SYNC_F:
|
|
if (byte == 'L') {
|
|
inst->priv_state = FLAC_SYNC_L;
|
|
} else {
|
|
inst->priv_state = FLAC_SYNC_INIT;
|
|
}
|
|
break;
|
|
case FLAC_SYNC_L:
|
|
if (byte == 'a') {
|
|
inst->priv_state = FLAC_SYNC_A;
|
|
} else {
|
|
inst->priv_state = FLAC_SYNC_INIT;
|
|
}
|
|
break;
|
|
case FLAC_SYNC_A:
|
|
if (byte == 'C') {
|
|
inst->state = FLAC_IN_METADATA;
|
|
inst->priv_state = FLAC_METADATA_HEADER;
|
|
} else {
|
|
inst->priv_state = FLAC_SYNC_INIT;
|
|
}
|
|
break;
|
|
default:
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool _fx_flac_process_in_metadata(fx_flac_t *inst) {
|
|
int64_t tmp_; /* Used by the READ_BITS macro */
|
|
switch (inst->priv_state) {
|
|
case FLAC_METADATA_HEADER:
|
|
ENSURE_BITS(32U);
|
|
inst->metadata->is_last = READ_BITS_FAST(1U);
|
|
inst->metadata->type = (fx_flac_metadata_type_t)READ_BITS_FAST(7U);
|
|
if (inst->metadata->type == META_TYPE_INVALID) {
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
inst->metadata->length = inst->n_bytes_rem = READ_BITS_FAST(24U);
|
|
if (inst->metadata->type == META_TYPE_STREAMINFO) {
|
|
inst->priv_state = FLAC_METADATA_SINFO;
|
|
/* The stream info header must be exactly 33 bytes long */
|
|
if (inst->metadata->length != 34U) {
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
} else {
|
|
inst->priv_state = FLAC_METADATA_SKIP;
|
|
}
|
|
break;
|
|
case FLAC_METADATA_SINFO:
|
|
switch (inst->n_bytes_rem) {
|
|
case 34U:
|
|
inst->streaminfo->min_block_size = READ_BITS(16U);
|
|
inst->n_bytes_rem -= 2U;
|
|
break;
|
|
case 32U:
|
|
inst->streaminfo->max_block_size = READ_BITS(16U);
|
|
inst->n_bytes_rem -= 2U;
|
|
break;
|
|
case 30U:
|
|
inst->streaminfo->min_frame_size = READ_BITS(24U);
|
|
inst->n_bytes_rem -= 3U;
|
|
break;
|
|
case 27U:
|
|
inst->streaminfo->max_frame_size = READ_BITS(24U);
|
|
inst->n_bytes_rem -= 3U;
|
|
break;
|
|
case 24U:
|
|
ENSURE_BITS(28U);
|
|
inst->streaminfo->sample_rate = READ_BITS_FAST(20U);
|
|
inst->streaminfo->n_channels = 1U + READ_BITS_FAST(3U);
|
|
inst->streaminfo->sample_size = 1U + READ_BITS_FAST(5U);
|
|
inst->n_bytes_rem -= 4U;
|
|
break;
|
|
case 20U:
|
|
inst->streaminfo->n_samples = READ_BITS(36U);
|
|
inst->n_bytes_rem -= 4U;
|
|
break;
|
|
case 1U:
|
|
case 2U:
|
|
case 3U:
|
|
case 4U:
|
|
case 5U:
|
|
case 6U:
|
|
case 7U:
|
|
case 8U:
|
|
case 9U:
|
|
case 10U:
|
|
case 11U:
|
|
case 12U:
|
|
case 13U:
|
|
case 14U:
|
|
case 15U:
|
|
case 16U:
|
|
inst->streaminfo->md5_sum[16U - inst->n_bytes_rem] =
|
|
READ_BITS(8);
|
|
inst->n_bytes_rem -= 1U;
|
|
break;
|
|
case 0U:
|
|
/* Use the FLAC_END_OF_METADATA_SKIP state logic below */
|
|
inst->priv_state = FLAC_METADATA_SKIP;
|
|
break;
|
|
default:
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
break;
|
|
case FLAC_METADATA_SKIP: {
|
|
const uint8_t n_read =
|
|
(inst->n_bytes_rem >= 7U) ? 7U : inst->n_bytes_rem;
|
|
if (n_read == 0U) { /* We read all the data for this block */
|
|
if (inst->metadata->is_last) {
|
|
/* Last metadata block, transition to the next state */
|
|
inst->state = FLAC_END_OF_METADATA;
|
|
} else {
|
|
/* End of metadata block, read the next one */
|
|
inst->priv_state = FLAC_METADATA_HEADER;
|
|
}
|
|
break;
|
|
}
|
|
READ_BITS(n_read * 8U);
|
|
inst->n_bytes_rem -= n_read;
|
|
break;
|
|
}
|
|
default:
|
|
return _fx_flac_handle_err(inst); /* Internal error */
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool _fx_flac_process_search_frame(fx_flac_t *inst) {
|
|
int64_t tmp_; /* Used by the READ_BITS macro */
|
|
fx_flac_frame_header_t *fh = inst->frame_header;
|
|
fx_flac_streaminfo_t *si = inst->streaminfo;
|
|
switch (inst->priv_state) {
|
|
case FLAC_FRAME_SYNC:
|
|
/* Synchronise with the underlying bytestream */
|
|
SYNC_BYTESTREAM();
|
|
|
|
ENSURE_BITS(15U);
|
|
uint16_t sync_code = PEEK_BITS(15U);
|
|
if (sync_code != 0x7FFCU) {
|
|
READ_BITS(8U); /* Next byte (assume frames are byte aligned). */
|
|
return true;
|
|
} else {
|
|
inst->crc8 = 0U; /* Reset the checksums */
|
|
inst->crc16 = 0U;
|
|
inst->priv_state = FLAC_FRAME_HEADER;
|
|
READ_BITS_FAST_DCRC(15U);
|
|
}
|
|
break;
|
|
case FLAC_FRAME_HEADER:
|
|
ENSURE_BITS(17U);
|
|
|
|
/* Read the frame header bits */
|
|
fh->blocking_strategy =
|
|
(fx_flac_blocking_strategy_t)READ_BITS_FAST_DCRC(1U);
|
|
fh->block_size_enum = (fx_flac_block_size_t)READ_BITS_FAST_DCRC(4U);
|
|
fh->sample_rate_enum =
|
|
(fx_flac_sample_rate_t)READ_BITS_FAST_DCRC(4U);
|
|
fh->channel_assignment =
|
|
(fx_flac_channel_assignment_t)READ_BITS_FAST_DCRC(4U);
|
|
fh->sample_size_enum =
|
|
(fx_flac_sample_size_t)READ_BITS_FAST_DCRC(3U);
|
|
READ_BITS_FAST_DCRC(1U);
|
|
if (tmp_ != 0U || fh->channel_assignment > MID_SIDE_STEREO) {
|
|
return _fx_flac_handle_err(inst); /* Invalid header */
|
|
}
|
|
|
|
/* Copy sample rate and sample size from the streaminfo */
|
|
fh->sample_rate = si->sample_rate;
|
|
fh->sample_size = si->sample_size;
|
|
|
|
/* Decode the individual enums */
|
|
if (!_fx_flac_decode_block_size(fh->block_size_enum,
|
|
&fh->block_size) ||
|
|
!_fx_flac_decode_sample_rate(fh->sample_rate_enum,
|
|
&fh->sample_rate) ||
|
|
!_fx_flac_decode_sample_size(fh->sample_size_enum,
|
|
&fh->sample_size) ||
|
|
!_fx_flac_decode_channel_count(fh->channel_assignment,
|
|
&fh->channel_count)) {
|
|
inst->priv_state = FLAC_FRAME_SYNC; /* Got invalid value */
|
|
break;
|
|
}
|
|
inst->priv_state = FLAC_FRAME_HEADER_SYNC_INFO;
|
|
break;
|
|
case FLAC_FRAME_HEADER_SYNC_INFO:
|
|
if (!_fx_flac_reader_utf8_coded_int(
|
|
inst, (fh->blocking_strategy == BLK_VARIABLE) ? 7U : 6U,
|
|
&fh->sync_info)) {
|
|
return false;
|
|
}
|
|
inst->priv_state = FLAC_FRAME_HEADER_AUX;
|
|
break;
|
|
case FLAC_FRAME_HEADER_AUX:
|
|
ENSURE_BITS(32U);
|
|
/* Read block size/sample rate if not directly packed into the
|
|
previous header */
|
|
switch (fh->block_size_enum) {
|
|
case BLK_SIZE_READ_8BIT:
|
|
fh->block_size = 1U + READ_BITS_FAST_DCRC(8U);
|
|
break;
|
|
case BLK_SIZE_READ_16BIT:
|
|
fh->block_size = 1U + READ_BITS_FAST_DCRC(16U);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
switch (fh->sample_rate_enum) {
|
|
case FS_READ_8BIT_KHZ:
|
|
fh->sample_rate = 1000UL * READ_BITS_FAST_DCRC(8U);
|
|
break;
|
|
case FS_READ_16BIT_HZ:
|
|
fh->sample_rate = READ_BITS_FAST_DCRC(16U);
|
|
break;
|
|
case FS_READ_16BIT_DHZ:
|
|
fh->sample_rate = 10UL * READ_BITS_FAST_DCRC(16U);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
inst->priv_state = FLAC_FRAME_HEADER_CRC;
|
|
break;
|
|
case FLAC_FRAME_HEADER_CRC:
|
|
/* Read the CRC8 checksum, make sure it equals the checksum written
|
|
to the header. If not, this is not a valid header. Continue
|
|
searching. */
|
|
fh->crc8 = READ_BITS_CRC(8U);
|
|
#ifndef FX_FLAC_NO_CRC
|
|
if (fh->crc8 != inst->crc8) {
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
#endif
|
|
|
|
/* Make sure the decode has enough space */
|
|
if ((fh->block_size > inst->max_block_size) ||
|
|
(fh->channel_count > inst->max_channels)) {
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
|
|
/* Decode the subframes */
|
|
inst->state = FLAC_IN_FRAME;
|
|
inst->priv_state = FLAC_SUBFRAME_HEADER;
|
|
inst->chan_cur = 0U; /* Start with the first channel */
|
|
break;
|
|
default:
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool _fx_flac_process_in_frame(fx_flac_t *inst) {
|
|
int64_t tmp_ = 0; /* Used by the READ_BITS macro */
|
|
fx_flac_frame_header_t *fh = inst->frame_header;
|
|
fx_flac_subframe_header_t *sfh = inst->subframe_header;
|
|
int32_t *blk = inst->blkbuf[inst->chan_cur % FLAC_MAX_CHANNEL_COUNT];
|
|
const uint32_t blk_n = fh->block_size;
|
|
|
|
/* Figure out the number of bits to read for sample. This depends on the
|
|
channel assignment. */
|
|
uint8_t bps = fh->sample_size - sfh->wasted_bits;
|
|
if ((fh->channel_assignment == LEFT_SIDE_STEREO && inst->chan_cur == 1) ||
|
|
(fh->channel_assignment == RIGHT_SIDE_STEREO && inst->chan_cur == 0) ||
|
|
(fh->channel_assignment == MID_SIDE_STEREO && inst->chan_cur == 1)) {
|
|
bps++;
|
|
}
|
|
|
|
/* Discard frames with invalid bits per sample values */
|
|
if (bps == 0U || bps > 32U) {
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
|
|
/* This flag is set to false whenever a state in the state machine
|
|
encounters and error. */
|
|
switch (inst->priv_state) {
|
|
case FLAC_SUBFRAME_HEADER: {
|
|
ENSURE_BITS(40U);
|
|
|
|
/* Reset the block write cursor, make sure initial blk sample is set
|
|
to zero for zero-order fixed LPC */
|
|
inst->blk_cur = 0U;
|
|
blk[0U] = 0U;
|
|
|
|
/* Read a zero padding bit. This must be zero. */
|
|
uint8_t padding = READ_BITS_FAST_CRC(1U);
|
|
bool valid = padding == 0U;
|
|
|
|
/* Read the frame type and order */
|
|
uint8_t type = READ_BITS_FAST_CRC(6U);
|
|
if (type & 0x20U) {
|
|
sfh->order = (type & 0x1FU) + 1U;
|
|
sfh->type = SFT_LPC;
|
|
sfh->lpc_coeffs = inst->qbuf;
|
|
inst->priv_state = FLAC_SUBFRAME_LPC;
|
|
} else if (type & 0x10U) {
|
|
return _fx_flac_handle_err(inst);
|
|
} else if (type & 0x08U) {
|
|
sfh->order = type & 0x07U;
|
|
sfh->type = SFT_FIXED;
|
|
sfh->lpc_shift = 0;
|
|
inst->priv_state = FLAC_SUBFRAME_FIXED;
|
|
valid = valid && (sfh->order <= 4U);
|
|
if (valid) {
|
|
sfh->lpc_coeffs =
|
|
(int32_t *)_fx_flac_fixed_coeffs[sfh->order];
|
|
}
|
|
} else if ((type & 0x04U) || (type & 0x02U)) {
|
|
return _fx_flac_handle_err(inst);
|
|
} else if (type & 0x01U) {
|
|
sfh->type = SFT_VERBATIM;
|
|
inst->priv_state = FLAC_SUBFRAME_VERBATIM;
|
|
} else {
|
|
sfh->type = SFT_CONSTANT;
|
|
inst->priv_state = FLAC_SUBFRAME_CONSTANT;
|
|
}
|
|
|
|
/* Read the "wasted_bits" flag */
|
|
sfh->wasted_bits = READ_BITS_FAST_CRC(1U);
|
|
if (sfh->wasted_bits) {
|
|
for (uint8_t i = 1U; i <= 30U; i++) {
|
|
const uint8_t bit = READ_BITS_FAST_CRC(1U);
|
|
if (bit == 1U) {
|
|
sfh->wasted_bits = i;
|
|
break;
|
|
}
|
|
}
|
|
valid = valid && (sfh->wasted_bits > 0U) &&
|
|
(sfh->wasted_bits < fh->sample_size);
|
|
}
|
|
|
|
/* Make sure the block is large enough for the initial samples */
|
|
valid = valid && (blk_n >= sfh->order);
|
|
if (!valid) {
|
|
_fx_flac_handle_err(inst);
|
|
}
|
|
break;
|
|
}
|
|
case FLAC_SUBFRAME_CONSTANT: {
|
|
/* Read a single sample value and spread it over the entire block
|
|
buffer for this subframe. */
|
|
blk[0U] = READ_BITS_CRC(bps);
|
|
blk[0U] = SIGN_EXTEND(blk[0U], bps);
|
|
for (uint16_t i = 1U; i < blk_n; i++) {
|
|
blk[i] = blk[0U];
|
|
}
|
|
inst->priv_state = FLAC_SUBFRAME_FINALIZE;
|
|
break;
|
|
}
|
|
case FLAC_SUBFRAME_VERBATIM:
|
|
case FLAC_SUBFRAME_FIXED:
|
|
case FLAC_SUBFRAME_LPC: {
|
|
/* Either just read up to "order" samples, or the entire block */
|
|
const uint32_t n = (sfh->type == SFT_VERBATIM) ? blk_n : sfh->order;
|
|
while (inst->blk_cur < n) {
|
|
blk[inst->blk_cur] = READ_BITS_CRC(bps);
|
|
blk[inst->blk_cur] = SIGN_EXTEND(blk[inst->blk_cur], bps);
|
|
inst->blk_cur++;
|
|
}
|
|
inst->priv_state =
|
|
(fx_flac_private_state_t)((int)inst->priv_state + 1U);
|
|
break;
|
|
}
|
|
case FLAC_SUBFRAME_LPC_HEADER: {
|
|
/* Read the coefficient precision as well as the shift value */
|
|
ENSURE_BITS(9U);
|
|
const uint8_t prec = READ_BITS_FAST_CRC(4U);
|
|
const uint8_t shift = READ_BITS_FAST_CRC(5U);
|
|
if (prec == 15U) { /* Precision of 15 bits is invalid */
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
sfh->lpc_prec = prec + 1U;
|
|
sfh->lpc_shift = SIGN_EXTEND(shift, 5U);
|
|
if (sfh->lpc_shift < 0) {
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
inst->coef_cur = 0U;
|
|
inst->priv_state = FLAC_SUBFRAME_LPC_COEFFS;
|
|
break;
|
|
}
|
|
case FLAC_SUBFRAME_LPC_COEFFS:
|
|
/* Read the individual predictor coefficients */
|
|
while (inst->coef_cur < sfh->order) {
|
|
uint32_t coef = READ_BITS_CRC(sfh->lpc_prec);
|
|
sfh->lpc_coeffs[inst->coef_cur] =
|
|
SIGN_EXTEND(coef, sfh->lpc_prec);
|
|
inst->coef_cur++;
|
|
}
|
|
inst->priv_state = FLAC_SUBFRAME_LPC_RESIDUAL;
|
|
break;
|
|
case FLAC_SUBFRAME_FIXED_RESIDUAL:
|
|
case FLAC_SUBFRAME_LPC_RESIDUAL: {
|
|
ENSURE_BITS(6U);
|
|
|
|
/* Read the residual encoding type and the rice partition order */
|
|
sfh->residual_method =
|
|
(fx_flac_residual_method_t)READ_BITS_FAST_CRC(2U);
|
|
if (sfh->residual_method > RES_RICE2) {
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
sfh->rice_partition_order = READ_BITS_FAST_CRC(4U);
|
|
inst->partition_cur = 0U;
|
|
inst->priv_state = FLAC_SUBFRAME_RICE_INIT;
|
|
break;
|
|
}
|
|
case FLAC_SUBFRAME_RICE_INIT: {
|
|
/* Read the Rice parameter */
|
|
ENSURE_BITS(10U);
|
|
|
|
uint8_t n_bits = (sfh->residual_method == RES_RICE) ? 4U : 5U;
|
|
sfh->rice_parameter = READ_BITS_FAST_CRC(n_bits);
|
|
if (sfh->rice_parameter == ((1U << n_bits) - 1U)) {
|
|
sfh->rice_parameter = READ_BITS_FAST_CRC(5U);
|
|
inst->priv_state = FLAC_SUBFRAME_RICE_VERBATIM;
|
|
} else {
|
|
inst->priv_state = FLAC_SUBFRAME_RICE_UNARY;
|
|
inst->rice_unary_counter = 0U;
|
|
}
|
|
|
|
/* Compute the number of samples to read */
|
|
inst->partition_sample = blk_n >> sfh->rice_partition_order;
|
|
if (inst->partition_cur == 0U) {
|
|
/* First partition alread includes verbatim samples */
|
|
if (inst->partition_sample < sfh->order) {
|
|
return _fx_flac_handle_err(
|
|
inst); /* Number of samples is negative */
|
|
}
|
|
inst->partition_sample -= sfh->order;
|
|
}
|
|
|
|
/* Make sure we're never writing beyond the buffer for this
|
|
channel */
|
|
if ((inst->partition_sample + inst->blk_cur) > blk_n) {
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
break;
|
|
}
|
|
case FLAC_SUBFRAME_RICE:
|
|
case FLAC_SUBFRAME_RICE_UNARY:
|
|
/* Read the individual rice samples */
|
|
while (inst->partition_sample > 0U) {
|
|
/* Read the unary part of the Rice encoded sample bit-by-bit */
|
|
if (inst->priv_state == FLAC_SUBFRAME_RICE_UNARY) {
|
|
while (true) {
|
|
const uint8_t bit = READ_BITS_CRC(1U);
|
|
if (bit) {
|
|
break;
|
|
}
|
|
inst->rice_unary_counter++;
|
|
}
|
|
}
|
|
|
|
/* If there are no more bits left below, make sure we end up
|
|
here instead of going through the unary decoder again. */
|
|
inst->priv_state = FLAC_SUBFRAME_RICE;
|
|
|
|
/* Read the remainder */
|
|
uint32_t r = 0U;
|
|
if (sfh->rice_parameter > 0U) {
|
|
r = READ_BITS_CRC(sfh->rice_parameter);
|
|
}
|
|
const uint16_t q = inst->rice_unary_counter;
|
|
const uint32_t val = (q << sfh->rice_parameter) | r;
|
|
|
|
/* Last bit determines sign */
|
|
if (val & 1) {
|
|
blk[inst->blk_cur] = -((int32_t)(val >> 1)) - 1;
|
|
} else {
|
|
blk[inst->blk_cur] = (int32_t)(val >> 1);
|
|
}
|
|
|
|
/* Read the next sample */
|
|
inst->rice_unary_counter = 0U;
|
|
inst->priv_state = FLAC_SUBFRAME_RICE_UNARY;
|
|
inst->blk_cur++;
|
|
inst->partition_sample--;
|
|
}
|
|
inst->priv_state = FLAC_SUBFRAME_RICE_FINALIZE;
|
|
break;
|
|
case FLAC_SUBFRAME_RICE_VERBATIM: {
|
|
/* Samples are encoded in verbatim in this partition */
|
|
const uint8_t bps = sfh->rice_parameter;
|
|
while (inst->partition_sample > 0U) {
|
|
blk[inst->blk_cur] = (bps == 0) ? 0U : READ_BITS_CRC(bps);
|
|
blk[inst->blk_cur] = SIGN_EXTEND(blk[inst->blk_cur], bps);
|
|
inst->blk_cur++;
|
|
inst->partition_sample--;
|
|
}
|
|
inst->priv_state = FLAC_SUBFRAME_RICE_FINALIZE;
|
|
break;
|
|
}
|
|
case FLAC_SUBFRAME_RICE_FINALIZE:
|
|
/* Go to the next partition or finalize this subframe */
|
|
inst->partition_cur++;
|
|
if (inst->partition_cur == (1U << sfh->rice_partition_order)) {
|
|
/* Decode the residual */
|
|
_fx_flac_restore_lpc_signal(blk, blk_n, sfh->lpc_coeffs,
|
|
sfh->order, sfh->lpc_shift);
|
|
inst->priv_state = FLAC_SUBFRAME_FINALIZE;
|
|
} else {
|
|
inst->priv_state = FLAC_SUBFRAME_RICE_INIT;
|
|
}
|
|
break;
|
|
case FLAC_SUBFRAME_FINALIZE: {
|
|
/* Apply the wasted bits transformation */
|
|
if (sfh->wasted_bits) {
|
|
uint8_t shift = sfh->wasted_bits;
|
|
for (uint16_t i = 0U; i < blk_n; i++) {
|
|
blk[i] = blk[i] * (1 << shift);
|
|
}
|
|
}
|
|
|
|
/* There is another subframe to read, continue! */
|
|
inst->chan_cur++; /* Go to the next channel */
|
|
if (inst->chan_cur < fh->channel_count) {
|
|
inst->priv_state = FLAC_SUBFRAME_HEADER;
|
|
break;
|
|
}
|
|
|
|
/* Synchronise with the underlying byte stream */
|
|
SYNC_BYTESTREAM_CRC();
|
|
|
|
/* Read the CRC16 sum, resync if it doesn't match our own */
|
|
uint16_t crc16 = READ_BITS(16U);
|
|
#ifndef FX_FLAC_NO_CRC
|
|
if (crc16 != inst->crc16) {
|
|
return _fx_flac_handle_err(inst);
|
|
}
|
|
#else
|
|
(void)crc16;
|
|
#endif
|
|
|
|
/* Post process side-stereo */
|
|
int32_t *c1 = inst->blkbuf[0], *c2 = inst->blkbuf[1];
|
|
switch (fh->channel_assignment) {
|
|
case LEFT_SIDE_STEREO:
|
|
_fx_flac_post_process_left_side(c1, c2, blk_n);
|
|
break;
|
|
case RIGHT_SIDE_STEREO:
|
|
_fx_flac_post_process_right_side(c1, c2, blk_n);
|
|
break;
|
|
case MID_SIDE_STEREO:
|
|
_fx_flac_post_process_mid_side(c1, c2, blk_n);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* Shift the output such that the resulting int32 stream can be
|
|
played back. */
|
|
uint8_t shift = 32U - fh->sample_size;
|
|
if (shift) {
|
|
for (uint8_t c = 0U; c < fh->channel_count; c++) {
|
|
int32_t *blk = inst->blkbuf[c];
|
|
for (uint16_t i = 0U; i < blk_n; i++) {
|
|
blk[i] = blk[i] * (1 << shift);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* We're done decoding this frame! Notify the outer loop! */
|
|
inst->blk_cur = 0U; /* Reset the read cursor */
|
|
inst->chan_cur = 0U;
|
|
inst->state = FLAC_DECODED_FRAME;
|
|
break;
|
|
}
|
|
default:
|
|
inst->state = FLAC_ERR;
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool _fx_flac_process_decoded_frame(fx_flac_t *inst, int32_t *out,
|
|
uint32_t *out_len) {
|
|
/* Fetch the current stream and frame info. */
|
|
const fx_flac_frame_header_t *fh = inst->frame_header;
|
|
|
|
/* Fetch channel count and number of samples left to write */
|
|
const uint8_t cc = fh->channel_count;
|
|
uint32_t n_smpls_rem =
|
|
(fh->block_size - inst->blk_cur - 1U) * cc + (cc - inst->chan_cur);
|
|
|
|
/* Truncate to the actually available space. */
|
|
if (n_smpls_rem > *out_len) {
|
|
n_smpls_rem = *out_len;
|
|
}
|
|
|
|
/* Interlace the decoded samples in the output array */
|
|
uint32_t tar = 0U; /* Number of samples written. */
|
|
while (tar < n_smpls_rem) {
|
|
/* Write to the output buffer */
|
|
out[tar] = inst->blkbuf[inst->chan_cur][inst->blk_cur];
|
|
|
|
/* Advance the read and write cursors */
|
|
inst->chan_cur++;
|
|
if (inst->chan_cur == cc) {
|
|
inst->chan_cur = 0U;
|
|
inst->blk_cur++;
|
|
}
|
|
tar++;
|
|
}
|
|
|
|
/* Inform the caller about the number of samples written */
|
|
*out_len = tar;
|
|
|
|
/* We're done with this frame! */
|
|
if (inst->blk_cur == fh->block_size) {
|
|
inst->state = FLAC_END_OF_FRAME;
|
|
return true;
|
|
}
|
|
|
|
/* Since we're here, we need more space in the output array. */
|
|
return false;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* PUBLIC API *
|
|
******************************************************************************/
|
|
|
|
uint32_t fx_flac_size(uint32_t max_block_size, uint8_t max_channels) {
|
|
/* Calculate the size of the fixed-size structures */
|
|
uint32_t size;
|
|
bool ok = _fx_flac_check_params(max_block_size, max_channels) &&
|
|
fx_mem_init_size(&size) &&
|
|
fx_mem_update_size(&size, sizeof(fx_flac_t)) &&
|
|
fx_mem_update_size(&size, sizeof(fx_flac_metadata_t)) &&
|
|
fx_mem_update_size(&size, sizeof(fx_flac_streaminfo_t)) &&
|
|
fx_mem_update_size(&size, sizeof(fx_flac_frame_header_t)) &&
|
|
fx_mem_update_size(&size, sizeof(fx_flac_subframe_header_t)) &&
|
|
fx_mem_update_size(&size, sizeof(int32_t) * 32U);
|
|
|
|
/* Calculate the size of the structures depending on the given parameters.
|
|
*/
|
|
for (uint8_t i = 0; i < max_channels; i++) {
|
|
ok = ok && fx_mem_update_size(&size, sizeof(int32_t) * max_block_size);
|
|
}
|
|
return ok ? size : 0;
|
|
}
|
|
|
|
fx_flac_t *fx_flac_init(void *mem, uint16_t max_block_size,
|
|
uint8_t max_channels) {
|
|
/* Make sure the parameters are valid. */
|
|
if (!_fx_flac_check_params(max_block_size, max_channels)) {
|
|
return NULL;
|
|
}
|
|
|
|
/* Abort if mem is NULL to allow passing malloc as a direct argument to this
|
|
code. Furthermore, store the original "mem" pointer and return it later
|
|
so the calling code is safe to pass the returned pointer to free. */
|
|
fx_flac_t *inst_unaligned = (fx_flac_t *)mem;
|
|
if (mem) {
|
|
/* Fetch the base address of the flac_t address. */
|
|
fx_flac_t *inst = (fx_flac_t *)fx_mem_align(&mem, sizeof(fx_flac_t));
|
|
|
|
/* Copy the given parameters */
|
|
inst->max_block_size = max_block_size;
|
|
inst->max_channels = max_channels;
|
|
|
|
/* Fetch the base addresses of the internal pointers. */
|
|
inst->metadata = (fx_flac_metadata_t *)fx_mem_align(
|
|
&mem, sizeof(fx_flac_metadata_t));
|
|
inst->streaminfo = (fx_flac_streaminfo_t *)fx_mem_align(
|
|
&mem, sizeof(fx_flac_streaminfo_t));
|
|
inst->frame_header = (fx_flac_frame_header_t *)fx_mem_align(
|
|
&mem, sizeof(fx_flac_frame_header_t));
|
|
inst->subframe_header = (fx_flac_subframe_header_t *)fx_mem_align(
|
|
&mem, sizeof(fx_flac_subframe_header_t));
|
|
inst->qbuf = (int32_t *)fx_mem_align(&mem, sizeof(int32_t) * 32U);
|
|
|
|
/* Compute the addresses of the per-channel buffers */
|
|
for (uint8_t i = 0; i < FLAC_MAX_CHANNEL_COUNT; i++) {
|
|
inst->blkbuf[i] = NULL;
|
|
}
|
|
for (uint8_t i = 0; i < max_channels; i++) {
|
|
inst->blkbuf[i] =
|
|
(int32_t *)fx_mem_align(&mem, sizeof(int32_t) * max_block_size);
|
|
}
|
|
|
|
/* Reset the instance, i.e. zero most/all fields. */
|
|
fx_flac_reset(inst);
|
|
}
|
|
/* Return the original pointer. */
|
|
return inst_unaligned;
|
|
}
|
|
|
|
void fx_flac_reset(fx_flac_t *inst) {
|
|
inst = (fx_flac_t *)FX_ALIGN_ADDR(inst);
|
|
|
|
/* Initialize the bitstream reader */
|
|
fx_bitstream_init(&inst->bitstream);
|
|
|
|
/* Initialize the current metadata block header */
|
|
FX_MEM_ZERO_ALIGNED(inst->metadata);
|
|
inst->metadata->type = META_TYPE_INVALID;
|
|
|
|
/* Initialize the streaminfo structure */
|
|
FX_MEM_ZERO_ALIGNED(inst->streaminfo);
|
|
|
|
/* Initialize the frame_header structure */
|
|
FX_MEM_ZERO_ALIGNED(inst->frame_header);
|
|
|
|
/* Initialize the subframe_header structure */
|
|
FX_MEM_ZERO_ALIGNED(inst->subframe_header);
|
|
|
|
/* Initialize private member variables */
|
|
inst->state = FLAC_INIT;
|
|
inst->priv_state = FLAC_SYNC_INIT;
|
|
inst->n_bytes_rem = 0U;
|
|
inst->crc8 = 0U;
|
|
inst->coef_cur = 0U;
|
|
inst->partition_cur = 0U;
|
|
inst->partition_sample = 0U;
|
|
inst->rice_unary_counter = 0U;
|
|
inst->chan_cur = 0U;
|
|
inst->blk_cur = 0U;
|
|
}
|
|
|
|
fx_flac_state_t fx_flac_get_state(const fx_flac_t *inst) {
|
|
return ((const fx_flac_t *)FX_ALIGN_ADDR(inst))->state;
|
|
}
|
|
|
|
int64_t fx_flac_get_streaminfo(fx_flac_t const *inst,
|
|
fx_flac_streaminfo_key_t key) {
|
|
inst = (fx_flac_t *)FX_ALIGN_ADDR(inst);
|
|
switch (key) {
|
|
case FLAC_KEY_MIN_BLOCK_SIZE:
|
|
return inst->streaminfo->min_block_size;
|
|
case FLAC_KEY_MAX_BLOCK_SIZE:
|
|
return inst->streaminfo->max_block_size;
|
|
case FLAC_KEY_MIN_FRAME_SIZE:
|
|
return inst->streaminfo->min_frame_size;
|
|
case FLAC_KEY_MAX_FRAME_SIZE:
|
|
return inst->streaminfo->max_frame_size;
|
|
case FLAC_KEY_SAMPLE_RATE:
|
|
return inst->streaminfo->sample_rate;
|
|
case FLAC_KEY_N_CHANNELS:
|
|
return inst->streaminfo->n_channels;
|
|
case FLAC_KEY_SAMPLE_SIZE:
|
|
return inst->streaminfo->sample_size;
|
|
case FLAC_KEY_N_SAMPLES:
|
|
return inst->streaminfo->n_samples;
|
|
case FLAC_KEY_MD5_SUM_0:
|
|
case FLAC_KEY_MD5_SUM_1:
|
|
case FLAC_KEY_MD5_SUM_2:
|
|
case FLAC_KEY_MD5_SUM_3:
|
|
case FLAC_KEY_MD5_SUM_4:
|
|
case FLAC_KEY_MD5_SUM_5:
|
|
case FLAC_KEY_MD5_SUM_6:
|
|
case FLAC_KEY_MD5_SUM_7:
|
|
case FLAC_KEY_MD5_SUM_8:
|
|
case FLAC_KEY_MD5_SUM_9:
|
|
case FLAC_KEY_MD5_SUM_A:
|
|
case FLAC_KEY_MD5_SUM_B:
|
|
case FLAC_KEY_MD5_SUM_C:
|
|
case FLAC_KEY_MD5_SUM_D:
|
|
case FLAC_KEY_MD5_SUM_E:
|
|
case FLAC_KEY_MD5_SUM_F:
|
|
return inst->streaminfo->md5_sum[key - FLAC_KEY_MD5_SUM_0];
|
|
default:
|
|
return FLAC_INVALID_METADATA_KEY;
|
|
}
|
|
}
|
|
|
|
fx_flac_state_t fx_flac_process(fx_flac_t *inst, const uint8_t *in,
|
|
uint32_t *in_len, int32_t *out,
|
|
uint32_t *out_len) {
|
|
inst = (fx_flac_t *)FX_ALIGN_ADDR(inst);
|
|
|
|
/* Set the current bytestream source to the provided input buffer */
|
|
fx_bitstream_t *bs = &inst->bitstream; /* Alias */
|
|
fx_bitstream_set_source(bs, in, *in_len);
|
|
|
|
/* Advance the statemachine */
|
|
bool done = false;
|
|
uint32_t out_len_ = 0U;
|
|
fx_flac_state_t old_state = inst->state;
|
|
while (!done) {
|
|
/* Abort once we've reached an error state. */
|
|
if (inst->state == FLAC_ERR) {
|
|
done = true;
|
|
continue; /* Panic, all hope is lost! */
|
|
}
|
|
|
|
/* Automatically return once the state transitions to a relevant state,
|
|
even if there is still data to read. */
|
|
if (old_state != inst->state) {
|
|
old_state = inst->state;
|
|
switch (inst->state) {
|
|
case FLAC_END_OF_METADATA:
|
|
case FLAC_END_OF_FRAME:
|
|
done = true; /* Good point to return to the caller */
|
|
continue;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Main state machine. Dispatch calls to the corresponding state
|
|
handlers. These will returns false in case there is no more data
|
|
to read/space to write to. */
|
|
switch (inst->state) {
|
|
case FLAC_INIT:
|
|
done = !_fx_flac_process_init(inst);
|
|
break;
|
|
case FLAC_IN_METADATA:
|
|
done = !_fx_flac_process_in_metadata(inst);
|
|
break;
|
|
case FLAC_END_OF_METADATA:
|
|
case FLAC_END_OF_FRAME:
|
|
inst->state = FLAC_SEARCH_FRAME;
|
|
inst->priv_state = FLAC_FRAME_SYNC;
|
|
break;
|
|
case FLAC_SEARCH_FRAME:
|
|
done = !_fx_flac_process_search_frame(inst);
|
|
break;
|
|
case FLAC_IN_FRAME:
|
|
done = !_fx_flac_process_in_frame(inst);
|
|
break;
|
|
case FLAC_DECODED_FRAME:
|
|
/* If no output buffers are given, just discard the data. */
|
|
if (!out || !out_len) {
|
|
inst->state = FLAC_END_OF_FRAME;
|
|
break;
|
|
}
|
|
out_len_ = *out_len;
|
|
done = !_fx_flac_process_decoded_frame(inst, out, &out_len_);
|
|
break;
|
|
default:
|
|
inst->state = FLAC_ERR; /* Internal error */
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Write the number of bytes we read from the input stream to in_len, the
|
|
caller must not provide these bytes again. Also write the number of
|
|
samples we wrote to the output buffer. */
|
|
if (out_len) {
|
|
*out_len = out_len_;
|
|
}
|
|
*in_len = bs->src - in;
|
|
|
|
/* Return the current state */
|
|
return inst->state;
|
|
}
|
|
|
|
|