From 73ba7064365dd86154b56f087deaa1482fa63da1 Mon Sep 17 00:00:00 2001 From: andon Date: Mon, 6 Feb 2017 07:48:18 -0500 Subject: [PATCH] Audio volume monitoring :) --- include/DLL_VERSION.H | 2 +- src/ImGui/control_panel.cpp | 144 ++++++++++++++++++++++++++++++++++++ version.ini | Bin 10096 -> 10274 bytes 3 files changed, 145 insertions(+), 1 deletion(-) diff --git a/include/DLL_VERSION.H b/include/DLL_VERSION.H index 7f95f18..8fa2790 100644 --- a/include/DLL_VERSION.H +++ b/include/DLL_VERSION.H @@ -4,7 +4,7 @@ #define TBF_MAJOR 0 #define TBF_MINOR 8 #define TBF_BUILD 0 -#define TBF_REV 1 +#define TBF_REV 2 diff --git a/src/ImGui/control_panel.cpp b/src/ImGui/control_panel.cpp index 0908dc6..44792f8 100644 --- a/src/ImGui/control_panel.cpp +++ b/src/ImGui/control_panel.cpp @@ -3,6 +3,8 @@ #define _CRT_SECURE_NO_WARNINGS +#define NOMINMAX + #include #include #define DIRECTINPUT_VERSION 0x0800 @@ -24,6 +26,51 @@ #include #include + +#include +#include +#include +#include +#include + +IAudioMeterInformation* +TBFix_GetAudioMeterInfo (void) +{ + CComPtr pDevEnum = nullptr; + + if (FAILED ((pDevEnum.CoCreateInstance (__uuidof (MMDeviceEnumerator))))) + return nullptr; + + // Most game audio a user will not want to hear while a game is in the + // background will pass through eConsole. + // + // eCommunication will be headset stuff and that's something a user is not + // going to appreciate having muted :) Consider overloading this function + // to allow independent control. + // + CComPtr pDevice; + if ( FAILED ( + pDevEnum->GetDefaultAudioEndpoint ( eRender, + eConsole, + &pDevice ) + ) + ) return nullptr; + + IAudioMeterInformation* pMeterInfo = nullptr; + + HRESULT hr = pDevice->Activate ( __uuidof (IAudioMeterInformation), + CLSCTX_ALL, + nullptr, + IID_PPV_ARGS_Helper (&pMeterInfo) ); + + if (SUCCEEDED (hr)) + return pMeterInfo; + + return nullptr; +} + + + __declspec (dllimport) bool SK_ImGui_ControlPanel (void); @@ -605,6 +652,99 @@ TBFix_DrawConfigUI (void) ImGui::TreePop ( ); } + if (ImGui::CollapsingHeader ("Audio Volume")) + { + IAudioMeterInformation* pMeterInfo = + TBFix_GetAudioMeterInfo (); + + if (pMeterInfo != nullptr) + { + UINT channels = 0; + + if (SUCCEEDED (pMeterInfo->GetMeteringChannelCount (&channels))) + { + static float channel_peaks_ [32]; + + struct + { + struct { + float inst_min = FLT_MAX; DWORD dwMinSample = 0; float disp_min = FLT_MAX; + float inst_max = FLT_MIN; DWORD dwMaxSample = 0; float disp_max = FLT_MIN; + } vu_peaks; + + float peaks [120]; + int current_idx; + } static history [32]; + + #define VUMETER_TIME 300 + + ImGui::Columns (2); + + for (int i = 0 ; i < channels; i++) + { + if (SUCCEEDED (pMeterInfo->GetChannelsPeakValues (channels, channel_peaks_))) + { + history [i].vu_peaks.inst_min = std::min (history [i].vu_peaks.inst_min, channel_peaks_ [i]); + history [i].vu_peaks.inst_max = std::max (history [i].vu_peaks.inst_max, channel_peaks_ [i]); + + if (history [i].vu_peaks.dwMinSample < timeGetTime () - VUMETER_TIME * 2) { + history [i].vu_peaks.disp_min = history [i].vu_peaks.inst_min; + history [i].vu_peaks.inst_min = channel_peaks_ [i]; + history [i].vu_peaks.dwMinSample = timeGetTime (); + } + + history [i].vu_peaks.disp_max = history [i].vu_peaks.inst_max; + + if (history [i].vu_peaks.dwMaxSample < timeGetTime () - VUMETER_TIME * 4) { + history [i].vu_peaks.inst_max = channel_peaks_ [i]; + history [i].vu_peaks.dwMaxSample = timeGetTime (); + } + + history [i].peaks [history [i].current_idx] = channel_peaks_ [i]; + history [i].current_idx = (history [i].current_idx + 1) % IM_ARRAYSIZE (history [i].peaks); + + ImGui::BeginGroup (); + + ImGui::PlotLines ( "", + history [i].peaks, + IM_ARRAYSIZE (history [i].peaks), + history [i].current_idx, + "", + history [i].vu_peaks.disp_min, + 1.0f, + ImVec2 (ImGui::GetContentRegionAvailWidth (), 80) ); + + //char szName [64]; + //sprintf (szName, "Channel: %lu", i); + + ImGui::PushStyleColor (ImGuiCol_PlotHistogram, ImVec4 (0.9f, 0.1f, 0.1f, 0.15f)); + ImGui::ProgressBar (history [i].vu_peaks.disp_max, ImVec2 (-1.0f, 0.0f)); + ImGui::PopStyleColor (); + + ImGui::ProgressBar (channel_peaks_ [i], ImVec2 (-1.0f, 0.0f)); + + ImGui::PushStyleColor (ImGuiCol_PlotHistogram, ImVec4 (0.1f, 0.1f, 0.9f, 0.15f)); + ImGui::ProgressBar (history [i].vu_peaks.disp_min, ImVec2 (-1.0f, 0.0f)); + ImGui::PopStyleColor (); + ImGui::EndGroup (); + + if (i % 2) { + ImGui::SameLine (); ImGui::NextColumn (); + } else { + ImGui::Columns ( 1 ); + ImGui::Separator ( ); + ImGui::Columns ( 2 ); + } + } + } + + ImGui::Columns (1); + } + + pMeterInfo->Release (); + } + } + #if 0 if (ImGui::CollapsingHeader ("Audio (DO NOT USE ON RETAIL VERSION OF GAME)", ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_DefaultOpen)) { @@ -780,3 +920,7 @@ TBFix_ImGui_Init (void) TBFix_ImGui_DrawFrame, (LPVOID *)&SK_ImGui_DrawFrame_Original ); } + + +#define ID_TIMER 1 +#define TIMER_PERIOD 125 \ No newline at end of file diff --git a/version.ini b/version.ini index 4267b30e0b79e0ae4b41db826a56286e8b4c2772..1b2650c7ea3c3f500d8bbe5513eeaff2f1ea14ba 100644 GIT binary patch delta 175 zcmez1wL+xfguE_vJyz^0-*wf6Hq*vArWW>NR=KMdlP~fZP7Yw=ntV&GVe=98HSz$= CiYM#< delta 41 zcmV+^0M`GaQ1DK$+yaqwERzTWQnL;L3IUU#2L_W!1Ui#g0wS}d1bhOs^am~=JZTN;