Commit 9faed78b authored by Jean-Paul Saman's avatar Jean-Paul Saman

Smooth sound (not tested on iPaq)

parent c1aa8904
...@@ -165,7 +165,11 @@ static int InitThread( mad_adec_thread_t * p_mad_adec ) ...@@ -165,7 +165,11 @@ static int InitThread( mad_adec_thread_t * p_mad_adec )
/* Initialize the libmad decoder structures */ /* Initialize the libmad decoder structures */
p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder)); p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
if (p_mad_adec->libmad_decoder == NULL) {
intf_ErrMsg ( "mad_adec error: not enough memory "
"for decoder_InitThread() to allocate p_mad_adec->libmad_decder" );
return -1;
}
/* /*
* Initialize bit stream * Initialize bit stream
*/ */
...@@ -179,32 +183,20 @@ static int InitThread( mad_adec_thread_t * p_mad_adec ) ...@@ -179,32 +183,20 @@ 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 */
0, /* 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);
mad_timer_reset(&p_mad_adec->libmad_timer);
/* /*
* Initialize the output properties * Initialize the output properties
*/ */
p_mad_adec->p_aout_fifo=NULL; p_mad_adec->p_aout_fifo=NULL;
/* Creating the audio output fifo */
// p_mad_adec->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_STEREO_FIFO, /* fifo type */
// 2, /* nr. of channels */
// 48000, /* frame rate in Hz ?*/
// 0, /* units */
// ADEC_FRAME_SIZE/2, /* frame size */
// NULL ); /* buffer */
//
// if ( p_mad_adec->p_aout_fifo == NULL )
// {
// return( -1 );
// }
intf_ErrMsg("mad_adec debug: mad decoder thread %p initialized", p_mad_adec); intf_ErrMsg("mad_adec debug: mad decoder thread %p initialized", p_mad_adec);
return( 0 ); return( 0 );
......
...@@ -22,7 +22,10 @@ ...@@ -22,7 +22,10 @@
*****************************************************************************/ *****************************************************************************/
// FIXME: Ugly define inside a decoder // FIXME: Ugly define inside a decoder
#define ADEC_FRAME_SIZE (4*1152) #define ADEC_FRAME_SIZE (2*1152)
#define MAD_BUFFER_SIZE (ADEC_FRAME_SIZE*2)
//#define MAD_BUFFER_SIZE (MAD_BUFFER_MDLEN*2)
#define MAD_OUTPUT_SIZE (ADEC_FRAME_SIZE*2)
typedef struct mad_adec_thread_s typedef struct mad_adec_thread_s
{ {
...@@ -30,7 +33,9 @@ typedef struct mad_adec_thread_s ...@@ -30,7 +33,9 @@ typedef struct mad_adec_thread_s
* Decoder properties * Decoder properties
*/ */
struct mad_decoder *libmad_decoder; struct mad_decoder *libmad_decoder;
mad_timer_t libmad_timer;
byte_t buffer[MAD_BUFFER_SIZE];
/* /*
* Thread properties * Thread properties
*/ */
...@@ -43,6 +48,7 @@ typedef struct mad_adec_thread_s ...@@ -43,6 +48,7 @@ typedef struct mad_adec_thread_s
/* The bit stream structure handles the PES stream at the bit level */ /* The bit stream structure handles the PES stream at the bit level */
bit_stream_t bit_stream; bit_stream_t bit_stream;
decoder_config_t * p_config; decoder_config_t * p_config;
/* Store i_pts for syncing audio frames */ /* Store i_pts for syncing audio frames */
mtime_t i_pts_save; mtime_t i_pts_save;
......
...@@ -47,7 +47,8 @@ ...@@ -47,7 +47,8 @@
enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream) enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
{ {
mad_adec_thread_t *p_mad_adec = (mad_adec_thread_t *) data; mad_adec_thread_t *p_mad_adec = (mad_adec_thread_t *) data;
byte_t buffer[ADEC_FRAME_SIZE]; size_t ReadSize, Remaining;
unsigned char *ReadStart;
/* Store time stamp of current frame */ /* Store time stamp of current frame */
if ( p_mad_adec->p_fifo->p_first->i_pts ) { if ( p_mad_adec->p_fifo->p_first->i_pts ) {
...@@ -58,20 +59,62 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream) ...@@ -58,20 +59,62 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
p_mad_adec->i_pts_save = LAST_MDATE; p_mad_adec->i_pts_save = LAST_MDATE;
} }
GetChunk( &p_mad_adec->bit_stream, buffer, ADEC_FRAME_SIZE ); /* libmad_stream_buffer does not consume the total buffer, it consumes only data
* for one frame only. So all data left in the buffer should be put back in front.
*/
if ((p_libmad_stream->buffer==NULL) || (p_libmad_stream->error==MAD_ERROR_BUFLEN))
{
if ( p_mad_adec->p_fifo->b_die == 1 ) { /* libmad does not consume all the buffer it's given. Some
intf_ErrMsg( "mad_adec error: libmad_input stopping libmad decoder" ); * datas, part of a truncated frame, is left unused at the
return MAD_FLOW_STOP; * end of the buffer. Those datas must be put back at the
} * beginning of the buffer and taken in account for
* refilling the buffer. This means that the input buffer
* must be large enough to hold a complete frame at the
* highest observable bit-rate (currently 448 kb/s). XXX=XXX
* Is 2016 bytes the size of the largest frame?
* (448000*(1152/32000))/8
*/
if(p_libmad_stream->next_frame!=NULL)
{
Remaining=p_libmad_stream->bufend-p_libmad_stream->next_frame;
memmove(p_mad_adec->buffer,p_libmad_stream->next_frame,Remaining);
ReadStart=p_mad_adec->buffer+Remaining;
ReadSize=(MAD_BUFFER_SIZE)-Remaining;
}
else
{
ReadSize=(MAD_BUFFER_SIZE);
ReadStart=p_mad_adec->buffer;
Remaining=0;
}
//intf_ErrMsg( "mad_adec debug: buffer size remaining [%d] and readsize [%d] total [%d]",
// Remaining, ReadSize, ReadSize+Remaining);
/* Fill-in the buffer. If an error occurs print a message
* and leave the decoding loop. If the end of stream is
* reached we also leave the loop but the return status is
* left untouched.
*/
GetChunk( &p_mad_adec->bit_stream, ReadStart, ReadSize );
if ( p_mad_adec->p_fifo->b_die == 1 ) {
intf_ErrMsg( "mad_adec error: libmad_input stopping libmad decoder" );
return MAD_FLOW_STOP;
}
if ( p_mad_adec->p_fifo->b_error == 1 ) { if ( p_mad_adec->p_fifo->b_error == 1 ) {
intf_ErrMsg( "mad_adec error: libmad_input ignoring current audio frame" ); intf_ErrMsg( "mad_adec error: libmad_input ignoring current audio frame" );
return MAD_FLOW_IGNORE; return MAD_FLOW_IGNORE;
} }
/* the length meant to be in bytes */ /* Pipe the new buffer content to libmad's stream decoder facility.
mad_stream_buffer(p_libmad_stream, (unsigned char*) &buffer, ADEC_FRAME_SIZE ); * Libmad never copies the buffer, but just references it. So keep it in
* mad_adec_thread_t structure.
*/
mad_stream_buffer(p_libmad_stream,(unsigned char*) &p_mad_adec->buffer,ReadSize+Remaining);
p_libmad_stream->error=0;
}
return MAD_FLOW_CONTINUE; return MAD_FLOW_CONTINUE;
} }
...@@ -80,17 +123,19 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream) ...@@ -80,17 +123,19 @@ 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;
* *
* intf_ErrMsg( "mad_adec: libmad_header samplerate %d", p_libmad_header->samplerate); * 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_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;
* mad_timer_add(&p_mad_adec->libmad_timer,p_libmad_header->duration);
* *
* return MAD_FLOW_CONTINUE; * return MAD_FLOW_CONTINUE;
* } *}
*/ */
/***************************************************************************** /*****************************************************************************
...@@ -137,7 +182,7 @@ static __inline__ unsigned long prng(unsigned long state) ...@@ -137,7 +182,7 @@ static __inline__ unsigned long prng(unsigned long state)
* NAME: audio_linear_dither() * NAME: audio_linear_dither()
* DESCRIPTION: generic linear sample quantize and dither routine * DESCRIPTION: generic linear sample quantize and dither routine
*/ */
static __inline__ signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample, static __inline__ signed int audio_linear_dither(unsigned int bits, mad_fixed_t sample,
struct audio_dither *dither) struct audio_dither *dither)
{ {
unsigned int scalebits; unsigned int scalebits;
...@@ -145,7 +190,7 @@ static __inline__ signed long audio_linear_dither(unsigned int bits, mad_fixed_t ...@@ -145,7 +190,7 @@ static __inline__ signed long audio_linear_dither(unsigned int bits, mad_fixed_t
enum { enum {
MIN = -MAD_F_ONE, MIN = -MAD_F_ONE,
MAX = MAD_F_ONE - 1 MAX = MAD_F_ONE - 1
}; };
/* noise shape */ /* noise shape */
...@@ -231,7 +276,7 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header ...@@ -231,7 +276,7 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
p_libmad_pcm->channels, /* nr. of channels */ p_libmad_pcm->channels, /* nr. of channels */
p_libmad_pcm->samplerate, /* frame rate in Hz ?*/ p_libmad_pcm->samplerate, /* frame rate in Hz ?*/
0, /* units */ 0, /* units */
ADEC_FRAME_SIZE/2, /* frame size */ ADEC_FRAME_SIZE, /* frame size */
NULL ); /* buffer */ NULL ); /* buffer */
if ( p_mad_adec->p_aout_fifo == NULL ) if ( p_mad_adec->p_aout_fifo == NULL )
...@@ -241,13 +286,30 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header ...@@ -241,13 +286,30 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
intf_ErrMsg("mad_adec debug: in libmad_output aout fifo created"); intf_ErrMsg("mad_adec debug: in libmad_output aout fifo created");
} }
else {
p_mad_adec->p_aout_fifo->l_rate = p_libmad_pcm->samplerate;
}
/* Some frames are nog quite right. Why ??? I do not know. Probably syncing and CRC errors ??
* Leaving those frames out futher removes the jitter in the sound and makes it more fluent.
* Still I am missing something, because it is not completely fluent.
*/
if ((p_mad_adec->libmad_decoder->sync->stream.error==MAD_ERROR_BADCRC) ||
(p_mad_adec->libmad_decoder->sync->stream.error==MAD_ERROR_BADBITRATE) ||
(p_mad_adec->libmad_decoder->sync->stream.error==MAD_ERROR_BADSCALEFACTOR)
) {
// intf_ErrMsg( "LIBMAD_OUTPUT: nr of channels [%d], samplerate in Hz [%d,%d], sample size [%d], error_code [%0x]",
// p_libmad_pcm->channels, p_libmad_pcm->samplerate, p_libmad_header->samplerate,
// p_libmad_pcm->length, p_mad_adec->libmad_decoder->sync->stream.error);
// PrintFrameInfo(&p_libmad_header);
return MAD_FLOW_IGNORE;
}
/* 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);
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;
mad_timer_add(&p_mad_adec->libmad_timer,p_libmad_header->duration);
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 * MAD_OUTPUT_SIZE);
while (nsamples--) while (nsamples--)
{ {
...@@ -258,11 +320,11 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header ...@@ -258,11 +320,11 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
#endif #endif
#ifndef WORDS_BIGENDIAN #ifndef WORDS_BIGENDIAN
*buffer++ = (byte_t) (sample) & 0xFF; *buffer++ = (byte_t) (sample >> 0);
*buffer++ = (byte_t) (sample >> 8) & 0xFF; *buffer++ = (byte_t) (sample >> 8);
#else #else
*buffer++ = (byte_t) (sample >> 8); *buffer++ = (byte_t) (sample >> 8);
*buffer++ = (byte_t) (sample); *buffer++ = (byte_t) (sample >> 0);
#endif #endif
if (p_libmad_pcm->channels == 2) { if (p_libmad_pcm->channels == 2) {
...@@ -274,16 +336,28 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header ...@@ -274,16 +336,28 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
#endif #endif
#ifndef WORDS_BIGENDIAN #ifndef WORDS_BIGENDIAN
*buffer++ = (byte_t) (sample) & 0xFF; *buffer++ = (byte_t) (sample >> 0);
*buffer++ = (byte_t) (sample >> 8) & 0xFF; *buffer++ = (byte_t) (sample >> 8);
#else #else
*buffer++ = (byte_t) (sample >> 8); *buffer++ = (byte_t) (sample >> 8);
*buffer++ = (byte_t) (sample); *buffer++ = (byte_t) (sample >> 0);
#endif #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);
} }
// 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