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:
beveloper
2003-08-16 19:40:31 +00:00
parent 26bf7cd399
commit 4224efc3c7
5 changed files with 91 additions and 18 deletions
@@ -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);