AE: add S24NEMSB and treat S24NE4 with bit in lower 3 bytes
authorRainer Hochecker <fernetmenta@online.de>
Thu, 29 May 2014 15:22:58 +0000 (17:22 +0200)
committerRainer Hochecker <fernetmenta@online.de>
Fri, 30 May 2014 09:42:08 +0000 (11:42 +0200)
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.cpp
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp
xbmc/cores/AudioEngine/Utils/AEAudioFormat.h
xbmc/cores/AudioEngine/Utils/AEUtil.cpp
xbmc/cores/AudioEngine/Utils/AEUtil.h

index d6fa3df..e4178d1 100644 (file)
@@ -2593,6 +2593,7 @@ bool CActiveAE::ResampleSound(CActiveAESound *sound)
   dst_config.sample_rate = m_internalFormat.m_sampleRate;
   dst_config.fmt = CActiveAEResample::GetAVSampleFormat(m_internalFormat.m_dataFormat);
   dst_config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_internalFormat.m_dataFormat);
+  dst_config.dither_bits = CAEUtil::DataFormatToDitherBits(m_internalFormat.m_dataFormat);
 
   CActiveAEResample *resampler = new CActiveAEResample();
   resampler->Init(dst_config.channel_layout,
@@ -2600,11 +2601,13 @@ bool CActiveAE::ResampleSound(CActiveAESound *sound)
                   dst_config.sample_rate,
                   dst_config.fmt,
                   dst_config.bits_per_sample,
+                  dst_config.dither_bits,
                   orig_config.channel_layout,
                   orig_config.channels,
                   orig_config.sample_rate,
                   orig_config.fmt,
                   orig_config.bits_per_sample,
+                  orig_config.dither_bits,
                   false,
                   true,
                   NULL,
index f2fd023..a10753e 100644 (file)
@@ -107,6 +107,7 @@ bool CActiveAEBufferPool::Create(unsigned int totaltime)
   SampleConfig config;
   config.fmt = CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat);
   config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat);
+  config.dither_bits = CAEUtil::DataFormatToDitherBits(m_format.m_dataFormat);
   config.channels = m_format.m_channelLayout.Count();
   config.sample_rate = m_format.m_sampleRate;
   config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_format.m_channelLayout);
@@ -174,11 +175,13 @@ bool CActiveAEBufferPoolResample::Create(unsigned int totaltime, bool remap, boo
                                 m_format.m_sampleRate,
                                 CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat),
                                 CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat),
+                                CAEUtil::DataFormatToDitherBits(m_format.m_dataFormat),
                                 CActiveAEResample::GetAVChannelLayout(m_inputFormat.m_channelLayout),
                                 m_inputFormat.m_channelLayout.Count(),
                                 m_inputFormat.m_sampleRate,
                                 CActiveAEResample::GetAVSampleFormat(m_inputFormat.m_dataFormat),
                                 CAEUtil::DataFormatToUsedBits(m_inputFormat.m_dataFormat),
+                                CAEUtil::DataFormatToDitherBits(m_format.m_dataFormat),
                                 upmix,
                                 m_normalize,
                                 remap ? &m_format.m_channelLayout : NULL,
@@ -200,11 +203,13 @@ void CActiveAEBufferPoolResample::ChangeResampler()
                                 m_format.m_sampleRate,
                                 CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat),
                                 CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat),
+                                CAEUtil::DataFormatToDitherBits(m_format.m_dataFormat),
                                 CActiveAEResample::GetAVChannelLayout(m_inputFormat.m_channelLayout),
                                 m_inputFormat.m_channelLayout.Count(),
                                 m_inputFormat.m_sampleRate,
                                 CActiveAEResample::GetAVSampleFormat(m_inputFormat.m_dataFormat),
                                 CAEUtil::DataFormatToUsedBits(m_inputFormat.m_dataFormat),
+                                CAEUtil::DataFormatToDitherBits(m_format.m_dataFormat),
                                 m_stereoUpmix,
                                 m_normalize,
                                 NULL,
index f8d0ba0..a854470 100644 (file)
@@ -38,6 +38,7 @@ struct SampleConfig
   int channels;
   int sample_rate;
   int bits_per_sample;
+  int dither_bits;
 };
 
 /**
index a50dda1..78b533d 100644 (file)
@@ -41,7 +41,7 @@ CActiveAEResample::~CActiveAEResample()
     swr_free(&m_pContext);
 }
 
-bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality)
+bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality)
 {
   if (!m_loaded)
     return false;
@@ -51,11 +51,13 @@ bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst
   m_dst_rate = dst_rate;
   m_dst_fmt = dst_fmt;
   m_dst_bits = dst_bits;
+  m_dst_dither_bits = dst_dither;
   m_src_chan_layout = src_chan_layout;
   m_src_channels = src_channels;
   m_src_rate = src_rate;
   m_src_fmt = src_fmt;
   m_src_bits = src_bits;
+  m_src_dither_bits = src_dither;
 
   if (m_dst_chan_layout == 0)
     m_dst_chan_layout = av_get_default_channel_layout(m_dst_channels);
@@ -195,6 +197,24 @@ int CActiveAEResample::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t *
     CLog::Log(LOGERROR, "CActiveAEResample::Resample - resample failed");
     return 0;
   }
+
+  // shift bits if destination format requires it, swr_resamples aligns to the left
+  if (m_dst_fmt == AV_SAMPLE_FMT_S32 || m_dst_fmt == AV_SAMPLE_FMT_S32P)
+  {
+    if (m_dst_bits != 32 && (m_dst_dither_bits + m_dst_bits) != 32)
+    {
+      int planes = av_sample_fmt_is_planar(m_dst_fmt) ? m_dst_channels : 1;
+      int samples = ret * m_dst_channels / planes;
+      for (int i=0; i<planes; i++)
+      {
+        uint32_t* buf = (uint32_t*)dst_buffer[i];
+        for (int j=0; j<samples; j++)
+        {
+          *buf = *buf >> m_dst_dither_bits;
+        }
+      }
+    }
+  }
   return ret;
 }
 
@@ -282,6 +302,7 @@ AVSampleFormat CActiveAEResample::GetAVSampleFormat(AEDataFormat format)
   else if (format == AE_FMT_S16NE)  return AV_SAMPLE_FMT_S16;
   else if (format == AE_FMT_S32NE)  return AV_SAMPLE_FMT_S32;
   else if (format == AE_FMT_S24NE4) return AV_SAMPLE_FMT_S32;
+  else if (format == AE_FMT_S24NE4MSB)return AV_SAMPLE_FMT_S32;
   else if (format == AE_FMT_FLOAT)  return AV_SAMPLE_FMT_FLT;
   else if (format == AE_FMT_DOUBLE) return AV_SAMPLE_FMT_DBL;
 
@@ -289,6 +310,7 @@ AVSampleFormat CActiveAEResample::GetAVSampleFormat(AEDataFormat format)
   else if (format == AE_FMT_S16NEP)  return AV_SAMPLE_FMT_S16P;
   else if (format == AE_FMT_S32NEP)  return AV_SAMPLE_FMT_S32P;
   else if (format == AE_FMT_S24NE4P) return AV_SAMPLE_FMT_S32P;
+  else if (format == AE_FMT_S24NE4MSBP)return AV_SAMPLE_FMT_S32P;
   else if (format == AE_FMT_FLOATP)  return AV_SAMPLE_FMT_FLTP;
   else if (format == AE_FMT_DOUBLEP) return AV_SAMPLE_FMT_DBLP;
 
index 9c89b1b..f943605 100644 (file)
@@ -37,7 +37,7 @@ class CActiveAEResample
 public:
   CActiveAEResample();
   virtual ~CActiveAEResample();
-  bool Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality);
+  bool Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, int dst_dither, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, int src_dither, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality);
   int Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio);
   int64_t GetDelay(int64_t base);
   int GetBufferedSamples();
@@ -58,6 +58,7 @@ protected:
   int m_src_channels, m_dst_channels;
   AVSampleFormat m_src_fmt, m_dst_fmt;
   int m_src_bits, m_dst_bits;
+  int m_src_dither_bits, m_dst_dither_bits;
   SwrContext *m_pContext;
   double m_rematrix[AE_CH_MAX][AE_CH_MAX];
 };
index df30614..1001288 100644 (file)
@@ -758,6 +758,7 @@ void CActiveAESink::OpenSink()
   SampleConfig config;
   config.fmt = CActiveAEResample::GetAVSampleFormat(m_sinkFormat.m_dataFormat);
   config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_sinkFormat.m_dataFormat);
+  config.dither_bits = CAEUtil::DataFormatToDitherBits(m_sinkFormat.m_dataFormat);
   config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_sinkFormat.m_channelLayout);
   config.channels = m_sinkFormat.m_channelLayout.Count();
   config.sample_rate = m_sinkFormat.m_sampleRate;
@@ -882,6 +883,7 @@ void CActiveAESink::EnsureConvertBuffer(CSampleBuffer* samples)
   SampleConfig config;
   config.fmt = CActiveAEResample::GetAVSampleFormat(m_sinkFormat.m_dataFormat);
   config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_sinkFormat.m_dataFormat);
+  config.dither_bits = CAEUtil::DataFormatToDitherBits(m_sinkFormat.m_dataFormat);
   config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_sinkFormat.m_channelLayout);
   config.channels = m_sinkFormat.m_channelLayout.Count();
   config.sample_rate = m_sinkFormat.m_sampleRate;
index 0287e73..d964fbf 100644 (file)
@@ -149,11 +149,13 @@ void CActiveAEStream::InitRemapper()
                      m_format.m_sampleRate,
                      CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat),
                      CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat),
+                     CAEUtil::DataFormatToDitherBits(m_format.m_dataFormat),
                      avLayout,
                      m_format.m_channelLayout.Count(),
                      m_format.m_sampleRate,
                      CActiveAEResample::GetAVSampleFormat(m_format.m_dataFormat),
                      CAEUtil::DataFormatToUsedBits(m_format.m_dataFormat),
+                     CAEUtil::DataFormatToDitherBits(m_format.m_dataFormat),
                      false,
                      false,
                      &remapLayout,
index 9ac5c79..7f882b6 100644 (file)
@@ -43,7 +43,8 @@ enum AEDataFormat
   
   AE_FMT_S24BE4,
   AE_FMT_S24LE4,
-  AE_FMT_S24NE4, /* S24 in 4 bytes */
+  AE_FMT_S24NE4,    // 24 bits in lower 3 bytes
+  AE_FMT_S24NE4MSB, // S32 with bits_per_sample < 32
 
   AE_FMT_S24BE3,
   AE_FMT_S24LE3,
@@ -66,6 +67,7 @@ enum AEDataFormat
   AE_FMT_S16NEP,
   AE_FMT_S32NEP,
   AE_FMT_S24NE4P,
+  AE_FMT_S24NE4MSBP,
   AE_FMT_S24NE3P,
   AE_FMT_DOUBLEP,
   AE_FMT_FLOATP,
index feaa621..61c7368 100644 (file)
@@ -95,6 +95,7 @@ const unsigned int CAEUtil::DataFormatToBits(const enum AEDataFormat dataFormat)
     32,                  /* S24BE  */
     32,                  /* S24LE  */
     32,                  /* S24NE  */
+    32,                  /* S24NER */
     
     24,                  /* S24BE3 */
     24,                  /* S24LE3 */
@@ -115,6 +116,7 @@ const unsigned int CAEUtil::DataFormatToBits(const enum AEDataFormat dataFormat)
     16,                  /* S16NEP */
     32,                  /* S32NEP */
     32,                  /* S24NEP */
+    32,                  /* S24NERP*/
     24,                  /* S24NE3P*/
     sizeof(double) << 3, /* DOUBLEP */
     sizeof(float ) << 3  /* FLOATP  */
@@ -125,12 +127,21 @@ const unsigned int CAEUtil::DataFormatToBits(const enum AEDataFormat dataFormat)
 
 const unsigned int CAEUtil::DataFormatToUsedBits(const enum AEDataFormat dataFormat)
 {
-  if (dataFormat == AE_FMT_S24BE4 || dataFormat == AE_FMT_S24LE4 || dataFormat == AE_FMT_S24NE4)
+  if (dataFormat == AE_FMT_S24BE4 || dataFormat == AE_FMT_S24LE4 ||
+      dataFormat == AE_FMT_S24NE4 || dataFormat == AE_FMT_S24NE4MSB)
     return 24;
   else
     return DataFormatToBits(dataFormat);
 }
 
+const unsigned int CAEUtil::DataFormatToDitherBits(const enum AEDataFormat dataFormat)
+{
+  if (dataFormat == AE_FMT_S24NE4MSB)
+    return 8;
+  else
+    return 0;
+}
+
 const char* CAEUtil::DataFormatToStr(const enum AEDataFormat dataFormat)
 {
   if (dataFormat < 0 || dataFormat >= AE_FMT_MAX)
@@ -152,6 +163,7 @@ const char* CAEUtil::DataFormatToStr(const enum AEDataFormat dataFormat)
     "AE_FMT_S24BE4",
     "AE_FMT_S24LE4",
     "AE_FMT_S24NE4",  /* S24 in 4 bytes */
+    "AE_FMT_S24NE4MSB",
     
     "AE_FMT_S24BE3",
     "AE_FMT_S24LE3",
@@ -174,6 +186,7 @@ const char* CAEUtil::DataFormatToStr(const enum AEDataFormat dataFormat)
     "AE_FMT_S16NEP",
     "AE_FMT_S32NEP",
     "AE_FMT_S24NE4P",
+    "AE_FMT_S24NE4MSBP",
     "AE_FMT_S24NE3P",
     "AE_FMT_DOUBLEP",
     "AE_FMT_FLOATP"
index c008557..9954ac2 100644 (file)
@@ -72,6 +72,7 @@ public:
   static const char*             GetStdChLayoutName(const enum AEStdChLayout layout);
   static const unsigned int      DataFormatToBits  (const enum AEDataFormat dataFormat);
   static const unsigned int      DataFormatToUsedBits (const enum AEDataFormat dataFormat);
+  static const unsigned int      DataFormatToDitherBits(const enum AEDataFormat dataFormat);
   static const char*             DataFormatToStr   (const enum AEDataFormat dataFormat);
 
   /*! \brief convert a volume percentage (as a proportion) to a dB gain