# HG changeset patch # User Eugene Zagidullin # Date 1202077853 -10800 # Node ID 29c8603a877a115d18e8d22264e4606983a7f9b1 # Parent 51291ce4eb54b8922095eef97bea79765ca155b1 added FMT_FIXED32, an equivalent of mad_fixed_t, already supported by libSAD; some endianness-related changes diff -r 51291ce4eb54 -r 29c8603a877a src/audacious/output.c --- a/src/audacious/output.c Sun Feb 03 19:02:04 2008 +0300 +++ b/src/audacious/output.c Mon Feb 04 01:30:53 2008 +0300 @@ -52,6 +52,8 @@ #include #endif +#define FMT_FRACBITS(a) ( (a) == FMT_FIXED32 ? __AUDACIOUS_ASSUMED_MAD_F_FRACBITS__ : 0 ) + OutputPluginData op_data = { NULL, NULL @@ -113,8 +115,11 @@ {FMT_U32_NE, SAD_SAMPLE_U32}, {FMT_FLOAT, SAD_SAMPLE_FLOAT}, + {FMT_FIXED32, SAD_SAMPLE_FIXED32}, }; +static void apply_replaygain_info (ReplayGainInfo *rg_info); + static inline unsigned sample_size(AFormat fmt) { switch(fmt) { case FMT_S8: @@ -136,14 +141,13 @@ case FMT_S32_BE: case FMT_U32_NE: case FMT_U32_LE: - case FMT_U32_BE: return sizeof(gint32); + case FMT_U32_BE: + case FMT_FIXED32: return sizeof(gint32); case FMT_FLOAT: return sizeof(float); default: return 0; } } -static void apply_replaygain_info (ReplayGainInfo *rg_info); - static SAD_sample_format sadfmt_from_afmt(AFormat fmt) { @@ -420,7 +424,7 @@ AUDDBG("initializing dithering engine for 2 stage conversion\n"); input_sad_fmt.sample_format = sadfmt_from_afmt(fmt); if (input_sad_fmt.sample_format < 0) return FALSE; - input_sad_fmt.fracbits = 0; + input_sad_fmt.fracbits = FMT_FRACBITS(fmt); input_sad_fmt.channels = nch; input_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED; input_sad_fmt.samplerate = 0; @@ -446,7 +450,7 @@ output_sad_fmt.sample_format = sadfmt_from_afmt(output_fmt); if (output_sad_fmt.sample_format < 0) return FALSE; - output_sad_fmt.fracbits = 0; + output_sad_fmt.fracbits = FMT_FRACBITS(output_fmt); output_sad_fmt.channels = nch; output_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED; output_sad_fmt.samplerate = 0; @@ -467,13 +471,13 @@ input_sad_fmt.sample_format = sadfmt_from_afmt(fmt); if (input_sad_fmt.sample_format < 0) return FALSE; - input_sad_fmt.fracbits = 0; + input_sad_fmt.fracbits = FMT_FRACBITS(fmt); input_sad_fmt.channels = nch; input_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED; input_sad_fmt.samplerate = 0; /* resampling not implemented yet in libSAD */ output_sad_fmt.sample_format = sadfmt_from_afmt(output_fmt); - output_sad_fmt.fracbits = 0; + output_sad_fmt.fracbits = FMT_FRACBITS(output_fmt); output_sad_fmt.channels = nch; output_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED; output_sad_fmt.samplerate = 0; diff -r 51291ce4eb54 -r 29c8603a877a src/audacious/plugin.h --- a/src/audacious/plugin.h Sun Feb 03 19:02:04 2008 +0300 +++ b/src/audacious/plugin.h Mon Feb 04 01:30:53 2008 +0300 @@ -86,8 +86,32 @@ FMT_S32_NE, FMT_FLOAT, + FMT_FIXED32, /* equivalent of libmad's mad_fixed_t explained below */ } AFormat; +/* From mad.h: + * + * Fixed-point format: 0xABBBBBBB + * A == whole part (sign + 3 bits) + * B == fractional part (28 bits) + * + * Values are signed two's complement, so the effective range is: + * 0x80000000 to 0x7fffffff + * -8.0 to +7.9999999962747097015380859375 + * + * The smallest representable value is: + * 0x00000001 == 0.0000000037252902984619140625 (i.e. about 3.725e-9) + * + * 28 bits of fractional accuracy represent about + * 8.6 digits of decimal accuracy. + * + * Fixed-point numbers can be added or subtracted as normal + * integers, but multiplication requires shifting the 64-bit result + * from 56 fractional bits back to 28 (and rounding.) + */ + +#define __AUDACIOUS_ASSUMED_MAD_F_FRACBITS__ 28 /* useful for build time check for plugins linked against libmad, i.e. madplug */ + typedef enum { INPUT_VIS_ANALYZER, INPUT_VIS_SCOPE, diff -r 51291ce4eb54 -r 29c8603a877a src/libSAD/dither.c --- a/src/libSAD/dither.c Sun Feb 03 19:02:04 2008 +0300 +++ b/src/libSAD/dither.c Mon Feb 04 01:30:53 2008 +0300 @@ -313,7 +313,9 @@ case SAD_SAMPLE_S24: case SAD_SAMPLE_S24_LE: case SAD_SAMPLE_S24_BE: - case SAD_SAMPLE_U24: priv->output_bits = 24; break; + case SAD_SAMPLE_U24: + case SAD_SAMPLE_U24_LE: + case SAD_SAMPLE_U24_BE: priv->output_bits = 24; break; case SAD_SAMPLE_S32: case SAD_SAMPLE_U32: priv->output_bits = 32; break; case SAD_SAMPLE_FLOAT: break; @@ -335,7 +337,9 @@ case SAD_SAMPLE_S24: case SAD_SAMPLE_S24_LE: case SAD_SAMPLE_S24_BE: - case SAD_SAMPLE_U24: priv->input_bits = 24; break; + case SAD_SAMPLE_U24: + case SAD_SAMPLE_U24_LE: + case SAD_SAMPLE_U24_BE: priv->input_bits = 24; break; case SAD_SAMPLE_S32: case SAD_SAMPLE_U32: priv->input_bits = 32; break; case SAD_SAMPLE_FIXED32: priv->input_fracbits = inbuf_format->fracbits; break; diff -r 51291ce4eb54 -r 29c8603a877a src/libSAD/dither_ops.c --- a/src/libSAD/dither_ops.c Sun Feb 03 19:02:04 2008 +0300 +++ b/src/libSAD/dither_ops.c Mon Feb 04 01:30:53 2008 +0300 @@ -303,15 +303,16 @@ ****************************************************************************************************************/ /*expand 24-bit signed value to 32-bit*/ -#define EXPAND_24_TO_32(x) (((int32_t)(((x) & 0x00ffffff) << 8)) >> 8) +#define EXPAND_S24_TO_32(x) (((int32_t)(((x) & 0x00ffffff) << 8)) >> 8) +#define EXPAND_U24_TO_32(x) ((int32_t)(x) & 0x00ffffff) /* signed */ static int32_t get_s24_i_sample (void *buf, int nch, int ch, int i) { - return (int32_t)EXPAND_24_TO_32(((int32_t*)buf)[i*nch+ch]); + return (int32_t)EXPAND_S24_TO_32(((int32_t*)buf)[i*nch+ch]); } static int32_t get_s24_s_sample (void *buf, int nch, int ch, int i) { - return (int32_t)EXPAND_24_TO_32(((int32_t**)buf)[ch][i]); + return (int32_t)EXPAND_S24_TO_32(((int32_t**)buf)[ch][i]); } static void put_s24_i_sample (void *buf, int32_t sample, int nch, int ch, int i) { @@ -326,12 +327,12 @@ static int32_t get_s24_le_i_sample (void *buf, int nch, int ch, int i) { int32_t *tmp = (int32_t*)buf+i*nch+ch; - return (int32_t)EXPAND_24_TO_32(SAD_GET_LE32(tmp)); + return (int32_t)EXPAND_S24_TO_32(SAD_GET_LE32(tmp)); } static int32_t get_s24_le_s_sample (void *buf, int nch, int ch, int i) { int32_t *tmp = ((int32_t**)buf)[ch]+i; - return (int32_t)EXPAND_24_TO_32(SAD_GET_LE32(tmp)); + return (int32_t)EXPAND_S24_TO_32(SAD_GET_LE32(tmp)); } static void put_s24_le_i_sample (void *buf, int32_t sample, int nch, int ch, int i) { @@ -348,12 +349,12 @@ static int32_t get_s24_be_i_sample (void *buf, int nch, int ch, int i) { int32_t *tmp = (int32_t*)buf+i*nch+ch; - return (int32_t)EXPAND_24_TO_32(SAD_GET_BE32(tmp)); + return (int32_t)EXPAND_S24_TO_32(SAD_GET_BE32(tmp)); } static int32_t get_s24_be_s_sample (void *buf, int nch, int ch, int i) { int32_t *tmp = ((int32_t**)buf)[ch]+i; - return (int32_t)EXPAND_24_TO_32(SAD_GET_BE32(tmp)); + return (int32_t)EXPAND_S24_TO_32(SAD_GET_BE32(tmp)); } static void put_s24_be_i_sample (void *buf, int32_t sample, int nch, int ch, int i) { @@ -368,11 +369,11 @@ /* unsigned */ static int32_t get_u24_i_sample (void *buf, int nch, int ch, int i) { - return (int32_t)EXPAND_24_TO_32(((uint32_t*)buf)[i*nch+ch]) - 8388608; + return (int32_t)EXPAND_U24_TO_32(((uint32_t*)buf)[i*nch+ch]) - 8388608; } static int32_t get_u24_s_sample (void *buf, int nch, int ch, int i) { - return (int32_t)EXPAND_24_TO_32(((uint32_t**)buf)[ch][i]) - 8388608; + return (int32_t)EXPAND_U24_TO_32(((uint32_t**)buf)[ch][i]) - 8388608; } static void put_u24_i_sample (void *buf, int32_t sample, int nch, int ch, int i) { @@ -383,6 +384,51 @@ ((uint32_t**)buf)[ch][i] = ((uint32_t)sample + 8388608) & 0x00ffffff; } +/* LE unsigned */ + +static int32_t get_u24_le_i_sample (void *buf, int nch, int ch, int i) { + int32_t *tmp = (int32_t*)buf+i*nch+ch; + /*fprintf(stderr, "%d\n", (int32_t)EXPAND_U24_TO_32(SAD_GET_LE32(tmp)) - 8388608);*/ + return (int32_t)EXPAND_U24_TO_32(SAD_GET_LE32(tmp)) - 8388608; +} + +static int32_t get_u24_le_s_sample (void *buf, int nch, int ch, int i) { + int32_t *tmp = ((int32_t**)buf)[ch]+i; + return (int32_t)EXPAND_U24_TO_32(SAD_GET_LE32(tmp)) - 8388608; +} + +static void put_u24_le_i_sample (void *buf, int32_t sample, int nch, int ch, int i) { + int32_t *tmp = (int32_t*)buf+i*nch+ch; + SAD_PUT_LE32(tmp, (uint32_t)(sample + 8388608) & 0x00ffffff); +} + +static void put_u24_le_s_sample (void *buf, int32_t sample, int nch, int ch, int i) { + int32_t *tmp = ((int32_t**)buf)[ch]+i; + SAD_PUT_LE32(tmp, (uint32_t)(sample + 8388608) & 0x00ffffff); +} + +/* BE unsigned */ + +static int32_t get_u24_be_i_sample (void *buf, int nch, int ch, int i) { + int32_t *tmp = (int32_t*)buf+i*nch+ch; + return (int32_t)EXPAND_U24_TO_32(SAD_GET_BE32(tmp)) - 8388608; +} + +static int32_t get_u24_be_s_sample (void *buf, int nch, int ch, int i) { + int32_t *tmp = ((int32_t**)buf)[ch]+i; + return (int32_t)EXPAND_U24_TO_32(SAD_GET_BE32(tmp)) - 8388608; +} + +static void put_u24_be_i_sample (void *buf, int32_t sample, int nch, int ch, int i) { + int32_t *tmp = (int32_t*)buf+i*nch+ch; + SAD_PUT_BE32(tmp, (uint32_t)(sample + 8388608) & 0x00ffffff); +} + +static void put_u24_be_s_sample (void *buf, int32_t sample, int nch, int ch, int i) { + int32_t *tmp = ((int32_t**)buf)[ch]+i; + SAD_PUT_BE32(tmp, (uint32_t)(sample + 8388608) & 0x00ffffff); +} + static SAD_buffer_ops buf_s24_i_ops = { &get_s24_i_sample, &put_s24_i_sample @@ -423,6 +469,26 @@ &put_u24_s_sample }; +static SAD_buffer_ops buf_u24_le_i_ops = { + &get_u24_le_i_sample, + &put_u24_le_i_sample +}; + +static SAD_buffer_ops buf_u24_le_s_ops = { + &get_u24_le_s_sample, + &put_u24_le_s_sample +}; + +static SAD_buffer_ops buf_u24_be_i_ops = { + &get_u24_be_i_sample, + &put_u24_be_i_sample +}; + +static SAD_buffer_ops buf_u24_be_s_ops = { + &get_u24_be_s_sample, + &put_u24_be_s_sample +}; + /**************************************************************************************************************** * 32-bit * ****************************************************************************************************************/ @@ -496,8 +562,8 @@ {&buf_s24_le_i_ops, &buf_s24_le_s_ops}, /* SAD_SAMPLE_S24_LE */ {&buf_s24_be_i_ops, &buf_s24_be_s_ops}, /* SAD_SAMPLE_S24_BE */ {&buf_u24_i_ops, &buf_u24_s_ops}, /* SAD_SAMPLE_U24 */ - {NULL, NULL}, /* SAD_SAMPLE_U24_LE */ - {NULL, NULL}, /* SAD_SAMPLE_U24_BE */ + {&buf_u24_le_i_ops, &buf_u24_le_s_ops}, /* SAD_SAMPLE_U24_LE */ + {&buf_u24_be_i_ops, &buf_u24_be_s_ops}, /* SAD_SAMPLE_U24_BE */ {&buf_s32_i_ops, &buf_s32_s_ops}, /* SAD_SAMPLE_S32 */ {NULL, NULL}, /* SAD_SAMPLE_S32_LE */