Commit 8d59e936 authored by Jean-Paul Saman's avatar Jean-Paul Saman

Optimized libmad_output() for smoother sound. It is still not optimal.

parent 6a4d3ed0
...@@ -69,7 +69,7 @@ MODULE_CONFIG_STOP ...@@ -69,7 +69,7 @@ MODULE_CONFIG_STOP
MODULE_INIT_START MODULE_INIT_START
SET_DESCRIPTION( "Libmad MPEG 1/2/3 audio decoder library" ) SET_DESCRIPTION( "Libmad MPEG 1/2/3 audio decoder library" )
ADD_CAPABILITY( DECODER, 50 ) ADD_CAPABILITY( DECODER, 950 )
MODULE_INIT_STOP MODULE_INIT_STOP
MODULE_ACTIVATE_START MODULE_ACTIVATE_START
...@@ -180,10 +180,10 @@ static int InitThread( mad_adec_thread_t * p_mad_adec ) ...@@ -180,10 +180,10 @@ static int InitThread( mad_adec_thread_t * p_mad_adec )
mad_decoder_init( p_mad_adec->libmad_decoder, 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 */ libmad_input, /* input_func */
libmad_header, /* header_func */ 0, /* header_func */
0, /* filter */ 0, /* filter */
libmad_output, /* output_func */ libmad_output, /* output_func */
0, /* error */ 0, /* error */
0); /* message */ 0); /* message */
mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC); mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
...@@ -231,9 +231,8 @@ static void EndThread (mad_adec_thread_t * p_mad_adec) ...@@ -231,9 +231,8 @@ static void EndThread (mad_adec_thread_t * p_mad_adec)
/* mad_decoder_finish releases the memory allocated inside the struct */ /* mad_decoder_finish releases the memory allocated inside the struct */
mad_decoder_finish( p_mad_adec->libmad_decoder ); mad_decoder_finish( p_mad_adec->libmad_decoder );
/* Unlock the modules */ /* Unlock the modules, p_mad_adec->p_config is released by the decoder subsystem */
free( p_mad_adec->libmad_decoder ); free( p_mad_adec->libmad_decoder );
// free( p_mad_adec->p_config ); /* for now a reminder until integration with cvs */
free( p_mad_adec ); free( p_mad_adec );
intf_ErrMsg ("mad_adec debug: mad decoder thread %p destroyed", p_mad_adec); intf_ErrMsg ("mad_adec debug: mad decoder thread %p destroyed", p_mad_adec);
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
/***************************************************************************** /*****************************************************************************
* Libmad includes files * Libmad includes files
*****************************************************************************/ *****************************************************************************/
#include <mad.h> #include <mad.h>
#include "mad_adec.h" #include "mad_adec.h"
#include "mad_libmad.h" #include "mad_libmad.h"
...@@ -81,21 +80,18 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream) ...@@ -81,21 +80,18 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
* libmad_header: this function is called just after the header of a frame is * libmad_header: this function is called just after the header of a frame is
* decoded * decoded
*****************************************************************************/ *****************************************************************************/
enum mad_flow libmad_header(void *data, struct mad_header const *p_libmad_header) /* enum mad_flow libmad_header(void *data, struct mad_header const *p_libmad_header)
{ * {
mad_adec_thread_t *p_mad_adec = (mad_adec_thread_t *) data; * mad_adec_thread_t *p_mad_adec = (mad_adec_thread_t *) data;
*
vlc_mutex_lock (&p_mad_adec->p_aout_fifo->data_lock); * intf_ErrMsg( "mad_adec: libmad_header samplerate %d", p_libmad_header->samplerate);
/* * intf_DbgMsg( "mad_adec: libmad_header bitrate %d", p_libmad_header->bitrate);
intf_ErrMsg( "mad_adec: libmad_header samplerate %d", p_libmad_header->samplerate); *
intf_DbgMsg( "mad_adec: libmad_header bitrate %d", p_libmad_header->bitrate); * p_mad_adec->p_aout_fifo->l_rate = p_libmad_header->samplerate;
*/ *
p_mad_adec->p_aout_fifo->l_rate = p_libmad_header->samplerate; * return MAD_FLOW_CONTINUE;
vlc_cond_signal (&p_mad_adec->p_aout_fifo->data_wait); * }
vlc_mutex_unlock (&p_mad_adec->p_aout_fifo->data_lock); */
return MAD_FLOW_CONTINUE;
}
/***************************************************************************** /*****************************************************************************
* lib_mad_filter: this function is called to filter data of a frame * lib_mad_filter: this function is called to filter data of a frame
...@@ -106,6 +102,8 @@ enum mad_flow libmad_header(void *data, struct mad_header const *p_libmad_header ...@@ -106,6 +102,8 @@ enum mad_flow libmad_header(void *data, struct mad_header const *p_libmad_header
* } * }
*/ */
//#define MPG321_ROUTINES 1
#ifdef MPG321_ROUTINES
/***************************************************************************** /*****************************************************************************
* support routines borrowed from mpg321 (file: mad.c), which is distributed * support routines borrowed from mpg321 (file: mad.c), which is distributed
* under GPL license * under GPL license
...@@ -191,6 +189,25 @@ static __inline__ signed long audio_linear_dither(unsigned int bits, mad_fixed_t ...@@ -191,6 +189,25 @@ static __inline__ signed long audio_linear_dither(unsigned int bits, mad_fixed_t
/* scale */ /* scale */
return output >> scalebits; return output >> scalebits;
} }
#endif
/*****************************************************************************
* s24_to_s16_pcm: Scale a 24 bit pcm sample to a 16 bit pcm sample.
*****************************************************************************/
static __inline__ mad_fixed_t s24_to_s16_pcm(mad_fixed_t sample)
{
/* round */
sample += (1L << (MAD_F_FRACBITS - 16));
/* clip */
if (sample >= MAD_F_ONE)
sample = MAD_F_ONE - 1;
else if (sample < -MAD_F_ONE)
sample = -MAD_F_ONE;
/* quantize */
return sample >> (MAD_F_FRACBITS + 1 - 16);
}
/***************************************************************************** /*****************************************************************************
* libmad_ouput: this function is called just after the frame is decoded * libmad_ouput: this function is called just after the frame is decoded
...@@ -201,19 +218,15 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header ...@@ -201,19 +218,15 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
byte_t *buffer=NULL; byte_t *buffer=NULL;
mad_fixed_t const *left_ch = p_libmad_pcm->samples[0], *right_ch = p_libmad_pcm->samples[1]; mad_fixed_t const *left_ch = p_libmad_pcm->samples[0], *right_ch = p_libmad_pcm->samples[1];
/*
* 1152 because that's what mad has as a max; *4 because
* there are 4 distinct bytes per sample (in 2 channel case)
*/
static unsigned char stream[ADEC_FRAME_SIZE];
register int nsamples = p_libmad_pcm->length; register int nsamples = p_libmad_pcm->length;
mad_fixed_t sample;
#ifdef MPG321_ROUTINES
static struct audio_dither dither; static struct audio_dither dither;
#endif
register char * ptr = stream;
register signed int sample;
/* Set timestamp to synchronize audio and video decoder fifo's */ /* Set timestamp to synchronize audio and video decoder fifo's */
vlc_mutex_lock (&p_mad_adec->p_aout_fifo->data_lock); vlc_mutex_lock (&p_mad_adec->p_aout_fifo->data_lock);
p_mad_adec->p_aout_fifo->l_rate = p_libmad_header->samplerate;
p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->l_end_frame] = p_mad_adec->i_pts_save; p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->l_end_frame] = p_mad_adec->i_pts_save;
buffer = ((byte_t *)p_mad_adec->p_aout_fifo->buffer) + (p_mad_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE); buffer = ((byte_t *)p_mad_adec->p_aout_fifo->buffer) + (p_mad_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE);
...@@ -222,47 +235,56 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header ...@@ -222,47 +235,56 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
{ {
while (nsamples--) while (nsamples--)
{ {
sample = (signed int) audio_linear_dither(16, *left_ch++, &dither); #ifdef MPG321_ROUTINES
sample = audio_linear_dither(16, *left_ch++, &dither);
#else
sample = s24_to_s16_pcm(*left_ch++);
#endif
#ifndef WORDS_BIGENDIAN #ifndef WORDS_BIGENDIAN
*ptr++ = (unsigned char) (sample >> 0); *buffer++ = (byte_t) (sample) & 0xFF;
*ptr++ = (unsigned char) (sample >> 8); *buffer++ = (byte_t) (sample >> 8) & 0xFF;
#else
*buffer++ = (byte_t) (sample >> 8);
*buffer++ = (byte_t) (sample);
#endif
/* right audio channel */
#ifdef MPG321_ROUTINES
sample = audio_linear_dither(16, *right_ch++, &dither);
#else #else
*ptr++ = (unsigned char) (sample >> 8); sample = s24_to_s16_pcm(*right_ch++);
*ptr++ = (unsigned char) (sample >> 0);
#endif #endif
sample = (signed int) audio_linear_dither(16, *right_ch++, &dither);
#ifndef WORDS_BIGENDIAN #ifndef WORDS_BIGENDIAN
*ptr++ = (unsigned char) (sample >> 0); *buffer++ = (byte_t) (sample);
*ptr++ = (unsigned char) (sample >> 8); *buffer++ = (byte_t) (sample >> 8);
#else #else
*ptr++ = (unsigned char) (sample >> 8); *buffer++ = (byte_t) (sample >> 8);
*ptr++ = (unsigned char) (sample >> 0); *buffer++ = (byte_t) (sample);
#endif #endif
} }
buffer = memcpy(buffer,stream,p_libmad_pcm->length*4);
vlc_cond_signal (&p_mad_adec->p_aout_fifo->data_wait);
} }
else else
{ {
while (nsamples--) while (nsamples--)
{ {
sample = (signed int) audio_linear_dither(16, *left_ch++, &dither); #ifdef MPG321_ROUTINES
sample = audio_linear_dither(16, *left_ch++, &dither);
#else
sample = s24_to_s16_pcm(*left_ch++);
#endif
#ifndef WORDS_BIGENDIAN #ifndef WORDS_BIGENDIAN
*ptr++ = (unsigned char) (sample >> 0); *buffer++ = (byte_t) (sample);
*ptr++ = (unsigned char) (sample >> 8); *buffer++ = (byte_t) (sample >> 8);
#else #else
*ptr++ = (unsigned char) (sample >> 8); *buffer++ = (byte_t) (sample >> 8);
*ptr++ = (unsigned char) (sample >> 0); *buffer++ = (byte_t) (sample);
#endif #endif
} }
buffer = memcpy(buffer,stream,p_libmad_pcm->length*2);
vlc_cond_signal (&p_mad_adec->p_aout_fifo->data_wait);
} }
vlc_mutex_unlock (&p_mad_adec->p_aout_fifo->data_lock);
vlc_mutex_lock (&p_mad_adec->p_aout_fifo->data_lock); // vlc_mutex_lock (&p_mad_adec->p_aout_fifo->data_lock);
p_mad_adec->p_aout_fifo->l_end_frame = (p_mad_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE; p_mad_adec->p_aout_fifo->l_end_frame = (p_mad_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
vlc_cond_signal (&p_mad_adec->p_aout_fifo->data_wait); vlc_cond_signal (&p_mad_adec->p_aout_fifo->data_wait);
vlc_mutex_unlock (&p_mad_adec->p_aout_fifo->data_lock); vlc_mutex_unlock (&p_mad_adec->p_aout_fifo->data_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment