--- TiMidity++-2.13.2/timidity/flac_a.c.flac 2004-05-23 06:35:44.000000000 +0200 +++ TiMidity++-2.13.2/timidity/flac_a.c 2006-12-13 07:45:39.000000000 +0100 @@ -38,14 +38,21 @@ #if defined(AU_FLAC_DLL) || defined(AU_OGGFLAC_DLL) #include <windows.h> -#define FLAC__EXPORT_H /* don't include "OggFLAC/export.h" */ -#define FLAC_API -#define OggFLAC__EXPORT_H /* don't include "FLAC/export.h" */ -#define OggFLAC_API +#include <FLAC/export.h> /* need export.h to figure out API version from FLAC_API_VERSION_CURRENT */ +#undef FLAC_API +#undef OggFLAC_API #endif +/* by LEGACY_FLAC we mean before FLAC 1.1.3 */ +/* in FLAC 1.1.3, libOggFLAC is merged into libFLAC and all encoding layers are merged into the stream encoder */ +/*#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT < 8 +#define LEGACY_FLAC +#else*/ +#undef LEGACY_FLAC +/*#endif*/ + #include <FLAC/all.h> -#ifdef AU_OGGFLAC +#if defined(LEGACY_FLAC) && defined(AU_OGGFLAC) #include <OggFLAC/stream_encoder.h> #endif @@ -100,17 +107,21 @@ typedef struct { unsigned long out_bytes; union { FLAC__StreamEncoderState flac; +#ifdef LEGACY_FLAC FLAC__SeekableStreamEncoderState s_flac; #ifdef AU_OGGFLAC OggFLAC__StreamEncoderState ogg; #endif +#endif } state; union { union { FLAC__StreamEncoder *stream; +#ifdef LEGACY_FLAC FLAC__SeekableStreamEncoder *s_stream; +#endif } flac; -#ifdef AU_OGGFLAC +#if defined(LEGACY_FLAC) && defined(AU_OGGFLAC) union { OggFLAC__StreamEncoder *stream; } ogg; @@ -119,7 +130,7 @@ typedef struct { } FLAC_ctx; typedef struct { -#ifdef AU_OGGFLAC +#if defined(LEGACY_FLAC) && defined(AU_OGGFLAC) int isogg; #endif int verify; @@ -138,7 +149,7 @@ typedef struct { /* default compress level is 5 */ FLAC_options flac_options = { -#ifdef AU_OGGFLAC +#if defined(LEGACY_FLAC) && defined(AU_OGGFLAC) 0, /* isogg */ #endif 0, /* verify */ @@ -158,7 +169,7 @@ FLAC_options flac_options = { static long serial_number = 0; FLAC_ctx *flac_ctx = NULL; -#ifdef AU_OGGFLAC +#if defined(LEGACY_FLAC) && defined(AU_OGGFLAC) static FLAC__StreamEncoderWriteStatus ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], @@ -168,8 +179,13 @@ ogg_stream_encoder_write_callback(const static FLAC__StreamEncoderWriteStatus flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], +#ifdef LEGACY_FLAC unsigned bytes, unsigned samples, +#else + size_t bytes, unsigned samples, +#endif unsigned current_frame, void *client_data); +#ifdef LEGACY_FLAC static void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data); @@ -181,6 +197,7 @@ flac_seekable_stream_encoder_write_callb static void flac_seekable_stream_encoder_metadata_callback(const FLAC__SeekableStreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data); +#endif /* preset */ void flac_set_compression_level(int compression_level) @@ -295,6 +312,7 @@ static int flac_session_close() dpm.fd = -1; if (ctx != NULL) { +#ifdef LEGACY_FLAC #ifdef AU_OGGFLAC if (flac_options.isogg) { if (ctx->encoder.ogg.stream) { @@ -317,6 +335,12 @@ static int flac_session_close() FLAC__stream_encoder_delete(ctx->encoder.flac.stream); } } +#else + if (ctx->encoder.flac.stream) { + FLAC__stream_encoder_finish(ctx->encoder.flac.stream); + FLAC__stream_encoder_delete(ctx->encoder.flac.stream); + } +#endif free(ctx); flac_ctx = NULL; } @@ -329,6 +353,9 @@ static int flac_output_open(const char * FLAC__StreamMetadata padding; FLAC__StreamMetadata *metadata[4]; int num_metadata = 0; +#ifndef LEGACY_FLAC + FLAC__StreamEncoderInitStatus init_status; +#endif FLAC_ctx *ctx; @@ -371,6 +398,7 @@ static int flac_output_open(const char * metadata[num_metadata++] = &padding; } +#ifdef LEGACY_FLAC #ifdef AU_OGGFLAC if (flac_options.isogg) { if ((ctx->encoder.ogg.stream = OggFLAC__stream_encoder_new()) == NULL) { @@ -542,6 +570,67 @@ static int flac_output_open(const char * return -1; } } +#else /* !LEGACY_FLAC */ + if ((ctx->encoder.flac.stream = FLAC__stream_encoder_new()) == NULL) { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "cannot create FLAC stream"); + flac_session_close(); + return -1; + } + +#ifdef AU_OGGFLAC + if (flac_options.isogg) { + /* set sequential number for serial */ + serial_number++; + if (serial_number == 1) { + srand(time(NULL)); + serial_number = rand(); + } + FLAC__stream_encoder_set_ogg_serial_number(ctx->encoder.flac.stream, serial_number); + } +#endif /* AU_OGGFLAC */ + FLAC__stream_encoder_set_channels(ctx->encoder.flac.stream, nch); + /* 16bps only */ + FLAC__stream_encoder_set_bits_per_sample(ctx->encoder.flac.stream, 16); + + FLAC__stream_encoder_set_verify(ctx->encoder.flac.stream, flac_options.verify); + + if (!FLAC__format_sample_rate_is_valid(dpm.rate)) { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "invalid sampling rate %d", dpm.rate); + flac_session_close(); + return -1; + } + FLAC__stream_encoder_set_sample_rate(ctx->encoder.flac.stream, dpm.rate); + + FLAC__stream_encoder_set_qlp_coeff_precision(ctx->encoder.flac.stream, flac_options.qlp_coeff_precision); + /* expensive! */ + FLAC__stream_encoder_set_do_qlp_coeff_prec_search(ctx->encoder.flac.stream, flac_options.qlp_coeff_precision_search); + + if (nch == 2) { + FLAC__stream_encoder_set_do_mid_side_stereo(ctx->encoder.flac.stream, flac_options.mid_side); + FLAC__stream_encoder_set_loose_mid_side_stereo(ctx->encoder.flac.stream, flac_options.adaptive_mid_side); + } + + FLAC__stream_encoder_set_max_lpc_order(ctx->encoder.flac.stream, flac_options.max_lpc_order); + FLAC__stream_encoder_set_min_residual_partition_order(ctx->encoder.flac.stream, flac_options.min_residual_partition_order); + FLAC__stream_encoder_set_max_residual_partition_order(ctx->encoder.flac.stream, flac_options.max_residual_partition_order); + + FLAC__stream_encoder_set_blocksize(ctx->encoder.flac.stream, flac_options.blocksize); + + if (0 < num_metadata) + FLAC__stream_encoder_set_metadata(ctx->encoder.flac.stream, metadata, num_metadata); + +#ifdef AU_OGGFLAC + if (flac_options.isogg) + init_status = FLAC__stream_encoder_init_ogg_stream(ctx->encoder.flac.stream, flac_stream_encoder_write_callback, NULL, NULL, NULL, ctx); + else +#endif + init_status = FLAC__stream_encoder_init_stream(ctx->encoder.flac.stream, flac_stream_encoder_write_callback, NULL, NULL, NULL, ctx); + if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "cannot create FLAC encoder (init status: %s)", FLAC__StreamEncoderInitStatusString[init_status]); + flac_session_close(); + return -1; + } +#endif return 0; } @@ -638,7 +727,7 @@ static int open_output(void) return 0; } -#ifdef AU_OGGFLAC +#if defined(LEGACY_FLAC) && defined(AU_OGGFLAC) static FLAC__StreamEncoderWriteStatus ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], @@ -658,7 +747,11 @@ ogg_stream_encoder_write_callback(const static FLAC__StreamEncoderWriteStatus flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], +#ifdef LEGACY_FLAC unsigned bytes, unsigned samples, +#else + size_t bytes, unsigned samples, +#endif unsigned current_frame, void *client_data) { FLAC_ctx *ctx = (FLAC_ctx *)client_data; @@ -670,6 +763,7 @@ flac_stream_encoder_write_callback(const else return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; } +#ifdef LEGACY_FLAC static void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data) @@ -695,6 +789,7 @@ static void flac_seekable_stream_encoder void *client_data) { } +#endif static int output_data(char *buf, int32 nbytes) { @@ -723,6 +818,7 @@ static int output_data(char *buf, int32 oggbuf[i] = *s++; } +#ifdef LEGACY_FLAC #ifdef AU_OGGFLAC if (flac_options.isogg) { ctx->state.ogg = OggFLAC__stream_encoder_get_state(ctx->encoder.ogg.stream); @@ -793,6 +889,29 @@ static int output_data(char *buf, int32 return -1; } } +#else /* !LEGACY_FLAC */ + ctx->state.flac = FLAC__stream_encoder_get_state(ctx->encoder.flac.stream); + if (ctx->state.flac != FLAC__STREAM_ENCODER_OK) { + if (ctx->state.flac == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR | + FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "FLAC stream verify error (%s)", + FLAC__StreamDecoderStateString[FLAC__stream_encoder_get_verify_decoder_state(ctx->encoder.flac.stream)]); + } + else { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "cannot encode FLAC stream (%s)", + FLAC__StreamEncoderStateString[ctx->state.flac]); + } + flac_session_close(); + return -1; + } + + if (!FLAC__stream_encoder_process_interleaved(ctx->encoder.flac.stream, oggbuf, + nbytes / nch / 2 )) { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "cannot encode FLAC stream"); + flac_session_close(); + return -1; + } +#endif ctx->in_bytes += nbytes; free(oggbuf); @@ -813,6 +932,7 @@ static void close_output(void) return; } +#ifdef LEGACY_FLAC if (flac_options.isogg) { #ifdef AU_OGGFLAC if ((ctx->state.ogg = OggFLAC__stream_encoder_get_state(ctx->encoder.ogg.stream)) != OggFLAC__STREAM_ENCODER_OK) { @@ -838,6 +958,13 @@ static void close_output(void) /* fall through */ } } +#else /* !LEGACY_FLAC */ + if ((ctx->state.flac = FLAC__stream_encoder_get_state(ctx->encoder.flac.stream)) != FLAC__STREAM_ENCODER_OK) { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "FLAC stream encoder is invalid (%s)", + FLAC__StreamEncoderStateString[ctx->state.flac]); + /* fall through */ + } +#endif ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Wrote %lu/%lu bytes(%g%% compressed)", ctx->out_bytes, ctx->in_bytes, ((double)ctx->out_bytes / (double)ctx->in_bytes) * 100.);