[cvs-annodex] commit (libfishsound): trunk/include/fishsound/fishsound.h trunk/src/examples/fishsound-decode.c trunk/src/libfishsound/Version_script.in trunk/src/libfishsound/fishsound.c trunk/src/libfishsound/private.h trunk/src/libfishsound/speex.c trunk/src/libfishsound/vorbis.c trunk/src/tests/encdec-audio.c trunk/win32/libfishsound/libfishsound.def

conrad nobody at lists.annodex.net
Tue May 18 10:37:35 EST 2004


Update of /annodex/libfishsound (new revision 77)

Modified files:
   trunk/include/fishsound/fishsound.h
   trunk/src/examples/fishsound-decode.c
   trunk/src/libfishsound/Version_script.in
   trunk/src/libfishsound/fishsound.c
   trunk/src/libfishsound/private.h
   trunk/src/libfishsound/speex.c
   trunk/src/libfishsound/vorbis.c
   trunk/src/tests/encdec-audio.c
   trunk/win32/libfishsound/libfishsound.def

Log Message:
Improved handling of first and last blocks of data (bos and eos packets in Ogg):
	* new fish_sound_prepare_truncation() API call
	* improved encdec-audio test to keep track of frames in and out,
	  and warn if unequal. (Currently not set to FAIL on this condition
	  as it appears to be common for Speex)



Modified: trunk/include/fishsound/fishsound.h
===================================================================
--- trunk/include/fishsound/fishsound.h	2004-05-13 02:06:37 UTC (rev 76)
+++ trunk/include/fishsound/fishsound.h	2004-05-18 00:37:35 UTC (rev 77)
@@ -609,6 +609,39 @@
  */
 int fish_sound_set_frameno (FishSound * fsound, long frameno);
 
+/**
+ * Prepare truncation details for the next block of data.
+ * The semantics of these parameters derives directly from Ogg encapsulation
+ * of Vorbis, described
+ * <a href="http://www.xiph.org/ogg/vorbis/doc/Vorbis_I_spec.html#vorbis-over-ogg">here</a>.
+ *
+ * When decoding from Ogg, you should call this function with the \a granulepos
+ * and \a eos of the \a ogg_packet structure. This call should be made before
+ * passing the packet's data to fish_sound_decode(). Failure to do so may
+ * result in minor decode errors on the first and/or last packet of the stream.
+ *
+ * When encoding into Ogg, you should call this function with the \a granulepos
+ * and \a eos that will be used for the \a ogg_packet structure. This call
+ * should be made before passing the block of audio data to
+ * fish_sound_encode(). Failure to do so may result in minor encoding errors
+ * on the first and/or last packet of the stream.
+ *
+ * \param fsound A FishSound* handle
+ * \param next_granulepos The "granulepos" for the next block to decode.
+ *        If unknown, set \a next_granulepos to -1. Otherwise,
+ *        \a next_granulepos specifies the frameno of the final frame in the
+ *        block. This is authoritative, hence can be used to indicate
+ *        various forms of truncation at the beginning or end of a stream.
+ *        Mid-stream, a later-than-expected "granulepos" indicates that some
+ *        data was missing. 
+ * \param next_eos A boolean indicating whether the next data block will be
+ *        the last in the stream.
+ * \retval 0 Success
+ * \retval -1 Invalid \a fsound
+ */
+int fish_sound_prepare_truncation (FishSound * fsound, long next_granulepos,
+                                   int next_eos);
+
 #ifdef __cplusplus
 }
 #endif

Modified: trunk/src/examples/fishsound-decode.c
===================================================================
--- trunk/src/examples/fishsound-decode.c	2004-05-13 02:06:37 UTC (rev 76)
+++ trunk/src/examples/fishsound-decode.c	2004-05-18 00:37:35 UTC (rev 77)
@@ -79,6 +79,7 @@
 {
   FishSound * fsound = (FishSound *)user_data;
 
+  fish_sound_prepare_truncation (fsound, op->granulepos, op->e_o_s);
   fish_sound_decode (fsound, op->packet, op->bytes);
 
   return 0;

Modified: trunk/src/libfishsound/Version_script.in
===================================================================
--- trunk/src/libfishsound/Version_script.in	2004-05-13 02:06:37 UTC (rev 76)
+++ trunk/src/libfishsound/Version_script.in	2004-05-18 00:37:35 UTC (rev 77)
@@ -22,6 +22,7 @@
 		fish_sound_set_interleave;
 		fish_sound_get_frameno;
 		fish_sound_set_frameno;
+		fish_sound_prepare_truncation;
 
 		fish_sound_comment_get_vendor;
 		fish_sound_comment_first;

Modified: trunk/src/libfishsound/fishsound.c
===================================================================
--- trunk/src/libfishsound/fishsound.c	2004-05-13 02:06:37 UTC (rev 76)
+++ trunk/src/libfishsound/fishsound.c	2004-05-18 00:37:35 UTC (rev 77)
@@ -101,6 +101,8 @@
   fsound->mode = mode;
   fsound->interleave = 0;
   fsound->frameno = 0;
+  fsound->next_granulepos = -1;
+  fsound->next_eos = 0;
   fsound->codec = NULL;
   fsound->codec_data = NULL;
   fsound->callback = NULL;
@@ -303,3 +305,15 @@
 
   return 0;
 }
+
+int
+fish_sound_prepare_truncation (FishSound * fsound, long next_granulepos,
+			       int next_eos)
+{
+  if (fsound == NULL) return -1;
+
+  fsound->next_granulepos = next_granulepos;
+  fsound->next_eos = next_eos;
+
+  return 0;
+}

Modified: trunk/src/libfishsound/private.h
===================================================================
--- trunk/src/libfishsound/private.h	2004-05-13 02:06:37 UTC (rev 76)
+++ trunk/src/libfishsound/private.h	2004-05-18 00:37:35 UTC (rev 77)
@@ -95,9 +95,29 @@
   /** General info related to sound */
   FishSoundInfo info;
 
+  /** Interleave boolean */
   int interleave;
+
+  /**
+   * Current frameno.
+   */
   long frameno;
 
+  /**
+   * Truncation frameno for the next block of data sent to decode.
+   * In Ogg encapsulation, this is represented by the Ogg packet's
+   * "granulepos" field.
+   */
+  long next_granulepos;
+
+  /**
+   * Flag if the next block of data sent to decode will be the last one
+   * for this stream (eos = End Of Stream).
+   * In Ogg encapsulation, this is represented by the Ogg packet's
+   * "eos" field.
+   */
+  int next_eos;
+
   /** The codec class structure */
   FishSoundCodec * codec;
 

Modified: trunk/src/libfishsound/speex.c
===================================================================
--- trunk/src/libfishsound/speex.c	2004-05-13 02:06:37 UTC (rev 76)
+++ trunk/src/libfishsound/speex.c	2004-05-18 00:37:35 UTC (rev 77)
@@ -512,6 +512,9 @@
   FishSoundSpeexEnc * fse = (FishSoundSpeexEnc *)fss->enc;
   long nencoded = 0;
 
+  if (fsound->mode != FISH_SOUND_ENCODE)
+    return 0;
+
   if (fse->pcm_offset > 0) {
     nencoded += fs_speex_encode_block (fsound);
   }

Modified: trunk/src/libfishsound/vorbis.c
===================================================================
--- trunk/src/libfishsound/vorbis.c	2004-05-13 02:06:37 UTC (rev 76)
+++ trunk/src/libfishsound/vorbis.c	2004-05-18 00:37:35 UTC (rev 77)
@@ -188,12 +188,12 @@
   long samples;
   int ret;
 
-  /* Make a fake ogg_packet structure to pass the data to libvorbis */
+  /* Make an ogg_packet structure to pass the data to libvorbis */
   op.packet = buf;
   op.bytes = bytes;
   op.b_o_s = (fsv->packetno == 0) ? 1 : 0;
-  op.e_o_s = 0;
-  op.granulepos = 7;
+  op.e_o_s = fsound->next_eos;
+  op.granulepos = fsound->next_granulepos;
   op.packetno = fsv->packetno;
 
   if (fsv->packetno < 3) {
@@ -237,16 +237,22 @@
       } else {
 	retpcm = pcm;
       }
-
-      fsound->frameno += samples;
       
       if (fsound->callback) {
 	((FishSoundDecoded)fsound->callback) (fsound, retpcm, samples,
 					      fsound->user_data);
       }
+
+      if (fsound->frameno != -1)
+	fsound->frameno += samples;
     }
   }
 
+  if (fsound->next_granulepos != -1) {
+    fsound->frameno = fsound->next_granulepos;
+    fsound->next_granulepos = -1;
+  }
+
   fsv->packetno++;
 
   return 0;
@@ -321,8 +327,11 @@
       if (fsound->callback) {
 	FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback;
 
-	fsound->frameno = op.granulepos;
 	encoded (fsound, op.packet, op.bytes, fsound->user_data);
+
+	if (op.granulepos != -1)
+	  fsound->frameno = op.granulepos;
+
 	fsv->packetno++;
       }
     }
@@ -358,6 +367,13 @@
     remaining -= len;
   }
 
+  /**
+   * End of input. Tell libvorbis we're at the end of stream so that it can
+   * handle the last frame and marke end of stream in the output properly.
+   */
+  if (fsound->next_eos)
+    fs_vorbis_encode_write (fsound, 0);
+
   return 0;
 }
 
@@ -397,6 +413,13 @@
     remaining -= len;
   }
 
+  /**
+   * End of input. Tell libvorbis we're at the end of stream so that it can
+   * handle the last frame and marke end of stream in the output properly.
+   */
+  if (fsound->next_eos)
+    fs_vorbis_encode_write (fsound, 0);
+
   return 0;
 }
 

Modified: trunk/src/tests/encdec-audio.c
===================================================================
--- trunk/src/tests/encdec-audio.c	2004-05-13 02:06:37 UTC (rev 76)
+++ trunk/src/tests/encdec-audio.c	2004-05-18 00:37:35 UTC (rev 77)
@@ -42,16 +42,53 @@
 
 #define DEBUG
 
+#define DEFAULT_ITER 2
+
+static void
+usage (char * progname)
+{
+  printf ("Usage: %s [options]\n\n", progname);
+  printf ("Options:\n");
+  printf ("  --iter n                  Specify iterations per test (default %d)\n", DEFAULT_ITER);
+  printf ("  --nasty                   Run with large test parameters\n");
+  printf ("  --disable-vorbis          Disable testing of Vorbis codec\n");
+  printf ("  --disable-speex           Disable testing of Speex codec\n");
+  printf ("  --disable-interleave      Disable testing of interleave\n");
+  printf ("  --disable-non-interleave  Disable testing of non-interleave\n");
+  exit (1);
+}
+
+/* For one-time tests, configure these by commandline args */
+static int * test_blocksizes, * test_samplerates, * test_channels;
+static int iter = DEFAULT_ITER;
+static int test_vorbis = 1, test_speex = 1;
+static int test_interleave = 1, test_non_interleave = 1;
+
+static int nasty_blocksizes[] = {128, 256, 512, 1024, 2048, 4096, 0};
+static int nasty_samplerates[] = {8000, 16000, 32000, 48000, 0};
+static int nasty_channels[] = {1, 2, 4, 5, 6, 8, 10, 16, 32, 0};
+
+static int default_blocksizes[] = {128, 1024, 0};
+static int default_samplerates[] = {8000, 48000, 0};
+static int default_channels[] = {1, 2, 6, 16, 0};
+
 typedef struct {
   FishSound * encoder;
   FishSound * decoder;
+  int interleave;
+  int channels;
   float ** pcm;
+  long frames_in;
+  long frames_out;
 } FS_EncDec;
 
 static int
 decoded (FishSound * fsound, float ** pcm, long frames, void * user_data)
 {
-  /* Boo! */
+  FS_EncDec * ed = (FS_EncDec *) user_data;
+
+  ed->frames_out += frames;
+
   return 0;
 }
 
@@ -101,6 +138,9 @@
   fish_sound_set_encoded_callback (ed->encoder, encoded, ed);
   fish_sound_set_decoded_callback (ed->decoder, decoded, ed);
 
+  ed->interleave = interleave;
+  ed->channels = channels;
+
   if (interleave) {
     ed->pcm = (float **) malloc (sizeof (float) * channels * blocksize);
     fs_fill_square ((float *)ed->pcm, channels * blocksize);
@@ -112,16 +152,28 @@
     }
   }
 
+  ed->frames_in = 0;
+  ed->frames_out = 0;
+
   return ed;
 }
 
 static int
 fs_encdec_delete (FS_EncDec * ed)
 {
+  int i;
+
   if (!ed) return -1;
 
   fish_sound_delete (ed->encoder);
   fish_sound_delete (ed->decoder);
+
+  if (!ed->interleave) {
+    for (i = 0; i < ed->channels; i++)
+      free (ed->pcm[i]);
+  }
+  free (ed->pcm);
+  
   free (ed);
 
   return 0;
@@ -132,61 +184,129 @@
 		int blocksize)
 {
   FS_EncDec * ed;
+  char msg[128];
   int i;
+
+  snprintf (msg, 128,
+	    "+ %2d channel %6d Hz %s, %d frame buffer (%s)",
+	    channels, samplerate,
+	    format == FISH_SOUND_VORBIS ? "Vorbis" : "Speex",
+	    blocksize,
+	    interleave ? "interleave" : "non-interleave");
+  INFO (msg);
   
   ed = fs_encdec_new (samplerate, channels, format, interleave, blocksize);
 
-  for (i = 0; i < 2; i++) {
+  for (i = 0; i < iter; i++) {
+    ed->frames_in += blocksize;
+    fish_sound_prepare_truncation (ed->encoder, ed->frames_in,
+				   (i == (iter - 1)));
     fish_sound_encode (ed->encoder, ed->pcm, blocksize);
   }
 
+  fish_sound_flush (ed->encoder);
+
+  if (ed->frames_in != ed->frames_out) {
+    snprintf (msg, 128,
+	      "%ld frames encoded, %ld frames decoded",
+	      ed->frames_in, ed->frames_out);
+    WARN (msg);
+  }
+
   fs_encdec_delete (ed);
 
   return 0;
 }
 
+static void
+parse_args (int argc, char * argv[])
+{
+  int i;
+
+  for (i = 1; i < argc; i++) {
+    if (!strcmp (argv[i], "--nasty")) {
+      test_blocksizes = nasty_blocksizes;
+      test_samplerates = nasty_samplerates;
+      test_channels = nasty_channels;
+    } else if (!strcmp (argv[i], "--iter")) {
+      i++; if (i >= argc) usage(argv[0]);
+      iter = atoi (argv[i]);
+    } else if (!strcmp (argv[i], "--disable-vorbis")) {
+      test_vorbis = 0;
+    } else if (!strcmp (argv[i], "--disable-speex")) {
+      test_speex = 0;
+    } else if (!strcmp (argv[i], "--disable-interleave")) {
+      test_interleave = 0;
+    } else if (!strcmp (argv[i], "--disable-non-interleave")) {
+      test_non_interleave = 0;
+    } else if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "-h")) {
+      usage(argv[0]);
+    }
+  }
+
+  INFO ("Testing encode/decode pipeline for audio");
+
+  /* Report abnormal options */
+
+  if (test_blocksizes == nasty_blocksizes)
+    INFO ("* Running NASTY large test parameters");
+
+  if (!test_vorbis) INFO ("* DISABLED testing of Vorbis");
+  if (!test_speex) INFO ("* DISABLED testing of Speex");
+  if (!test_interleave) INFO ("* DISABLED testing of INTERLEAVE");
+  if (!test_non_interleave) INFO ("* DISABLED testing of NON-INTERLEAVE");
+}
+
 int
 main (int argc, char * argv[])
 {
+  int b, s, c;
 
-#ifdef NASTY
-  int blocksizes[6] = {128, 256, 512, 1024, 2048, 4096};
-  int samplerates[4] = {8000, 16000, 32000, 48000};
-  int channels[9] = {1, 2, 4, 5, 6, 8, 10, 16, 32};
-#else
-  int blocksizes[2] = {128, 1024};
-  int samplerates[2] = {8000, 48000};
-  int channels[4] = {1, 2, 6, 16};
-#endif
-  int interleave, b, s, c;
-  char buf[128];
+  test_blocksizes = default_blocksizes;
+  test_samplerates = default_samplerates;
+  test_channels = default_channels;
 
-  INFO ("Testing encode/decode pipeline for audio");
+  parse_args (argc, argv);
+  
+  for (b = 0; test_blocksizes[b]; b++) {
+    for (s = 0; test_samplerates[s]; s++) {
+      for (c = 0; test_channels[c]; c++) {
 
-  for (b = 0; b < sizeof (blocksizes) / sizeof (int); b++) {
-    for (s = 0; s < sizeof (samplerates) / sizeof (int); s++) {
-      for (c = 0; c < sizeof (channels) / sizeof (int); c++) {
-	for (interleave = 0; interleave < 2; interleave++) {
-
+	if (test_non_interleave) {
 	  /* Test VORBIS */
-	  snprintf (buf, 128, "+ %2d channel %6d Hz Vorbis, %d frame buffer (%s)",
-		    channels[c], samplerates[s], blocksizes[b],
-		    interleave ? "interleave" : "non-interleave");
-	  INFO (buf);
-	  fs_encdec_test (samplerates[s], channels[c], FISH_SOUND_VORBIS,
-			  interleave, blocksizes[b]);
-
+	  if (test_vorbis) {
+	    fs_encdec_test (test_samplerates[s], test_channels[c],
+			    FISH_SOUND_VORBIS, 0, test_blocksizes[b]);
+	  }
+	  
 	  /* Test SPEEX */
-	  if (channels[c] <= 2) {
-	    snprintf (buf, 128, "+ %2d channel %6d Hz Speex,  %d frame buffer (%s)",
-		      channels[c], samplerates[s], blocksizes[b],
-		      interleave ? "interleave" : "non-interleave");
-	    INFO (buf);
-	    fs_encdec_test (samplerates[s], channels[c], FISH_SOUND_SPEEX,
-			    interleave, blocksizes[b]);
+	  if (test_speex) {
+	    if (test_channels[c] <= 2) {
+	      fs_encdec_test (test_samplerates[s], test_channels[c],
+			      FISH_SOUND_SPEEX, 0, test_blocksizes[b]);
+	      
+	    }
+	  }
+	}
 
+	if (test_interleave) {
+	  /* Test VORBIS */
+	  if (test_vorbis) {
+	    fs_encdec_test (test_samplerates[s], test_channels[c],
+			    FISH_SOUND_VORBIS, 1, test_blocksizes[b]);
 	  }
+	  
+	  /* Test SPEEX */
+	  if (test_speex) {
+	    if (test_channels[c] <= 2) {
+	      fs_encdec_test (test_samplerates[s], test_channels[c],
+			      FISH_SOUND_SPEEX, 1, test_blocksizes[b]);
+	      
+	    }
+	  }
 	}
+
+
       }
     }
   }

Modified: trunk/win32/libfishsound/libfishsound.def
===================================================================
--- trunk/win32/libfishsound/libfishsound.def	2004-05-13 02:06:37 UTC (rev 76)
+++ trunk/win32/libfishsound/libfishsound.def	2004-05-18 00:37:35 UTC (rev 77)
@@ -14,6 +14,7 @@
 		fish_sound_set_interleave
 		fish_sound_get_frameno
 		fish_sound_set_frameno
+		fish_sound_prepare_truncation
 		fish_sound_get_vendor
 		fish_sound_comment_first
 		fish_sound_comment_next


-- 
conrad



More information about the cvs-annodex mailing list