From 2f5b4728bcb076603637198c91d2056b66c0377a Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Tue, 16 Feb 2021 21:44:58 +0100 Subject: [PATCH 01/14] Initial version of auto-adjustment of channel faders (Proof of concept) --- src/audiomixerboard.cpp | 50 +++++++++++++++++++++++++++++++++++++++++ src/audiomixerboard.h | 2 ++ src/clientdlg.cpp | 2 ++ src/clientdlg.h | 1 + src/global.h | 3 +++ 5 files changed, 58 insertions(+) diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index 616a24f025..4f48fca583 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -857,6 +857,8 @@ CAudioMixerBoard::CAudioMixerBoard ( QWidget* parent ) : // create all mixer controls and make them invisible vecpChanFader.Init ( MAX_NUM_CHANNELS ); + vecAvgLevels.Init ( MAX_NUM_CHANNELS ); + for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) { vecpChanFader[i] = new CChannelFader ( this ); @@ -1308,6 +1310,49 @@ void CAudioMixerBoard::SetAllFaderLevelsToNewClientLevel() } } +void CAudioMixerBoard::AutoAdjustAllFaderLevels() +{ + QMutexLocker locker ( &Mutex ); + + for ( int i = 0; i < MAX_NUM_CHANNELS; ++i ) + { + // only apply to visible faders (and not to my own channel fader) + if ( vecpChanFader[i]->IsVisible() && ( true /* i != iMyChannelID */ ) ) + { + // get averaged level meter value (range 0...8) + float levelMeter = vecAvgLevels[i]; + + // map meter output level to deciber (range -50dB...0dB) + // (invert CStereoSignalLevelMeter::CalcLogResultForMeter) + float leveldB = levelMeter * + ( UPPER_BOUND_SIG_METER - LOW_BOUND_SIG_METER ) / + NUM_STEPS_LED_BAR + LOW_BOUND_SIG_METER; + + // map decibels to linear level + // level = pow ( 10.0f, level / 20.0f ); + + // do not adjust channels with zero level to full level since + // the channel might simply be silent at the moment + if ( leveldB < -40.0f ) + { + // specify target level + float targetdBLevel = -30.0f; + + // compute new level + float newdBLevel = -leveldB + targetdBLevel; + + // map range from -35..0 dB to 0..1 + float newVal = (newdBLevel + 35.0f) / 35.0f; + + // set fader level + vecpChanFader[i]->SetFaderLevel ( newVal * AUD_MIX_FADER_MAX, true ); + + // printf("%.2f dB => %.2f dB\n", leveldB, newdBLevel); + } + } + } +} + void CAudioMixerBoard::StoreAllFaderSettings() { QMutexLocker locker ( &Mutex ); @@ -1506,11 +1551,16 @@ void CAudioMixerBoard::SetChannelLevels ( const CVector& vecChannelLev { const int iNumChannelLevels = vecChannelLevel.Size(); int i = 0; + float alpha = AUTO_FADER_ADJUST_ALPHA; for ( int iChId = 0; iChId < MAX_NUM_CHANNELS; iChId++ ) { if ( vecpChanFader[iChId]->IsVisible() && ( i < iNumChannelLevels ) ) { + // compute exponential moving average + vecAvgLevels[iChId] = (1.0f - alpha) * vecAvgLevels[iChId] + + alpha * vecChannelLevel[i]; + vecpChanFader[iChId]->SetChannelLevel ( vecChannelLevel[i++] ); // show level only if we successfully received levels from the diff --git a/src/audiomixerboard.h b/src/audiomixerboard.h index 6a9ac0a347..3fd9168170 100755 --- a/src/audiomixerboard.h +++ b/src/audiomixerboard.h @@ -232,6 +232,7 @@ class CAudioMixerBoard : void SetAllFaderLevelsToNewClientLevel(); void StoreAllFaderSettings(); void LoadAllFaderSettings(); + void AutoAdjustAllFaderLevels(); protected: class CMixerBoardScrollArea : public QScrollArea @@ -276,6 +277,7 @@ class CAudioMixerBoard : ERecorderState eRecorderState; QMutex Mutex; EChSortType eChSortType; + CVector vecAvgLevels; virtual void UpdateGainValue ( const int iChannelIdx, const float fValue, diff --git a/src/clientdlg.cpp b/src/clientdlg.cpp index 7f58a969e6..993a343f72 100755 --- a/src/clientdlg.cpp +++ b/src/clientdlg.cpp @@ -340,6 +340,8 @@ CClientDlg::CClientDlg ( CClient* pNCliP, pEditMenu->addAction ( tr ( "Set All Faders to New Client &Level" ), this, SLOT ( OnSetAllFadersToNewClientLevel() ), QKeySequence ( Qt::CTRL + Qt::Key_L ) ); + pEditMenu->addAction ( tr ( "Auto-Adjust all &Faders" ), this, + SLOT ( OnAutoAdjustAllFaderLevels() ), QKeySequence ( Qt::CTRL + Qt::Key_F ) ); // Main menu bar ----------------------------------------------------------- QMenuBar* pMenu = new QMenuBar ( this ); diff --git a/src/clientdlg.h b/src/clientdlg.h index ee5d3da9b5..e3e1469287 100755 --- a/src/clientdlg.h +++ b/src/clientdlg.h @@ -177,6 +177,7 @@ public slots: void OnUseTowRowsForMixerPanel ( bool Checked ) { MainMixerBoard->SetNumMixerPanelRows ( Checked ? 2 : 1 ); } void OnClearAllStoredSoloMuteSettings(); void OnSetAllFadersToNewClientLevel() { MainMixerBoard->SetAllFaderLevelsToNewClientLevel(); } + void OnAutoAdjustAllFaderLevels() { MainMixerBoard->AutoAdjustAllFaderLevels(); } void OnSettingsStateChanged ( int value ); void OnChatStateChanged ( int value ); diff --git a/src/global.h b/src/global.h index aad0daefc2..14c7c16881 100755 --- a/src/global.h +++ b/src/global.h @@ -152,6 +152,9 @@ LED bar: lbr #define AUD_MIX_FADER_MAX 100 #define AUD_MIX_PAN_MAX 100 +// coefficient for averaging channel levels for automatic fader adjustment +#define AUTO_FADER_ADJUST_ALPHA 0.2 + // maximum number of fader groups (must be consistent to audiomixerboard implementation) #define MAX_NUM_FADER_GROUPS 4 From 425bb3d305863b0a08460a9f3f7f30ed91031326 Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Sat, 20 Feb 2021 08:20:36 +0100 Subject: [PATCH 02/14] Incorporate review changes requested by pljones --- src/audiomixerboard.cpp | 31 +++++++++++-------------------- src/global.h | 9 ++++++++- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index 4f48fca583..cb0f285413 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -1317,37 +1317,28 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() for ( int i = 0; i < MAX_NUM_CHANNELS; ++i ) { // only apply to visible faders (and not to my own channel fader) - if ( vecpChanFader[i]->IsVisible() && ( true /* i != iMyChannelID */ ) ) + if ( vecpChanFader[i]->IsVisible() && ( i != iMyChannelID ) ) { - // get averaged level meter value (range 0...8) - float levelMeter = vecAvgLevels[i]; - - // map meter output level to deciber (range -50dB...0dB) + // map averaged meter output level to decibels // (invert CStereoSignalLevelMeter::CalcLogResultForMeter) - float leveldB = levelMeter * + float leveldB = vecAvgLevels[i] * ( UPPER_BOUND_SIG_METER - LOW_BOUND_SIG_METER ) / NUM_STEPS_LED_BAR + LOW_BOUND_SIG_METER; - // map decibels to linear level - // level = pow ( 10.0f, level / 20.0f ); - // do not adjust channels with zero level to full level since // the channel might simply be silent at the moment - if ( leveldB < -40.0f ) + if ( leveldB < AUTO_FADER_NOISE_THRESHOLD_DB ) { - // specify target level - float targetdBLevel = -30.0f; - // compute new level - float newdBLevel = -leveldB + targetdBLevel; + float newdBLevel = -leveldB + AUTO_FADER_TARGET_LEVEL_DB; - // map range from -35..0 dB to 0..1 - float newVal = (newdBLevel + 35.0f) / 35.0f; + // map range from decibels to fader level + // (this inverts MathUtils::CalcFaderGain) + float newFaderLevel = (newdBLevel + 35.0f) / 35.0f * + AUD_MIX_FADER_MAX; // set fader level - vecpChanFader[i]->SetFaderLevel ( newVal * AUD_MIX_FADER_MAX, true ); - - // printf("%.2f dB => %.2f dB\n", leveldB, newdBLevel); + vecpChanFader[i]->SetFaderLevel ( newFaderLevel, true ); } } } @@ -1551,13 +1542,13 @@ void CAudioMixerBoard::SetChannelLevels ( const CVector& vecChannelLev { const int iNumChannelLevels = vecChannelLevel.Size(); int i = 0; - float alpha = AUTO_FADER_ADJUST_ALPHA; for ( int iChId = 0; iChId < MAX_NUM_CHANNELS; iChId++ ) { if ( vecpChanFader[iChId]->IsVisible() && ( i < iNumChannelLevels ) ) { // compute exponential moving average + float alpha = AUTO_FADER_ADJUST_ALPHA; vecAvgLevels[iChId] = (1.0f - alpha) * vecAvgLevels[iChId] + alpha * vecChannelLevel[i]; diff --git a/src/global.h b/src/global.h index 14c7c16881..769d128468 100755 --- a/src/global.h +++ b/src/global.h @@ -153,7 +153,14 @@ LED bar: lbr #define AUD_MIX_PAN_MAX 100 // coefficient for averaging channel levels for automatic fader adjustment -#define AUTO_FADER_ADJUST_ALPHA 0.2 +#define AUTO_FADER_ADJUST_ALPHA 0.2f + +// target level for auto fader adjustment in decibels +#define AUTO_FADER_TARGET_LEVEL_DB -30.0f + +// threshold in decibels below which the channel is considered as noise +// and not adjusted +#define AUTO_FADER_NOISE_THRESHOLD_DB -40.0f // maximum number of fader groups (must be consistent to audiomixerboard implementation) #define MAX_NUM_FADER_GROUPS 4 From 9877159ae73eb4545d1f23e178059ab2b10b3032 Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Sat, 20 Feb 2021 15:00:00 +0100 Subject: [PATCH 03/14] Fixed bug regarding minimum threshold --- src/audiomixerboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index cb0f285413..86b7b594bf 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -1327,7 +1327,7 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() // do not adjust channels with zero level to full level since // the channel might simply be silent at the moment - if ( leveldB < AUTO_FADER_NOISE_THRESHOLD_DB ) + if ( leveldB > AUTO_FADER_NOISE_THRESHOLD_DB ) { // compute new level float newdBLevel = -leveldB + AUTO_FADER_TARGET_LEVEL_DB; From 03811e3ff35ff02c5c66f49c145a7ff75ea5290d Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Sun, 21 Feb 2021 17:15:58 +0100 Subject: [PATCH 04/14] Remove extra variable 'alpha' and use 'AUTO_FADER_ADJUST_ALPHA' instead --- src/audiomixerboard.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index 86b7b594bf..13e05dad1f 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -1548,9 +1548,9 @@ void CAudioMixerBoard::SetChannelLevels ( const CVector& vecChannelLev if ( vecpChanFader[iChId]->IsVisible() && ( i < iNumChannelLevels ) ) { // compute exponential moving average - float alpha = AUTO_FADER_ADJUST_ALPHA; - vecAvgLevels[iChId] = (1.0f - alpha) * vecAvgLevels[iChId] + - alpha * vecChannelLevel[i]; + vecAvgLevels[iChId] = + (1.0f - AUTO_FADER_ADJUST_ALPHA) * vecAvgLevels[iChId] + + AUTO_FADER_ADJUST_ALPHA * vecChannelLevel[i]; vecpChanFader[iChId]->SetChannelLevel ( vecChannelLevel[i++] ); From 147dbdbc9769f964645c9032e10b8b5f383ae2dd Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Tue, 23 Feb 2021 22:46:18 +0100 Subject: [PATCH 05/14] Advanced channel fader adjustment considering groups --- src/audiomixerboard.cpp | 107 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 5 deletions(-) diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index 13e05dad1f..85218afdcb 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -1314,6 +1314,18 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() { QMutexLocker locker ( &Mutex ); + // initialize variables used for statistics + float vecMinLevel[MAX_NUM_FADER_GROUPS + 1]; + float vecMaxLevel[MAX_NUM_FADER_GROUPS + 1]; + int vecChannelsPerGroup[MAX_NUM_FADER_GROUPS + 1]; + for ( int i = 0; i < MAX_NUM_FADER_GROUPS + 1; ++i ) + { + vecMinLevel[i] = UPPER_BOUND_SIG_METER; + vecMaxLevel[i] = LOW_BOUND_SIG_METER; + vecChannelsPerGroup[i] = 0; + } + + // compute min/max level per group and number of channels per group for ( int i = 0; i < MAX_NUM_CHANNELS; ++i ) { // only apply to visible faders (and not to my own channel fader) @@ -1325,20 +1337,105 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() ( UPPER_BOUND_SIG_METER - LOW_BOUND_SIG_METER ) / NUM_STEPS_LED_BAR + LOW_BOUND_SIG_METER; - // do not adjust channels with zero level to full level since + int group = vecpChanFader[i]->GetGroupID(); + if ( group == INVALID_INDEX ) + group = 4; + + if ( leveldB >= AUTO_FADER_NOISE_THRESHOLD_DB ) + { + vecMinLevel[group] = fmin ( vecMinLevel[group], leveldB ); + vecMaxLevel[group] = fmax ( vecMaxLevel[group], leveldB ); + } + ++vecChannelsPerGroup[group]; + } + } + + // compute the number of active groups (at least one channel) + int cntActiveGroups = 0; + for ( int i = 0; i < MAX_NUM_FADER_GROUPS + 1; ++i ) + { + cntActiveGroups += vecChannelsPerGroup[i] > 0; + } + + // only my channel is active, nothing to do + if ( cntActiveGroups == 0 ) + return; + + // compute target level for each group + // (prevent clipping when each group contributes at maximum level) + float targetLevelPerGroup = -20.0f * log10 ( cntActiveGroups ); + + // compute target levels for the channels of each group individually + float vecTargetChannelLevel[MAX_NUM_FADER_GROUPS + 1]; + float levelOffset = 0.0f; + float minFader = 0.0f; + for ( int i = 0; i < MAX_NUM_FADER_GROUPS + 1; ++i ) + { + // compute the target level for each channel in the current group + // (prevent clipping when each channel in this group contributes at + // the maximum level) + vecTargetChannelLevel[i] = vecChannelsPerGroup[i] > 0 ? + targetLevelPerGroup - 20.0f * log10 ( vecChannelsPerGroup[i] ) : + 0.0f; + + // since we can only attenuate channels but not amplify, we have to + // check that the weakest (min) channel can be brought to the target + // level + if ( vecTargetChannelLevel[i] > vecMinLevel[i] ) + { + // otherwise, we adjust the level offset in such a way that + // the level can be reached + levelOffset = fmin ( levelOffset, + vecMinLevel[i] - vecTargetChannelLevel[i] ); + + // compute the minimum necessary fader setting + minFader = fmin ( minFader, -vecMaxLevel[i] + + vecTargetChannelLevel[i] + levelOffset ); + } + } + + // take minimum fader value into account + // very weak channels would actually require strong channels to be + // attenuated to a large amount; however, the attenuation is limited by + // the faders + if ( minFader < -35.0f ) + levelOffset += -35.0f - minFader; + + // adjust all levels + for ( int i = 0; i < MAX_NUM_CHANNELS; ++i ) + { + // only apply to visible faders (and not to my own channel fader) + if ( vecpChanFader[i]->IsVisible() && ( i != iMyChannelID ) ) + { + // map averaged meter output level to decibels + // (invert CStereoSignalLevelMeter::CalcLogResultForMeter) + float leveldB = vecAvgLevels[i] * + ( UPPER_BOUND_SIG_METER - LOW_BOUND_SIG_METER ) / + NUM_STEPS_LED_BAR + LOW_BOUND_SIG_METER; + + int group = vecpChanFader[i]->GetGroupID(); + if ( group == INVALID_INDEX ) + group = 4; + + // do not adjust channels with almost zero level to full level since // the channel might simply be silent at the moment - if ( leveldB > AUTO_FADER_NOISE_THRESHOLD_DB ) + if ( leveldB >= AUTO_FADER_NOISE_THRESHOLD_DB ) { // compute new level - float newdBLevel = -leveldB + AUTO_FADER_TARGET_LEVEL_DB; + float newdBLevel = -leveldB + vecTargetChannelLevel[group] + + levelOffset; // map range from decibels to fader level // (this inverts MathUtils::CalcFaderGain) - float newFaderLevel = (newdBLevel + 35.0f) / 35.0f * + float newFaderLevel = ( newdBLevel + 35.0f ) / 35.0f * AUD_MIX_FADER_MAX; + // limit fader + newFaderLevel = fmin ( fmax ( newFaderLevel, 0.0f), + float ( AUD_MIX_FADER_MAX ) ); + // set fader level - vecpChanFader[i]->SetFaderLevel ( newFaderLevel, true ); + vecpChanFader[i]->SetFaderLevel ( newFaderLevel, false ); } } } From c42db6c46cc5bf31506d7bb17bf8c357c0890120 Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Fri, 26 Feb 2021 08:09:00 +0100 Subject: [PATCH 06/14] Fixed bug regarding misleading "bIsGroupUpdate" flag --- src/audiomixerboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index 85218afdcb..ced0c52b31 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -1435,7 +1435,7 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() float ( AUD_MIX_FADER_MAX ) ); // set fader level - vecpChanFader[i]->SetFaderLevel ( newFaderLevel, false ); + vecpChanFader[i]->SetFaderLevel ( newFaderLevel, true ); } } } From c2e826f8dfd622a807128785981e283c18ca2f41 Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Fri, 26 Feb 2021 19:06:22 +0100 Subject: [PATCH 07/14] Fix initialization of average level buffer --- src/audiomixerboard.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index ced0c52b31..112804a158 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -857,7 +857,7 @@ CAudioMixerBoard::CAudioMixerBoard ( QWidget* parent ) : // create all mixer controls and make them invisible vecpChanFader.Init ( MAX_NUM_CHANNELS ); - vecAvgLevels.Init ( MAX_NUM_CHANNELS ); + vecAvgLevels.Init ( MAX_NUM_CHANNELS, 0.0f ); for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) { @@ -1147,6 +1147,7 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector& vecChanInf { // the fader was not in use, reset everything for new client vecpChanFader[i]->Reset(); + vecAvgLevels[i] = 0.0f; // check if this is my own fader and set fader property if ( i == iMyChannelID ) From 9c71284da021f47dc75b9cae9c4635449b278fa2 Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Fri, 26 Feb 2021 19:28:28 +0100 Subject: [PATCH 08/14] Replace fader range with named constant --- src/audiomixerboard.cpp | 8 ++++---- src/global.h | 3 +++ src/util.h | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index 112804a158..d275fb2516 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -1399,8 +1399,8 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() // very weak channels would actually require strong channels to be // attenuated to a large amount; however, the attenuation is limited by // the faders - if ( minFader < -35.0f ) - levelOffset += -35.0f - minFader; + if ( minFader < -AUD_MIX_FADER_RANGE_DB ) + levelOffset += -AUD_MIX_FADER_RANGE_DB - minFader; // adjust all levels for ( int i = 0; i < MAX_NUM_CHANNELS; ++i ) @@ -1428,8 +1428,8 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() // map range from decibels to fader level // (this inverts MathUtils::CalcFaderGain) - float newFaderLevel = ( newdBLevel + 35.0f ) / 35.0f * - AUD_MIX_FADER_MAX; + float newFaderLevel = ( newdBLevel / AUD_MIX_FADER_RANGE_DB + + 1.0f ) * AUD_MIX_FADER_MAX; // limit fader newFaderLevel = fmin ( fmax ( newFaderLevel, 0.0f), diff --git a/src/global.h b/src/global.h index 769d128468..28ff6444b6 100755 --- a/src/global.h +++ b/src/global.h @@ -152,6 +152,9 @@ LED bar: lbr #define AUD_MIX_FADER_MAX 100 #define AUD_MIX_PAN_MAX 100 +// range of audio mixer fader +#define AUD_MIX_FADER_RANGE_DB 35.0f + // coefficient for averaging channel levels for automatic fader adjustment #define AUTO_FADER_ADJUST_ALPHA 0.2f diff --git a/src/util.h b/src/util.h index fc7076c871..70a05b7e39 100755 --- a/src/util.h +++ b/src/util.h @@ -1281,7 +1281,8 @@ class MathUtils } else { - return powf ( 10.0f, ( fInValueRange0_1 * 35.0f - 35.0f ) / 20.0f ); + return powf ( 10.0f, ( fInValueRange0_1 - 1.0f ) * + AUD_MIX_FADER_RANGE_DB / 20.0f ); } } }; From 0a0e9c2eb9c02e685aab0a7286d872d50e6d548e Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Sat, 27 Feb 2021 13:37:43 +0100 Subject: [PATCH 09/14] Minor code style correction --- src/audiomixerboard.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index d275fb2516..4610307c92 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -1360,7 +1360,9 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() // only my channel is active, nothing to do if ( cntActiveGroups == 0 ) + { return; + } // compute target level for each group // (prevent clipping when each group contributes at maximum level) From d0a867817e56eb1fab1efaf73987f65e2b183aae Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Wed, 3 Mar 2021 21:24:19 +0100 Subject: [PATCH 10/14] Revised adjustment strategy for weak channels. Do not adjust channels without group in group mode. --- src/audiomixerboard.cpp | 44 +++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index 4610307c92..5370e0db04 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -1316,15 +1316,15 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() QMutexLocker locker ( &Mutex ); // initialize variables used for statistics - float vecMinLevel[MAX_NUM_FADER_GROUPS + 1]; float vecMaxLevel[MAX_NUM_FADER_GROUPS + 1]; int vecChannelsPerGroup[MAX_NUM_FADER_GROUPS + 1]; for ( int i = 0; i < MAX_NUM_FADER_GROUPS + 1; ++i ) { - vecMinLevel[i] = UPPER_BOUND_SIG_METER; vecMaxLevel[i] = LOW_BOUND_SIG_METER; vecChannelsPerGroup[i] = 0; } + CVector> levels; + levels.resize ( MAX_NUM_FADER_GROUPS + 1 ); // compute min/max level per group and number of channels per group for ( int i = 0; i < MAX_NUM_CHANNELS; ++i ) @@ -1344,29 +1344,37 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() if ( leveldB >= AUTO_FADER_NOISE_THRESHOLD_DB ) { - vecMinLevel[group] = fmin ( vecMinLevel[group], leveldB ); vecMaxLevel[group] = fmax ( vecMaxLevel[group], leveldB ); + levels[group].Add ( leveldB ); } ++vecChannelsPerGroup[group]; } } + // sort levels for later median computation + for ( int i = 0; i < MAX_NUM_FADER_GROUPS + 1; ++i ) + { + std::sort ( levels[i].begin(), levels[i].end() ); + } + // compute the number of active groups (at least one channel) int cntActiveGroups = 0; - for ( int i = 0; i < MAX_NUM_FADER_GROUPS + 1; ++i ) + for ( int i = 0; i < MAX_NUM_FADER_GROUPS; ++i ) { cntActiveGroups += vecChannelsPerGroup[i] > 0; } // only my channel is active, nothing to do - if ( cntActiveGroups == 0 ) + if ( cntActiveGroups == 0 && + vecChannelsPerGroup[MAX_NUM_FADER_GROUPS] == 0 ) { return; } // compute target level for each group // (prevent clipping when each group contributes at maximum level) - float targetLevelPerGroup = -20.0f * log10 ( cntActiveGroups ); + float targetLevelPerGroup = -20.0f * log10 ( + std::max ( cntActiveGroups, 1 ) ); // compute target levels for the channels of each group individually float vecTargetChannelLevel[MAX_NUM_FADER_GROUPS + 1]; @@ -1381,15 +1389,21 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() targetLevelPerGroup - 20.0f * log10 ( vecChannelsPerGroup[i] ) : 0.0f; + // get median level + int cntChannels = levels[i].Size(); + if ( cntChannels == 0 ) + continue; + float refLevel = levels[i][cntChannels / 2]; + // since we can only attenuate channels but not amplify, we have to - // check that the weakest (min) channel can be brought to the target + // check that the reference channel can be brought to the target // level - if ( vecTargetChannelLevel[i] > vecMinLevel[i] ) + if ( refLevel < vecTargetChannelLevel[i] ) { // otherwise, we adjust the level offset in such a way that // the level can be reached levelOffset = fmin ( levelOffset, - vecMinLevel[i] - vecTargetChannelLevel[i] ); + refLevel - vecTargetChannelLevel[i] ); // compute the minimum necessary fader setting minFader = fmin ( minFader, -vecMaxLevel[i] + @@ -1418,7 +1432,17 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() int group = vecpChanFader[i]->GetGroupID(); if ( group == INVALID_INDEX ) - group = 4; + { + if ( cntActiveGroups > 0 ) + { + // do not adjust the channels without group in group mode + continue; + } + else + { + group = 4; + } + } // do not adjust channels with almost zero level to full level since // the channel might simply be silent at the moment From fe747d3527a0e3028571c3663011a766e3a2a6ae Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Thu, 4 Mar 2021 08:15:22 +0100 Subject: [PATCH 11/14] Fixed code style --- src/audiomixerboard.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index 5370e0db04..116699cdbb 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -1340,7 +1340,9 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() int group = vecpChanFader[i]->GetGroupID(); if ( group == INVALID_INDEX ) - group = 4; + { + group = MAX_NUM_FADER_GROUPS; + } if ( leveldB >= AUTO_FADER_NOISE_THRESHOLD_DB ) { @@ -1392,7 +1394,9 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() // get median level int cntChannels = levels[i].Size(); if ( cntChannels == 0 ) + { continue; + } float refLevel = levels[i][cntChannels / 2]; // since we can only attenuate channels but not amplify, we have to @@ -1440,7 +1444,7 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() } else { - group = 4; + group = MAX_NUM_FADER_GROUPS; } } From c0712349d7aac0dd2eb43fb7a69babe7f54b5a52 Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Thu, 18 Mar 2021 19:22:25 +0100 Subject: [PATCH 12/14] Fixed coding style --- src/audiomixerboard.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index 116699cdbb..531228c49d 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -1420,7 +1420,9 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels() // attenuated to a large amount; however, the attenuation is limited by // the faders if ( minFader < -AUD_MIX_FADER_RANGE_DB ) + { levelOffset += -AUD_MIX_FADER_RANGE_DB - minFader; + } // adjust all levels for ( int i = 0; i < MAX_NUM_CHANNELS; ++i ) From 98b6b0be141f48dff8bd69b963c1e8029ad2a39c Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Sat, 20 Mar 2021 23:10:43 +0100 Subject: [PATCH 13/14] Added JohannesBrx to contributors --- src/util.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util.cpp b/src/util.cpp index 0202de2a25..fd922cf285 100755 --- a/src/util.cpp +++ b/src/util.cpp @@ -485,6 +485,7 @@ CAboutDlg::CAboutDlg ( QWidget* parent ) : CBaseDlg ( parent ) "

David Kastrup (dakhubgit)

" "

Jordan Lum (mulyaj)

" "

Noam Postavsky (npostavs)

" + "

Johannes Brauers (JohannesBrx)

" "
" + tr ( "For details on the contributions check out the " ) + "" + tr ( "Github Contributors list" ) + "." ); From 45174e3af4956d643e9de11c223602b07fbe836a Mon Sep 17 00:00:00 2001 From: JohannesBrx <8805876+JohannesBrx@users.noreply.github.com> Date: Sat, 20 Mar 2021 23:57:44 +0100 Subject: [PATCH 14/14] Added channel fader adjustment in changelog --- ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a36e6e6da2..557d4e4ef0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,8 @@ ### 3.7.0dev <- NOTE: the release version number will be 3.7.1 ### - +- Automatic channel fader adjustment simplifies mixer setup by using the channel level meters (#1071). + (contributed by @JohannesBrx) ### 3.7.0 (2021-03-17) ###