mirror of
https://github.com/aaru-dps/Aaru.Compression.Native.git
synced 2026-11-03 18:56:18 +00:00
Add decoding of headerless FLAC frames, as stored in MAME CHD, returning the consumed bytes, and report FLAC decoding errors instead of printing them.
This commit is contained in:
129
flac.c
129
flac.c
@@ -26,6 +26,10 @@ static void error_callback(const FLAC__StreamDecoder * decoder,
|
||||
FLAC__StreamDecoderErrorStatus status,
|
||||
void * client_data);
|
||||
|
||||
static FLAC__StreamDecoderTellStatus tell_callback(const FLAC__StreamDecoder *decoder,
|
||||
FLAC__uint64 * absolute_byte_offset,
|
||||
void * client_data);
|
||||
|
||||
static size_t flac_decode_redbook(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer, size_t src_size)
|
||||
{
|
||||
FLAC__StreamDecoder * decoder;
|
||||
@@ -70,12 +74,11 @@ static size_t flac_decode_redbook(uint8_t *dst_buffer, size_t dst_size, const ui
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: Return error somehow
|
||||
FLAC__stream_decoder_process_until_end_of_stream(decoder);
|
||||
|
||||
FLAC__stream_decoder_delete(decoder);
|
||||
|
||||
ret_size = ctx->dst_pos;
|
||||
ret_size = ctx->error ? (size_t)-1 : ctx->dst_pos;
|
||||
|
||||
free(ctx);
|
||||
|
||||
@@ -87,18 +90,49 @@ static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *de
|
||||
size_t * bytes,
|
||||
void * client_data)
|
||||
{
|
||||
aaru_flac_ctx *ctx = (aaru_flac_ctx *)client_data;
|
||||
aaru_flac_ctx *ctx = (aaru_flac_ctx *)client_data;
|
||||
size_t requested = *bytes;
|
||||
size_t copied = 0;
|
||||
size_t chunk;
|
||||
|
||||
if(ctx->src_len - ctx->src_pos < *bytes) *bytes = ctx->src_len - ctx->src_pos;
|
||||
// Synthesized header, if any, goes before the source data
|
||||
if(ctx->hdr_pos < ctx->hdr_len)
|
||||
{
|
||||
chunk = ctx->hdr_len - ctx->hdr_pos;
|
||||
|
||||
if(*bytes == 0) return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
|
||||
if(chunk > requested) chunk = requested;
|
||||
|
||||
memcpy(buffer, ctx->src_buffer + ctx->src_pos, *bytes);
|
||||
ctx->src_pos += *bytes;
|
||||
memcpy(buffer, ctx->hdr_buffer + ctx->hdr_pos, chunk);
|
||||
ctx->hdr_pos += chunk;
|
||||
copied += chunk;
|
||||
}
|
||||
|
||||
chunk = ctx->src_len - ctx->src_pos;
|
||||
|
||||
if(chunk > requested - copied) chunk = requested - copied;
|
||||
|
||||
memcpy(buffer + copied, ctx->src_buffer + ctx->src_pos, chunk);
|
||||
ctx->src_pos += chunk;
|
||||
copied += chunk;
|
||||
|
||||
*bytes = copied;
|
||||
|
||||
if(copied == 0) return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
|
||||
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderTellStatus tell_callback(const FLAC__StreamDecoder *decoder,
|
||||
FLAC__uint64 * absolute_byte_offset,
|
||||
void * client_data)
|
||||
{
|
||||
aaru_flac_ctx *ctx = (aaru_flac_ctx *)client_data;
|
||||
|
||||
*absolute_byte_offset = ctx->hdr_pos + ctx->src_pos;
|
||||
|
||||
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder,
|
||||
const FLAC__Frame * frame,
|
||||
const FLAC__int32 *const buffer[],
|
||||
@@ -135,8 +169,6 @@ static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecod
|
||||
{
|
||||
aaru_flac_ctx *ctx = (aaru_flac_ctx *)client_data;
|
||||
|
||||
fprintf(stderr, "Got error callback: %s\n", FLAC__StreamDecoderErrorStatusString[status]);
|
||||
|
||||
ctx->error = 1;
|
||||
}
|
||||
|
||||
@@ -290,6 +322,85 @@ AARU_EXPORT int32_t AARU_CALL AARU_flac_decode_redbook_buffer(const uint8_t *src
|
||||
return AARU_ERROR_NONE;
|
||||
}
|
||||
|
||||
// Decodes a stream of FLAC frames that has no "fLaC" marker nor STREAMINFO, as stored by MAME's CHD. A STREAMINFO for
|
||||
// 44100Hz, 2 channels, 16-bit samples and the given block size is synthesized in front of the frames. Decoding stops
|
||||
// as soon as the destination buffer is full, so any data following the frames is left untouched, and the number of
|
||||
// source bytes used by the frames is returned in src_consumed.
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_flac_decode_redbook_frames(const uint8_t *src_buffer, size_t src_size,
|
||||
uint8_t *dst_buffer, size_t *dst_size,
|
||||
uint32_t block_size, size_t *src_consumed)
|
||||
{
|
||||
static const uint8_t header_template[FLAC_SYNTHETIC_HEADER_LEN] = {
|
||||
0x66, 0x4C, 0x61, 0x43, // "fLaC"
|
||||
0x80, // STREAMINFO, last metadata block
|
||||
0x00, 0x00, 0x22, // Metadata block length
|
||||
0x00, 0x00, // Minimum block size
|
||||
0x00, 0x00, // Maximum block size
|
||||
0x00, 0x00, 0x00, // Minimum frame size (unknown)
|
||||
0x00, 0x00, 0x00, // Maximum frame size (unknown)
|
||||
0x0A, 0xC4, 0x42, 0xF0, 0x00, 0x00, 0x00, 0x00, // 44100Hz, 2 channels, 16 bits, unknown samples
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MD5 (none)
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t header[FLAC_SYNTHETIC_HEADER_LEN];
|
||||
aaru_flac_ctx ctx;
|
||||
FLAC__StreamDecoder *decoder;
|
||||
FLAC__StreamDecoderInitStatus init_status;
|
||||
FLAC__uint64 position = 0;
|
||||
int32_t ret = AARU_ERROR_NONE;
|
||||
|
||||
if(!src_buffer || !dst_buffer || !dst_size || !src_consumed) return AARU_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
if(block_size < 16 || block_size > 65535) return AARU_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
memcpy(header, header_template, sizeof(header));
|
||||
header[0x08] = header[0x0A] = (uint8_t)(block_size >> 8);
|
||||
header[0x09] = header[0x0B] = (uint8_t)(block_size & 0xFF);
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.hdr_buffer = header;
|
||||
ctx.hdr_len = sizeof(header);
|
||||
ctx.src_buffer = src_buffer;
|
||||
ctx.src_len = src_size;
|
||||
ctx.dst_buffer = dst_buffer;
|
||||
ctx.dst_len = *dst_size;
|
||||
|
||||
decoder = FLAC__stream_decoder_new();
|
||||
|
||||
if(!decoder) return AARU_ERROR_FAILURE;
|
||||
|
||||
FLAC__stream_decoder_set_md5_checking(decoder, false);
|
||||
|
||||
init_status = FLAC__stream_decoder_init_stream(decoder, read_callback, NULL, tell_callback, NULL, NULL,
|
||||
write_callback, NULL, error_callback, &ctx);
|
||||
|
||||
if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
|
||||
{
|
||||
FLAC__stream_decoder_delete(decoder);
|
||||
return AARU_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
while(ctx.dst_pos < ctx.dst_len)
|
||||
{
|
||||
if(!FLAC__stream_decoder_process_single(decoder) || ctx.error ||
|
||||
FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
|
||||
break;
|
||||
}
|
||||
|
||||
if(ctx.error || ctx.dst_pos < ctx.dst_len ||
|
||||
!FLAC__stream_decoder_get_decode_position(decoder, &position) || position < sizeof(header))
|
||||
ret = AARU_ERROR_FAILURE;
|
||||
else
|
||||
{
|
||||
*src_consumed = (size_t)(position - sizeof(header));
|
||||
*dst_size = ctx.dst_pos;
|
||||
}
|
||||
|
||||
FLAC__stream_decoder_finish(decoder);
|
||||
FLAC__stream_decoder_delete(decoder);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_flac_encode_redbook_buffer(
|
||||
const uint8_t *src_buffer, size_t src_size, uint8_t *dst_buffer, size_t *dst_size, uint32_t blocksize,
|
||||
int32_t do_mid_side_stereo, int32_t loose_mid_side_stereo, const char *apodization, uint32_t max_lpc_order,
|
||||
|
||||
5
flac.h
5
flac.h
@@ -5,8 +5,13 @@
|
||||
#ifndef AARU_COMPRESSION_NATIVE__FLAC_H_
|
||||
#define AARU_COMPRESSION_NATIVE__FLAC_H_
|
||||
|
||||
#define FLAC_SYNTHETIC_HEADER_LEN 0x2A
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const uint8_t *hdr_buffer;
|
||||
size_t hdr_len;
|
||||
size_t hdr_pos;
|
||||
const uint8_t *src_buffer;
|
||||
size_t src_len;
|
||||
size_t src_pos;
|
||||
|
||||
@@ -95,6 +95,10 @@ AARU_EXPORT int32_t AARU_CALL AARU_apple_lzh_decode_buffer(const uint8_t *src_bu
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_flac_decode_redbook_buffer(const uint8_t *src_buffer, size_t src_size,
|
||||
uint8_t *dst_buffer, size_t *dst_size);
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_flac_decode_redbook_frames(const uint8_t *src_buffer, size_t src_size,
|
||||
uint8_t *dst_buffer, size_t *dst_size,
|
||||
uint32_t block_size, size_t *src_consumed);
|
||||
|
||||
AARU_EXPORT int32_t AARU_CALL AARU_flac_encode_redbook_buffer(
|
||||
const uint8_t *src_buffer, size_t src_size, uint8_t *dst_buffer, size_t *dst_size, uint32_t blocksize,
|
||||
int32_t do_mid_side_stereo, int32_t loose_mid_side_stereo, const char *apodization, uint32_t max_lpc_order,
|
||||
|
||||
Reference in New Issue
Block a user