2013-03-06 02:40:17 -08:00
|
|
|
/********************************************************************************
|
|
|
|
Copyright (C) 2013 Lucas Murray <lmurray@undefinedfire.com>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
********************************************************************************/
|
|
|
|
|
|
|
|
#include "NoiseGate.h"
|
2013-03-10 01:54:54 -08:00
|
|
|
#include "resource.h"
|
2013-03-06 02:40:17 -08:00
|
|
|
|
2013-03-14 07:48:19 -07:00
|
|
|
//============================================================================
|
|
|
|
// Helpers
|
|
|
|
|
|
|
|
inline float rmsToDb(float rms)
|
|
|
|
{
|
|
|
|
float db = 20.0f * log10(rms);
|
|
|
|
if(!_finite(db))
|
|
|
|
return VOL_MIN;
|
|
|
|
return db;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline float dbToRms(float db)
|
|
|
|
{
|
|
|
|
return pow(10.0f, db / 20.0f);
|
|
|
|
}
|
|
|
|
|
2013-03-06 02:40:17 -08:00
|
|
|
//============================================================================
|
|
|
|
// NoiseGateFilter class
|
|
|
|
|
|
|
|
NoiseGateFilter::NoiseGateFilter(NoiseGate *parent)
|
2013-03-09 22:39:02 -08:00
|
|
|
: parent(parent)
|
|
|
|
, attenuation(0.0f)
|
|
|
|
, level(0.0f)
|
|
|
|
, heldTime(0.0f)
|
|
|
|
, isOpen(false)
|
2013-03-06 02:40:17 -08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NoiseGateFilter::~NoiseGateFilter()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
AudioSegment *NoiseGateFilter::Process(AudioSegment *segment)
|
|
|
|
{
|
2013-03-15 06:15:30 -07:00
|
|
|
if(parent->isEnabled)
|
|
|
|
{
|
|
|
|
ApplyNoiseGate(segment->audioData.Array(), segment->audioData.Num());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Reset state
|
|
|
|
attenuation = 0.0f;
|
|
|
|
level = 0.0f;
|
|
|
|
heldTime = 0.0f;
|
|
|
|
isOpen = false;
|
|
|
|
}
|
2013-03-06 02:40:17 -08:00
|
|
|
return segment;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NoiseGateFilter::ApplyNoiseGate(float *buffer, int totalFloats)
|
|
|
|
{
|
|
|
|
// We assume stereo input
|
|
|
|
if(totalFloats % 2)
|
|
|
|
return; // Odd number of samples
|
|
|
|
|
|
|
|
// OBS is currently hard-coded to 44.1ksps
|
|
|
|
const float SAMPLE_RATE_F = 44100.0f;
|
|
|
|
const float dtPerSample = 1.0f / SAMPLE_RATE_F;
|
|
|
|
|
|
|
|
// Convert configuration times into per-sample amounts
|
2013-03-09 22:39:02 -08:00
|
|
|
const float attackRate = 1.0f / (parent->attackTime * SAMPLE_RATE_F);
|
|
|
|
const float releaseRate = 1.0f / (parent->releaseTime * SAMPLE_RATE_F);
|
2013-03-06 02:40:17 -08:00
|
|
|
|
|
|
|
// Determine level decay rate. We don't want human voice (75-300Hz) to cross the close
|
|
|
|
// threshold if the previous peak crosses the open threshold. 75Hz at 44.1ksps is ~590
|
|
|
|
// samples between peaks.
|
2013-03-09 22:39:02 -08:00
|
|
|
const float thresholdDiff = parent->openThreshold - parent->closeThreshold;
|
2013-03-06 02:40:17 -08:00
|
|
|
const float minDecayPeriod = (1.0f / 75.0f) * SAMPLE_RATE_F; // ~590 samples
|
|
|
|
const float decayRate = thresholdDiff / minDecayPeriod;
|
|
|
|
|
|
|
|
// We can't use SSE as the processing of each sample depends on the processed
|
|
|
|
// result of the previous sample.
|
|
|
|
for(int i = 0; i < totalFloats; i += 2)
|
|
|
|
{
|
|
|
|
// Get current input level
|
|
|
|
float curLvl = abs(buffer[i] + buffer[i+1]) * 0.5f;
|
|
|
|
|
|
|
|
// Test thresholds
|
2013-03-09 22:39:02 -08:00
|
|
|
if(curLvl > parent->openThreshold && !isOpen)
|
|
|
|
isOpen = true;
|
|
|
|
if(level < parent->closeThreshold && isOpen)
|
2013-03-06 02:40:17 -08:00
|
|
|
{
|
2013-03-09 22:39:02 -08:00
|
|
|
heldTime = 0.0f;
|
|
|
|
isOpen = false;
|
2013-03-06 02:40:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Decay level slowly so human voice (75-300Hz) doesn't cross the close threshold
|
|
|
|
// (Essentially a peak detector with very fast decay)
|
2013-03-09 22:39:02 -08:00
|
|
|
level = max(level, curLvl) - decayRate;
|
2013-03-06 02:40:17 -08:00
|
|
|
|
|
|
|
// Apply gate state to attenuation
|
2013-03-09 22:39:02 -08:00
|
|
|
if(isOpen)
|
|
|
|
attenuation = min(1.0f, attenuation + attackRate);
|
2013-03-06 02:40:17 -08:00
|
|
|
else
|
|
|
|
{
|
2013-03-09 22:39:02 -08:00
|
|
|
heldTime += dtPerSample;
|
|
|
|
if(heldTime > parent->holdTime)
|
|
|
|
attenuation = max(0.0f, attenuation - releaseRate);
|
2013-03-06 02:40:17 -08:00
|
|
|
}
|
|
|
|
|
2013-03-15 06:15:30 -07:00
|
|
|
// Test if disabled from the config window here so that the above state calculations
|
|
|
|
// are still processed when playing around with the configuration
|
|
|
|
if(!parent->isDisabledFromConfig) {
|
|
|
|
// Multiple input by gate multiplier (0.0f if fully closed, 1.0f if fully open)
|
2013-03-14 07:07:23 -07:00
|
|
|
buffer[i] *= attenuation;
|
|
|
|
buffer[i+1] *= attenuation;
|
|
|
|
}
|
2013-03-06 02:40:17 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-10 01:54:54 -08:00
|
|
|
//============================================================================
|
|
|
|
// NoiseGateConfigWindow class
|
|
|
|
|
|
|
|
NoiseGateConfigWindow::NoiseGateConfigWindow(NoiseGate *parent, HWND parentHwnd)
|
|
|
|
: parent(parent)
|
|
|
|
, parentHwnd(parentHwnd)
|
|
|
|
, hwnd(NULL)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NoiseGateConfigWindow::~NoiseGateConfigWindow()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
INT_PTR CALLBACK NoiseGateConfigWindow::DialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
// Get the pointer to our class instance
|
|
|
|
NoiseGateConfigWindow *window = (NoiseGateConfigWindow *)GetWindowLongPtr(hwnd, DWLP_USER);
|
|
|
|
|
|
|
|
switch(message)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
// Unhandled
|
|
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)lParam);
|
|
|
|
window = (NoiseGateConfigWindow *)lParam;
|
|
|
|
window->hwnd = hwnd;
|
|
|
|
window->MsgInitDialog();
|
|
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
|
|
if(window != NULL)
|
2013-03-14 07:07:23 -07:00
|
|
|
return window->MsgClicked(LOWORD(wParam), (HWND)lParam);
|
|
|
|
break;
|
|
|
|
case WM_VSCROLL:
|
|
|
|
case WM_HSCROLL:
|
|
|
|
if(window != NULL)
|
|
|
|
return window->MsgScroll(message == WM_VSCROLL, wParam, lParam);
|
|
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
|
|
if(window != NULL)
|
|
|
|
return window->MsgTimer((int)wParam);
|
2013-03-10 01:54:54 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Display the dialog and begin its message loop. Returns \t{true} if the
|
|
|
|
* user clicked the "OK" button.
|
|
|
|
*/
|
|
|
|
bool NoiseGateConfigWindow::Process()
|
|
|
|
{
|
|
|
|
INT_PTR res = DialogBoxParam(parent->hinstDLL, MAKEINTRESOURCE(IDD_CONFIGURENOISEGATE), parentHwnd, (DLGPROC)DialogProc, (LPARAM)this);
|
|
|
|
if(res == IDOK)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-03-14 07:07:23 -07:00
|
|
|
/**
|
|
|
|
* Sets the caption of the open and close threshold trackbars ("-24 dB")
|
|
|
|
*/
|
|
|
|
void NoiseGateConfigWindow::SetTrackbarCaption(int controlId, int db)
|
|
|
|
{
|
|
|
|
SetWindowText(GetDlgItem(hwnd, controlId), FormattedString(TEXT("%d dB"), db));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the current audio volume control.
|
|
|
|
*/
|
|
|
|
void NoiseGateConfigWindow::RepaintVolume()
|
|
|
|
{
|
|
|
|
float rms, max, peak;
|
2013-03-14 07:48:19 -07:00
|
|
|
|
|
|
|
rms = max = peak = -96.0f;
|
|
|
|
if(OBSGetStreaming())
|
|
|
|
OBSGetCurMicVolumeStats(&rms, &max, &peak);
|
2013-03-15 06:15:30 -07:00
|
|
|
//SetWindowText(GetDlgItem(hwnd, IDC_OPENTHRES_DB), FormattedString(TEXT("%.3f"), max));
|
|
|
|
//SetWindowText(GetDlgItem(hwnd, IDC_CLOSETHRES_DB), FormattedString(TEXT("%d"), (int)((max + 96.0f) * 4.0f)));
|
|
|
|
SendMessage(GetDlgItem(hwnd, IDC_CURVOL), PBM_SETPOS, (int)((max + 96.0f) * 4.0f), 0);
|
2013-03-14 07:07:23 -07:00
|
|
|
}
|
|
|
|
|
2013-03-15 06:15:30 -07:00
|
|
|
/**
|
|
|
|
* Reload the configuration settings from the main object. Useful for resetting to defaults.
|
|
|
|
*/
|
|
|
|
void NoiseGateConfigWindow::RefreshConfig()
|
2013-03-10 01:54:54 -08:00
|
|
|
{
|
2013-03-14 07:48:19 -07:00
|
|
|
float val;
|
2013-03-14 07:07:23 -07:00
|
|
|
HWND ctrlHwnd;
|
|
|
|
|
2013-03-15 06:15:30 -07:00
|
|
|
// Gate enabled
|
|
|
|
SendMessage(GetDlgItem(hwnd, IDC_ENABLEGATE), BM_SETCHECK, parent->isEnabled ? BST_CHECKED : BST_UNCHECKED, 0);
|
2013-03-14 07:07:23 -07:00
|
|
|
|
2013-03-15 06:15:30 -07:00
|
|
|
// Attack, hold and release times
|
|
|
|
SetWindowText(GetDlgItem(hwnd, IDC_ATTACKTIME_EDIT), IntString((int)(parent->attackTime * 1000.0f)));
|
|
|
|
SetWindowText(GetDlgItem(hwnd, IDC_HOLDTIME_EDIT), IntString((int)(parent->holdTime * 1000.0f)));
|
|
|
|
SetWindowText(GetDlgItem(hwnd, IDC_RELEASETIME_EDIT), IntString((int)(parent->releaseTime * 1000.0f)));
|
2013-03-14 07:07:23 -07:00
|
|
|
|
|
|
|
// Close threshold trackbar (Control uses positive values)
|
2013-03-14 07:48:19 -07:00
|
|
|
val = rmsToDb(parent->closeThreshold);
|
|
|
|
SetTrackbarCaption(IDC_CLOSETHRES_DB, (int)val);
|
2013-03-14 07:07:23 -07:00
|
|
|
ctrlHwnd = GetDlgItem(hwnd, IDC_CLOSETHRES_SLIDER);
|
|
|
|
SendMessage(ctrlHwnd, TBM_SETRANGEMIN, FALSE, 0);
|
|
|
|
SendMessage(ctrlHwnd, TBM_SETRANGEMAX, FALSE, 96);
|
2013-03-14 07:48:19 -07:00
|
|
|
SendMessage(ctrlHwnd, TBM_SETPOS, TRUE, -(int)val);
|
2013-03-14 07:07:23 -07:00
|
|
|
|
|
|
|
// Open threshold trackbar (Control uses positive values)
|
2013-03-14 07:48:19 -07:00
|
|
|
val = rmsToDb(parent->openThreshold);
|
|
|
|
SetTrackbarCaption(IDC_OPENTHRES_DB, (int)val);
|
2013-03-14 07:07:23 -07:00
|
|
|
ctrlHwnd = GetDlgItem(hwnd, IDC_OPENTHRES_SLIDER);
|
|
|
|
SendMessage(ctrlHwnd, TBM_SETRANGEMIN, FALSE, 0);
|
|
|
|
SendMessage(ctrlHwnd, TBM_SETRANGEMAX, FALSE, 96);
|
2013-03-14 07:48:19 -07:00
|
|
|
SendMessage(ctrlHwnd, TBM_SETPOS, TRUE, -(int)val);
|
2013-03-15 06:15:30 -07:00
|
|
|
}
|
2013-03-14 07:48:19 -07:00
|
|
|
|
2013-03-15 06:15:30 -07:00
|
|
|
void NoiseGateConfigWindow::MsgInitDialog()
|
|
|
|
{
|
|
|
|
HWND ctrlHwnd;
|
|
|
|
|
|
|
|
LocalizeWindow(hwnd);
|
|
|
|
|
|
|
|
// Load settings from parent object
|
|
|
|
RefreshConfig();
|
|
|
|
|
|
|
|
// Volume preview
|
|
|
|
// FIXME: Don't use a progress bar as the default Windows style smoothly interpolates between
|
|
|
|
// values making if difficult to see the real sound level.
|
|
|
|
ctrlHwnd = GetDlgItem(hwnd, IDC_CURVOL);
|
|
|
|
SendMessage(ctrlHwnd, PBM_SETRANGE32, 0, CURVOL_RESOLUTION); // Bottom = 0, top = CURVOL_RESOLUTION
|
|
|
|
RepaintVolume(); // Repaint immediately
|
|
|
|
SetTimer(hwnd, REPAINT_TIMER_ID, 16, NULL); // Repaint every 16ms (~60fps)
|
2013-03-14 07:07:23 -07:00
|
|
|
|
|
|
|
// Enable/disable stream button
|
|
|
|
ctrlHwnd = GetDlgItem(hwnd, IDC_PREVIEWON);
|
|
|
|
if(OBSGetStreaming())
|
|
|
|
{
|
|
|
|
SetWindowText(ctrlHwnd, Str("Plugins.NoiseGate.DisablePreview"));
|
2013-03-14 07:48:19 -07:00
|
|
|
|
|
|
|
// If not in preview mode then prevent the user from stopping the stream from this window
|
|
|
|
if(OBSGetPreviewOnly())
|
|
|
|
EnableWindow(ctrlHwnd, TRUE);
|
|
|
|
else
|
|
|
|
EnableWindow(ctrlHwnd, FALSE);
|
2013-03-14 07:07:23 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetWindowText(ctrlHwnd, Str("Plugins.NoiseGate.EnablePreview"));
|
|
|
|
EnableWindow(ctrlHwnd, TRUE);
|
|
|
|
}
|
2013-03-10 01:54:54 -08:00
|
|
|
}
|
|
|
|
|
2013-03-14 07:07:23 -07:00
|
|
|
INT_PTR NoiseGateConfigWindow::MsgClicked(int controlId, HWND controlHwnd)
|
2013-03-10 01:54:54 -08:00
|
|
|
{
|
2013-03-14 07:07:23 -07:00
|
|
|
switch(controlId)
|
2013-03-10 01:54:54 -08:00
|
|
|
{
|
2013-03-14 07:07:23 -07:00
|
|
|
default:
|
|
|
|
// Unknown button
|
|
|
|
break;
|
2013-03-15 06:15:30 -07:00
|
|
|
case IDOK: {
|
|
|
|
String str;
|
|
|
|
int val;
|
|
|
|
HWND ctrlHwnd;
|
|
|
|
|
|
|
|
// Gate enabled
|
|
|
|
if(SendMessage(GetDlgItem(hwnd, IDC_ENABLEGATE), BM_GETCHECK, 0, 0) == BST_CHECKED)
|
|
|
|
parent->isEnabled = true;
|
|
|
|
else
|
|
|
|
parent->isEnabled = false;
|
|
|
|
|
|
|
|
// Attack time
|
|
|
|
ctrlHwnd = GetDlgItem(hwnd, IDC_ATTACKTIME_EDIT);
|
|
|
|
str.SetLength(GetWindowTextLength(ctrlHwnd));
|
|
|
|
GetWindowText(ctrlHwnd, str, str.Length() + 1);
|
|
|
|
parent->attackTime = (float)str.ToInt() * 0.001f;
|
|
|
|
|
|
|
|
// Hold time
|
|
|
|
ctrlHwnd = GetDlgItem(hwnd, IDC_HOLDTIME_EDIT);
|
|
|
|
str.SetLength(GetWindowTextLength(ctrlHwnd));
|
|
|
|
GetWindowText(ctrlHwnd, str, str.Length() + 1);
|
|
|
|
parent->holdTime = (float)str.ToInt() * 0.001f;
|
|
|
|
|
|
|
|
// Release time
|
|
|
|
ctrlHwnd = GetDlgItem(hwnd, IDC_RELEASETIME_EDIT);
|
|
|
|
str.SetLength(GetWindowTextLength(ctrlHwnd));
|
|
|
|
GetWindowText(ctrlHwnd, str, str.Length() + 1);
|
|
|
|
parent->releaseTime = (float)str.ToInt() * 0.001f;
|
|
|
|
|
|
|
|
// Close threshold
|
|
|
|
val = (int)SendMessage(GetDlgItem(hwnd, IDC_CLOSETHRES_SLIDER), TBM_GETPOS, 0, 0);
|
|
|
|
parent->closeThreshold = dbToRms((float)(-val));
|
|
|
|
|
|
|
|
// Open threshold
|
|
|
|
val = (int)SendMessage(GetDlgItem(hwnd, IDC_OPENTHRES_SLIDER), TBM_GETPOS, 0, 0);
|
|
|
|
parent->openThreshold = dbToRms((float)(-val));
|
|
|
|
|
|
|
|
// Return IDOK (1)
|
|
|
|
EndDialog(hwnd, controlId);
|
|
|
|
return TRUE; }
|
2013-03-10 01:54:54 -08:00
|
|
|
case IDCANCEL:
|
2013-03-15 06:15:30 -07:00
|
|
|
EndDialog(hwnd, controlId); // Return IDCANCEL (2)
|
2013-03-10 01:54:54 -08:00
|
|
|
return TRUE;
|
2013-03-14 07:07:23 -07:00
|
|
|
case IDC_PREVIEWON:
|
|
|
|
// Toggle stream preview
|
|
|
|
if(OBSGetStreaming())
|
|
|
|
{
|
|
|
|
OBSStartStopPreview();
|
2013-03-15 06:15:30 -07:00
|
|
|
parent->isDisabledFromConfig = false;
|
2013-03-14 07:07:23 -07:00
|
|
|
SetWindowText(controlHwnd, Str("Plugins.NoiseGate.EnablePreview"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OBSStartStopPreview();
|
2013-03-15 06:15:30 -07:00
|
|
|
parent->isDisabledFromConfig = true;
|
2013-03-14 07:07:23 -07:00
|
|
|
SetWindowText(controlHwnd, Str("Plugins.NoiseGate.DisablePreview"));
|
|
|
|
}
|
|
|
|
return TRUE;
|
2013-03-15 06:15:30 -07:00
|
|
|
case IDC_RESETTODEFAULTS:
|
|
|
|
parent->LoadDefaults();
|
|
|
|
RefreshConfig();
|
|
|
|
return TRUE;
|
2013-03-14 07:07:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
INT_PTR NoiseGateConfigWindow::MsgScroll(bool vertical, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
if(lParam == NULL)
|
|
|
|
return FALSE;
|
|
|
|
HWND barHwnd = (HWND)lParam;
|
|
|
|
|
|
|
|
// Determine the current value of the trackbar
|
|
|
|
int pos;
|
|
|
|
switch(LOWORD(wParam))
|
|
|
|
{
|
|
|
|
case SB_THUMBPOSITION:
|
|
|
|
case SB_THUMBTRACK: // The user dragged the slider
|
|
|
|
pos = -HIWORD(wParam);
|
|
|
|
break;
|
|
|
|
default: // Everything else
|
|
|
|
pos = -(int)SendMessage(barHwnd, TBM_GETPOS, 0, 0);
|
|
|
|
break;
|
2013-03-10 01:54:54 -08:00
|
|
|
}
|
|
|
|
|
2013-03-14 07:07:23 -07:00
|
|
|
// Figure out which trackbar it was
|
|
|
|
if(barHwnd == GetDlgItem(hwnd, IDC_CLOSETHRES_SLIDER))
|
|
|
|
{
|
|
|
|
// User modified the close threshold trackbar
|
|
|
|
SetTrackbarCaption(IDC_CLOSETHRES_DB, pos);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else if(barHwnd == GetDlgItem(hwnd, IDC_OPENTHRES_SLIDER))
|
|
|
|
{
|
|
|
|
// User modified the open threshold trackbar
|
|
|
|
SetTrackbarCaption(IDC_OPENTHRES_DB, pos);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
INT_PTR NoiseGateConfigWindow::MsgTimer(int timerId)
|
|
|
|
{
|
|
|
|
if(timerId == REPAINT_TIMER_ID)
|
|
|
|
{
|
|
|
|
RepaintVolume();
|
|
|
|
return TRUE;
|
|
|
|
}
|
2013-03-10 01:54:54 -08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2013-03-06 02:40:17 -08:00
|
|
|
//============================================================================
|
|
|
|
// NoiseGate class
|
|
|
|
|
|
|
|
// Statics
|
2013-03-09 22:45:18 -08:00
|
|
|
HINSTANCE NoiseGate::hinstDLL = NULL;
|
|
|
|
NoiseGate *NoiseGate::instance = NULL;
|
2013-03-06 02:40:17 -08:00
|
|
|
|
|
|
|
NoiseGate::NoiseGate()
|
2013-03-09 22:39:02 -08:00
|
|
|
: micSource(NULL)
|
|
|
|
, filter(NULL)
|
2013-03-15 06:15:30 -07:00
|
|
|
, isDisabledFromConfig(false)
|
|
|
|
//, isEnabled() // Initialized in LoadDefaults()
|
|
|
|
//, openThreshold()
|
|
|
|
//, closeThreshold()
|
|
|
|
//, attackTime()
|
|
|
|
//, holdTime()
|
|
|
|
//, releaseTime()
|
2013-03-06 02:40:17 -08:00
|
|
|
{
|
2013-03-15 06:15:30 -07:00
|
|
|
LoadDefaults();
|
2013-03-06 02:40:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
NoiseGate::~NoiseGate()
|
|
|
|
{
|
|
|
|
// Delete our filter if it exists
|
|
|
|
StreamStopped();
|
|
|
|
}
|
|
|
|
|
2013-03-15 06:15:30 -07:00
|
|
|
void NoiseGate::LoadDefaults()
|
|
|
|
{
|
|
|
|
isEnabled = false;
|
|
|
|
openThreshold = dbToRms(-26.0f);
|
|
|
|
closeThreshold = dbToRms(-32.0f);
|
|
|
|
attackTime = 0.05f;
|
|
|
|
holdTime = 0.2f;
|
|
|
|
releaseTime = 0.2f;
|
|
|
|
}
|
|
|
|
|
2013-03-06 02:40:17 -08:00
|
|
|
void NoiseGate::StreamStarted()
|
|
|
|
{
|
2013-03-09 22:39:02 -08:00
|
|
|
micSource = OBSGetMicAudioSource();
|
|
|
|
if(micSource == NULL)
|
2013-03-06 02:40:17 -08:00
|
|
|
return; // No microphone
|
2013-03-09 22:39:02 -08:00
|
|
|
filter = new NoiseGateFilter(this);
|
|
|
|
micSource->AddAudioFilter(filter);
|
2013-03-06 02:40:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void NoiseGate::StreamStopped()
|
|
|
|
{
|
2013-03-09 22:39:02 -08:00
|
|
|
if(filter) {
|
|
|
|
micSource->RemoveAudioFilter(filter);
|
|
|
|
delete filter;
|
|
|
|
filter = NULL;
|
2013-03-06 02:40:17 -08:00
|
|
|
}
|
2013-03-09 22:39:02 -08:00
|
|
|
micSource = NULL;
|
2013-03-06 02:40:17 -08:00
|
|
|
}
|
|
|
|
|
2013-03-10 01:54:54 -08:00
|
|
|
void NoiseGate::ShowConfigDialog(HWND parentHwnd)
|
|
|
|
{
|
|
|
|
NoiseGateConfigWindow dialog(this, parentHwnd);
|
2013-03-14 07:07:23 -07:00
|
|
|
if(OBSGetStreaming())
|
2013-03-15 06:15:30 -07:00
|
|
|
isDisabledFromConfig = true; // Disable the filter if we are currently streaming
|
2013-03-10 01:54:54 -08:00
|
|
|
dialog.Process();
|
2013-03-15 06:15:30 -07:00
|
|
|
isDisabledFromConfig = false; // Force enable
|
2013-03-10 01:54:54 -08:00
|
|
|
}
|
|
|
|
|
2013-03-06 02:40:17 -08:00
|
|
|
//============================================================================
|
|
|
|
// Plugin entry points
|
|
|
|
|
|
|
|
bool LoadPlugin()
|
|
|
|
{
|
2013-03-09 22:45:18 -08:00
|
|
|
if(NoiseGate::instance != NULL)
|
2013-03-06 02:40:17 -08:00
|
|
|
return false;
|
2013-03-09 22:45:18 -08:00
|
|
|
NoiseGate::instance = new NoiseGate();
|
2013-03-06 02:40:17 -08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnloadPlugin()
|
|
|
|
{
|
2013-03-09 22:45:18 -08:00
|
|
|
if(NoiseGate::instance == NULL)
|
2013-03-06 02:40:17 -08:00
|
|
|
return;
|
2013-03-09 22:45:18 -08:00
|
|
|
delete NoiseGate::instance;
|
|
|
|
NoiseGate::instance = NULL;
|
2013-03-06 02:40:17 -08:00
|
|
|
}
|
|
|
|
|
2013-03-10 01:54:54 -08:00
|
|
|
void ConfigPlugin(HWND parentHwnd)
|
|
|
|
{
|
|
|
|
if(NoiseGate::instance == NULL)
|
|
|
|
return;
|
|
|
|
NoiseGate::instance->ShowConfigDialog(parentHwnd);
|
|
|
|
}
|
|
|
|
|
2013-03-06 02:40:17 -08:00
|
|
|
void OnStartStream()
|
|
|
|
{
|
2013-03-09 22:45:18 -08:00
|
|
|
if(NoiseGate::instance == NULL)
|
2013-03-06 02:40:17 -08:00
|
|
|
return;
|
2013-03-09 22:45:18 -08:00
|
|
|
NoiseGate::instance->StreamStarted();
|
2013-03-06 02:40:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void OnStopStream()
|
|
|
|
{
|
2013-03-09 22:45:18 -08:00
|
|
|
if(NoiseGate::instance == NULL)
|
2013-03-06 02:40:17 -08:00
|
|
|
return;
|
2013-03-09 22:45:18 -08:00
|
|
|
NoiseGate::instance->StreamStopped();
|
2013-03-06 02:40:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
CTSTR GetPluginName()
|
|
|
|
{
|
|
|
|
return Str("Plugins.NoiseGate.PluginName");
|
|
|
|
}
|
|
|
|
|
|
|
|
CTSTR GetPluginDescription()
|
|
|
|
{
|
|
|
|
return Str("Plugins.NoiseGate.PluginDescription");
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL CALLBACK DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|
|
|
{
|
|
|
|
if(fdwReason == DLL_PROCESS_ATTACH)
|
2013-03-09 22:45:18 -08:00
|
|
|
NoiseGate::hinstDLL = hinstDLL;
|
2013-03-06 02:40:17 -08:00
|
|
|
return TRUE;
|
|
|
|
}
|