[xiph-commits] r3347 - in libfishsound/branches/1.0-stable/src:
examples libfishsound tests
conrad at svn.annodex.net
conrad at svn.annodex.net
Fri Jan 11 23:09:27 PST 2008
Author: conrad
Date: 2008-01-11 23:09:26 -0800 (Fri, 11 Jan 2008)
New Revision: 3347
Modified:
libfishsound/branches/1.0-stable/src/examples/fishsound-encode.c
libfishsound/branches/1.0-stable/src/libfishsound/flac.c
libfishsound/branches/1.0-stable/src/tests/encdec-audio.c
libfishsound/branches/1.0-stable/src/tests/encdec-comments.c
Log:
add encoding of vorbiscomment metadata for Ogg FLAC streams
Modified: libfishsound/branches/1.0-stable/src/examples/fishsound-encode.c
===================================================================
--- libfishsound/branches/1.0-stable/src/examples/fishsound-encode.c 2008-01-12 04:17:01 UTC (rev 3346)
+++ libfishsound/branches/1.0-stable/src/examples/fishsound-encode.c 2008-01-12 07:09:26 UTC (rev 3347)
@@ -83,7 +83,6 @@
int format = FISH_SOUND_VORBIS;
float pcm[2048];
- long n;
if (argc < 3) {
printf ("usage: %s infile outfile\n", argv[0]);
@@ -123,6 +122,8 @@
fish_sound_set_interleave (fsound, 1);
+ fish_sound_comment_add_byname (fsound, "Encoder", "fishsound-encode");
+
while (sf_readf_float (sndfile, pcm, ENCODE_BLOCK_SIZE) > 0) {
fish_sound_encode (fsound, (float **)pcm, ENCODE_BLOCK_SIZE);
oggz_run (oggz);
Modified: libfishsound/branches/1.0-stable/src/libfishsound/flac.c
===================================================================
--- libfishsound/branches/1.0-stable/src/libfishsound/flac.c 2008-01-12 04:17:01 UTC (rev 3346)
+++ libfishsound/branches/1.0-stable/src/libfishsound/flac.c 2008-01-12 07:09:26 UTC (rev 3347)
@@ -66,8 +66,14 @@
} version;
unsigned short header_packets;
void * ipcm;
+#if FS_DECODE
float * pcm_out[8]; /* non-interleaved pcm, output (decode only);
* FLAC does max 8 channels */
+#endif
+#if FS_ENCODE
+ FLAC__StreamMetadata * enc_vc_metadata; /* FLAC metadata structure for
+ * vorbiscomments (encode only) */
+#endif
} FishSoundFlacInfo;
int
@@ -359,6 +365,7 @@
fi->buffer[8] = 1; /* LSB(be): Nr. other non-audio header packets */
memcpy (fi->buffer+9, buffer, bytes); /* fLaC header ++ STREAMINFO */
fi->bufferlength = bytes+9;
+
fi->header++;
} else {
/* Make a temporary copy of the metadata header to pass to the user
@@ -416,10 +423,118 @@
return;
}
+/* Create a local alias for an unwieldy type name */
+typedef FLAC__StreamMetadata_VorbisComment_Entry FLAC__VCEntry;
+
+static void
+fs_flac_metadata_free (FLAC__StreamMetadata * metadata)
+{
+ unsigned int i, length;
+ FLAC__VCEntry * comments;
+
+ if (metadata == NULL) return;
+
+ length = metadata->data.vorbis_comment.num_comments;
+ comments = metadata->data.vorbis_comment.comments;
+
+ for (i = 0; i < length; i++) {
+ fs_free (comments[i].entry);
+ }
+
+ fs_free (comments);
+ fs_free (metadata);
+
+ return;
+}
+
+static FLAC__byte *
+fs_flac_encode_vcentry (const FishSoundComment * comment)
+{
+ FLAC__byte * entry;
+ FLAC__uint32 length;
+ size_t name_len=0, value_len=0;
+
+ name_len = strlen(comment->name);
+ length = name_len + 1;
+
+ if (comment->value) {
+ value_len = strlen (comment->value);
+ length += value_len + 1;
+ }
+
+ entry = fs_malloc (length);
+
+ /* We assume that comment->name, value are NUL terminated, as they were
+ * produced by our own comments.c */
+ strcpy ((char *)entry, comment->name);
+
+ if (comment->value) {
+ entry[name_len] = '=';
+ strcpy ((char *)&entry[name_len+1], comment->value);
+ }
+
+ entry[length-1] = '\0';
+
+ return entry;
+}
+
+static FLAC__StreamMetadata *
+fs_flac_encode_vorbiscomments (FishSound * fsound)
+{
+ FishSoundFlacInfo * fi = fsound->codec_data;
+ FLAC__StreamMetadata * metadata;
+ const FishSoundComment * comment;
+ unsigned int i=0, length=0, total_length;
+ FLAC__VCEntry * comments;
+
+ /* libFLAC seems to require us to know the total length of the generated
+ * vorbiscomment packet, even though it will silently generate the
+ * vendor string. Hence, this value was determined by inspection for
+ * the version "reference libFLAC 1.1.2"
+ */
+ total_length = 40;
+
+ /* Count the number of comments */
+ for (comment = fish_sound_comment_first (fsound); comment;
+ comment = fish_sound_comment_next (fsound, comment)) {
+ length++;
+ }
+
+ if (length == 0) return NULL;
+
+ comments = (FLAC__VCEntry *)fs_malloc (sizeof(FLAC__VCEntry) * length);
+
+ for (comment = fish_sound_comment_first (fsound); comment;
+ comment = fish_sound_comment_next (fsound, comment)) {
+ comments[i].entry = fs_flac_encode_vcentry (comment);
+ comments[i].length = strlen((char *)comments[i].entry);
+
+ /* In the generated vorbiscomment data, each entry is preceded by a
+ * 32bit length specifier. */
+ total_length += 4 + comments[i].length;
+ i++;
+ }
+
+ metadata = (FLAC__StreamMetadata *) fs_malloc (sizeof (*metadata));
+ metadata->type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
+ metadata->is_last = true;
+ metadata->length = total_length;
+ /* Don't bother setting the vendor_string, as libFLAC ignores it */
+ metadata->data.vorbis_comment.num_comments = length;
+ metadata->data.vorbis_comment.comments = comments;
+
+ /* Remember the allocated metadata */
+ fi->enc_vc_metadata = metadata;
+
+ return metadata;
+}
+
static FishSound *
fs_flac_enc_headers (FishSound * fsound)
{
- FishSoundFlacInfo *fi = fsound->codec_data;
+ FishSoundFlacInfo * fi = fsound->codec_data;
+ FLAC__StreamMetadata * metadata;
+
fi->fse = FLAC__stream_encoder_new();
FLAC__stream_encoder_set_channels(fi->fse, fsound->info.channels);
FLAC__stream_encoder_set_sample_rate(fi->fse, fsound->info.samplerate);
@@ -427,9 +542,15 @@
FLAC__stream_encoder_set_write_callback(fi->fse, fs_flac_enc_write_callback);
FLAC__stream_encoder_set_metadata_callback(fi->fse, fs_flac_enc_meta_callback);
FLAC__stream_encoder_set_client_data(fi->fse, fsound);
+
+ metadata = fs_flac_encode_vorbiscomments (fsound);
+ if (metadata != NULL)
+ FLAC__stream_encoder_set_metadata (fi->fse, &metadata, 1);
+
/* FLAC__stream_encoder_set_total_samples_estimate(fi->fse, ...);*/
if (FLAC__stream_encoder_init(fi->fse) != FLAC__STREAM_ENCODER_OK)
return NULL;
+
return fsound;
}
@@ -524,6 +645,12 @@
for (i = 0; i < 8; i++) {
if (fi->pcm_out[i]) fs_free (fi->pcm_out[i]);
}
+
+#if FS_ENCODE
+ if (fi->enc_vc_metadata) {
+ fs_flac_metadata_free (fi->enc_vc_metadata);
+ }
+#endif
fs_free (fi);
fsound->codec_data = NULL;
@@ -588,6 +715,10 @@
fi->pcm_out[i] = NULL;
}
+#if FS_ENCODE
+ fi->enc_vc_metadata = NULL;
+#endif
+
fsound->codec_data = fi;
return fsound;
Modified: libfishsound/branches/1.0-stable/src/tests/encdec-audio.c
===================================================================
--- libfishsound/branches/1.0-stable/src/tests/encdec-audio.c 2008-01-12 04:17:01 UTC (rev 3346)
+++ libfishsound/branches/1.0-stable/src/tests/encdec-audio.c 2008-01-12 07:09:26 UTC (rev 3347)
@@ -217,6 +217,11 @@
ed = fs_encdec_new (samplerate, channels, format, interleave, blocksize);
+#if 0
+ fish_sound_comment_add_byname (ed->encoder, "Encoder", "encdec-audio");
+ fish_sound_comment_add_byname (ed->encoder, "Format", msg);
+#endif
+
for (i = 0; i < iter; i++) {
ed->actual_frames_in += blocksize;
fish_sound_prepare_truncation (ed->encoder, ed->actual_frames_in,
Modified: libfishsound/branches/1.0-stable/src/tests/encdec-comments.c
===================================================================
--- libfishsound/branches/1.0-stable/src/tests/encdec-comments.c 2008-01-12 04:17:01 UTC (rev 3346)
+++ libfishsound/branches/1.0-stable/src/tests/encdec-comments.c 2008-01-12 07:09:26 UTC (rev 3347)
@@ -213,6 +213,9 @@
fish_sound_encode (ed->encoder, ed->pcm, blocksize);
+ fish_sound_flush (ed->encoder);
+ fish_sound_flush (ed->decoder);
+
fs_encdec_delete (ed);
return 0;
@@ -231,5 +234,10 @@
fs_encdec_comments_test (FISH_SOUND_SPEEX, 2048);
#endif
+#if HAVE_FLAC
+ INFO ("Testing encode/decode pipeline for comments: FLAC");
+ fs_encdec_comments_test (FISH_SOUND_FLAC, 2048);
+#endif
+
exit (0);
}
More information about the commits
mailing list