changeset 4240:29c8603a877a

added FMT_FIXED32, an equivalent of mad_fixed_t, already supported by libSAD; some endianness-related changes
author Eugene Zagidullin <e.asphyx@gmail.com>
date Mon, 04 Feb 2008 01:30:53 +0300
parents 51291ce4eb54
children 63eb5966f105
files src/audacious/output.c src/audacious/plugin.h src/libSAD/dither.c src/libSAD/dither_ops.c
diffstat 4 files changed, 118 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- 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 <samplerate.h>
 #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;
--- 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,
--- 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;
--- 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 */