Added mad plugin downscale config option for selecting downscaling routine. Choices...
authorJean-Paul Saman <jpsaman@videolan.org>
Mon, 6 May 2002 22:09:58 +0000 (22:09 +0000)
committerJean-Paul Saman <jpsaman@videolan.org>
Mon, 6 May 2002 22:09:58 +0000 (22:09 +0000)
Mono audio streams get now duplicated on the right channel instead of silencing the right channel (untested).

plugins/mad/mad_adec.c
plugins/mad/mad_adec.h
plugins/mad/mad_libmad.c

index f57da48..088e4f0 100644 (file)
@@ -60,7 +60,14 @@ void _M( adec_getfunctions )( function_list_t * p_function_list )
 /*****************************************************************************
  * Build configuration tree.
  *****************************************************************************/
+#define DOWNSCALE_TEXT N_("Mad audio downscale routine (fast,mp321)")
+#define DOWNSCALE_LONGTEXT N_( \
+    "Specify the mad audio downscale routine you want to use.\nBy default mad plugins will " \
+    "use the fastest routine.")
+
 MODULE_CONFIG_START
+ADD_CATEGORY_HINT( N_("Miscellaneous"), NULL )
+ADD_STRING  ( "downscale", "fast", NULL, DOWNSCALE_TEXT, DOWNSCALE_LONGTEXT )
 MODULE_CONFIG_STOP
 
 MODULE_INIT_START
@@ -156,11 +163,33 @@ static int decoder_Run ( decoder_config_t * p_config )
 static int InitThread( mad_adec_thread_t * p_mad_adec )
 {
     decoder_fifo_t * p_fifo = p_mad_adec->p_fifo;
+    char *psz_downscale = NULL;
 
     /*
      * Properties of audio for libmad
      */
-        
+               
+               /* Look what scaling method was requested by the user */
+    psz_downscale = config_GetPszVariable( "downscale" );
+
+    if ( strncmp(psz_downscale,"fast",4)==0 )
+    {
+        p_mad_adec->audio_scaling = FAST_SCALING;
+        intf_ErrMsg( "mad_adec debug: downscale fast selected" );
+    }
+    else if ( strncmp(psz_downscale,"mpg321",7)==0 )
+    {
+        p_mad_adec->audio_scaling = MPG321_SCALING;
+        intf_ErrMsg( "mad_adec debug: downscale mpg321 selected" );
+    }
+    else
+    {
+        p_mad_adec->audio_scaling = FAST_SCALING;
+        intf_ErrMsg( "mad_adec debug: downscale default fast selected" );
+    }
+
+               if (psz_downscale) free(psz_downscale);
+
     /* Initialize the libmad decoder structures */
     p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
     if (p_mad_adec->libmad_decoder == NULL)
@@ -172,7 +201,7 @@ static int InitThread( mad_adec_thread_t * p_mad_adec )
     p_mad_adec->i_current_pts = p_mad_adec->i_next_pts = 0;
 
     mad_decoder_init( p_mad_adec->libmad_decoder,
-                          p_mad_adec,         /* vlc's thread structure and p_fifo playbuffer */
+                      p_mad_adec,         /* vlc's thread structure and p_fifo playbuffer */
                       libmad_input,          /* input_func */
                       0,                /* header_func */
                       0,                /* filter */
index 621f53e..c5214e1 100644 (file)
@@ -22,6 +22,8 @@
  * mad_adec_thread_t : mad decoder thread descriptor
  *****************************************************************************/
 
+enum mad_scaling { FAST_SCALING, MPG321_SCALING };
+
 typedef struct mad_adec_thread_s
 {
     /*
@@ -50,6 +52,7 @@ typedef struct mad_adec_thread_s
      * Output properties
      */
     aout_fifo_t *       p_aout_fifo; /* stores the decompressed audio frames */
+    enum mad_scaling     audio_scaling;
 
 } mad_adec_thread_t;
 
index 144a5e9..2b4b483 100644 (file)
@@ -38,6 +38,8 @@
 #include "mad_adec.h"
 #include "mad_libmad.h"
 
+static void PrintFrameInfo(struct mad_header *Header);
+
 /*****************************************************************************
  * libmad_input: this function is called by libmad when the input buffer needs
  * to be filled.
@@ -153,9 +155,7 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
  *
  *   intf_ErrMsg( "mad_adec: libmad_header samplerate %d", p_libmad_header->samplerate);
  *
- *   p_mad_adec->p_aout_fifo->i_rate = p_libmad_header->samplerate;
- * //  mad_timer_add(&p_mad_adec->libmad_timer,p_libmad_header->duration);
- *
+ *   PrintFrameInfo(p_limad_mad_header)
  *   return MAD_FLOW_CONTINUE;
  *}
  */
@@ -169,8 +169,6 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
  * }
  */
 
-//#define MPG321_ROUTINES     1
-#ifdef MPG321_ROUTINES
 /*****************************************************************************
  * support routines borrowed from mpg321 (file: mad.c), which is distributed
  * under GPL license
@@ -201,10 +199,10 @@ static __inline__ unsigned long prng(unsigned long state)
 }
 
 /*
-* NAME:                audio_linear_dither()
+* NAME:        mpg321_s24_to_s16_pcm()
 * DESCRIPTION: generic linear sample quantize and dither routine
 */
-static __inline__ signed int audio_linear_dither(unsigned int bits, mad_fixed_t sample,
+static __inline__ signed int mpg321_s24_to_s16_pcm(unsigned int bits, mad_fixed_t sample,
                                     struct audio_dither *dither)
 {
     unsigned int scalebits;
@@ -256,7 +254,6 @@ static __inline__ signed int audio_linear_dither(unsigned int bits, mad_fixed_t
     /* scale */
     return output >> scalebits;
 }
-#else
 
 /*****************************************************************************
  * s24_to_s16_pcm: Scale a 24 bit pcm sample to a 16 bit pcm sample.
@@ -275,7 +272,6 @@ static __inline__ mad_fixed_t s24_to_s16_pcm(mad_fixed_t sample)
   /* quantize */
   return sample >> (MAD_F_FRACBITS + 1 - 16);
 }
-#endif
 
 /*****************************************************************************
  * libmad_ouput: this function is called just after the frame is decoded
@@ -284,13 +280,10 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
 {
     mad_adec_thread_t *p_mad_adec= (mad_adec_thread_t *) data;
     byte_t *buffer=NULL;
-
     mad_fixed_t const *left_ch = p_libmad_pcm->samples[0], *right_ch = p_libmad_pcm->samples[1];
     register int nsamples = p_libmad_pcm->length;
     mad_fixed_t sample;
-#ifdef MPG321_ROUTINES
     static struct audio_dither dither;
-#endif
 
     /* Creating the audio output fifo.
      * Assume the samplerate and nr of channels from the first decoded frame is right for the entire audio track.
@@ -336,12 +329,18 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
 
     while (nsamples--)
     {
-#ifdef MPG321_ROUTINES
-        sample = audio_linear_dither(16, *left_ch++, &dither);
-#else
-         sample = s24_to_s16_pcm(*left_ch++);
-#endif
-
+        switch (p_mad_adec->audio_scaling)
+        {
+          case MPG321_SCALING:
+               sample = mpg321_s24_to_s16_pcm(16, *left_ch++, &dither);
+          break;
+          case FAST_SCALING: /* intended fall through */
+          default:
+               sample = s24_to_s16_pcm(*left_ch++);
+          break;
+                         }
+
+        /* left audio channel */
 #ifndef WORDS_BIGENDIAN
         *buffer++ = (byte_t) (sample >> 0);
         *buffer++ = (byte_t) (sample >> 8);
@@ -352,29 +351,27 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
        if (p_libmad_pcm->channels == 2)
         {
                    /* right audio channel */
-#ifdef MPG321_ROUTINES
-            sample = audio_linear_dither(16, *right_ch++, &dither);
-#else
-            sample = s24_to_s16_pcm(*right_ch++);
-#endif
-
+            switch (p_mad_adec->audio_scaling)
+            {
+              case MPG321_SCALING:
+                   sample = mpg321_s24_to_s16_pcm(16, *right_ch++, &dither);
+              break;
+              case FAST_SCALING: /* intended fall through */
+              default:
+                   sample = s24_to_s16_pcm(*right_ch++);
+              break;
+                         }
+        }
+        /* else reuse left_ch */
 #ifndef WORDS_BIGENDIAN
-            *buffer++ = (byte_t) (sample >> 0);
-            *buffer++ = (byte_t) (sample >> 8);
+        *buffer++ = (byte_t) (sample >> 0);
+        *buffer++ = (byte_t) (sample >> 8);
 #else
-            *buffer++ = (byte_t) (sample >> 8);
-            *buffer++ = (byte_t) (sample >> 0);
+        *buffer++ = (byte_t) (sample >> 8);
+        *buffer++ = (byte_t) (sample >> 0);
 #endif                                         
-        }
-       else {
-           /* Somethimes a single channel frame is found, while the rest of the movie are
-             * stereo channel frames. How to deal with this ??
-             * One solution is to silence the second channel.
-             */
-            *buffer++ = (byte_t) (0);
-            *buffer++ = (byte_t) (0);
-       }
     }
+
     /* DEBUG */
     if (p_libmad_pcm->channels == 1) {
        intf_ErrMsg( "mad debug: libmad_output channels [%d]", p_libmad_pcm->channels);
@@ -498,3 +495,73 @@ enum mad_flow libmad_error(void *data, struct mad_stream *p_libmad_stream, struc
  */
 
 
+
+/****************************************************************************
+ * Print human readable informations about an audio MPEG frame.                                *
+ ****************************************************************************/
+static void PrintFrameInfo(struct mad_header *Header)
+{
+       const char      *Layer,
+                       *Mode,
+                       *Emphasis;
+
+       /* Convert the layer number to it's printed representation. */
+       switch(Header->layer)
+       {
+               case MAD_LAYER_I:
+                       Layer="I";
+                       break;
+               case MAD_LAYER_II:
+                       Layer="II";
+                       break;
+               case MAD_LAYER_III:
+                       Layer="III";
+                       break;
+               default:
+                       Layer="(unexpected layer value)";
+                       break;
+       }
+
+       /* Convert the audio mode to it's printed representation. */
+       switch(Header->mode)
+       {
+               case MAD_MODE_SINGLE_CHANNEL:
+                       Mode="single channel";
+                       break;
+               case MAD_MODE_DUAL_CHANNEL:
+                       Mode="dual channel";
+                       break;
+               case MAD_MODE_JOINT_STEREO:
+                       Mode="joint (MS/intensity) stereo";
+                       break;
+               case MAD_MODE_STEREO:
+                       Mode="normal LR stereo";
+                       break;
+               default:
+                       Mode="(unexpected mode value)";
+                       break;
+       }
+
+       /* Convert the emphasis to it's printed representation. */
+       switch(Header->emphasis)
+       {
+               case MAD_EMPHASIS_NONE:
+                       Emphasis="no";
+                       break;
+               case MAD_EMPHASIS_50_15_US:
+                       Emphasis="50/15 us";
+                       break;
+               case MAD_EMPHASIS_CCITT_J_17:
+                       Emphasis="CCITT J.17";
+                       break;
+               default:
+                       Emphasis="(unexpected emphasis value)";
+                       break;
+       }
+
+       intf_ErrMsg("statistics: %lu kb/s audio mpeg layer %s stream %s crc, "
+                       "%s with %s emphasis at %d Hz sample rate\n",
+                       Header->bitrate,Layer,
+                       Header->flags&MAD_FLAG_PROTECTION?"with":"without",
+                       Mode,Emphasis,Header->samplerate);
+}