commit
fe6622c653
|
@ -46,11 +46,27 @@ struct obs_fader {
|
|||
bool ignore_next_signal;
|
||||
};
|
||||
|
||||
struct obs_volmeter {
|
||||
pthread_mutex_t mutex;
|
||||
signal_handler_t *signals;
|
||||
obs_fader_conversion_t pos_to_db;
|
||||
obs_fader_conversion_t db_to_pos;
|
||||
obs_source_t *source;
|
||||
enum obs_fader_type type;
|
||||
float cur_db;
|
||||
};
|
||||
|
||||
static const char *fader_signals[] = {
|
||||
"void volume_changed(ptr fader, float db)",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *volmeter_signals[] = {
|
||||
"void levels_updated(ptr volmeter, float level, "
|
||||
"float magnitude, float peak)",
|
||||
NULL
|
||||
};
|
||||
|
||||
static inline float mul_to_db(const float mul)
|
||||
{
|
||||
return (mul == 0.0f) ? -INFINITY : 20.0f * log10f(mul);
|
||||
|
@ -81,6 +97,94 @@ static float cubic_db_to_def(const float db)
|
|||
return cbrtf(db_to_mul(db));
|
||||
}
|
||||
|
||||
static float iec_def_to_db(const float def)
|
||||
{
|
||||
if (def == 1.0f)
|
||||
return 0.0f;
|
||||
else if (def <= 0.0f)
|
||||
return -INFINITY;
|
||||
|
||||
float db;
|
||||
|
||||
if (def >= 0.75f)
|
||||
db = (def - 1.0f) / 0.25f * 9.0f;
|
||||
else if (def >= 0.5f)
|
||||
db = (def - 0.75f) / 0.25f * 11.0f - 9.0f;
|
||||
else if (def >= 0.3f)
|
||||
db = (def - 0.5f) / 0.2f * 10.0f - 20.0f;
|
||||
else if (def >= 0.15f)
|
||||
db = (def - 0.3f) / 0.15f * 10.0f - 30.0f;
|
||||
else if (def >= 0.075f)
|
||||
db = (def - 0.15f) / 0.075f * 10.0f - 40.0f;
|
||||
else if (def >= 0.025f)
|
||||
db = (def - 0.075f) / 0.05f * 10.0f - 50.0f;
|
||||
else if (def >= 0.001f)
|
||||
db = (def - 0.025f) / 0.025f * 90.0f - 60.0f;
|
||||
else
|
||||
db = -INFINITY;
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
static float iec_db_to_def(const float db)
|
||||
{
|
||||
if (db == 0.0f)
|
||||
return 1.0f;
|
||||
else if (db == -INFINITY)
|
||||
return 0.0f;
|
||||
|
||||
float def;
|
||||
|
||||
if (db >= -9.0f)
|
||||
def = (db + 9.0f) / 9.0f * 0.25f + 0.75f;
|
||||
else if (db >= -20.0f)
|
||||
def = (db + 20.0f) / 11.0f * 0.25f + 0.5f;
|
||||
else if (db >= -30.0f)
|
||||
def = (db + 30.0f) / 10.0f * 0.2f + 0.3f;
|
||||
else if (db >= -40.0f)
|
||||
def = (db + 40.0f) / 10.0f * 0.15f + 0.15f;
|
||||
else if (db >= -50.0f)
|
||||
def = (db + 50.0f) / 10.0f * 0.075f + 0.075f;
|
||||
else if (db >= -60.0f)
|
||||
def = (db + 60.0f) / 10.0f * 0.05f + 0.025f;
|
||||
else if (db >= -114.0f)
|
||||
def = (db + 150.0f) / 90.0f * 0.025f;
|
||||
else
|
||||
def = 0.0f;
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
#define LOG_OFFSET_DB 6.0f
|
||||
#define LOG_RANGE_DB 96.0f
|
||||
/* equals -log10f(LOG_OFFSET_DB) */
|
||||
#define LOG_OFFSET_VAL -0.77815125038364363f
|
||||
/* equals -log10f(-LOG_RANGE_DB + LOG_OFFSET_DB) */
|
||||
#define LOG_RANGE_VAL -2.00860017176191756f
|
||||
|
||||
static float log_def_to_db(const float def)
|
||||
{
|
||||
if (def >= 1.0f)
|
||||
return 0.0f;
|
||||
else if (def <= 0.0f)
|
||||
return -INFINITY;
|
||||
|
||||
return -(LOG_RANGE_DB + LOG_OFFSET_DB) * powf(
|
||||
(LOG_RANGE_DB + LOG_OFFSET_DB) / LOG_OFFSET_DB, -def)
|
||||
+ LOG_OFFSET_DB;
|
||||
}
|
||||
|
||||
static float log_db_to_def(const float db)
|
||||
{
|
||||
if (db >= 0.0f)
|
||||
return 1.0f;
|
||||
else if (db <= -96.0f)
|
||||
return 0.0f;
|
||||
|
||||
return (-log10f(-db + LOG_OFFSET_DB) - LOG_RANGE_VAL)
|
||||
/ (LOG_OFFSET_VAL - LOG_RANGE_VAL);
|
||||
}
|
||||
|
||||
static void signal_volume_changed(signal_handler_t *sh,
|
||||
struct obs_fader *fader, const float db)
|
||||
{
|
||||
|
@ -96,6 +200,24 @@ static void signal_volume_changed(signal_handler_t *sh,
|
|||
calldata_free(&data);
|
||||
}
|
||||
|
||||
static void signal_levels_updated(signal_handler_t *sh,
|
||||
struct obs_volmeter *volmeter,
|
||||
const float level, const float magnitude, const float peak)
|
||||
{
|
||||
struct calldata data;
|
||||
|
||||
calldata_init(&data);
|
||||
|
||||
calldata_set_ptr (&data, "volmeter", volmeter);
|
||||
calldata_set_float(&data, "level", level);
|
||||
calldata_set_float(&data, "magnitude", magnitude);
|
||||
calldata_set_float(&data, "peak", peak);
|
||||
|
||||
signal_handler_signal(sh, "levels_updated", &data);
|
||||
|
||||
calldata_free(&data);
|
||||
}
|
||||
|
||||
static void fader_source_volume_changed(void *vptr, calldata_t *calldata)
|
||||
{
|
||||
struct obs_fader *fader = (struct obs_fader *) vptr;
|
||||
|
@ -118,6 +240,18 @@ static void fader_source_volume_changed(void *vptr, calldata_t *calldata)
|
|||
signal_volume_changed(sh, fader, db);
|
||||
}
|
||||
|
||||
static void volmeter_source_volume_changed(void *vptr, calldata_t *calldata)
|
||||
{
|
||||
struct obs_volmeter *volmeter = (struct obs_volmeter *) vptr;
|
||||
|
||||
pthread_mutex_lock(&volmeter->mutex);
|
||||
|
||||
float mul = (float) calldata_float(calldata, "volume");
|
||||
volmeter->cur_db = mul_to_db(mul);
|
||||
|
||||
pthread_mutex_unlock(&volmeter->mutex);
|
||||
}
|
||||
|
||||
static void fader_source_destroyed(void *vptr, calldata_t *calldata)
|
||||
{
|
||||
UNUSED_PARAMETER(calldata);
|
||||
|
@ -126,6 +260,37 @@ static void fader_source_destroyed(void *vptr, calldata_t *calldata)
|
|||
obs_fader_detach_source(fader);
|
||||
}
|
||||
|
||||
static void volmeter_source_volume_levels(void *vptr, calldata_t *calldata)
|
||||
{
|
||||
struct obs_volmeter *volmeter = (struct obs_volmeter *) vptr;
|
||||
|
||||
pthread_mutex_lock(&volmeter->mutex);
|
||||
|
||||
float mul = db_to_mul(volmeter->cur_db);
|
||||
|
||||
float level = (float) calldata_float(calldata, "level");
|
||||
float magnitude = (float) calldata_float(calldata, "magnitude");
|
||||
float peak = (float) calldata_float(calldata, "peak");
|
||||
|
||||
level = volmeter->db_to_pos(mul_to_db(level * mul));
|
||||
magnitude = volmeter->db_to_pos(mul_to_db(magnitude * mul));
|
||||
peak = volmeter->db_to_pos(mul_to_db(peak * mul));
|
||||
|
||||
signal_handler_t *sh = volmeter->signals;
|
||||
|
||||
pthread_mutex_unlock(&volmeter->mutex);
|
||||
|
||||
signal_levels_updated(sh, volmeter, level, magnitude, peak);
|
||||
}
|
||||
|
||||
static void volmeter_source_destroyed(void *vptr, calldata_t *calldata)
|
||||
{
|
||||
UNUSED_PARAMETER(calldata);
|
||||
struct obs_volmeter *volmeter = (struct obs_volmeter *) vptr;
|
||||
|
||||
obs_volmeter_detach_source(volmeter);
|
||||
}
|
||||
|
||||
obs_fader_t *obs_fader_create(enum obs_fader_type type)
|
||||
{
|
||||
struct obs_fader *fader = bzalloc(sizeof(struct obs_fader));
|
||||
|
@ -148,6 +313,18 @@ obs_fader_t *obs_fader_create(enum obs_fader_type type)
|
|||
fader->max_db = 0.0f;
|
||||
fader->min_db = -INFINITY;
|
||||
break;
|
||||
case OBS_FADER_IEC:
|
||||
fader->def_to_db = iec_def_to_db;
|
||||
fader->db_to_def = iec_db_to_def;
|
||||
fader->max_db = 0.0f;
|
||||
fader->min_db = -INFINITY;
|
||||
break;
|
||||
case OBS_FADER_LOG:
|
||||
fader->def_to_db = log_def_to_db;
|
||||
fader->db_to_def = log_db_to_def;
|
||||
fader->max_db = 0.0f;
|
||||
fader->min_db = -96.0f;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
break;
|
||||
|
@ -309,3 +486,114 @@ signal_handler_t *obs_fader_get_signal_handler(obs_fader_t *fader)
|
|||
return (fader) ? fader->signals : NULL;
|
||||
}
|
||||
|
||||
obs_volmeter_t *obs_volmeter_create(enum obs_fader_type type)
|
||||
{
|
||||
struct obs_volmeter *volmeter = bzalloc(sizeof(struct obs_volmeter));
|
||||
if (!volmeter)
|
||||
return NULL;
|
||||
|
||||
pthread_mutex_init_value(&volmeter->mutex);
|
||||
if (pthread_mutex_init(&volmeter->mutex, NULL) != 0)
|
||||
goto fail;
|
||||
volmeter->signals = signal_handler_create();
|
||||
if (!volmeter->signals)
|
||||
goto fail;
|
||||
if (!signal_handler_add_array(volmeter->signals, volmeter_signals))
|
||||
goto fail;
|
||||
|
||||
/* set conversion functions */
|
||||
switch(type) {
|
||||
case OBS_FADER_CUBIC:
|
||||
volmeter->pos_to_db = cubic_def_to_db;
|
||||
volmeter->db_to_pos = cubic_db_to_def;
|
||||
break;
|
||||
case OBS_FADER_IEC:
|
||||
volmeter->pos_to_db = iec_def_to_db;
|
||||
volmeter->db_to_pos = iec_db_to_def;
|
||||
break;
|
||||
case OBS_FADER_LOG:
|
||||
volmeter->pos_to_db = log_def_to_db;
|
||||
volmeter->db_to_pos = log_db_to_def;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
volmeter->type = type;
|
||||
|
||||
return volmeter;
|
||||
fail:
|
||||
obs_volmeter_destroy(volmeter);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void obs_volmeter_destroy(obs_volmeter_t *volmeter)
|
||||
{
|
||||
if (!volmeter)
|
||||
return;
|
||||
|
||||
obs_volmeter_detach_source(volmeter);
|
||||
signal_handler_destroy(volmeter->signals);
|
||||
pthread_mutex_destroy(&volmeter->mutex);
|
||||
|
||||
bfree(volmeter);
|
||||
}
|
||||
|
||||
bool obs_volmeter_attach_source(obs_volmeter_t *volmeter, obs_source_t *source)
|
||||
{
|
||||
signal_handler_t *sh;
|
||||
|
||||
if (!volmeter || !source)
|
||||
return false;
|
||||
|
||||
obs_volmeter_detach_source(volmeter);
|
||||
|
||||
pthread_mutex_lock(&volmeter->mutex);
|
||||
|
||||
sh = obs_source_get_signal_handler(source);
|
||||
signal_handler_connect(sh, "volume",
|
||||
volmeter_source_volume_changed, volmeter);
|
||||
signal_handler_connect(sh, "volume_level",
|
||||
volmeter_source_volume_levels, volmeter);
|
||||
signal_handler_connect(sh, "destroy",
|
||||
volmeter_source_destroyed, volmeter);
|
||||
|
||||
volmeter->source = source;
|
||||
volmeter->cur_db = mul_to_db(obs_source_get_volume(source));
|
||||
|
||||
pthread_mutex_unlock(&volmeter->mutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void obs_volmeter_detach_source(obs_volmeter_t *volmeter)
|
||||
{
|
||||
signal_handler_t *sh;
|
||||
|
||||
if (!volmeter)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&volmeter->mutex);
|
||||
|
||||
if (!volmeter->source)
|
||||
goto exit;
|
||||
|
||||
sh = obs_source_get_signal_handler(volmeter->source);
|
||||
signal_handler_disconnect(sh, "volume",
|
||||
volmeter_source_volume_changed, volmeter);
|
||||
signal_handler_disconnect(sh, "volume_level",
|
||||
volmeter_source_volume_levels, volmeter);
|
||||
signal_handler_disconnect(sh, "destroy",
|
||||
volmeter_source_destroyed, volmeter);
|
||||
|
||||
volmeter->source = NULL;
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&volmeter->mutex);
|
||||
}
|
||||
|
||||
signal_handler_t *obs_volmeter_get_signal_handler(obs_volmeter_t *volmeter)
|
||||
{
|
||||
return (volmeter) ? volmeter->signals : NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,31 @@ enum obs_fader_type {
|
|||
* results while being quite performant.
|
||||
* The input value is mapped to mul values with the simple formula x^3.
|
||||
*/
|
||||
OBS_FADER_CUBIC
|
||||
OBS_FADER_CUBIC,
|
||||
/**
|
||||
* @brief A fader compliant to IEC 60-268-18
|
||||
*
|
||||
* This type of fader has several segments with different slopes that
|
||||
* map deflection linearly to dB values. The segments are defined as
|
||||
* in the following table:
|
||||
*
|
||||
@code
|
||||
Deflection | Volume
|
||||
------------------------------------------
|
||||
[ 100 %, 75 % ] | [ 0 dB, -9 dB ]
|
||||
[ 75 %, 50 % ] | [ -9 dB, -20 dB ]
|
||||
[ 50 %, 30 % ] | [ -20 dB, -30 dB ]
|
||||
[ 30 %, 15 % ] | [ -30 dB, -40 dB ]
|
||||
[ 15 %, 7.5 % ] | [ -40 dB, -50 dB ]
|
||||
[ 7.5 %, 2.5 % ] | [ -50 dB, -60 dB ]
|
||||
[ 2.5 %, 0 % ] | [ -60 dB, -inf dB ]
|
||||
@endcode
|
||||
*/
|
||||
OBS_FADER_IEC,
|
||||
/**
|
||||
* @brief Logarithmic fader
|
||||
*/
|
||||
OBS_FADER_LOG
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -137,6 +161,53 @@ EXPORT void obs_fader_detach_source(obs_fader_t *fader);
|
|||
*/
|
||||
EXPORT signal_handler_t *obs_fader_get_signal_handler(obs_fader_t *fader);
|
||||
|
||||
/**
|
||||
* @brief Create a volume meter
|
||||
* @param type the mapping type to use for the volume meter
|
||||
* @return pointer to the volume meter object
|
||||
*
|
||||
* A volume meter object is used to prepare the sound levels reported by audio
|
||||
* sources for display in a GUI.
|
||||
* It will automatically take source volume into account and map the levels
|
||||
* to a range [0.0f, 1.0f].
|
||||
*/
|
||||
EXPORT obs_volmeter_t *obs_volmeter_create(enum obs_fader_type type);
|
||||
|
||||
/**
|
||||
* @brief Destroy a volume meter
|
||||
* @param volmeter pointer to the volmeter object
|
||||
*
|
||||
* Destroy the volume meter and free all related data
|
||||
*/
|
||||
EXPORT void obs_volmeter_destroy(obs_volmeter_t *volmeter);
|
||||
|
||||
/**
|
||||
* @brief Attach the volume meter to a source
|
||||
* @param volmeter pointer to the volume meter object
|
||||
* @param source pointer to the source object
|
||||
* @return true on success
|
||||
*
|
||||
* When the volume meter is attached to a source it will start to listen to
|
||||
* volume updates on the source and after preparing the data emit its own
|
||||
* signal.
|
||||
*/
|
||||
EXPORT bool obs_volmeter_attach_source(obs_volmeter_t *volmeter,
|
||||
obs_source_t *source);
|
||||
|
||||
/**
|
||||
* @brief Detach the volume meter from the currently attached source
|
||||
* @param volmeter pointer to the volume meter object
|
||||
*/
|
||||
EXPORT void obs_volmeter_detach_source(obs_volmeter_t *volmeter);
|
||||
|
||||
/**
|
||||
* @brief Get signal handler for the volume meter object
|
||||
* @param volmeter pointer to the volume meter object
|
||||
* @return signal handler
|
||||
*/
|
||||
EXPORT signal_handler_t *obs_volmeter_get_signal_handler(
|
||||
obs_volmeter_t *volmeter);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -627,15 +627,6 @@ static inline void handle_ts_jump(obs_source_t *source, uint64_t expected,
|
|||
reset_audio_timing(source, ts, os_time);
|
||||
}
|
||||
|
||||
#define VOL_MIN -96.0f
|
||||
#define VOL_MAX 0.0f
|
||||
|
||||
static inline float to_db(float val)
|
||||
{
|
||||
float db = 20.0f * log10f(val);
|
||||
return isfinite(db) ? db : VOL_MIN;
|
||||
}
|
||||
|
||||
static void calc_volume_levels(struct obs_source *source, float *array,
|
||||
size_t frames, float volume)
|
||||
{
|
||||
|
@ -665,8 +656,8 @@ static void calc_volume_levels(struct obs_source *source, float *array,
|
|||
|
||||
UNUSED_PARAMETER(volume);
|
||||
|
||||
rms_val = to_db(sqrtf(sum_val / (float)count));
|
||||
max_val = to_db(sqrtf(max_val));
|
||||
rms_val = sqrtf(sum_val / (float)count);
|
||||
max_val = sqrtf(max_val);
|
||||
|
||||
if (max_val > source->vol_max)
|
||||
source->vol_max = max_val;
|
||||
|
|
|
@ -48,6 +48,7 @@ struct obs_encoder;
|
|||
struct obs_service;
|
||||
struct obs_module;
|
||||
struct obs_fader;
|
||||
struct obs_volmeter;
|
||||
|
||||
typedef struct obs_display obs_display_t;
|
||||
typedef struct obs_view obs_view_t;
|
||||
|
@ -59,6 +60,7 @@ typedef struct obs_encoder obs_encoder_t;
|
|||
typedef struct obs_service obs_service_t;
|
||||
typedef struct obs_module obs_module_t;
|
||||
typedef struct obs_fader obs_fader_t;
|
||||
typedef struct obs_volmeter obs_volmeter_t;
|
||||
|
||||
#include "obs-source.h"
|
||||
#include "obs-encoder.h"
|
||||
|
|
|
@ -12,31 +12,8 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
#define VOL_MIN -96.0f
|
||||
#define VOL_MAX 0.0f
|
||||
|
||||
/*
|
||||
VOL_MIN_LOG = DBToLog(VOL_MIN)
|
||||
VOL_MAX_LOG = DBToLog(VOL_MAX)
|
||||
... just in case someone wants to use a smaller scale
|
||||
*/
|
||||
|
||||
#define VOL_MIN_LOG -2.0086001717619175
|
||||
#define VOL_MAX_LOG -0.77815125038364363
|
||||
|
||||
#define UPDATE_INTERVAL_MS 50
|
||||
|
||||
static inline float DBToLog(float db)
|
||||
{
|
||||
return -log10f(0.0f - (db - 6.0f));
|
||||
}
|
||||
|
||||
static inline float DBToLinear(float db_full)
|
||||
{
|
||||
float db = fmaxf(fminf(db_full, VOL_MAX), VOL_MIN);
|
||||
return (DBToLog(db) - VOL_MIN_LOG) / (VOL_MAX_LOG - VOL_MIN_LOG);
|
||||
}
|
||||
|
||||
void VolControl::OBSVolumeChanged(void *data, calldata_t *calldata)
|
||||
{
|
||||
Q_UNUSED(calldata);
|
||||
|
@ -73,11 +50,8 @@ void VolControl::VolumeLevel(float mag, float peak, float peakHold)
|
|||
|
||||
/* only update after a certain amount of time */
|
||||
if ((curMeterTime - lastMeterTime) > UPDATE_INTERVAL_MS) {
|
||||
float vol = (float)slider->value() * 0.01f;
|
||||
lastMeterTime = curMeterTime;
|
||||
volMeter->setLevels(DBToLinear(mag) * vol,
|
||||
DBToLinear(peak) * vol,
|
||||
DBToLinear(peakHold) * vol);
|
||||
volMeter->setLevels(mag, peak, peakHold);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +77,8 @@ VolControl::VolControl(OBSSource source_)
|
|||
lastMeterTime (0),
|
||||
levelTotal (0.0f),
|
||||
levelCount (0.0f),
|
||||
obs_fader (obs_fader_create(OBS_FADER_CUBIC))
|
||||
obs_fader (obs_fader_create(OBS_FADER_CUBIC)),
|
||||
obs_volmeter (obs_volmeter_create(OBS_FADER_LOG))
|
||||
{
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout();
|
||||
QHBoxLayout *textLayout = new QHBoxLayout();
|
||||
|
@ -141,13 +116,15 @@ VolControl::VolControl(OBSSource source_)
|
|||
signal_handler_connect(obs_fader_get_signal_handler(obs_fader),
|
||||
"volume_changed", OBSVolumeChanged, this);
|
||||
|
||||
signal_handler_connect(obs_source_get_signal_handler(source),
|
||||
"volume_level", OBSVolumeLevel, this);
|
||||
signal_handler_connect(obs_volmeter_get_signal_handler(obs_volmeter),
|
||||
"levels_updated", OBSVolumeLevel, this);
|
||||
|
||||
QWidget::connect(slider, SIGNAL(valueChanged(int)),
|
||||
this, SLOT(SliderChanged(int)));
|
||||
|
||||
obs_fader_attach_source(obs_fader, source);
|
||||
obs_volmeter_attach_source(obs_volmeter, source);
|
||||
|
||||
/* Call volume changed once to init the slider position and label */
|
||||
VolumeChanged();
|
||||
}
|
||||
|
@ -157,10 +134,11 @@ VolControl::~VolControl()
|
|||
signal_handler_disconnect(obs_fader_get_signal_handler(obs_fader),
|
||||
"volume_changed", OBSVolumeChanged, this);
|
||||
|
||||
signal_handler_disconnect(obs_source_get_signal_handler(source),
|
||||
"volume_level", OBSVolumeLevel, this);
|
||||
signal_handler_disconnect(obs_volmeter_get_signal_handler(obs_volmeter),
|
||||
"levels_updated", OBSVolumeLevel, this);
|
||||
|
||||
obs_fader_destroy(obs_fader);
|
||||
obs_volmeter_destroy(obs_volmeter);
|
||||
}
|
||||
|
||||
VolumeMeter::VolumeMeter(QWidget *parent)
|
||||
|
|
|
@ -36,6 +36,7 @@ private:
|
|||
float levelTotal;
|
||||
float levelCount;
|
||||
obs_fader_t *obs_fader;
|
||||
obs_volmeter_t *obs_volmeter;
|
||||
|
||||
static void OBSVolumeChanged(void *param, calldata_t *calldata);
|
||||
static void OBSVolumeLevel(void *data, calldata_t *calldata);
|
||||
|
|
Loading…
Reference in New Issue