Index: cfg-common.h =================================================================== RCS file: /cvsroot/mplayer/main/cfg-common.h,v retrieving revision 1.138 diff -u -p -r1.138 cfg-common.h --- cfg-common.h 19 Jan 2005 18:05:03 -0000 1.138 +++ cfg-common.h 20 Feb 2005 01:17:49 -0000 @@ -139,6 +139,7 @@ #ifdef USE_LIBA52 {"a52drc", &a52_drc_level, CONF_TYPE_FLOAT, CONF_RANGE, 0, 1, NULL}, + {"a52float", &a52_float, CONF_TYPE_FLAG, 0, 0, 1, NULL}, #endif // ------------------------- codec/vfilter options -------------------- @@ -315,6 +316,7 @@ extern int network_ipv4_only_proxy; #endif extern float a52_drc_level; +extern int a52_float; /* defined in libmpdemux: */ extern int hr_mp3_seek; Index: libmpcodecs/ad_liba52.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpcodecs/ad_liba52.c,v retrieving revision 1.14 diff -u -p -r1.14 ad_liba52.c --- libmpcodecs/ad_liba52.c 21 Sep 2004 20:34:46 -0000 1.14 +++ libmpcodecs/ad_liba52.c 20 Feb 2005 01:17:49 -0000 @@ -2,6 +2,7 @@ #include #include #include +#include #include "config.h" #ifdef USE_LIBA52 @@ -13,17 +14,21 @@ #include "cpudetect.h" +#include "../libaf/af_format.h" + #include "../liba52/a52.h" #include "../liba52/mm_accel.h" static sample_t * a52_samples; static a52_state_t a52_state; static uint32_t a52_flags=0; +static uint32_t channel_map; #define DRC_NO_ACTION 0 #define DRC_NO_COMPRESSION 1 #define DRC_CALLBACK 2 +int a52_float = 0; float a52_drc_level = 1.0; static int a52_drc_action = DRC_NO_ACTION; @@ -115,10 +120,29 @@ static int preinit(sh_audio_t *sh) /* Dolby AC3 audio: */ /* however many channels, 2 bytes in a word, 256 samples in a block, 6 blocks in a frame */ sh->audio_out_minsize=audio_output_channels*2*256*6; + if (a52_float) sh->audio_out_minsize *= 2; sh->audio_in_minsize=3840; return 1; } +static int a52_resample_float(float *in, int16_t *out) +{ + unsigned long i; + float *p = (float*) out; + for (i = 0; i != 256; i++) { + unsigned long map = channel_map; + do { + unsigned long ch = map & 15; + if (ch == 15) + *p = 0; + else + *p = in[i + ((ch-1)<<8)]; + p++; + } while ((map >>= 4)); + } + return (int16_t*) p - out; +} + static int init(sh_audio_t *sh_audio) { uint32_t a52_accel=0; @@ -169,6 +193,11 @@ while(sh_audio->channels>0){ case 5: a52_flags=A52_3F2R; break; case 6: a52_flags=A52_3F2R|A52_LFE; break; /* 5.1*/ } + if (a52_float) { + bias = 0; + sh_audio->sample_format = AF_FORMAT_FLOAT_NE; + sh_audio->samplesize = 4; + } /* test:*/ flags=a52_flags|A52_ADJUST_LEVEL; mp_msg(MSGT_DECAUDIO,MSGL_V,"A52 flags before a52_frame: 0x%X\n",flags); @@ -178,6 +207,36 @@ while(sh_audio->channels>0){ } mp_msg(MSGT_DECAUDIO,MSGL_V,"A52 flags after a52_frame: 0x%X\n",flags); /* frame decoded, let's init resampler:*/ + channel_map = 0; + if (sh_audio->sample_format == AF_FORMAT_FLOAT_NE) { + if (!(flags & A52_LFE)) { + switch ((flags<<3) | sh_audio->channels) { + case (A52_MONO << 3) | 1: channel_map = 0x1; break; + case (A52_CHANNEL << 3) | 2: + case (A52_STEREO << 3) | 2: + case (A52_DOLBY << 3) | 2: channel_map = 0x21; break; + case (A52_2F1R << 3) | 3: channel_map = 0x321; break; + case (A52_2F2R << 3) | 4: channel_map = 0x4321; break; + case (A52_3F << 3) | 5: channel_map = 0x2ff31; break; + case (A52_3F2R << 3) | 5: channel_map = 0x25431; break; + } + } else if (sh_audio->channels == 6) { + switch (flags & ~A52_LFE) { + case A52_MONO : channel_map = 0x12ffff; break; + case A52_CHANNEL: + case A52_STEREO : + case A52_DOLBY : channel_map = 0x1fff32; break; + case A52_3F : channel_map = 0x13ff42; break; + case A52_2F1R : channel_map = 0x1f4432; break; + case A52_2F2R : channel_map = 0x1f5432; break; + case A52_3F2R : channel_map = 0x136542; break; + } + } + if (channel_map) { + a52_resample = a52_resample_float; + break; + } + } else if(a52_resample_init(a52_accel,flags,sh_audio->channels)) break; --sh_audio->channels; /* try to decrease no. of channels*/ } @@ -208,6 +267,8 @@ static int decode_audio(sh_audio_t *sh_a sample_t level=1, bias=384; int flags=a52_flags|A52_ADJUST_LEVEL; int i,len=-1; + if (sh_audio->sample_format == AF_FORMAT_FLOAT_NE) + bias = 0; if(!sh_audio->a_in_buffer_len) if(a52_fillbuff(sh_audio)<0) return len; /* EOF */ sh_audio->a_in_buffer_len=0; @@ -232,6 +293,7 @@ static int decode_audio(sh_audio_t *sh_a } len+=2*a52_resample(a52_samples,(int16_t *)&buf[len]); } + assert(len <= maxlen); return len; } #endif Index: DOCS/man/en/mplayer.1 =================================================================== RCS file: /cvsroot/mplayer/main/DOCS/man/en/mplayer.1,v retrieving revision 1.876 diff -u -p -r1.876 mplayer.1 --- DOCS/man/en/mplayer.1 19 Feb 2005 14:58:39 -0000 1.876 +++ DOCS/man/en/mplayer.1 20 Feb 2005 01:17:53 -0000 @@ -709,6 +709,12 @@ This option only shows an effect if the compression information. . .TP +.B \-a52float +Decode AC3 using native float sample format. +This is useful if you use audio filters such as volume to reduce the +error coming from float to int conversions. +. +.TP .B \-aid (also see \-alang) Select audio channel (MPEG: 0\-31, AVI/\:OGM: 1\-99, ASF/\:RM: 0\-127, VOB(AC3): 128\-159, VOB(LPCM): 160\-191, MPEG-TS 17\-8190).