support for 24 bit pcm/wav files
authorreimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2>
Sun, 16 May 2004 10:48:59 +0000 (10:48 +0000)
committerreimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2>
Sun, 16 May 2004 10:48:59 +0000 (10:48 +0000)
git-svn-id: svn://git.mplayerhq.hu/mplayer/trunk@12479 b3059339-0415-0410-9bf9-f77b7e298cf2

libaf/af_format.c
libaf/af_mp.c
libao2/afmt.h
libmpcodecs/ad_pcm.c

index 8d9f3e6..7a5fd04 100644 (file)
@@ -131,9 +131,9 @@ char* fmt2str(int format, char* str, size_t size)
 // Sanity check for bytes per sample
 int check_bps(int bps)
 {
 // Sanity check for bytes per sample
 int check_bps(int bps)
 {
-  if(bps != 4 && bps != 2 && bps != 1){
+  if(bps != 4 && bps != 3 && bps != 2 && bps != 1){
     af_msg(AF_MSG_ERROR,"[format] The number of bytes per sample" 
     af_msg(AF_MSG_ERROR,"[format] The number of bytes per sample" 
-          " must be 1, 2 or 4. Current value is %i \n",bps);
+          " must be 1, 2, 3 or 4. Current value is %i \n",bps);
     return AF_ERROR;
   }
   return AF_OK;
     return AF_ERROR;
   }
   return AF_OK;
@@ -349,6 +349,30 @@ af_info_t af_info_format = {
   open
 };
 
   open
 };
 
+static inline uint32_t load24bit(void* data, int pos) {
+#if WORDS_BIGENDIAN
+  return (((uint32_t)((uint8_t*)data)[3*pos])<<24) |
+        (((uint32_t)((uint8_t*)data)[3*pos+1])<<16) |
+        (((uint32_t)((uint8_t*)data)[3*pos+2])<<8);
+#else
+  return (((uint32_t)((uint8_t*)data)[3*pos])<<8) |
+        (((uint32_t)((uint8_t*)data)[3*pos+1])<<16) |
+        (((uint32_t)((uint8_t*)data)[3*pos+2])<<24);
+#endif
+}
+
+static inline void store24bit(void* data, int pos, uint32_t expanded_value) {
+#if WORDS_BIGENDIAN
+      ((uint8_t*)data)[3*pos]=expanded_value>>24;
+      ((uint8_t*)data)[3*pos+1]=expanded_value>>16;
+      ((uint8_t*)data)[3*pos+2]=expanded_value>>8;
+#else
+      ((uint8_t*)data)[3*pos]=expanded_value>>8;
+      ((uint8_t*)data)[3*pos+1]=expanded_value>>16;
+      ((uint8_t*)data)[3*pos+2]=expanded_value>>24;
+#endif
+}
+
 // Function implementations used by play
 static void endian(void* in, void* out, int len, int bps)
 {
 // Function implementations used by play
 static void endian(void* in, void* out, int len, int bps)
 {
@@ -362,6 +386,15 @@ static void endian(void* in, void* out, int len, int bps)
       }
       break;
     }
       }
       break;
     }
+    case(3):{
+      register uint8_t s;
+      for(i=0;i<len;i++){
+       s=((uint8_t*)in)[3*i];
+       ((uint8_t*)out)[3*i]=((uint8_t*)in)[3*i+2];
+       ((uint8_t*)out)[3*i+2]=s;
+      }
+      break;
+    }
     case(4):{
       register uint32_t s;
       for(i=0;i<len;i++){
     case(4):{
       register uint32_t s;
       for(i=0;i<len;i++){
@@ -388,6 +421,10 @@ static void si2us(void* in, void* out, int len, int bps)
     for(i=0;i<len;i++)
       ((uint16_t*)out)[i]=(uint16_t)(SHRT_MAX+((int)((int16_t*)in)[i]));
     break;
     for(i=0;i<len;i++)
       ((uint16_t*)out)[i]=(uint16_t)(SHRT_MAX+((int)((int16_t*)in)[i]));
     break;
+  case(3):
+    for(i=0;i<len;i++)
+      store24bit(out, i, (uint32_t)(INT_MAX+(int32_t)load24bit(in, i)));
+    break;
   case(4):
     for(i=0;i<len;i++)
       ((uint32_t*)out)[i]=(uint32_t)(INT_MAX+((int32_t*)in)[i]);
   case(4):
     for(i=0;i<len;i++)
       ((uint32_t*)out)[i]=(uint32_t)(INT_MAX+((int32_t*)in)[i]);
@@ -407,6 +444,10 @@ static void us2si(void* in, void* out, int len, int bps)
     for(i=0;i<len;i++)
       ((int16_t*)out)[i]=(int16_t)(SHRT_MIN+((int)((uint16_t*)in)[i]));
     break;
     for(i=0;i<len;i++)
       ((int16_t*)out)[i]=(int16_t)(SHRT_MIN+((int)((uint16_t*)in)[i]));
     break;
+  case(3):
+    for(i=0;i<len;i++)
+      store24bit(out, i, (int32_t)(INT_MIN+(uint32_t)load24bit(in, i)));
+    break;
   case(4):
     for(i=0;i<len;i++)
       ((int32_t*)out)[i]=(int32_t)(INT_MIN+((uint32_t*)in)[i]);
   case(4):
     for(i=0;i<len;i++)
       ((int32_t*)out)[i]=(int32_t)(INT_MIN+((uint32_t*)in)[i]);
@@ -424,6 +465,10 @@ static void change_bps(void* in, void* out, int len, int inbps, int outbps)
       for(i=0;i<len;i++)
        ((uint16_t*)out)[i]=((uint16_t)((uint8_t*)in)[i])<<8;
       break;
       for(i=0;i<len;i++)
        ((uint16_t*)out)[i]=((uint16_t)((uint8_t*)in)[i])<<8;
       break;
+    case(3):
+      for(i=0;i<len;i++)
+       store24bit(out, i, ((uint32_t)((uint8_t*)in)[i])<<24);
+      break;
     case(4):
       for(i=0;i<len;i++)
        ((uint32_t*)out)[i]=((uint32_t)((uint8_t*)in)[i])<<24;
     case(4):
       for(i=0;i<len;i++)
        ((uint32_t*)out)[i]=((uint32_t)((uint8_t*)in)[i])<<24;
@@ -436,12 +481,32 @@ static void change_bps(void* in, void* out, int len, int inbps, int outbps)
       for(i=0;i<len;i++)
        ((uint8_t*)out)[i]=(uint8_t)((((uint16_t*)in)[i])>>8);
       break;
       for(i=0;i<len;i++)
        ((uint8_t*)out)[i]=(uint8_t)((((uint16_t*)in)[i])>>8);
       break;
+    case(3):
+      for(i=0;i<len;i++)
+       store24bit(out, i, ((uint32_t)((uint16_t*)in)[i])<<16);
+      break;
     case(4):
       for(i=0;i<len;i++)
        ((uint32_t*)out)[i]=((uint32_t)((uint16_t*)in)[i])<<16;
       break;
     }
     break;
     case(4):
       for(i=0;i<len;i++)
        ((uint32_t*)out)[i]=((uint32_t)((uint16_t*)in)[i])<<16;
       break;
     }
     break;
+  case(3):
+    switch(outbps){
+    case(1):
+      for(i=0;i<len;i++)
+       ((uint8_t*)out)[i]=(uint8_t)(load24bit(in, i)>>24);
+      break;
+    case(2):
+      for(i=0;i<len;i++)
+       ((uint16_t*)out)[i]=(uint16_t)(load24bit(in, i)>>16);
+      break;
+    case(4):
+      for(i=0;i<len;i++)
+       ((uint32_t*)out)[i]=(uint32_t)load24bit(in, i);
+      break;
+    }
+    break;      
   case(4):
     switch(outbps){
     case(1):
   case(4):
     switch(outbps){
     case(1):
@@ -452,6 +517,10 @@ static void change_bps(void* in, void* out, int len, int inbps, int outbps)
       for(i=0;i<len;i++)
        ((uint16_t*)out)[i]=(uint16_t)((((uint32_t*)in)[i])>>16);
       break;
       for(i=0;i<len;i++)
        ((uint16_t*)out)[i]=(uint16_t)((((uint32_t*)in)[i])>>16);
       break;
+    case(3):
+      for(i=0;i<len;i++)
+        store24bit(out, i, ((uint32_t*)in)[i]);
+      break;
     }
     break;      
   }
     }
     break;      
   }
@@ -469,6 +538,10 @@ static void float2int(void* in, void* out, int len, int bps)
     for(i=0;i<len;i++)
       ((int16_t*)out)[i]=(int16_t)lrintf(SHRT_MAX*((float*)in)[i]);
     break;
     for(i=0;i<len;i++)
       ((int16_t*)out)[i]=(int16_t)lrintf(SHRT_MAX*((float*)in)[i]);
     break;
+  case(3):
+    for(i=0;i<len;i++)
+      store24bit(out, i, (int32_t)lrintf(INT_MAX*((float*)in)[i]));
+    break;
   case(4):
     for(i=0;i<len;i++)
       ((int32_t*)out)[i]=(int32_t)lrintf(INT_MAX*((float*)in)[i]);
   case(4):
     for(i=0;i<len;i++)
       ((int32_t*)out)[i]=(int32_t)lrintf(INT_MAX*((float*)in)[i]);
@@ -488,6 +561,10 @@ static void int2float(void* in, void* out, int len, int bps)
     for(i=0;i<len;i++)
       ((float*)out)[i]=(1.0/SHRT_MAX)*((float)((int16_t*)in)[i]);
     break;
     for(i=0;i<len;i++)
       ((float*)out)[i]=(1.0/SHRT_MAX)*((float)((int16_t*)in)[i]);
     break;
+  case(3):
+    for(i=0;i<len;i++)
+      ((float*)out)[i]=(1.0/INT_MAX)*((float)((int32_t)load24bit(in, i)));
+    break;
   case(4):
     for(i=0;i<len;i++)
       ((float*)out)[i]=(1.0/INT_MAX)*((float)((int32_t*)in)[i]);
   case(4):
     for(i=0;i<len;i++)
       ((float*)out)[i]=(1.0/INT_MAX)*((float)((int32_t*)in)[i]);
index 835cba7..9dd4bd3 100644 (file)
@@ -35,6 +35,10 @@ int af_format_decode(int ifmt)
   case(AFMT_FLOAT):
     ofmt = AF_FORMAT_F | AF_FORMAT_NE; break;
   default: 
   case(AFMT_FLOAT):
     ofmt = AF_FORMAT_F | AF_FORMAT_NE; break;
   default: 
+    if (ifmt & AFMT_AF_FLAGS == AFMT_AF_FLAGS) {
+      ofmt = ifmt & ~AFMT_AF_FLAGS;
+      break;
+    }
     //This can not happen .... 
     af_msg(AF_MSG_FATAL,"Unrecognized input audio format %i\n",ifmt);
     break;
     //This can not happen .... 
     af_msg(AF_MSG_FATAL,"Unrecognized input audio format %i\n",ifmt);
     break;
@@ -75,6 +79,6 @@ int af_format_encode(void* fmtp)
   case AF_FORMAT_AC3:    return AFMT_AC3;
   case AF_FORMAT_IMA_ADPCM: return AFMT_IMA_ADPCM;
   }
   case AF_FORMAT_AC3:    return AFMT_AC3;
   case AF_FORMAT_IMA_ADPCM: return AFMT_IMA_ADPCM;
   }
-  return AFMT_S16_LE; // shouldn't happen
+  return (fmt->format | AFMT_AF_FLAGS);
 }
 
 }
 
index f7c4fcd..fbef3af 100644 (file)
@@ -53,3 +53,8 @@
 #ifndef AFMT_FLOAT
 # define AFMT_FLOAT               0x00004000
 #endif
 #ifndef AFMT_FLOAT
 # define AFMT_FLOAT               0x00004000
 #endif
+
+/* for formats that don't have a corresponding AFMT_* type,
+ * use the flags from libaf/af_format.h or'ed with this */
+#define AFMT_AF_FLAGS             0x70000000
+
index aedcedf..0d03fe5 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "config.h"
 #include "ad_internal.h"
 
 #include "config.h"
 #include "ad_internal.h"
+#include "../libaf/af_format.h"
 
 static ad_info_t info = 
 {
 
 static ad_info_t info = 
 {
@@ -29,6 +30,9 @@ static int init(sh_audio_t *sh_audio)
        switch (sh_audio->samplesize) {
          case 1: sh_audio->sample_format=AFMT_U8; break;
          case 2: sh_audio->sample_format=AFMT_S16_LE; break;
        switch (sh_audio->samplesize) {
          case 1: sh_audio->sample_format=AFMT_U8; break;
          case 2: sh_audio->sample_format=AFMT_S16_LE; break;
+         case 3: sh_audio->sample_format=AFMT_AF_FLAGS | AF_FORMAT_I |
+                   AF_FORMAT_LE | AF_FORMAT_SI;
+           break;
          case 4: sh_audio->sample_format=AFMT_S32_LE; break;
        }
        break;
          case 4: sh_audio->sample_format=AFMT_S32_LE; break;
        }
        break;