Skip to content
This repository
Browse code

Merge pull request #3185 from popcornmix/amplification

[rbp/omxplayer] Add Dynamic Range Compresssion scheme
  • Loading branch information...
commit af32fce167138e828a0cad55d83fd0074f657e9e 2 parents 4e13c22 + 6e4103b
huceke authored September 07, 2013
10  language/English/strings.po
@@ -14337,6 +14337,11 @@ msgctxt "#36542"
14337 14337
 msgid "Output to both analogue (headphones) and HDMI"
14338 14338
 msgstr ""
14339 14339
 
  14340
+#: system/settings/rbp.xml
  14341
+msgctxt "#36543"
  14342
+msgid "Enable this to make dialogue louder compared to background sounds when downmixing multichannel audio"
  14343
+msgstr ""
  14344
+
14340 14345
 #reserved strings 365XX
14341 14346
 
14342 14347
 #: xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp
@@ -14390,3 +14395,8 @@ msgstr ""
14390 14395
 msgctxt "#37017"
14391 14396
 msgid "Dual audio output"
14392 14397
 msgstr ""
  14398
+
  14399
+#: system/settings/rbp.xml
  14400
+msgctxt "#37018"
  14401
+msgid "Boost centre channel when downmixing"
  14402
+msgstr ""
4  system/settings/rbp.xml
@@ -88,6 +88,10 @@
88 88
           <level>2</level>
89 89
           <default>false</default>
90 90
         </setting>
  91
+        <setting id="audiooutput.boostcentre" type="boolean" label="37018" help="36543">
  92
+          <level>2</level>
  93
+          <default>false</default>
  94
+        </setting>
91 95
       </group>
92 96
       <group id="2">
93 97
         <visible>false</visible>
180  xbmc/cores/omxplayer/OMXAudio.cpp
@@ -89,6 +89,19 @@ const float downmixing_coefficients_8[OMX_AUDIO_MAXCHANNELS] = {
89 89
   /* Rr */  0,      0.7071
90 90
 };
91 91
 
  92
+// 7.1 downmixing coefficients with boosted centre channel
  93
+const float downmixing_coefficients_8_boostcentre[OMX_AUDIO_MAXCHANNELS] = {
  94
+  //        L       R
  95
+  /* L */   0.7071, 0,
  96
+  /* R */   0,      0.7071,
  97
+  /* C */   1,      1,
  98
+  /* LFE */ 0.7071, 0.7071,
  99
+  /* Ls */  0.7071, 0,
  100
+  /* Rs */  0,      0.7071,
  101
+  /* Lr */  0.7071, 0,
  102
+  /* Rr */  0,      0.7071
  103
+};
  104
+
92 105
 //////////////////////////////////////////////////////////////////////
93 106
 // Construction/Destruction
94 107
 //////////////////////////////////////////////////////////////////////
@@ -106,6 +119,10 @@ COMXAudio::COMXAudio() :
106 119
   m_ChunkLen        (0      ),
107 120
   m_OutputChannels  (0      ),
108 121
   m_BitsPerSample   (0      ),
  122
+  m_maxLevel        (0.0f   ),
  123
+  m_amplification   (1.0f   ),
  124
+  m_attenuation     (1.0f   ),
  125
+  m_desired_attenuation(1.0f),
109 126
   m_omx_clock       (NULL   ),
110 127
   m_av_clock        (NULL   ),
111 128
   m_settings_changed(false  ),
@@ -200,6 +217,7 @@ bool COMXAudio::PortSettingsChanged()
200 217
       return false;
201 218
   }
202 219
 
  220
+  SetDynamicRangeCompression((long)(CMediaSettings::Get().GetCurrentVideoSettings().m_VolumeAmplification * 100));
203 221
   ApplyVolume();
204 222
 
205 223
   if( m_omx_mixer.IsInitialized() )
@@ -518,7 +536,10 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo
518 536
   memset(&m_wave_header, 0x0, sizeof(m_wave_header));
519 537
 
520 538
   for(int i = 0; i < OMX_AUDIO_MAXCHANNELS; i++)
  539
+  {
521 540
     m_pcm_input.eChannelMapping[i] = OMX_AUDIO_ChannelNone;
  541
+    m_input_channels[i] = OMX_AUDIO_ChannelMax;
  542
+  }
522 543
 
523 544
   m_output_channels[0] = OMX_AUDIO_ChannelLF;
524 545
   m_output_channels[1] = OMX_AUDIO_ChannelRF;
@@ -846,6 +867,10 @@ void COMXAudio::Flush()
846 867
 //***********************************************************************************************
847 868
 void COMXAudio::SetDynamicRangeCompression(long drc)
848 869
 {
  870
+  CSingleLock lock (m_critSection);
  871
+  m_amplification = powf(10.0f, (float)drc / 2000.0f);
  872
+  if (m_settings_changed)
  873
+    ApplyVolume();
849 874
 }
850 875
 
851 876
 //***********************************************************************************************
@@ -876,87 +901,68 @@ bool COMXAudio::ApplyVolume(void)
876 901
 
877 902
   float fVolume = m_Mute ? VOLUME_MINIMUM : m_CurrentVolume;
878 903
 
  904
+  // the analogue volume is too quiet for some. Allow use of an advancedsetting to boost this (at risk of distortion) (deprecated)
879 905
   double gain = pow(10, (g_advancedSettings.m_ac3Gain - 12.0f) / 20.0);
  906
+  double r = 1.0;
  907
+  const float* coeff = downmixing_coefficients_8;
880 908
 
881  
-  if (m_format.m_channelLayout.Count() > 2)
882  
-  {
883  
-    double r = fVolume;
884  
-    const float* coeff = downmixing_coefficients_8;
  909
+  // alternate coffeciciants that boost centre channel more
  910
+  if(!CSettings::Get().GetBool("audiooutput.boostcentre"))
  911
+    coeff = downmixing_coefficients_8_boostcentre;
885 912
 
886  
-    // normally we normalalise the levels, can be skipped (boosted) at risk of distortion
887  
-    if(!CSettings::Get().GetBool("audiooutput.normalizelevels"))
  913
+  // normally we normalise the levels, can be skipped (boosted) at risk of distortion
  914
+  if(!CSettings::Get().GetBool("audiooutput.normalizelevels"))
  915
+  {
  916
+    double sum_L = 0;
  917
+    double sum_R = 0;
  918
+    for(size_t i = 0; i < OMX_AUDIO_MAXCHANNELS; ++i)
888 919
     {
889  
-      double sum_L = 0;
890  
-      double sum_R = 0;
  920
+      if (m_input_channels[i] == OMX_AUDIO_ChannelMax)
  921
+        break;
  922
+      if(i & 1)
  923
+        sum_R += coeff[i];
  924
+      else
  925
+        sum_L += coeff[i];
  926
+    }
891 927
 
892  
-      for(size_t i = 0; i < OMX_AUDIO_MAXCHANNELS; ++i)
893  
-      {
894  
-        if (m_input_channels[i] == OMX_AUDIO_ChannelMax)
895  
-          break;
896  
-        if(i & 1)
897  
-          sum_R += coeff[i];
898  
-        else
899  
-          sum_L += coeff[i];
900  
-      }
  928
+    r /= max(sum_L, sum_R);
  929
+  }
  930
+  r *= gain;
901 931
 
902  
-      r /= max(sum_L, sum_R);
903  
-    }
  932
+  OMX_CONFIG_BRCMAUDIODOWNMIXCOEFFICIENTS mix;
  933
+  OMX_INIT_STRUCTURE(mix);
  934
+  OMX_ERRORTYPE omx_err;
904 935
 
905  
-    // the analogue volume is too quiet for some. Allow use of an advancedsetting to boost this (at risk of distortion)
906  
-    r *= gain;
  936
+  assert(sizeof(mix.coeff)/sizeof(mix.coeff[0]) == 16);
907 937
 
908  
-    OMX_CONFIG_BRCMAUDIODOWNMIXCOEFFICIENTS mix;
909  
-    OMX_INIT_STRUCTURE(mix);
910  
-    mix.nPortIndex = m_omx_mixer.GetInputPort();
  938
+  // reduce scaling so overflow can be seen
  939
+  for(size_t i = 0; i < 16; ++i)
  940
+    mix.coeff[i] = static_cast<unsigned int>(0x10000 * (coeff[i] * r * 0.01f));
911 941
 
912  
-    assert(sizeof(mix.coeff)/sizeof(mix.coeff[0]) == 16);
  942
+  mix.nPortIndex = m_omx_decoder.GetInputPort();
  943
+  omx_err = m_omx_decoder.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients, &mix);
  944
+  if(omx_err != OMX_ErrorNone)
  945
+  {
  946
+    CLog::Log(LOGERROR, "%s::%s - error setting decoder OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
  947
+              CLASSNAME, __func__, omx_err);
  948
+    return false;
  949
+  }
913 950
 
  951
+  if (m_amplification != 1.0)
  952
+  {
914 953
     for(size_t i = 0; i < 16; ++i)
915  
-      mix.coeff[i] = static_cast<unsigned int>(0x10000 * (coeff[i] * r));
916  
-
917  
-    OMX_ERRORTYPE omx_err =
918  
-      m_omx_mixer.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients, &mix);
  954
+      mix.coeff[i] = static_cast<unsigned int>(0x10000 * (coeff[i] * r * fVolume * m_amplification * m_attenuation));
919 955
 
  956
+    mix.nPortIndex = m_omx_mixer.GetInputPort();
  957
+    omx_err = m_omx_mixer.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients, &mix);
920 958
     if(omx_err != OMX_ErrorNone)
921 959
     {
922  
-      CLog::Log(LOGERROR, "%s::%s - error setting OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
  960
+      CLog::Log(LOGERROR, "%s::%s - error setting mixer OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
923 961
                 CLASSNAME, __func__, omx_err);
924 962
       return false;
925 963
     }
926 964
   }
927  
-  else
928  
-  {
929  
-    OMX_AUDIO_CONFIG_VOLUMETYPE volume;
930  
-    OMX_INIT_STRUCTURE(volume);
931  
-
932  
-    volume.bLinear    = OMX_TRUE;
933  
-    float hardwareVolume = fVolume * gain * 100.0f;
934  
-    volume.sVolume.nValue = (int)(hardwareVolume + 0.5f);
935  
-
936  
-    if(m_omx_render_analog.IsInitialized())
937  
-    {
938  
-      volume.nPortIndex = m_omx_render_analog.GetInputPort();
939  
-      OMX_ERRORTYPE omx_err = m_omx_render_analog.SetConfig(OMX_IndexConfigAudioVolume, &volume);
940  
-      if(omx_err != OMX_ErrorNone)
941  
-      {
942  
-        CLog::Log(LOGERROR, "%s::%s - error setting OMX_IndexConfigAudioVolume, error 0x%08x\n",
943  
-                CLASSNAME, __func__, omx_err);
944  
-        return false;
945  
-      }
946  
-    }
947  
-    if(m_omx_render_hdmi.IsInitialized())
948  
-    {
949  
-      volume.nPortIndex = m_omx_render_hdmi.GetInputPort();
950  
-      OMX_ERRORTYPE omx_err = m_omx_render_hdmi.SetConfig(OMX_IndexConfigAudioVolume, &volume);
951  
-      if(omx_err != OMX_ErrorNone)
952  
-      {
953  
-        CLog::Log(LOGERROR, "%s::%s - error setting OMX_IndexConfigAudioVolume, error 0x%08x\n",
954  
-                CLASSNAME, __func__, omx_err);
955  
-        return false;
956  
-      }
957  
-    }
958  
-  }
959  
-  CLog::Log(LOGINFO, "%s::%s - Volume=%.2f\n", CLASSNAME, __func__, fVolume);
  965
+  CLog::Log(LOGINFO, "%s::%s - Volume=%.2f (* %.2f * %.2f)\n", CLASSNAME, __func__, fVolume, m_amplification, m_attenuation);
960 966
   return true;
961 967
 }
962 968
 
@@ -1171,6 +1177,27 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt
1171 1177
     }
1172 1178
   }
1173 1179
 
  1180
+  if (m_amplification != 1.0)
  1181
+  {
  1182
+    double level_pts = 0.0;
  1183
+    float level = GetMaxLevel(level_pts);
  1184
+    if (level_pts != 0.0)
  1185
+    {
  1186
+      float alpha_h = -1.0f/(0.025f*log10f(0.999f));
  1187
+      float alpha_r = -1.0f/(0.100f*log10f(0.900f));
  1188
+      float hold    = powf(10.0f, -1.0f / (alpha_h * g_advancedSettings.m_limiterHold));
  1189
+      float release = powf(10.0f, -1.0f / (alpha_r * g_advancedSettings.m_limiterRelease));
  1190
+      m_maxLevel = level > m_maxLevel ? level : hold * m_maxLevel + (1.0f-hold) * level;
  1191
+
  1192
+      float amp = m_amplification * m_desired_attenuation;
  1193
+
  1194
+      // want m_maxLevel * amp -> 1.0
  1195
+      m_desired_attenuation = std::min(1.0f, std::max(m_desired_attenuation / (amp * m_maxLevel), 1.0f/m_amplification));
  1196
+      m_attenuation = release * m_attenuation + (1.0f-release) * m_desired_attenuation;
  1197
+
  1198
+      ApplyVolume();
  1199
+    }
  1200
+  }
1174 1201
   return len;
1175 1202
 }
1176 1203
 
@@ -1269,6 +1296,33 @@ unsigned int COMXAudio::GetAudioRenderingLatency()
1269 1296
   return param.nU32;
1270 1297
 }
1271 1298
 
  1299
+float COMXAudio::GetMaxLevel(double &pts)
  1300
+{
  1301
+  CSingleLock lock (m_critSection);
  1302
+
  1303
+  if(!m_Initialized)
  1304
+    return 0;
  1305
+
  1306
+  OMX_CONFIG_BRCMAUDIOMAXSAMPLE param;
  1307
+  OMX_INIT_STRUCTURE(param);
  1308
+
  1309
+  if(m_omx_decoder.IsInitialized())
  1310
+  {
  1311
+    param.nPortIndex = m_omx_decoder.GetInputPort();
  1312
+
  1313
+    OMX_ERRORTYPE omx_err = m_omx_decoder.GetConfig(OMX_IndexConfigBrcmAudioMaxSample, &param);
  1314
+
  1315
+    if(omx_err != OMX_ErrorNone)
  1316
+    {
  1317
+      CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigBrcmAudioMaxSample error 0x%08x\n",
  1318
+        CLASSNAME, __func__, omx_err);
  1319
+      return 0;
  1320
+    }
  1321
+  }
  1322
+  pts = FromOMXTime(param.nTimeStamp);
  1323
+  return (float)param.nMaxSample * (100.0f / (1<<15));
  1324
+}
  1325
+
1272 1326
 void COMXAudio::SubmitEOS()
1273 1327
 {
1274 1328
   CSingleLock lock (m_critSection);
6  xbmc/cores/omxplayer/OMXAudio.h
@@ -72,6 +72,7 @@ class COMXAudio
72 72
   void SetVolume(float nVolume);
73 73
   void SetMute(bool bOnOff);
74 74
   void SetDynamicRangeCompression(long drc);
  75
+  float GetDynamicRangeAmplification() { return 20.0f * log10f(m_amplification * m_attenuation); }
75 76
   bool ApplyVolume();
76 77
   int SetPlaySpeed(int iSpeed);
77 78
   void SubmitEOS();
@@ -94,6 +95,7 @@ class COMXAudio
94 95
 
95 96
   bool BadState() { return !m_Initialized; };
96 97
   unsigned int GetAudioRenderingLatency();
  98
+  float GetMaxLevel(double &pts);
97 99
   void VizPacket(const void* data, unsigned int len, double pts);
98 100
 
99 101
 private:
@@ -109,6 +111,10 @@ class COMXAudio
109 111
   unsigned int  m_ChunkLen;
110 112
   unsigned int  m_OutputChannels;
111 113
   unsigned int  m_BitsPerSample;
  114
+  float         m_maxLevel;
  115
+  float         m_amplification;
  116
+  float         m_attenuation;
  117
+  float         m_desired_attenuation;
112 118
   COMXCoreComponent *m_omx_clock;
113 119
   OMXClock       *m_av_clock;
114 120
   bool          m_settings_changed;
6  xbmc/cores/omxplayer/OMXPlayer.cpp
@@ -2875,7 +2875,7 @@ void COMXPlayer::GetGeneralInfo(CStdString& strGeneralInfo)
2875 2875
         strBuf.AppendFormat(" %d sec", DVD_TIME_TO_SEC(m_State.cache_delay));
2876 2876
     }
2877 2877
 
2878  
-    strGeneralInfo.Format("C( ad:% 6.3f, a/v:% 6.3f%s, dcpu:%2i%% acpu:%2i%% vcpu:%2i%%%s af:%d%% vf:%d%% )"
  2878
+    strGeneralInfo.Format("C( ad:% 6.3f a/v:% 6.3f%s, dcpu:%2i%% acpu:%2i%% vcpu:%2i%%%s af:%d%% vf:%d%% amp:% 5.2f )"
2879 2879
                          , m_omxPlayerAudio.GetDelay()
2880 2880
                          , dDiff
2881 2881
                          , strEDL.c_str()
@@ -2884,7 +2884,8 @@ void COMXPlayer::GetGeneralInfo(CStdString& strGeneralInfo)
2884 2884
                          , (int)(m_omxPlayerVideo.GetRelativeUsage()*100)
2885 2885
                          , strBuf.c_str()
2886 2886
                          , m_audio_fifo
2887  
-                         , m_video_fifo);
  2887
+                         , m_video_fifo
  2888
+                         , m_omxPlayerAudio.GetDynamicRangeAmplification());
2888 2889
 
2889 2890
   }
2890 2891
 }
@@ -4464,6 +4465,7 @@ void COMXPlayer::GetAudioCapabilities(std::vector<int> &audioCaps)
4464 4465
   audioCaps.push_back(IPC_AUD_OFFSET);
4465 4466
   audioCaps.push_back(IPC_AUD_SELECT_STREAM);
4466 4467
   audioCaps.push_back(IPC_AUD_SELECT_OUTPUT);
  4468
+  audioCaps.push_back(IPC_AUD_AMP);
4467 4469
 }
4468 4470
 
4469 4471
 void COMXPlayer::GetSubtitleCapabilities(std::vector<int> &subCaps)
1  xbmc/cores/omxplayer/OMXPlayerAudio.h
@@ -112,6 +112,7 @@ class OMXPlayerAudio : public CThread
112 112
   void SetVolume(float fVolume)                          { m_omxAudio.SetVolume(fVolume); }
113 113
   void SetMute(bool bOnOff)                              { m_omxAudio.SetMute(bOnOff); }
114 114
   void SetDynamicRangeCompression(long drc)              { m_omxAudio.SetDynamicRangeCompression(drc); }
  115
+  float GetDynamicRangeAmplification()                   { return m_omxAudio.GetDynamicRangeAmplification(); }
115 116
   void SetSpeed(int iSpeed);
116 117
   int  GetAudioBitrate();
117 118
   std::string GetPlayerInfo();

0 notes on commit af32fce

Please sign in to comment.
Something went wrong with that request. Please try again.