diff options
author | Hendrik Leppkes <h.leppkes@gmail.com> | 2012-07-02 13:31:51 +0400 |
---|---|---|
committer | Hendrik Leppkes <h.leppkes@gmail.com> | 2012-07-02 17:35:33 +0400 |
commit | 8c7bec11ba09c369e0e4de71aaa2195b1c28ca31 (patch) | |
tree | e1aeffec0f08279de37e30b4a31b74230da2a2ae /decoder/LAVAudio | |
parent | 3c813a547c5ef0503c6b579e52f390fa0b94b159 (diff) |
mixing: Add options for matrix normalization and clip protection
Diffstat (limited to 'decoder/LAVAudio')
-rw-r--r-- | decoder/LAVAudio/AudioSettingsProp.cpp | 18 | ||||
-rw-r--r-- | decoder/LAVAudio/LAVAudio.cpp | 11 | ||||
-rw-r--r-- | decoder/LAVAudio/LAVAudio.h | 2 | ||||
-rw-r--r-- | decoder/LAVAudio/LAVAudio.rc | 2 | ||||
-rw-r--r-- | decoder/LAVAudio/LAVAudioSettings.h | 2 | ||||
-rw-r--r-- | decoder/LAVAudio/PostProcessor.cpp | 29 | ||||
-rw-r--r-- | decoder/LAVAudio/resource.h | 4 |
7 files changed, 64 insertions, 4 deletions
diff --git a/decoder/LAVAudio/AudioSettingsProp.cpp b/decoder/LAVAudio/AudioSettingsProp.cpp index 9861b99d..75b54624 100644 --- a/decoder/LAVAudio/AudioSettingsProp.cpp +++ b/decoder/LAVAudio/AudioSettingsProp.cpp @@ -386,6 +386,12 @@ HRESULT CLAVAudioMixingProp::OnApplyChanges() bVal = (BOOL)SendDlgItemMessage(m_Dlg, IDC_UNTOUCHED_STEREO, BM_GETCHECK, 0, 0); if (bVal) dwMixingFlags |= LAV_MIXING_FLAG_UNTOUCHED_STEREO; + bVal = (BOOL)SendDlgItemMessage(m_Dlg, IDC_NORMALIZE_MATRIX, BM_GETCHECK, 0, 0); + if (bVal) dwMixingFlags |= LAV_MIXING_FLAG_NORMALIZE_MATRIX; + + bVal = (BOOL)SendDlgItemMessage(m_Dlg, IDC_CLIP_PROTECTION, BM_GETCHECK, 0, 0); + if (bVal) dwMixingFlags |= LAV_MIXING_FLAG_CLIP_PROTECTION; + m_pAudioSettings->SetMixingFlags(dwMixingFlags); LoadData(); @@ -424,6 +430,8 @@ HRESULT CLAVAudioMixingProp::OnActivate() SendDlgItemMessage(m_Dlg, IDC_OUTPUT_SPEAKERS, CB_SETCURSEL, get_speaker_index(m_dwSpeakerLayout), 0); SendDlgItemMessage(m_Dlg, IDC_UNTOUCHED_STEREO, BM_SETCHECK, !!(m_dwFlags & LAV_MIXING_FLAG_UNTOUCHED_STEREO), 0); + SendDlgItemMessage(m_Dlg, IDC_NORMALIZE_MATRIX, BM_SETCHECK, !!(m_dwFlags & LAV_MIXING_FLAG_NORMALIZE_MATRIX), 0); + SendDlgItemMessage(m_Dlg, IDC_CLIP_PROTECTION, BM_SETCHECK, !!(m_dwFlags & LAV_MIXING_FLAG_CLIP_PROTECTION), 0); } return hr; @@ -461,6 +469,16 @@ INT_PTR CLAVAudioMixingProp::OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wPara if (lValue == !(m_dwFlags & LAV_MIXING_FLAG_UNTOUCHED_STEREO)) { SetDirty(); } + } else if (LOWORD(wParam) == IDC_NORMALIZE_MATRIX && HIWORD(wParam) == BN_CLICKED) { + lValue = SendDlgItemMessage(m_Dlg, LOWORD(wParam), BM_GETCHECK, 0, 0); + if (lValue == !(m_dwFlags & LAV_MIXING_FLAG_NORMALIZE_MATRIX)) { + SetDirty(); + } + } else if (LOWORD(wParam) == IDC_CLIP_PROTECTION && HIWORD(wParam) == BN_CLICKED) { + lValue = SendDlgItemMessage(m_Dlg, LOWORD(wParam), BM_GETCHECK, 0, 0); + if (lValue == !(m_dwFlags & LAV_MIXING_FLAG_CLIP_PROTECTION)) { + SetDirty(); + } } break; case WM_HSCROLL: diff --git a/decoder/LAVAudio/LAVAudio.cpp b/decoder/LAVAudio/LAVAudio.cpp index 833f0bcb..9cf2edab 100644 --- a/decoder/LAVAudio/LAVAudio.cpp +++ b/decoder/LAVAudio/LAVAudio.cpp @@ -85,6 +85,8 @@ CLAVAudio::CLAVAudio(LPUNKNOWN pUnk, HRESULT* phr) , m_bInputPadded(FALSE) , m_avrContext(NULL) , m_bAVResampleFailed(FALSE) + , m_bMixingSettingsChanged(FALSE) + , m_fMixingClipThreshold(0.0f) { #ifdef DEBUG DbgSetModuleLevel (LOG_CUSTOM1, DWORD_MAX); // FFMPEG messages use custom1 @@ -193,7 +195,7 @@ HRESULT CLAVAudio::LoadDefaults() m_settings.MixingEnabled = FALSE; m_settings.MixingLayout = AV_CH_LAYOUT_STEREO; - m_settings.MixingFlags = 0; + m_settings.MixingFlags = LAV_MIXING_FLAG_CLIP_PROTECTION; return S_OK; } @@ -633,6 +635,8 @@ STDMETHODIMP CLAVAudio::SetMixingEnabled(BOOL bEnabled) m_settings.MixingEnabled = bEnabled; SaveSettings(); + m_bMixingSettingsChanged = TRUE; + return S_OK; } @@ -646,6 +650,8 @@ STDMETHODIMP CLAVAudio::SetMixingLayout(DWORD dwLayout) m_settings.MixingLayout = dwLayout; SaveSettings(); + m_bMixingSettingsChanged = TRUE; + return S_OK; } @@ -659,6 +665,8 @@ STDMETHODIMP CLAVAudio::SetMixingFlags(DWORD dwFlags) m_settings.MixingFlags = dwFlags; SaveSettings(); + m_bMixingSettingsChanged = TRUE; + return S_OK; } @@ -1321,6 +1329,7 @@ HRESULT CLAVAudio::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, doubl m_dRate = dRate; else m_dRate = 1.0; + m_fMixingClipThreshold = 0.0f; return __super::NewSegment(tStart, tStop, dRate); } diff --git a/decoder/LAVAudio/LAVAudio.h b/decoder/LAVAudio/LAVAudio.h index aeb4de8b..3f670d81 100644 --- a/decoder/LAVAudio/LAVAudio.h +++ b/decoder/LAVAudio/LAVAudio.h @@ -268,6 +268,8 @@ private: LAVAudioSampleFormat m_sfRemixFormat; DWORD m_dwRemixLayout; BOOL m_bAVResampleFailed; + BOOL m_bMixingSettingsChanged; + float m_fMixingClipThreshold; // Settings struct AudioSettings { diff --git a/decoder/LAVAudio/LAVAudio.rc b/decoder/LAVAudio/LAVAudio.rc index 1e6dd81d..ea83beba 100644 --- a/decoder/LAVAudio/LAVAudio.rc +++ b/decoder/LAVAudio/LAVAudio.rc @@ -115,6 +115,8 @@ BEGIN COMBOBOX IDC_OUTPUT_SPEAKERS,121,30,90,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP GROUPBOX "Settings",IDC_MIX_SETTINGS,225,7,133,53 CONTROL "Don't mix Stereo sources",IDC_UNTOUCHED_STEREO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,237,19,100,10 + CONTROL "Normalize Matrix",IDC_NORMALIZE_MATRIX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,237,33,100,10 + CONTROL "Clipping Protection",IDC_CLIP_PROTECTION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,237,47,100,10 END IDD_PROPPAGE_FORMATS DIALOGEX 0, 0, 369, 215 diff --git a/decoder/LAVAudio/LAVAudioSettings.h b/decoder/LAVAudio/LAVAudioSettings.h index 6c1dbf75..d8689f74 100644 --- a/decoder/LAVAudio/LAVAudioSettings.h +++ b/decoder/LAVAudio/LAVAudioSettings.h @@ -148,6 +148,8 @@ interface ILAVAudioSettings : public IUnknown STDMETHOD_(DWORD,GetMixingLayout)() = 0; #define LAV_MIXING_FLAG_UNTOUCHED_STEREO 0x0001 +#define LAV_MIXING_FLAG_NORMALIZE_MATRIX 0x0002 +#define LAV_MIXING_FLAG_CLIP_PROTECTION 0x0004 // Enable/Disable Mixing STDMETHOD(SetMixingFlags)(DWORD dwFlags) = 0; STDMETHOD_(DWORD,GetMixingFlags)() = 0; diff --git a/decoder/LAVAudio/PostProcessor.cpp b/decoder/LAVAudio/PostProcessor.cpp index 49f04e31..89f487f1 100644 --- a/decoder/LAVAudio/PostProcessor.cpp +++ b/decoder/LAVAudio/PostProcessor.cpp @@ -560,8 +560,9 @@ HRESULT CLAVAudio::PerformMixing(BufferDetails *buffer) ConvertSampleFormat(buffer, SampleFormat_32); } - if (buffer->dwChannelMask != m_DecodeLayoutSanified || (!m_avrContext && !m_bAVResampleFailed) || m_settings.MixingLayout != m_dwRemixLayout) { + if (buffer->dwChannelMask != m_DecodeLayoutSanified || (!m_avrContext && !m_bAVResampleFailed) || m_bMixingSettingsChanged) { m_bAVResampleFailed = FALSE; + m_bMixingSettingsChanged = FALSE; if (m_avrContext) { avresample_close(m_avrContext); avresample_free(&m_avrContext); @@ -574,6 +575,11 @@ HRESULT CLAVAudio::PerformMixing(BufferDetails *buffer) if (m_sfRemixFormat == SampleFormat_24) m_sfRemixFormat = SampleFormat_32; + BOOL bNormalize = !!(m_settings.MixingFlags & LAV_MIXING_FLAG_NORMALIZE_MATRIX); + // Force FP32 output from remixing when not performing normalization + if (!bNormalize) + m_sfRemixFormat = SampleFormat_FP32; + m_avrContext = avresample_alloc_context(); av_opt_set_int(m_avrContext, "in_channel_layout", buffer->dwChannelMask, 0); av_opt_set_int(m_avrContext, "in_sample_fmt", get_ff_sample_fmt(buffer->sfFormat), 0); @@ -586,7 +592,7 @@ HRESULT CLAVAudio::PerformMixing(BufferDetails *buffer) int out_ch = av_get_channel_layout_nb_channels(m_settings.MixingLayout); double *matrix_dbl = (double *)av_mallocz(in_ch * out_ch * sizeof(*matrix_dbl)); - ret = avresample_build_matrix(buffer->dwChannelMask, m_settings.MixingLayout, M_SQRT1_2, M_SQRT1_2, 0.0, 1, matrix_dbl, in_ch, AV_MATRIX_ENCODING_NONE); + ret = avresample_build_matrix(buffer->dwChannelMask, m_settings.MixingLayout, M_SQRT1_2, M_SQRT1_2, 0.0, bNormalize, matrix_dbl, in_ch, AV_MATRIX_ENCODING_NONE); if (ret < 0) { DbgLog((LOG_ERROR, 10, L"avresample_build_matrix failed, layout in: %x, out: %x, sample fmt in: %d, out: %d", buffer->dwChannelMask, m_settings.MixingLayout, buffer->sfFormat, m_sfRemixFormat)); av_free(matrix_dbl); @@ -626,6 +632,25 @@ HRESULT CLAVAudio::PerformMixing(BufferDetails *buffer) return S_FALSE; } + if (!(m_settings.MixingFlags & LAV_MIXING_FLAG_NORMALIZE_MATRIX) && (m_settings.MixingFlags & LAV_MIXING_FLAG_CLIP_PROTECTION)) { + ASSERT(m_sfRemixFormat == SampleFormat_FP32); + + DWORD dwSamples = av_get_channel_layout_nb_channels(m_dwRemixLayout) * buffer->nSamples; + BOOL bNeedNormalize = (m_fMixingClipThreshold > 1.0f); + float *pfOut = (float *)pOut; + for (DWORD i = 0; i < dwSamples; i++) { + float fVal = abs(pfOut[i]); + if (fVal > 1.0f && fVal > m_fMixingClipThreshold) { + m_fMixingClipThreshold = fVal; + bNeedNormalize = TRUE; + DbgLog((LOG_TRACE, 10, L"PerformMixing: Clipping Protection engaged with coeff of %f", m_fMixingClipThreshold)); + } + if (bNeedNormalize) { + pfOut[i] /= m_fMixingClipThreshold; + } + } + } + delete buffer->bBuffer; buffer->bBuffer = pcmOut; buffer->dwChannelMask = m_dwRemixLayout; diff --git a/decoder/LAVAudio/resource.h b/decoder/LAVAudio/resource.h index 6bbf9149..8e149f36 100644 --- a/decoder/LAVAudio/resource.h +++ b/decoder/LAVAudio/resource.h @@ -95,6 +95,8 @@ #define IDC_MIX_SETTINGS 1110 #define IDC_LBL_OUTPUT_SPEAKERS 1111 #define IDC_LBL_MIXING 1112 +#define IDC_NORMALIZE_MATRIX 1113 +#define IDC_CLIP_PROTECTION 1114 // Next default values for new objects // @@ -102,7 +104,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 106 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1113 +#define _APS_NEXT_CONTROL_VALUE 1115 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif |