ref: 35ee321db20593ac93bfc6022142f79c919635e0
parent: 9ef99d2fb06ad3b96a216d0e5e949c8b65112f93
author: robs <robs>
date: Fri Feb 16 18:15:53 EST 2007
Added support for FLAC 1.1.3
--- a/configure.ac
+++ b/configure.ac
@@ -135,8 +135,8 @@
[with_flac=$withval],
[with_flac=yes])
if test "$with_flac" = yes; then
- AC_CHECK_HEADER(FLAC/file_encoder.h,
- [AC_CHECK_LIB(FLAC, FLAC__file_encoder_new,,with_flac=no)],
+ AC_CHECK_HEADER(FLAC/all.h,
+ [AC_CHECK_LIB(FLAC, FLAC__stream_encoder_new,,with_flac=no)],
with_flac=no)
fi
--- a/src/flac.c
+++ b/src/flac.c
@@ -1,18 +1,17 @@
/*
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
*
* This library 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
- * Lesser General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, write to the Free Software
- * Foundation, Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301,
- * USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, write to the Free Software Foundation,
+ * Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301, USA.
*/
/* File format: FLAC (c) 2006 robs@users.sourceforge.net */
@@ -28,14 +27,23 @@
#include <FLAC/all.h>
-/* Workaround for older flac versions */
+/* Workaround for flac versions < 1.1.2 */
#define FLAC__metadata_object_vorbiscomment_append_comment(object, entry, copy)\
FLAC__metadata_object_vorbiscomment_insert_comment(object, object->data.vorbis_comment.num_comments, entry, copy)
+#if !defined(FLAC_API_VERSION_CURRENT)
+#define FLAC_API_VERSION_CURRENT 7
+#define FLAC__StreamDecoder FLAC__FileDecoder
+#define FLAC__stream_decoder_new FLAC__file_decoder_new
+#define FLAC__stream_decoder_set_md5_checking FLAC__file_decoder_set_md5_checking
+#define FLAC__stream_decoder_process_until_end_of_metadata FLAC__file_decoder_process_until_end_of_metadata
+#define FLAC__stream_decoder_process_single FLAC__file_decoder_process_single
+#define FLAC__stream_decoder_finish FLAC__file_decoder_finish
+#define FLAC__stream_decoder_delete FLAC__file_decoder_delete
+#endif
-typedef struct
-{
+typedef struct {
/* Info: */
unsigned bits_per_sample;
unsigned channels;
@@ -47,7 +55,7 @@
unsigned number_of_wide_samples;
unsigned wide_sample_number;
- FLAC__FileDecoder * flac;
+ FLAC__StreamDecoder * flac;
FLAC__bool eof;
} Decoder;
@@ -57,7 +65,7 @@
-static void FLAC__decoder_metadata_callback(FLAC__FileDecoder const * const flac, FLAC__StreamMetadata const * const metadata, void * const client_data)
+static void FLAC__decoder_metadata_callback(FLAC__StreamDecoder const * const flac, FLAC__StreamMetadata const * const metadata, void * const client_data)
{
ft_t format = (ft_t) client_data;
Decoder * decoder = (Decoder *) format->priv;
@@ -64,42 +72,32 @@
(void) flac;
- if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
- {
+ if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
decoder->bits_per_sample = metadata->data.stream_info.bits_per_sample;
decoder->channels = metadata->data.stream_info.channels;
decoder->sample_rate = metadata->data.stream_info.sample_rate;
decoder->total_samples = metadata->data.stream_info.total_samples;
}
- else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
- {
+ else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
size_t i, comment_size = 0;
if (metadata->data.vorbis_comment.num_comments == 0)
- {
return;
- }
- if (format->comment != NULL)
- {
+ if (format->comment != NULL) {
st_warn("FLAC: multiple Vorbis comment block ignored");
return;
}
for (i = 0; i < metadata->data.vorbis_comment.num_comments; ++i)
- {
comment_size += metadata->data.vorbis_comment.comments[i].length + 1;
- }
format->comment = (char *) xcalloc(comment_size, sizeof(char));
- for (i = 0; i < metadata->data.vorbis_comment.num_comments; ++i)
- {
+ for (i = 0; i < metadata->data.vorbis_comment.num_comments; ++i) {
strcat(format->comment, (char const *) metadata->data.vorbis_comment.comments[i].entry);
if (i != metadata->data.vorbis_comment.num_comments - 1)
- {
strcat(format->comment, "\n");
- }
}
}
}
@@ -106,7 +104,7 @@
-static void FLAC__decoder_error_callback(FLAC__FileDecoder const * const flac, FLAC__StreamDecoderErrorStatus const status, void * const client_data)
+static void FLAC__decoder_error_callback(FLAC__StreamDecoder const * const flac, FLAC__StreamDecoderErrorStatus const status, void * const client_data)
{
ft_t format = (ft_t) client_data;
@@ -117,7 +115,7 @@
-static FLAC__StreamDecoderWriteStatus FLAC__frame_decode_callback(FLAC__FileDecoder const * const flac, FLAC__Frame const * const frame, FLAC__int32 const * const buffer[], void * const client_data)
+static FLAC__StreamDecoderWriteStatus FLAC__frame_decode_callback(FLAC__StreamDecoder const * const flac, FLAC__Frame const * const frame, FLAC__int32 const * const buffer[], void * const client_data)
{
ft_t format = (ft_t) client_data;
Decoder * decoder = (Decoder *) format->priv;
@@ -124,8 +122,7 @@
(void) flac;
- if (frame->header.bits_per_sample != decoder->bits_per_sample || frame->header.channels != decoder->channels || frame->header.sample_rate != decoder->sample_rate)
- {
+ if (frame->header.bits_per_sample != decoder->bits_per_sample || frame->header.channels != decoder->channels || frame->header.sample_rate != decoder->sample_rate) {
st_fail_errno(format, ST_EINVAL, "FLAC ERROR: parameters differ between frame and header");
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
@@ -138,19 +135,19 @@
-static int st_format_start_read(ft_t const format)
+static int start_read(ft_t const format)
{
Decoder * decoder = (Decoder *) format->priv;
memset(decoder, 0, sizeof(*decoder));
- decoder->flac = FLAC__file_decoder_new();
- if (decoder->flac == NULL)
- {
+ decoder->flac = FLAC__stream_decoder_new();
+ if (decoder->flac == NULL) {
st_fail_errno(format, ST_ENOMEM, "FLAC ERROR creating the decoder instance");
return ST_EOF;
}
- FLAC__file_decoder_set_md5_checking(decoder->flac, st_true);
+ FLAC__stream_decoder_set_md5_checking(decoder->flac, st_true);
+#if FLAC_API_VERSION_CURRENT <= 7
FLAC__file_decoder_set_filename(decoder->flac, format->filename);
FLAC__file_decoder_set_write_callback(decoder->flac, FLAC__frame_decode_callback);
FLAC__file_decoder_set_metadata_callback(decoder->flac, FLAC__decoder_metadata_callback);
@@ -157,21 +154,31 @@
FLAC__file_decoder_set_error_callback(decoder->flac, FLAC__decoder_error_callback);
FLAC__file_decoder_set_metadata_respond_all(decoder->flac);
FLAC__file_decoder_set_client_data(decoder->flac, format);
-
- if (FLAC__file_decoder_init(decoder->flac) != FLAC__FILE_DECODER_OK)
- {
+ if (FLAC__file_decoder_init(decoder->flac) != FLAC__FILE_DECODER_OK) {
+#else
+ if (FLAC__stream_decoder_init_file(
+ decoder->flac,
+ format->filename,
+ FLAC__frame_decode_callback,
+ FLAC__decoder_metadata_callback,
+ FLAC__decoder_error_callback,
+ format) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+#endif
st_fail_errno(format, ST_EHDR, "FLAC ERROR initialising decoder");
return ST_EOF;
}
- if (!FLAC__file_decoder_process_until_end_of_metadata(decoder->flac))
- {
+
+ if (!FLAC__stream_decoder_process_until_end_of_metadata(decoder->flac)) {
st_fail_errno(format, ST_EHDR, "FLAC ERROR whilst decoding metadata");
return ST_EOF;
}
- if (FLAC__file_decoder_get_state(decoder->flac) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(decoder->flac) != FLAC__FILE_DECODER_END_OF_FILE)
- {
+#if FLAC_API_VERSION_CURRENT <= 7
+ if (FLAC__file_decoder_get_state(decoder->flac) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(decoder->flac) != FLAC__FILE_DECODER_END_OF_FILE) {
+#else
+ if (FLAC__stream_decoder_get_state(decoder->flac) > FLAC__STREAM_DECODER_END_OF_STREAM) {
+#endif
st_fail_errno(format, ST_EHDR, "FLAC ERROR during metadata decoding");
return ST_EOF;
}
@@ -185,15 +192,14 @@
}
-static st_size_t st_format_read(ft_t const format, st_sample_t * sampleBuffer, st_size_t const requested)
+static st_size_t read(ft_t const format, st_sample_t * sampleBuffer, st_size_t const requested)
{
Decoder * decoder = (Decoder *) format->priv;
size_t actual = 0;
- while (!decoder->eof && actual < requested)
- {
+ while (!decoder->eof && actual < requested) {
if (decoder->wide_sample_number >= decoder->number_of_wide_samples)
- FLAC__file_decoder_process_single(decoder->flac);
+ FLAC__stream_decoder_process_single(decoder->flac);
if (decoder->wide_sample_number >= decoder->number_of_wide_samples)
decoder->eof = st_true;
else {
@@ -216,22 +222,19 @@
-static int st_format_stop_read(ft_t const format)
+static int stop_read(ft_t const format)
{
Decoder * decoder = (Decoder *) format->priv;
- if (!FLAC__file_decoder_finish(decoder->flac) && decoder->eof)
- {
+ if (!FLAC__stream_decoder_finish(decoder->flac) && decoder->eof)
st_warn("FLAC decoder MD5 checksum mismatch.");
- }
- FLAC__file_decoder_delete(decoder->flac);
+ FLAC__stream_decoder_delete(decoder->flac);
return ST_SUCCESS;
}
-typedef struct
-{
+typedef struct {
/* Info: */
unsigned bits_per_sample;
@@ -266,7 +269,7 @@
-static int st_format_start_write(ft_t const format)
+static int start_write(ft_t const format)
{
Encoder * encoder = (Encoder *) format->priv;
FLAC__StreamEncoderState status;
@@ -273,8 +276,7 @@
memset(encoder, 0, sizeof(*encoder));
encoder->flac = FLAC__stream_encoder_new();
- if (encoder->flac == NULL)
- {
+ if (encoder->flac == NULL) {
st_fail_errno(format, ST_ENOMEM, "FLAC ERROR creating the encoder instance");
return ST_EOF;
}
@@ -281,8 +283,7 @@
encoder->decoded_samples = xmalloc(ST_BUFSIZ * sizeof(FLAC__int32));
{ /* Select and set FLAC encoder options: */
- static struct
- {
+ static struct {
int blocksize;
FLAC__bool do_exhaustive_model_search;
FLAC__bool do_mid_side_stereo;
@@ -303,12 +304,10 @@
};
unsigned compression_level = array_length(options) - 1; /* Default to "best" */
- if (format->signal.compression != HUGE_VAL)
- {
+ if (format->signal.compression != HUGE_VAL) {
compression_level = format->signal.compression;
if (compression_level != format->signal.compression ||
- compression_level >= array_length(options))
- {
+ compression_level >= array_length(options)) {
st_fail_errno(format, ST_EINVAL,
"FLAC compression level must be a whole number from 0 to %i",
array_length(options) - 1);
@@ -325,8 +324,7 @@
SET_OPTION(max_lpc_order);
SET_OPTION(max_residual_partition_order);
SET_OPTION(min_residual_partition_order);
- if (format->signal.channels == 2)
- {
+ if (format->signal.channels == 2) {
SET_OPTION(do_mid_side_stereo);
SET_OPTION(loose_mid_side_stereo);
}
@@ -351,11 +349,8 @@
size_t i;
st_bool streamable = st_false;
for (i = 0; !streamable && i < array_length(streamable_rates); ++i)
- {
streamable = (streamable_rates[i] == format->signal.rate);
- }
- if (!streamable)
- {
+ if (!streamable) {
st_report("FLAC: non-standard rate; output may not be streamable");
FLAC__stream_encoder_set_streamable_subset(encoder->flac, st_false);
}
@@ -362,12 +357,9 @@
}
if (format->length != 0)
- {
FLAC__stream_encoder_set_total_samples_estimate(encoder->flac, (FLAC__uint64)format->length);
- }
- if (format->comment != NULL && * format->comment != '\0')
- {
+ if (format->comment != NULL && * format->comment != '\0') {
FLAC__StreamMetadata * metadata[1];
FLAC__StreamMetadata_VorbisComment_Entry entry;
char * comments, * comment, * end_of_comment;
@@ -375,8 +367,7 @@
encoder->metadata = metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
/* Check if there is a FIELD=value pair already in the comment; if not, add one */
- if (strchr(format->comment, '=') == NULL)
- {
+ if (strchr(format->comment, '=') == NULL) {
static const char prepend[] = "COMMENT=";
comments = xmalloc(strlen(format->comment) + sizeof(prepend));
strcpy(comments, prepend);
@@ -387,12 +378,10 @@
comment = comments;
- do
- {
+ do {
entry.entry = (FLAC__byte *) comment;
end_of_comment = strchr(comment, '\n');
- if (end_of_comment != NULL)
- {
+ if (end_of_comment != NULL) {
*end_of_comment = '\0';
comment = end_of_comment + 1;
}
@@ -405,13 +394,17 @@
free(comments);
}
+#if FLAC_API_VERSION_CURRENT <= 7
FLAC__stream_encoder_set_write_callback(encoder->flac, flac_stream_encoder_write_callback);
FLAC__stream_encoder_set_metadata_callback(encoder->flac, flac_stream_encoder_metadata_callback);
FLAC__stream_encoder_set_client_data(encoder->flac, format);
-
status = FLAC__stream_encoder_init(encoder->flac);
- if (status != FLAC__STREAM_ENCODER_OK)
- {
+#else
+ status = FLAC__stream_encoder_init_stream(encoder->flac, flac_stream_encoder_write_callback,
+ 0, 0, flac_stream_encoder_metadata_callback, format);
+#endif
+
+ if (status != FLAC__STREAM_ENCODER_OK) {
st_fail_errno(format, ST_EINVAL, "%s", FLAC__StreamEncoderStateString[status]);
return ST_EOF;
}
@@ -420,19 +413,17 @@
-static st_size_t st_format_write(ft_t const format, st_sample_t const * const sampleBuffer, st_size_t const len)
+static st_size_t write(ft_t const format, st_sample_t const * const sampleBuffer, st_size_t const len)
{
Encoder * encoder = (Encoder *) format->priv;
unsigned i;
- for (i = 0; i < len; ++i)
- {
- switch (encoder->bits_per_sample)
- {
+ for (i = 0; i < len; ++i) {
+ switch (encoder->bits_per_sample) {
case 8: encoder->decoded_samples[i] = ST_SAMPLE_TO_SIGNED_BYTE(sampleBuffer[i], format->clips); break;
case 16: encoder->decoded_samples[i] = ST_SAMPLE_TO_SIGNED_WORD(sampleBuffer[i], format->clips); break;
case 24: encoder->decoded_samples[i] = ST_SAMPLE_TO_SIGNED_24BIT(sampleBuffer[i],format->clips); break;
- case 32: encoder->decoded_samples[i] = ST_SAMPLE_TO_SIGNED_DWORD(sampleBuffer[i],); break;
+ case 32: encoder->decoded_samples[i] = ST_SAMPLE_TO_SIGNED_DWORD(sampleBuffer[i],format->clips); break;
}
}
FLAC__stream_encoder_process_interleaved(encoder->flac, encoder->decoded_samples, len / format->signal.channels);
@@ -441,7 +432,7 @@
-static int st_format_stop_write(ft_t const format)
+static int stop_write(ft_t const format)
{
Encoder * encoder = (Encoder *) format->priv;
FLAC__StreamEncoderState state = FLAC__stream_encoder_get_state(encoder->flac);
@@ -450,8 +441,7 @@
FLAC__stream_encoder_finish(encoder->flac);
FLAC__stream_encoder_delete(encoder->flac);
free(encoder->decoded_samples);
- if (state != FLAC__STREAM_ENCODER_OK)
- {
+ if (state != FLAC__STREAM_ENCODER_OK) {
st_fail_errno(format, ST_EINVAL, "FLAC ERROR: failed to encode to end of stream");
return ST_EOF;
}
@@ -460,33 +450,16 @@
-static char const * const st_format_names[] =
-{
- "flac",
- NULL
-};
-
-
-
-static st_format_t const st_format =
-{
- st_format_names,
- NULL,
- 0,
- st_format_start_read,
- st_format_read,
- st_format_stop_read,
- st_format_start_write,
- st_format_write,
- st_format_stop_write,
- st_format_nothing_seek
-};
-
-
-
st_format_t const * st_flac_format_fn(void)
{
- return &st_format;
+ static char const * const names[] = {"flac", NULL};
+ static st_format_t const driver = {
+ names, NULL, 0,
+ start_read, read, stop_read,
+ start_write, write, stop_write,
+ 0
+ };
+ return &driver;
}