From 898a06874c9c8983130cf556c9fe15cf58276e5a Mon Sep 17 00:00:00 2001
From: Andrea Iob <andrea_iob@hotmail.com>
Date: Sat, 9 Nov 2013 17:45:03 +0100
Subject: [PATCH] Add support for 24 bit 3 bytes format

---
 src/audacious/output.c         |  2 +-
 src/audacious/ui_preferences.c |  1 +
 src/libaudcore/audio.c         | 20 ++++++++++++++++++++
 src/libaudcore/audio.h.in      |  7 ++++++-
 4 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/src/audacious/output.c b/src/audacious/output.c
index dda7300..196fe2b 100644
--- a/src/audacious/output.c
+++ b/src/audacious/output.c
@@ -76,7 +76,7 @@ static inline int get_format (void)
     switch (get_int (NULL, "output_bit_depth"))
     {
         case 16: return FMT_S16_NE;
-        case 24: return FMT_S24_NE;
+        case 243: return FMT_S24_3NE;
         case 32: return FMT_S32_NE;
         default: return FMT_FLOAT;
     }
diff --git a/src/audacious/ui_preferences.c b/src/audacious/ui_preferences.c
index 6599b5c..8e84389 100644
--- a/src/audacious/ui_preferences.c
+++ b/src/audacious/ui_preferences.c
@@ -108,6 +108,7 @@ static ComboBoxElements chardet_detector_presets[] = {
 static ComboBoxElements bitdepth_elements[] = {
     { GINT_TO_POINTER(16), "16" },
     { GINT_TO_POINTER(24), "24" },
+    { GINT_TO_POINTER(243), "24 (3 bytes)" },
     { GINT_TO_POINTER(32), "32" },
     {GINT_TO_POINTER (0), N_("Floating point")},
 };
diff --git a/src/libaudcore/audio.c b/src/libaudcore/audio.c
index f866509..749377e 100644
--- a/src/libaudcore/audio.c
+++ b/src/libaudcore/audio.c
@@ -57,6 +57,10 @@ EXPORT void audio_interlace (const void * const * in, int format, int channels,
         INTERLACE_LOOP (int16_t);
         break;
 
+    case FMT_S24_3LE:
+    case FMT_S24_3BE:
+    case FMT_U24_3LE:
+    case FMT_U24_3BE:
     case FMT_S24_LE:
     case FMT_S24_BE:
     case FMT_U24_LE:
@@ -93,6 +97,8 @@ FROM_INT_LOOP (from_s8, int8_t, , 0x00, 0x7f)
 FROM_INT_LOOP (from_u8, int8_t, , 0x80, 0x7f)
 FROM_INT_LOOP (from_s16, int16_t, , 0x0000, 0x7fff)
 FROM_INT_LOOP (from_u16, int16_t, , 0x8000, 0x7fff)
+FROM_INT_LOOP (from_s24_3, int32_t, , 0x000000, 0x7fffff)
+FROM_INT_LOOP (from_u24_3, int32_t, , 0x800000, 0x7fffff)
 FROM_INT_LOOP (from_s24, int32_t, , 0x000000, 0x7fffff)
 FROM_INT_LOOP (from_u24, int32_t, , 0x800000, 0x7fffff)
 FROM_INT_LOOP (from_s32, int32_t, , 0x00000000, 0x7fffffff)
@@ -102,6 +108,8 @@ TO_INT_LOOP (to_s8, int8_t, , 0x00, 0x7f)
 TO_INT_LOOP (to_u8, int8_t, , 0x80, 0x7f)
 TO_INT_LOOP (to_s16, int16_t, , 0x0000, 0x7fff)
 TO_INT_LOOP (to_u16, int16_t, , 0x8000, 0x7fff)
+TO_INT_LOOP (to_s24_3, int32_t, , 0x000000, 0x7fffff)
+TO_INT_LOOP (to_u24_3, int32_t, , 0x800000, 0x7fffff)
 TO_INT_LOOP (to_s24, int32_t, , 0x000000, 0x7fffff)
 TO_INT_LOOP (to_u24, int32_t, , 0x800000, 0x7fffff)
 TO_INT_LOOP (to_s32, int32_t, , 0x00000000, 0x7fffffff)
@@ -112,6 +120,8 @@ static inline int32_t SWAP32 (int32_t i) {return GUINT32_SWAP_LE_BE (i);}
 
 FROM_INT_LOOP (from_s16_swap, int16_t, SWAP16, 0x0000, 0x7fff)
 FROM_INT_LOOP (from_u16_swap, int16_t, SWAP16, 0x8000, 0x7fff)
+FROM_INT_LOOP (from_s24_3_swap, int32_t, SWAP32, 0x000000, 0x7fffff)
+FROM_INT_LOOP (from_u24_3_swap, int32_t, SWAP32, 0x800000, 0x7fffff)
 FROM_INT_LOOP (from_s24_swap, int32_t, SWAP32, 0x000000, 0x7fffff)
 FROM_INT_LOOP (from_u24_swap, int32_t, SWAP32, 0x800000, 0x7fffff)
 FROM_INT_LOOP (from_s32_swap, int32_t, SWAP32, 0x00000000, 0x7fffffff)
@@ -119,6 +129,8 @@ FROM_INT_LOOP (from_u32_swap, int32_t, SWAP32, 0x80000000, 0x7fffffff)
 
 TO_INT_LOOP (to_s16_swap, int16_t, SWAP16, 0x0000, 0x7fff)
 TO_INT_LOOP (to_u16_swap, int16_t, SWAP16, 0x8000, 0x7fff)
+TO_INT_LOOP (to_s24_3_swap, int32_t, SWAP32, 0x000000, 0x7fffff)
+TO_INT_LOOP (to_u24_3_swap, int32_t, SWAP32, 0x800000, 0x7fffff)
 TO_INT_LOOP (to_s24_swap, int32_t, SWAP32, 0x000000, 0x7fffff)
 TO_INT_LOOP (to_u24_swap, int32_t, SWAP32, 0x800000, 0x7fffff)
 TO_INT_LOOP (to_s32_swap, int32_t, SWAP32, 0x00000000, 0x7fffffff)
@@ -141,6 +153,8 @@ convert_table [] =
 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
     {FMT_S16_LE, (FromFunc) from_s16, (ToFunc) to_s16},
     {FMT_U16_LE, (FromFunc) from_u16, (ToFunc) to_u16},
+    {FMT_S24_3_LE, (FromFunc) from_s24_3, (ToFunc) to_s24_3},
+    {FMT_U24_3_LE, (FromFunc) from_u24_3, (ToFunc) to_u24_3},
     {FMT_S24_LE, (FromFunc) from_s24, (ToFunc) to_s24},
     {FMT_U24_LE, (FromFunc) from_u24, (ToFunc) to_u24},
     {FMT_S32_LE, (FromFunc) from_s32, (ToFunc) to_s32},
@@ -148,6 +162,8 @@ convert_table [] =
 
     {FMT_S16_BE, (FromFunc) from_s16_swap, (ToFunc) to_s16_swap},
     {FMT_U16_BE, (FromFunc) from_u16_swap, (ToFunc) to_u16_swap},
+    {FMT_S24_3_BE, (FromFunc) from_s24_3_swap, (ToFunc) to_s24_3_swap},
+    {FMT_U24_3_BE, (FromFunc) from_u24_3_swap, (ToFunc) to_u24_3_swap},
     {FMT_S24_BE, (FromFunc) from_s24_swap, (ToFunc) to_s24_swap},
     {FMT_U24_BE, (FromFunc) from_u24_swap, (ToFunc) to_u24_swap},
     {FMT_S32_BE, (FromFunc) from_s32_swap, (ToFunc) to_s32_swap},
@@ -155,6 +171,8 @@ convert_table [] =
 #else
     {FMT_S16_BE, (FromFunc) from_s16, (ToFunc) to_s16},
     {FMT_U16_BE, (FromFunc) from_u16, (ToFunc) to_u16},
+    {FMT_S24_3_BE, (FromFunc) from_s24_3, (ToFunc) to_s24_3},
+    {FMT_U24_3_BE, (FromFunc) from_u24_3, (ToFunc) to_u24_3},
     {FMT_S24_BE, (FromFunc) from_s24, (ToFunc) to_s24},
     {FMT_U24_BE, (FromFunc) from_u24, (ToFunc) to_u24},
     {FMT_S32_BE, (FromFunc) from_s32, (ToFunc) to_s32},
@@ -162,6 +180,8 @@ convert_table [] =
 
     {FMT_S16_LE, (FromFunc) from_s16_swap, (ToFunc) to_s16_swap},
     {FMT_U16_LE, (FromFunc) from_u16_swap, (ToFunc) to_u16_swap},
+    {FMT_S24_3_LE, (FromFunc) from_s24_3_swap, (ToFunc) to_s24_3_swap},
+    {FMT_U24_3_LE, (FromFunc) from_u24_3_swap, (ToFunc) to_u24_3_swap},
     {FMT_S24_LE, (FromFunc) from_s24_swap, (ToFunc) to_s24_swap},
     {FMT_U24_LE, (FromFunc) from_u24_swap, (ToFunc) to_u24_swap},
     {FMT_S32_LE, (FromFunc) from_s32_swap, (ToFunc) to_s32_swap},
diff --git a/src/libaudcore/audio.h.in b/src/libaudcore/audio.h.in
index 19cfef2..af2c2b6 100644
--- a/src/libaudcore/audio.h.in
+++ b/src/libaudcore/audio.h.in
@@ -25,12 +25,15 @@ enum {
  FMT_FLOAT,
  FMT_S8, FMT_U8,
  FMT_S16_LE, FMT_S16_BE, FMT_U16_LE, FMT_U16_BE,
+ FMT_S24_3_LE, FMT_S24_3_BE, FMT_U24_3_LE, FMT_U24_3_BE, 
  FMT_S24_LE, FMT_S24_BE, FMT_U24_LE, FMT_U24_BE,
  FMT_S32_LE, FMT_S32_BE, FMT_U32_LE, FMT_U32_BE};
 
 #if @BIGENDIAN@
 #define FMT_S16_NE FMT_S16_BE
 #define FMT_U16_NE FMT_U16_BE
+#define FMT_S24_3NE FMT_S24_3BE
+#define FMT_U24_3NE FMT_U24_3BE
 #define FMT_S24_NE FMT_S24_BE
 #define FMT_U24_NE FMT_U24_BE
 #define FMT_S32_NE FMT_S32_BE
@@ -38,13 +41,15 @@ enum {
 #else
 #define FMT_S16_NE FMT_S16_LE
 #define FMT_U16_NE FMT_U16_LE
+#define FMT_S24_3NE FMT_S24_3LE
+#define FMT_U24_3NE FMT_U24_3LE
 #define FMT_S24_NE FMT_S24_LE
 #define FMT_U24_NE FMT_U24_LE
 #define FMT_S32_NE FMT_S32_LE
 #define FMT_U32_NE FMT_U32_LE
 #endif
 
-#define FMT_SIZEOF(f) ((f) == FMT_FLOAT ? sizeof (float) : (f) <= FMT_U8 ? 1 : (f) <= FMT_U16_BE ? 2 : 4)
+#define FMT_SIZEOF(f) ((f) == FMT_FLOAT ? sizeof (float) : (f) <= FMT_U8 ? 1 : (f) <= FMT_U16_BE ? 2 : (f) <= FMT_U24_3_BE ? 3 : 4)
 
 void audio_interlace (const void * const * in, int format, int channels, void * out, int frames);
 void audio_from_int (const void * in, int format, float * out, int samples);
-- 
1.8.4

