[Easytag-mailing] Re: [Patch] ... implement speex tag editing



Oops, I forgot to attach the patch!!

Pierre Marc Dumuid wrote:

Hi Jerome Courderc,
Here's a patch to have speex editing working.. in easytag...

Cheers,
Pierre

P.S. I'm not on the mailing list so please CC any comments about this patch to me...


diff -uar easytag-1.99.8/config.h.in easytag-1.99.8_comp/config.h.in
--- easytag-1.99.8/config.h.in	2005-08-26 06:12:19.000000000 +0930
+++ easytag-1.99.8_comp/config.h.in	2005-09-03 23:14:04.000000000 +0930
@@ -32,6 +32,9 @@
 /* Define for Ogg Vorbis support */
 #undef ENABLE_OGG
 
+/* Define for Speex support */
+#undef ENABLE_SPEEX
+
 /* Package name for gettext */
 #undef GETTEXT_PACKAGE
 
@@ -75,6 +78,9 @@
 /* Define to 1 if you have the `ogg' library (-logg). */
 #undef HAVE_LIBOGG
 
+/* Define to 1 if you have the `speex' library (-lspeex). */
+#undef HAVE_LIBSPEEX
+
 /* Define to 1 if you have the `vorbis' library (-lvorbis). */
 #undef HAVE_LIBVORBIS
 
diff -uar easytag-1.99.8/configure.in easytag-1.99.8_comp/configure.in
--- easytag-1.99.8/configure.in	2005-08-26 06:11:59.000000000 +0930
+++ easytag-1.99.8_comp/configure.in	2005-09-03 23:13:14.000000000 +0930
@@ -37,6 +37,10 @@
               AC_HELP_STRING([--disable-ogg], [Disable support for Ogg Vorbis files (default=enabled)]),
               , enable_ogg=yes)
 
+AC_ARG_ENABLE(speex,
+              AC_HELP_STRING([--disable-speex], [Disable support for Ogg Speex files (default=enabled)]),
+              , enable_speex=yes)
+
 AC_ARG_ENABLE(flac,
               AC_HELP_STRING([--disable-flac],[Disable support for FLAC files (default=enabled)]),
               , enable_flac=yes)
@@ -89,6 +93,40 @@
     echo "***"
 fi
 
+dnl libSpeex library
+dnl check for system libspeex
+dnl Note that libvorbis is required for speex support, even if the user chooses --disable-speex
+if test "x$enable_speex" = "xyes"; then
+    dnl Library required for speex files, if not found 'enable_speex' is disabled
+    AC_CHECK_LIB(m, cos) dnl Patch from Christian Weisgerber
+    AC_CHECK_LIB(speex, speex_packet_to_header, , speex_available=yes)
+    if test "x$speex_available" = "xno"; then
+        AC_MSG_RESULT(no)
+        enable_flac="no"
+        echo "***"
+        echo "*** Warning: Speex file support disabled, speex missing"
+        echo "*** (Install speex, libogg and libvorbis libraries to enable it)"
+        echo "***"
+    elif test "x$ogg_available" = "xno"; then
+        AC_MSG_RESULT(no)
+        enable_flac="no"
+        echo "***"
+        echo "*** Warning: Speex file support disabled, libvorbis missing"
+        echo "*** (Install speex, libogg and libvorbis libraries to enable it)"
+        echo "***"
+    else
+        AC_MSG_RESULT(yes)
+        AC_DEFINE(ENABLE_SPEEX,1,[Define for Speex support])
+    fi
+else
+    AC_MSG_CHECKING(for Speex file support)
+    AC_MSG_RESULT(no)
+    echo "***"
+    echo "*** Speex file support disabled on commandline"
+    echo "*** (Install speex, libogg and libvorbis libraries, and use --enable-speex to enable it)"
+    echo "***"
+fi
+
 dnl libFLAC library
 dnl check for system libflac
 dnl Note that libvorbis is required for flac support, even if the user chooses --disable-ogg
@@ -302,6 +340,7 @@
  Id3lib version ..........: $ID3LIB_MAJOR.$ID3LIB_MINOR.$ID3LIB_PATCH
  NLS/gettext .............: $USE_NLS
  Ogg Vorbis file support .: $enable_ogg
+ Speex file support ......: $enable_speex
  FLAC file support .......: $enable_flac $LIBFLAC_VERSION
  MP4 file support ......  : $enable_mp4 
  Install path ............: $prefix
diff -uar easytag-1.99.8/src/et_core.h easytag-1.99.8_comp/src/et_core.h
--- easytag-1.99.8/src/et_core.h	2005-08-19 07:35:23.000000000 +0930
+++ easytag-1.99.8_comp/src/et_core.h	2005-09-03 23:24:24.000000000 +0930
@@ -115,10 +115,10 @@
     MP3_FILE,        // Mpeg audio Layer 3        : .mp3            (.mpg) (.mpga)
     MP4_FILE,        // Mpeg audio Layer 4 / AAC  : .mp4            (.m4a) (.m4p)
     OGG_FILE,        // Ogg Vorbis audio          : .ogg            (.ogm)
+    SPEEX_FILE,      // Speech audio files        : .spx
     FLAC_FILE,       // FLAC (lossless)           : .flac .fla
     MPC_FILE,        // MusePack                  : .mpc .mp+ .mpp
     MAC_FILE,        // Monkey's Audio (lossless) : .ape            (.mac)
-//    SPEEX_FILE,      // Speech audio files        : .spx
     OFR_FILE,        // OptimFROG (lossless)      : .ofr .ofs
     UNKNOWN_FILE
 } ET_File_Type;
@@ -236,6 +236,9 @@
 #ifdef ENABLE_OGG
     {OGG_FILE,     ".ogg",  OGG_TAG},
 #endif
+#ifdef ENABLE_SPEEX
+    {SPEEX_FILE,   ".spx",  OGG_TAG},
+#endif
 #ifdef ENABLE_FLAC
     {FLAC_FILE,    ".flac", FLAC_TAG},
     {FLAC_FILE,    ".fla",  FLAC_TAG},
@@ -253,7 +256,6 @@
     {MP4_FILE,     ".m4a",  MP4_TAG},  // Implemented by Michael Ihde
     {MP4_FILE,     ".m4p",  MP4_TAG},  // Implemented by Michael Ihde
 #endif
-//    {SPEEX_FILE,   ".spx",  OGG_TAG},
     {UNKNOWN_FILE, "",      UNKNOWN_TAG}    /* This item must be placed to the end! */
 };
 
diff -uar easytag-1.99.8/src/vcedit.c easytag-1.99.8_comp/src/vcedit.c
--- easytag-1.99.8/src/vcedit.c	2004-11-24 03:43:26.000000000 +1030
+++ easytag-1.99.8_comp/src/vcedit.c	2005-09-03 23:35:19.000000000 +0930
@@ -30,6 +30,7 @@
 {
 	vcedit_state *state = malloc(sizeof(vcedit_state));
 	memset(state, 0, sizeof(vcedit_state));
+	state->oggtype = 0;
 
 	return state;
 }
@@ -98,15 +99,20 @@
 	}
 }
 
-static int _commentheader_out(vorbis_comment *vc, char *vendor, ogg_packet *op)
+static int _commentheader_out(vcedit_state *state, ogg_packet *op)
 {
+	vorbis_comment *vc = state->vc;
+	char           *vendor = state->vendor;
 	oggpack_buffer opb;
 
 	oggpack_writeinit(&opb);
 
-	/* preamble */  
-	oggpack_write(&opb,0x03,8);
-	_v_writestring(&opb,"vorbis", 6);
+	if (state->oggtype == VCEDIT_ISVORBIS)
+	{
+		/* preamble */  
+		oggpack_write(&opb,0x03,8);
+		_v_writestring(&opb,"vorbis", 6);
+	}
 
 	/* vendor */
 	oggpack_write(&opb,strlen(vendor),32);
@@ -135,6 +141,10 @@
 	op->b_o_s=0;
 	op->e_o_s=0;
 	op->granulepos=0;
+	if (state->oggtype == VCEDIT_ISVORBIS)
+	{
+		op->packetno = 1;
+	}
 
 	oggpack_writeclear(&opb);
 	return 0;
@@ -191,6 +201,44 @@
 	}
 }
 
+/* Next functions pulled straight from libvorbis,
+ */
+static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
+  while(bytes--){
+    *buf++=oggpack_read(o,8);
+  }
+}
+
+/* Next functions pulled straight from libvorbis, apart from one change
+   - disabled the EOP check
+ */
+static int _speex_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb)
+{
+	int i;
+	int vendorlen=oggpack_read(opb,32);
+	if(vendorlen<0)goto err_out;
+
+	vc->vendor=_ogg_calloc(vendorlen+1,1);
+	_v_readstring(opb,vc->vendor,vendorlen);
+
+	vc->comments=oggpack_read(opb,32);
+	if(vc->comments<0)goto err_out;
+	vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
+	vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
+	for(i=0;i<vc->comments;i++){
+		int len=oggpack_read(opb,32);
+		if(len<0)goto err_out;
+		vc->comment_lengths[i]=len;
+		vc->user_comments[i]=_ogg_calloc(len+1,1);
+		_v_readstring(opb,vc->user_comments[i],len);
+	}	  
+//	if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
+	return(0);
+err_out:
+	vorbis_comment_clear(vc);
+	return(1);
+}
+
 int vcedit_open(vcedit_state *state, FILE *in)
 {
 	return vcedit_open_callbacks(state, (void *)in, 
@@ -260,26 +308,52 @@
 		goto err;
 	}
 
-	if(vorbis_synthesis_headerin(state->vi, state->vc, &header_main) < 0)
-	{
-		state->lasterror = _("Ogg bitstream does not contain vorbis data.");
-		goto err;
-	}
-
+	// We save the main header first, (it seems speex_packet_to_header munge's it??)
 	state->mainlen = header_main.bytes;
 	state->mainbuf = malloc(state->mainlen);
 	memcpy(state->mainbuf, header_main.packet, header_main.bytes);
 
-	i = 0;
-	header = &header_comments;
-	while(i<2) {
-		while(i<2) {
+	state->oggtype = 0;
+	int headerpackets = 0;
+#ifdef ENABLE_SPEEX
+	state->si = malloc(sizeof(SpeexHeader));
+	if((state->si = speex_packet_to_header((char*)(&header_main)->packet,(&header_main)->bytes)))
+		state->oggtype = VCEDIT_ISSPEEX;
+#endif
+	if(vorbis_synthesis_headerin(state->vi, state->vc, &header_main) == 0) 
+		state->oggtype = VCEDIT_ISVORBIS;
+
+	if (!state->oggtype)
+	{
+		state->lasterror = _("Ogg bitstream contains neither speex or vorbis data.");
+		goto err;
+	}
+
+	switch (state->oggtype)
+	{
+	case VCEDIT_ISVORBIS:
+		header = &header_comments;
+		headerpackets = 3;
+		break;
+#ifdef ENABLE_SPEEX
+	case VCEDIT_ISSPEEX:
+		header = &header_comments;
+		headerpackets = 2 + state->si->extra_headers;
+		break;
+#endif
+	}
+	oggpack_buffer opb;
+	i = 1;
+	while(i<headerpackets)
+	{
+		while(i<headerpackets)
+		{
 			int result = ogg_sync_pageout(state->oy, &og);
 			if(result == 0) break; /* Too little data so far */
 			else if(result == 1)
 			{
 				ogg_stream_pagein(state->os, &og);
-				while(i<2)
+				while(i< headerpackets)
 				{
 					result = ogg_stream_packetout(state->os, header);
 					if(result == 0) break;
@@ -288,16 +362,39 @@
 						state->lasterror = _("Corrupt secondary header.");
 						goto err;
 					}
-					vorbis_synthesis_headerin(state->vi, state->vc, header);
-					if(i==1)
+					switch (state->oggtype)
 					{
-						state->booklen = header->bytes;
-						state->bookbuf = malloc(state->booklen);
-						memcpy(state->bookbuf, header->packet, 
-								header->bytes);
+					case VCEDIT_ISVORBIS:
+						vorbis_synthesis_headerin(state->vi, state->vc, header);
+						switch (i) 
+						{
+							// 0 packet was the vorbis header
+						case 1:
+							header = &header_codebooks;
+							break;
+						case 2:
+							state->booklen = header->bytes;
+							state->bookbuf = malloc(state->booklen);
+							memcpy(state->bookbuf, header->packet, 
+							       header->bytes);
+							break;
+						}
+						break;
+					case VCEDIT_ISSPEEX:
+						switch (i) 
+						{
+							// 0 packet was the speex header
+						case 1:
+							oggpack_readinit(&opb,header->packet,header->bytes);
+							_speex_unpack_comment(state->vc,&opb);
+							break;
+						default:
+							state->lasterror = _("Need to save extra headers - TODO!!");
+							goto err;
+							break;
+						}
 					}
 					i++;
-					header = &header_codebooks;
 				}
 			}
 		}
@@ -356,7 +453,7 @@
 
 	ogg_stream_init(&streamout, state->serial);
 
-	_commentheader_out(state->vc, state->vendor, &header_comments);
+	_commentheader_out(state, &header_comments);
 
     /* 2002/10/22 - new code here for padded headers */
     //header_comments.packet = realloc(header_comments.packet, header_comments.bytes + 1000);
@@ -365,7 +462,9 @@
 
 	ogg_stream_packetin(&streamout, &header_main);
 	ogg_stream_packetin(&streamout, &header_comments);
-	ogg_stream_packetin(&streamout, &header_codebooks);
+
+	if (state->oggtype != VCEDIT_ISSPEEX)
+		ogg_stream_packetin(&streamout, &header_codebooks);
 
 	while((result = ogg_stream_flush(&streamout, &ogout)))
 	{
@@ -379,10 +478,6 @@
 
 	while(_fetch_next_packet(state, &op, &ogin))
 	{
-		int size;
-		size = _blocksize(state, &op);
-		granpos += size;
-
 		if(needflush)
 		{
 			if(ogg_stream_flush(&streamout, &ogout))
@@ -409,27 +504,39 @@
 		}
 
 		needflush=needout=0;
+		if (state->oggtype == VCEDIT_ISVORBIS) {
+			int size;
+			size = _blocksize(state, &op);
+			granpos += size;
 
-		if(op.granulepos == -1)
-		{
-			op.granulepos = granpos;
-			ogg_stream_packetin(&streamout, &op);
-		}
-		else /* granulepos is set, validly. Use it, and force a flush to 
-				account for shortened blocks (vcut) when appropriate */ 
-		{
-			if(granpos > op.granulepos)
+			if(op.granulepos == -1)
 			{
-				granpos = op.granulepos;
+				op.granulepos = granpos;
 				ogg_stream_packetin(&streamout, &op);
-				needflush=1;
 			}
-			else 
+			else /* granulepos is set, validly. Use it, and force a flush to 
+				account for shortened blocks (vcut) when appropriate */ 
 			{
-				ogg_stream_packetin(&streamout, &op);
-				needout=1;
-			}
-		}		
+				if(granpos > op.granulepos)
+				{
+					granpos = op.granulepos;
+					ogg_stream_packetin(&streamout, &op);
+					needflush=1;
+				}
+				else 
+				{
+					ogg_stream_packetin(&streamout, &op);
+					needout=1;
+				}
+			}		
+		}
+
+		/* Don't know about granulepos for speex, will just assume the original 
+		   was appropriate. Not sure about the flushing?? */
+		else if (state->oggtype == VCEDIT_ISSPEEX) {
+			ogg_stream_packetin(&streamout, &op);
+			needout=1;
+		}
 	}
 
 	streamout.e_o_s = 1;
diff -uar easytag-1.99.8/src/vcedit.h easytag-1.99.8_comp/src/vcedit.h
--- easytag-1.99.8/src/vcedit.h	2003-09-03 17:28:05.000000000 +0930
+++ easytag-1.99.8_comp/src/vcedit.h	2005-09-03 23:23:07.000000000 +0930
@@ -19,6 +19,14 @@
 #include <ogg/ogg.h>
 #include <vorbis/codec.h>
 
+#ifdef ENABLE_SPEEX
+#include <speex/speex.h>
+#include <speex/speex_header.h>
+#endif
+
+#define VCEDIT_ISSPEEX  1
+#define VCEDIT_ISVORBIS 2
+
 typedef size_t (*vcedit_read_func)(void *, size_t, size_t, void *);
 typedef size_t (*vcedit_write_func)(const void *, size_t, size_t, void *);
 
@@ -26,8 +34,15 @@
 	ogg_sync_state		*oy;
 	ogg_stream_state	*os;
 
+	int                     oggtype;
+
 	vorbis_comment		*vc;
-	vorbis_info         *vi;
+
+	vorbis_info             *vi;
+
+#ifdef ENABLE_SPEEX
+	SpeexHeader             *si;
+#endif
 
 	vcedit_read_func read;
 	vcedit_write_func write;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]