Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #3185 from popcornmix/amplification

[rbp/omxplayer] Add Dynamic Range Compresssion scheme
  • Loading branch information...
commit af32fce167138e828a0cad55d83fd0074f657e9e 2 parents 4e13c22 + 6e4103b
huceke huceke authored
10 language/English/strings.po
View
@@ -14337,6 +14337,11 @@ msgctxt "#36542"
msgid "Output to both analogue (headphones) and HDMI"
msgstr ""
+#: system/settings/rbp.xml
+msgctxt "#36543"
+msgid "Enable this to make dialogue louder compared to background sounds when downmixing multichannel audio"
+msgstr ""
+
#reserved strings 365XX
#: xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp
@@ -14390,3 +14395,8 @@ msgstr ""
msgctxt "#37017"
msgid "Dual audio output"
msgstr ""
+
+#: system/settings/rbp.xml
+msgctxt "#37018"
+msgid "Boost centre channel when downmixing"
+msgstr ""
4 system/settings/rbp.xml
View
@@ -88,6 +88,10 @@
<level>2</level>
<default>false</default>
</setting>
+ <setting id="audiooutput.boostcentre" type="boolean" label="37018" help="36543">
+ <level>2</level>
+ <default>false</default>
+ </setting>
</group>
<group id="2">
<visible>false</visible>
180 xbmc/cores/omxplayer/OMXAudio.cpp
View
@@ -89,6 +89,19 @@ const float downmixing_coefficients_8[OMX_AUDIO_MAXCHANNELS] = {
/* Rr */ 0, 0.7071
};
+// 7.1 downmixing coefficients with boosted centre channel
+const float downmixing_coefficients_8_boostcentre[OMX_AUDIO_MAXCHANNELS] = {
+ // L R
+ /* L */ 0.7071, 0,
+ /* R */ 0, 0.7071,
+ /* C */ 1, 1,
+ /* LFE */ 0.7071, 0.7071,
+ /* Ls */ 0.7071, 0,
+ /* Rs */ 0, 0.7071,
+ /* Lr */ 0.7071, 0,
+ /* Rr */ 0, 0.7071
+};
+
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
@@ -106,6 +119,10 @@ COMXAudio::COMXAudio() :
m_ChunkLen (0 ),
m_OutputChannels (0 ),
m_BitsPerSample (0 ),
+ m_maxLevel (0.0f ),
+ m_amplification (1.0f ),
+ m_attenuation (1.0f ),
+ m_desired_attenuation(1.0f),
m_omx_clock (NULL ),
m_av_clock (NULL ),
m_settings_changed(false ),
@@ -200,6 +217,7 @@ bool COMXAudio::PortSettingsChanged()
return false;
}
+ SetDynamicRangeCompression((long)(CMediaSettings::Get().GetCurrentVideoSettings().m_VolumeAmplification * 100));
ApplyVolume();
if( m_omx_mixer.IsInitialized() )
@@ -518,7 +536,10 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo
memset(&m_wave_header, 0x0, sizeof(m_wave_header));
for(int i = 0; i < OMX_AUDIO_MAXCHANNELS; i++)
+ {
m_pcm_input.eChannelMapping[i] = OMX_AUDIO_ChannelNone;
+ m_input_channels[i] = OMX_AUDIO_ChannelMax;
+ }
m_output_channels[0] = OMX_AUDIO_ChannelLF;
m_output_channels[1] = OMX_AUDIO_ChannelRF;
@@ -846,6 +867,10 @@ void COMXAudio::Flush()
//***********************************************************************************************
void COMXAudio::SetDynamicRangeCompression(long drc)
{
+ CSingleLock lock (m_critSection);
+ m_amplification = powf(10.0f, (float)drc / 2000.0f);
+ if (m_settings_changed)
+ ApplyVolume();
}
//***********************************************************************************************
@@ -876,87 +901,68 @@ bool COMXAudio::ApplyVolume(void)
float fVolume = m_Mute ? VOLUME_MINIMUM : m_CurrentVolume;
+ // the analogue volume is too quiet for some. Allow use of an advancedsetting to boost this (at risk of distortion) (deprecated)
double gain = pow(10, (g_advancedSettings.m_ac3Gain - 12.0f) / 20.0);
+ double r = 1.0;
+ const float* coeff = downmixing_coefficients_8;
- if (m_format.m_channelLayout.Count() > 2)
- {
- double r = fVolume;
- const float* coeff = downmixing_coefficients_8;
+ // alternate coffeciciants that boost centre channel more
+ if(!CSettings::Get().GetBool("audiooutput.boostcentre"))
+ coeff = downmixing_coefficients_8_boostcentre;
- // normally we normalalise the levels, can be skipped (boosted) at risk of distortion
- if(!CSettings::Get().GetBool("audiooutput.normalizelevels"))
+ // normally we normalise the levels, can be skipped (boosted) at risk of distortion
+ if(!CSettings::Get().GetBool("audiooutput.normalizelevels"))
+ {
+ double sum_L = 0;
+ double sum_R = 0;
+ for(size_t i = 0; i < OMX_AUDIO_MAXCHANNELS; ++i)
{
- double sum_L = 0;
- double sum_R = 0;
+ if (m_input_channels[i] == OMX_AUDIO_ChannelMax)
+ break;
+ if(i & 1)
+ sum_R += coeff[i];
+ else
+ sum_L += coeff[i];
+ }
- for(size_t i = 0; i < OMX_AUDIO_MAXCHANNELS; ++i)
- {
- if (m_input_channels[i] == OMX_AUDIO_ChannelMax)
- break;
- if(i & 1)
- sum_R += coeff[i];
- else
- sum_L += coeff[i];
- }
+ r /= max(sum_L, sum_R);
+ }
+ r *= gain;
- r /= max(sum_L, sum_R);
- }
+ OMX_CONFIG_BRCMAUDIODOWNMIXCOEFFICIENTS mix;
+ OMX_INIT_STRUCTURE(mix);
+ OMX_ERRORTYPE omx_err;
- // the analogue volume is too quiet for some. Allow use of an advancedsetting to boost this (at risk of distortion)
- r *= gain;
+ assert(sizeof(mix.coeff)/sizeof(mix.coeff[0]) == 16);
- OMX_CONFIG_BRCMAUDIODOWNMIXCOEFFICIENTS mix;
- OMX_INIT_STRUCTURE(mix);
- mix.nPortIndex = m_omx_mixer.GetInputPort();
+ // reduce scaling so overflow can be seen
+ for(size_t i = 0; i < 16; ++i)
+ mix.coeff[i] = static_cast<unsigned int>(0x10000 * (coeff[i] * r * 0.01f));
- assert(sizeof(mix.coeff)/sizeof(mix.coeff[0]) == 16);
+ mix.nPortIndex = m_omx_decoder.GetInputPort();
+ omx_err = m_omx_decoder.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients, &mix);
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "%s::%s - error setting decoder OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
+ CLASSNAME, __func__, omx_err);
+ return false;
+ }
+ if (m_amplification != 1.0)
+ {
for(size_t i = 0; i < 16; ++i)
- mix.coeff[i] = static_cast<unsigned int>(0x10000 * (coeff[i] * r));
-
- OMX_ERRORTYPE omx_err =
- m_omx_mixer.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients, &mix);
+ mix.coeff[i] = static_cast<unsigned int>(0x10000 * (coeff[i] * r * fVolume * m_amplification * m_attenuation));
+ mix.nPortIndex = m_omx_mixer.GetInputPort();
+ omx_err = m_omx_mixer.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients, &mix);
if(omx_err != OMX_ErrorNone)
{
- CLog::Log(LOGERROR, "%s::%s - error setting OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
+ CLog::Log(LOGERROR, "%s::%s - error setting mixer OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
CLASSNAME, __func__, omx_err);
return false;
}
}
- else
- {
- OMX_AUDIO_CONFIG_VOLUMETYPE volume;
- OMX_INIT_STRUCTURE(volume);
-
- volume.bLinear = OMX_TRUE;
- float hardwareVolume = fVolume * gain * 100.0f;
- volume.sVolume.nValue = (int)(hardwareVolume + 0.5f);
-
- if(m_omx_render_analog.IsInitialized())
- {
- volume.nPortIndex = m_omx_render_analog.GetInputPort();
- OMX_ERRORTYPE omx_err = m_omx_render_analog.SetConfig(OMX_IndexConfigAudioVolume, &volume);
- if(omx_err != OMX_ErrorNone)
- {
- CLog::Log(LOGERROR, "%s::%s - error setting OMX_IndexConfigAudioVolume, error 0x%08x\n",
- CLASSNAME, __func__, omx_err);
- return false;
- }
- }
- if(m_omx_render_hdmi.IsInitialized())
- {
- volume.nPortIndex = m_omx_render_hdmi.GetInputPort();
- OMX_ERRORTYPE omx_err = m_omx_render_hdmi.SetConfig(OMX_IndexConfigAudioVolume, &volume);
- if(omx_err != OMX_ErrorNone)
- {
- CLog::Log(LOGERROR, "%s::%s - error setting OMX_IndexConfigAudioVolume, error 0x%08x\n",
- CLASSNAME, __func__, omx_err);
- return false;
- }
- }
- }
- CLog::Log(LOGINFO, "%s::%s - Volume=%.2f\n", CLASSNAME, __func__, fVolume);
+ CLog::Log(LOGINFO, "%s::%s - Volume=%.2f (* %.2f * %.2f)\n", CLASSNAME, __func__, fVolume, m_amplification, m_attenuation);
return true;
}
@@ -1171,6 +1177,27 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt
}
}
+ if (m_amplification != 1.0)
+ {
+ double level_pts = 0.0;
+ float level = GetMaxLevel(level_pts);
+ if (level_pts != 0.0)
+ {
+ float alpha_h = -1.0f/(0.025f*log10f(0.999f));
+ float alpha_r = -1.0f/(0.100f*log10f(0.900f));
+ float hold = powf(10.0f, -1.0f / (alpha_h * g_advancedSettings.m_limiterHold));
+ float release = powf(10.0f, -1.0f / (alpha_r * g_advancedSettings.m_limiterRelease));
+ m_maxLevel = level > m_maxLevel ? level : hold * m_maxLevel + (1.0f-hold) * level;
+
+ float amp = m_amplification * m_desired_attenuation;
+
+ // want m_maxLevel * amp -> 1.0
+ m_desired_attenuation = std::min(1.0f, std::max(m_desired_attenuation / (amp * m_maxLevel), 1.0f/m_amplification));
+ m_attenuation = release * m_attenuation + (1.0f-release) * m_desired_attenuation;
+
+ ApplyVolume();
+ }
+ }
return len;
}
@@ -1269,6 +1296,33 @@ unsigned int COMXAudio::GetAudioRenderingLatency()
return param.nU32;
}
+float COMXAudio::GetMaxLevel(double &pts)
+{
+ CSingleLock lock (m_critSection);
+
+ if(!m_Initialized)
+ return 0;
+
+ OMX_CONFIG_BRCMAUDIOMAXSAMPLE param;
+ OMX_INIT_STRUCTURE(param);
+
+ if(m_omx_decoder.IsInitialized())
+ {
+ param.nPortIndex = m_omx_decoder.GetInputPort();
+
+ OMX_ERRORTYPE omx_err = m_omx_decoder.GetConfig(OMX_IndexConfigBrcmAudioMaxSample, &param);
+
+ if(omx_err != OMX_ErrorNone)
+ {
+ CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigBrcmAudioMaxSample error 0x%08x\n",
+ CLASSNAME, __func__, omx_err);
+ return 0;
+ }
+ }
+ pts = FromOMXTime(param.nTimeStamp);
+ return (float)param.nMaxSample * (100.0f / (1<<15));
+}
+
void COMXAudio::SubmitEOS()
{
CSingleLock lock (m_critSection);
6 xbmc/cores/omxplayer/OMXAudio.h
View
@@ -72,6 +72,7 @@ class COMXAudio
void SetVolume(float nVolume);
void SetMute(bool bOnOff);
void SetDynamicRangeCompression(long drc);
+ float GetDynamicRangeAmplification() { return 20.0f * log10f(m_amplification * m_attenuation); }
bool ApplyVolume();
int SetPlaySpeed(int iSpeed);
void SubmitEOS();
@@ -94,6 +95,7 @@ class COMXAudio
bool BadState() { return !m_Initialized; };
unsigned int GetAudioRenderingLatency();
+ float GetMaxLevel(double &pts);
void VizPacket(const void* data, unsigned int len, double pts);
private:
@@ -109,6 +111,10 @@ class COMXAudio
unsigned int m_ChunkLen;
unsigned int m_OutputChannels;
unsigned int m_BitsPerSample;
+ float m_maxLevel;
+ float m_amplification;
+ float m_attenuation;
+ float m_desired_attenuation;
COMXCoreComponent *m_omx_clock;
OMXClock *m_av_clock;
bool m_settings_changed;
6 xbmc/cores/omxplayer/OMXPlayer.cpp
View
@@ -2875,7 +2875,7 @@ void COMXPlayer::GetGeneralInfo(CStdString& strGeneralInfo)
strBuf.AppendFormat(" %d sec", DVD_TIME_TO_SEC(m_State.cache_delay));
}
- strGeneralInfo.Format("C( ad:% 6.3f, a/v:% 6.3f%s, dcpu:%2i%% acpu:%2i%% vcpu:%2i%%%s af:%d%% vf:%d%% )"
+ 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 )"
, m_omxPlayerAudio.GetDelay()
, dDiff
, strEDL.c_str()
@@ -2884,7 +2884,8 @@ void COMXPlayer::GetGeneralInfo(CStdString& strGeneralInfo)
, (int)(m_omxPlayerVideo.GetRelativeUsage()*100)
, strBuf.c_str()
, m_audio_fifo
- , m_video_fifo);
+ , m_video_fifo
+ , m_omxPlayerAudio.GetDynamicRangeAmplification());
}
}
@@ -4464,6 +4465,7 @@ void COMXPlayer::GetAudioCapabilities(std::vector<int> &audioCaps)
audioCaps.push_back(IPC_AUD_OFFSET);
audioCaps.push_back(IPC_AUD_SELECT_STREAM);
audioCaps.push_back(IPC_AUD_SELECT_OUTPUT);
+ audioCaps.push_back(IPC_AUD_AMP);
}
void COMXPlayer::GetSubtitleCapabilities(std::vector<int> &subCaps)
1  xbmc/cores/omxplayer/OMXPlayerAudio.h
View
@@ -112,6 +112,7 @@ class OMXPlayerAudio : public CThread
void SetVolume(float fVolume) { m_omxAudio.SetVolume(fVolume); }
void SetMute(bool bOnOff) { m_omxAudio.SetMute(bOnOff); }
void SetDynamicRangeCompression(long drc) { m_omxAudio.SetDynamicRangeCompression(drc); }
+ float GetDynamicRangeAmplification() { return m_omxAudio.GetDynamicRangeAmplification(); }
void SetSpeed(int iSpeed);
int GetAudioBitrate();
std::string GetPlayerInfo();
Please sign in to comment.
Something went wrong with that request. Please try again.