ref: 682066657d61167c6cbe4d06b392699947b39d2d
parent: 98bfbd2576435fdec42096464434aa2acfd57a43
author: robs <robs>
date: Sun Apr 22 02:07:33 EDT 2007
encoder seektable generation, and seekable decode
--- a/src/flac.c
+++ b/src/flac.c
@@ -14,7 +14,7 @@
* Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301, USA.
*/
-/* File format: FLAC (c) 2006 robs@users.sourceforge.net */
+/* File format: FLAC (c) 2006-7 robs@users.sourceforge.net */
@@ -41,6 +41,7 @@
#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
+#define FLAC__stream_decoder_seek_absolute FLAC__file_decoder_seek_absolute
#endif
@@ -244,7 +245,8 @@
unsigned number_of_samples;
FLAC__StreamEncoder * flac;
- FLAC__StreamMetadata *metadata;
+ FLAC__StreamMetadata * metadata[2];
+ unsigned num_metadata;
} Encoder;
@@ -343,8 +345,8 @@
if (compression_level != format->signal.compression ||
compression_level >= array_length(options)) {
sox_fail_errno(format, SOX_EINVAL,
- "FLAC compression level must be a whole number from 0 to %i",
- array_length(options) - 1);
+ "FLAC compression level must be a whole number from 0 to %i",
+ array_length(options) - 1);
return SOX_EOF;
}
}
@@ -390,15 +392,35 @@
}
}
- if (format->length != 0)
+ if (format->length != 0) {
FLAC__stream_encoder_set_total_samples_estimate(encoder->flac, (FLAC__uint64)format->length);
+ encoder->metadata[encoder->num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE);
+ if (encoder->metadata[encoder->num_metadata] == NULL) {
+ sox_fail_errno(format, SOX_ENOMEM, "FLAC ERROR creating the encoder seek table template");
+ return SOX_EOF;
+ }
+ {
+#if FLAC_API_VERSION_CURRENT >= 8
+ if (!FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(encoder->metadata[encoder->num_metadata], 10 * format->signal.rate, (FLAC__uint64)(format->length/format->signal.channels))) {
+#else
+ sox_size_t samples = 10 * format->signal.rate;
+ sox_size_t total_samples = format->length/format->signal.channels;
+ if (!FLAC__metadata_object_seektable_template_append_spaced_points(encoder->metadata[encoder->num_metadata], total_samples / samples + (total_samples % samples != 0), (FLAC__uint64)total_samples)) {
+#endif
+ sox_fail_errno(format, SOX_ENOMEM, "FLAC ERROR creating the encoder seek table points");
+ return SOX_EOF;
+ }
+ }
+ encoder->metadata[encoder->num_metadata]->is_last = sox_false; /* the encoder will set this for us */
+ ++encoder->num_metadata;
+ }
+
if (format->comment != NULL && * format->comment != '\0') {
- FLAC__StreamMetadata * metadata[1];
FLAC__StreamMetadata_VorbisComment_Entry entry;
char * comments, * comment, * end_of_comment;
- encoder->metadata = metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
+ encoder->metadata[encoder->num_metadata] = 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) {
@@ -421,13 +443,16 @@
}
entry.length = strlen((char const *) entry.entry);
- FLAC__metadata_object_vorbiscomment_append_comment(metadata[0], entry, /*copy= */ sox_true);
+ FLAC__metadata_object_vorbiscomment_append_comment(encoder->metadata[encoder->num_metadata], entry, /*copy= */ sox_true);
} while (end_of_comment != NULL);
- FLAC__stream_encoder_set_metadata(encoder->flac, metadata, 1);
free(comments);
+ ++encoder->num_metadata;
}
+ if (encoder->num_metadata)
+ FLAC__stream_encoder_set_metadata(encoder->flac, encoder->metadata, encoder->num_metadata);
+
#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);
@@ -470,11 +495,12 @@
{
Encoder * encoder = (Encoder *) format->priv;
FLAC__StreamEncoderState state = FLAC__stream_encoder_get_state(encoder->flac);
+ unsigned i;
- if (encoder->metadata)
- FLAC__metadata_object_delete(encoder->metadata);
FLAC__stream_encoder_finish(encoder->flac);
FLAC__stream_encoder_delete(encoder->flac);
+ for (i = 0; i < encoder->num_metadata; ++i)
+ FLAC__metadata_object_delete(encoder->metadata[i]);
free(encoder->decoded_samples);
if (state != FLAC__STREAM_ENCODER_OK) {
sox_fail_errno(format, SOX_EINVAL, "FLAC ERROR: failed to encode to end of stream");
@@ -485,14 +511,23 @@
+static int seek(ft_t format, sox_size_t offset)
+{
+ Decoder * decoder = (Decoder *) format->priv;
+
+ return format->mode == 'r' && FLAC__stream_decoder_seek_absolute(decoder->flac, (FLAC__uint64)(offset / format->signal.channels)) ? SOX_SUCCESS : SOX_EOF;
+}
+
+
+
sox_format_t const * sox_flac_format_fn(void)
{
static char const * const names[] = {"flac", NULL};
static sox_format_t const driver = {
- names, 0,
+ names, SOX_FILE_SEEK,
start_read, read, stop_read,
start_write, write, stop_write,
- 0
+ seek
};
return &driver;
}