implemeted non linear gain controls (similar to BeOS R5)
allow to select gain control slider modus in setup (either controls physical input, or virtual output channels) git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4288 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -23,6 +23,13 @@
|
|||||||
#define VERSION_STRING "0.1 alpha 1"
|
#define VERSION_STRING "0.1 alpha 1"
|
||||||
#define BUILD_STRING __DATE__ " " __TIME__
|
#define BUILD_STRING __DATE__ " " __TIME__
|
||||||
|
|
||||||
|
// the range of the gain sliders (in dB)
|
||||||
|
#define DB_MAX 18.0
|
||||||
|
#define DB_MIN -60.0
|
||||||
|
// when using non linear sliders, we use a power function with
|
||||||
|
#define DB_EXPONENT_POSITIVE 1.4 // for dB values > 0
|
||||||
|
#define DB_EXPONENT_NEGATIVE 1.8 // for dB values < 0
|
||||||
|
|
||||||
#define USE_MEDIA_FORMAT_WORKAROUND 1
|
#define USE_MEDIA_FORMAT_WORKAROUND 1
|
||||||
|
|
||||||
#if USE_MEDIA_FORMAT_WORKAROUND
|
#if USE_MEDIA_FORMAT_WORKAROUND
|
||||||
@@ -945,12 +952,50 @@ AudioMixer::CreateBufferGroup()
|
|||||||
return new BBufferGroup(size, count);
|
return new BBufferGroup(size, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
AudioMixer::dB_to_Gain(float db)
|
||||||
|
{
|
||||||
|
TRACE("dB_to_Gain: dB in: %01.2f ", db);
|
||||||
|
if (fCore->Settings()->NonLinearGainSlider()) {
|
||||||
|
if (db > 0) {
|
||||||
|
db = db * (pow(abs(DB_MAX), (1.0 / DB_EXPONENT_POSITIVE)) / abs(DB_MAX));
|
||||||
|
db = pow(db, DB_EXPONENT_POSITIVE);
|
||||||
|
} else {
|
||||||
|
db = -db;
|
||||||
|
db = db * (pow(abs(DB_MIN), (1.0 / DB_EXPONENT_NEGATIVE)) / abs(DB_MIN));
|
||||||
|
db = pow(db, DB_EXPONENT_NEGATIVE);
|
||||||
|
db = -db;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TRACE("dB out: %01.2f\n", db);
|
||||||
|
return pow(10.0, db / 20.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
AudioMixer::Gain_to_dB(float gain)
|
||||||
|
{
|
||||||
|
float db;
|
||||||
|
db = 20.0 * log10(gain);
|
||||||
|
if (fCore->Settings()->NonLinearGainSlider()) {
|
||||||
|
if (db > 0) {
|
||||||
|
db = pow(db, (1.0 / DB_EXPONENT_POSITIVE));
|
||||||
|
db = db * (abs(DB_MAX) / pow(abs(DB_MAX), (1.0 / DB_EXPONENT_POSITIVE)));
|
||||||
|
} else {
|
||||||
|
db = -db;
|
||||||
|
db = pow(db, (1.0 / DB_EXPONENT_NEGATIVE));
|
||||||
|
db = db * (abs(DB_MIN) / pow(abs(DB_MIN), (1.0 / DB_EXPONENT_NEGATIVE)));
|
||||||
|
db = -db;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return db;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// BControllable methods
|
// BControllable methods
|
||||||
//
|
//
|
||||||
|
|
||||||
#define DB_TO_GAIN(db) (pow(10.0, (db) / 20.0))
|
#define DB_TO_GAIN(db) dB_to_Gain((db))
|
||||||
#define GAIN_TO_DB(gain) (20.0 * log10(gain))
|
#define GAIN_TO_DB(gain) Gain_to_dB((gain))
|
||||||
#define PERCENT_TO_GAIN(pct) ((pct) / 100.0)
|
#define PERCENT_TO_GAIN(pct) ((pct) / 100.0)
|
||||||
#define GAIN_TO_PERCENT(gain) ((gain) * 100.0)
|
#define GAIN_TO_PERCENT(gain) ((gain) * 100.0)
|
||||||
|
|
||||||
@@ -1087,11 +1132,21 @@ AudioMixer::GetParameterValue(int32 id, bigtime_t *last_change,
|
|||||||
}
|
}
|
||||||
if (PARAM_IS_GAIN(id)) {
|
if (PARAM_IS_GAIN(id)) {
|
||||||
// input gain control
|
// input gain control
|
||||||
if (*ioSize < input->GetMixerChannelCount() * sizeof(float))
|
if (fCore->Settings()->InputGainControls() == 0) {
|
||||||
goto err;
|
// Physical input channels
|
||||||
*ioSize = input->GetMixerChannelCount() * sizeof(float);
|
if (*ioSize < input->GetInputChannelCount() * sizeof(float))
|
||||||
for (int chan = 0; chan < input->GetMixerChannelCount(); chan++)
|
goto err;
|
||||||
static_cast<float *>(value)[chan] = GAIN_TO_DB(input->GetMixerChannelGain(chan));
|
*ioSize = input->GetInputChannelCount() * sizeof(float);
|
||||||
|
for (int chan = 0; chan < input->GetInputChannelCount(); chan++)
|
||||||
|
static_cast<float *>(value)[chan] = GAIN_TO_DB(input->GetInputChannelGain(chan));
|
||||||
|
} else {
|
||||||
|
// Virtual output channels
|
||||||
|
if (*ioSize < input->GetMixerChannelCount() * sizeof(float))
|
||||||
|
goto err;
|
||||||
|
*ioSize = input->GetMixerChannelCount() * sizeof(float);
|
||||||
|
for (int chan = 0; chan < input->GetMixerChannelCount(); chan++)
|
||||||
|
static_cast<float *>(value)[chan] = GAIN_TO_DB(input->GetMixerChannelGain(chan));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (PARAM_IS_DST_ENABLE(id)) {
|
if (PARAM_IS_DST_ENABLE(id)) {
|
||||||
if (*ioSize < sizeof(int32))
|
if (*ioSize < sizeof(int32))
|
||||||
@@ -1229,10 +1284,19 @@ AudioMixer::SetParameterValue(int32 id, bigtime_t when,
|
|||||||
}
|
}
|
||||||
if (PARAM_IS_GAIN(id)) {
|
if (PARAM_IS_GAIN(id)) {
|
||||||
// input gain control
|
// input gain control
|
||||||
if (size < input->GetMixerChannelCount() * sizeof(float))
|
if (fCore->Settings()->InputGainControls() == 0) {
|
||||||
goto err;
|
// Physical input channels
|
||||||
for (int chan = 0; chan < input->GetMixerChannelCount(); chan++)
|
if (size < input->GetInputChannelCount() * sizeof(float))
|
||||||
input->SetMixerChannelGain(chan, DB_TO_GAIN(static_cast<const float *>(value)[chan]));
|
goto err;
|
||||||
|
for (int chan = 0; chan < input->GetInputChannelCount(); chan++)
|
||||||
|
input->SetInputChannelGain(chan, DB_TO_GAIN(static_cast<const float *>(value)[chan]));
|
||||||
|
} else {
|
||||||
|
// Virtual output channels
|
||||||
|
if (size < input->GetMixerChannelCount() * sizeof(float))
|
||||||
|
goto err;
|
||||||
|
for (int chan = 0; chan < input->GetMixerChannelCount(); chan++)
|
||||||
|
input->SetMixerChannelGain(chan, DB_TO_GAIN(static_cast<const float *>(value)[chan]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (PARAM_IS_DST_ENABLE(id)) {
|
if (PARAM_IS_DST_ENABLE(id)) {
|
||||||
if (size != sizeof(int32))
|
if (size != sizeof(int32))
|
||||||
@@ -1293,7 +1357,7 @@ AudioMixer::UpdateParameterWeb()
|
|||||||
} else {
|
} else {
|
||||||
group->MakeNullParameter(PARAM_STR2(0), B_MEDIA_RAW_AUDIO, StringForFormat(buf, out), B_GENERIC);
|
group->MakeNullParameter(PARAM_STR2(0), B_MEDIA_RAW_AUDIO, StringForFormat(buf, out), B_GENERIC);
|
||||||
group->MakeDiscreteParameter(PARAM_MUTE(0), B_MEDIA_RAW_AUDIO, "Mute", B_MUTE);
|
group->MakeDiscreteParameter(PARAM_MUTE(0), B_MEDIA_RAW_AUDIO, "Mute", B_MUTE);
|
||||||
group->MakeContinuousParameter(PARAM_GAIN(0), B_MEDIA_RAW_AUDIO, "Gain", B_MASTER_GAIN, "dB", -60.0, 18.0, 0.1)
|
group->MakeContinuousParameter(PARAM_GAIN(0), B_MEDIA_RAW_AUDIO, "Gain", B_MASTER_GAIN, "dB", DB_MIN, DB_MAX, 0.1)
|
||||||
->SetChannelCount(out->GetOutputChannelCount());
|
->SetChannelCount(out->GetOutputChannelCount());
|
||||||
group->MakeNullParameter(PARAM_STR3(0), B_MEDIA_RAW_AUDIO, "To Output", B_WEB_BUFFER_OUTPUT);
|
group->MakeNullParameter(PARAM_STR3(0), B_MEDIA_RAW_AUDIO, "To Output", B_WEB_BUFFER_OUTPUT);
|
||||||
}
|
}
|
||||||
@@ -1305,8 +1369,15 @@ AudioMixer::UpdateParameterWeb()
|
|||||||
group->MakeDiscreteParameter(PARAM_MUTE(in->ID()), B_MEDIA_RAW_AUDIO, "Mute", B_MUTE);
|
group->MakeDiscreteParameter(PARAM_MUTE(in->ID()), B_MEDIA_RAW_AUDIO, "Mute", B_MUTE);
|
||||||
// XXX the gain control is ugly once you have more than two channels,
|
// XXX the gain control is ugly once you have more than two channels,
|
||||||
// as you don't know what channel each slider controls. Tooltips might help...
|
// as you don't know what channel each slider controls. Tooltips might help...
|
||||||
group->MakeContinuousParameter(PARAM_GAIN(in->ID()), B_MEDIA_RAW_AUDIO, "Gain", B_GAIN, "dB", -60.0, 18.0, 0.1)
|
if (fCore->Settings()->InputGainControls() == 0) {
|
||||||
->SetChannelCount(in->GetMixerChannelCount());
|
// Physical input channels
|
||||||
|
group->MakeContinuousParameter(PARAM_GAIN(in->ID()), B_MEDIA_RAW_AUDIO, "Gain", B_GAIN, "dB", DB_MIN, DB_MAX, 0.1)
|
||||||
|
->SetChannelCount(in->GetInputChannelCount());
|
||||||
|
} else {
|
||||||
|
// Virtual output channels
|
||||||
|
group->MakeContinuousParameter(PARAM_GAIN(in->ID()), B_MEDIA_RAW_AUDIO, "Gain", B_GAIN, "dB", DB_MIN, DB_MAX, 0.1)
|
||||||
|
->SetChannelCount(in->GetMixerChannelCount());
|
||||||
|
}
|
||||||
group->MakeNullParameter(PARAM_STR3(in->ID()), B_MEDIA_RAW_AUDIO, "To Master", B_WEB_BUFFER_OUTPUT);
|
group->MakeNullParameter(PARAM_STR3(in->ID()), B_MEDIA_RAW_AUDIO, "To Master", B_WEB_BUFFER_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ class AudioMixer :
|
|||||||
void HandleInputBuffer(BBuffer *buffer, bigtime_t lateness);
|
void HandleInputBuffer(BBuffer *buffer, bigtime_t lateness);
|
||||||
|
|
||||||
BBufferGroup * CreateBufferGroup();
|
BBufferGroup * CreateBufferGroup();
|
||||||
|
|
||||||
|
float dB_to_Gain(float db);
|
||||||
|
float Gain_to_dB(float gain);
|
||||||
|
|
||||||
// BMediaNode methods
|
// BMediaNode methods
|
||||||
|
|
||||||
|
|||||||
@@ -267,7 +267,6 @@ MixerInput::GetInputChannelType(int channel)
|
|||||||
return GetChannelType(channel, fInputChannelMask);
|
return GetChannelType(channel, fInputChannelMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
void
|
void
|
||||||
MixerInput::SetInputChannelGain(int channel, float gain)
|
MixerInput::SetInputChannelGain(int channel, float gain)
|
||||||
{
|
{
|
||||||
@@ -288,7 +287,6 @@ MixerInput::GetInputChannelGain(int channel)
|
|||||||
return 0.0f;
|
return 0.0f;
|
||||||
return fInputChannelInfo[channel].gain;
|
return fInputChannelInfo[channel].gain;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MixerInput::UpdateInputChannelDestinationMask()
|
MixerInput::UpdateInputChannelDestinationMask()
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ public:
|
|||||||
// The physical input channels
|
// The physical input channels
|
||||||
uint32 GetInputChannelCount();
|
uint32 GetInputChannelCount();
|
||||||
int GetInputChannelType(int channel);
|
int GetInputChannelType(int channel);
|
||||||
// void SetInputChannelGain(int channel, float gain);
|
void SetInputChannelGain(int channel, float gain);
|
||||||
// float GetInputChannelGain(int channel);
|
float GetInputChannelGain(int channel);
|
||||||
|
|
||||||
// The destinations for each channel
|
// The destinations for each channel
|
||||||
void AddInputChannelDestination(int channel, int destination_type);
|
void AddInputChannelDestination(int channel, int destination_type);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
template<class t> const t & max(const t &t1, const t &t2) { return (t1 > t2) ? t1 : t2; }
|
template<class t> const t & max(const t &t1, const t &t2) { return (t1 > t2) ? t1 : t2; }
|
||||||
template<class t> const t & min(const t &t1, const t &t2) { return (t1 < t2) ? t1 : t2; }
|
template<class t> const t & min(const t &t1, const t &t2) { return (t1 < t2) ? t1 : t2; }
|
||||||
|
template<class t> const t abs(const t t1) { return (t1 < 0) ? - t1 : t1; }
|
||||||
|
|
||||||
void fix_multiaudio_format(media_multi_audio_format *format);
|
void fix_multiaudio_format(media_multi_audio_format *format);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user