/*****************************************************************************
* 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
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)
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 */
#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.
*
* 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;
*}
*/
* }
*/
-//#define MPG321_ROUTINES 1
-#ifdef MPG321_ROUTINES
/*****************************************************************************
* support routines borrowed from mpg321 (file: mad.c), which is distributed
* under GPL license
}
/*
-* 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;
/* scale */
return output >> scalebits;
}
-#else
/*****************************************************************************
* s24_to_s16_pcm: Scale a 24 bit pcm sample to a 16 bit pcm sample.
/* quantize */
return sample >> (MAD_F_FRACBITS + 1 - 16);
}
-#endif
/*****************************************************************************
* libmad_ouput: this function is called just after the frame is decoded
{
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.
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);
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);
*/
+
+/****************************************************************************
+ * 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);
+}