Fixed some debug macros.

Cleanup of MixerInput class.
Implemented output destination mapping controls.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3819 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2003-07-03 22:01:27 +00:00
parent 3161d380ef
commit 9c3be6a557
5 changed files with 190 additions and 154 deletions
@@ -883,7 +883,7 @@ status_t
AudioMixer::GetParameterValue(int32 id, bigtime_t *last_change, AudioMixer::GetParameterValue(int32 id, bigtime_t *last_change,
void *value, size_t *ioSize) void *value, size_t *ioSize)
{ {
TRACE("GetParameterValue: id %ld, ioSize %ld\n", id, *ioSize); TRACE("GetParameterValue: id 0x%08x, ioSize %ld\n", id, *ioSize);
int param = PARAM(id); int param = PARAM(id);
fCore->Lock(); fCore->Lock();
if (param == 0) { if (param == 0) {
@@ -922,7 +922,7 @@ AudioMixer::GetParameterValue(int32 id, bigtime_t *last_change,
for (int i = 0; (input = fCore->Input(i)); i++) for (int i = 0; (input = fCore->Input(i)); i++)
if (input->ID() == param) if (input->ID() == param)
break; break;
if ((!PARAM_IS_MUTE(id) && !PARAM_IS_GAIN(id)) || !input) if (!input || (!PARAM_IS_MUTE(id) && !PARAM_IS_GAIN(id) && !PARAM_IS_DST_ENABLE(id) && !PARAM_IS_DST_GAIN(id)))
goto err; goto err;
if (PARAM_IS_MUTE(id)) { if (PARAM_IS_MUTE(id)) {
// input mute control // input mute control
@@ -939,6 +939,18 @@ AudioMixer::GetParameterValue(int32 id, bigtime_t *last_change,
for (int chan = 0; chan < input->GetInputChannelCount(); chan++) for (int chan = 0; chan < input->GetInputChannelCount(); chan++)
static_cast<float *>(value)[chan] = DB_TO_GAIN(input->GetInputChannelGain(chan)); static_cast<float *>(value)[chan] = DB_TO_GAIN(input->GetInputChannelGain(chan));
} }
if (PARAM_IS_DST_ENABLE(id)) {
if (*ioSize < sizeof(int32))
goto err;
*ioSize = sizeof(int32);
static_cast<int32 *>(value)[0] = input->HasInputChannelDestination(PARAM_CHAN(id), PARAM_DST(id));
}
if (PARAM_IS_DST_GAIN(id)) {
if (*ioSize < sizeof(float))
goto err;
*ioSize = sizeof(float);
static_cast<float *>(value)[0] = GAIN_TO_PERCENT(input->GetInputChannelDestinationGain(PARAM_CHAN(id), PARAM_DST(id)));
}
} }
*last_change = TimeSource()->Now(); // XXX we could do better *last_change = TimeSource()->Now(); // XXX we could do better
fCore->Unlock(); fCore->Unlock();
@@ -952,7 +964,7 @@ void
AudioMixer::SetParameterValue(int32 id, bigtime_t when, AudioMixer::SetParameterValue(int32 id, bigtime_t when,
const void *value, size_t size) const void *value, size_t size)
{ {
TRACE("SetParameterValue: id %ld, size %ld\n", id, size); TRACE("SetParameterValue: id 0x%08x, size %ld\n", id, size);
int param = PARAM(id); int param = PARAM(id);
fCore->Lock(); fCore->Lock();
if (param == 0) { if (param == 0) {
@@ -991,7 +1003,7 @@ AudioMixer::SetParameterValue(int32 id, bigtime_t when,
for (int i = 0; (input = fCore->Input(i)); i++) for (int i = 0; (input = fCore->Input(i)); i++)
if (input->ID() == param) if (input->ID() == param)
break; break;
if ((!PARAM_IS_MUTE(id) && !PARAM_IS_GAIN(id)) || !input) if (!input || (!PARAM_IS_MUTE(id) && !PARAM_IS_GAIN(id) && !PARAM_IS_DST_ENABLE(id) && !PARAM_IS_DST_GAIN(id)))
goto err; goto err;
if (PARAM_IS_MUTE(id)) { if (PARAM_IS_MUTE(id)) {
// input mute control // input mute control
@@ -1006,6 +1018,34 @@ AudioMixer::SetParameterValue(int32 id, bigtime_t when,
for (int chan = 0; chan < input->GetInputChannelCount(); chan++) for (int chan = 0; chan < input->GetInputChannelCount(); chan++)
input->SetInputChannelGain(chan, GAIN_TO_DB(static_cast<const float *>(value)[chan])); input->SetInputChannelGain(chan, GAIN_TO_DB(static_cast<const float *>(value)[chan]));
} }
if (PARAM_IS_DST_ENABLE(id)) {
if (size != sizeof(int32))
goto err;
if (static_cast<const int32 *>(value)[0]) {
int oldchan = input->GetInputChannelForDestination(PARAM_DST(id));
if (oldchan != -1) {
input->RemoveInputChannelDestination(oldchan, PARAM_DST(id));
int32 null = 0;
BroadcastNewParameterValue(when, PARAM_DST_ENABLE(PARAM(id), oldchan, PARAM_DST(id)), &null, sizeof(null));
}
input->AddInputChannelDestination(PARAM_CHAN(id), PARAM_DST(id));
} else {
input->RemoveInputChannelDestination(PARAM_CHAN(id), PARAM_DST(id));
}
}
if (PARAM_IS_DST_GAIN(id)) {
if (size != sizeof(float))
goto err;
input->SetInputChannelDestinationGain(PARAM_CHAN(id), PARAM_DST(id), PERCENT_TO_GAIN(static_cast<const float *>(value)[0]));
// We have an ugly display where each destination gain slider
// is diplayed for each input channel.
// Update all other sliders for this destination type
for (int chan = 0; chan < input->GetInputChannelCount(); chan++) {
if (PARAM_CHAN(id) == chan)
continue;
BroadcastNewParameterValue(when, PARAM_DST_GAIN(PARAM(id), chan, PARAM_DST(id)), const_cast<void *>(value), size);
}
}
} }
BroadcastNewParameterValue(when, id, const_cast<void *>(value), size); BroadcastNewParameterValue(when, id, const_cast<void *>(value), size);
err: err:
@@ -1077,10 +1117,10 @@ AudioMixer::UpdateParameterWeb()
} }
} }
#if 0
top = web->MakeGroup("Input Mapping"); // top level group top = web->MakeGroup("Input Mapping"); // top level group
inputchannels = top->MakeGroup(""); inputchannels = top->MakeGroup("");
inputchannels->MakeNullParameter(PARAM_STR7(0), B_MEDIA_RAW_AUDIO, "Input Channel Destinations", B_GENERIC); // inputchannels->MakeNullParameter(PARAM_STR7(0), B_MEDIA_RAW_AUDIO, "Input Channel Destinations", B_GENERIC);
inputchannels->MakeNullParameter(PARAM_STR7(0), B_MEDIA_RAW_AUDIO, "Input Channel Destinations (PREVIEW; DISPLAYS ONLY ONE CONNECTED INPUT)", B_GENERIC);
// for (int i = 0; (in = fCore->Input(i)); i++) { // for (int i = 0; (in = fCore->Input(i)); i++) {
if ((in = fCore->Input(1)) || (in = fCore->Input(0))) { // XXX limited to input 1 or 0 to aviod BSlider problems if ((in = fCore->Input(1)) || (in = fCore->Input(0))) { // XXX limited to input 1 or 0 to aviod BSlider problems
@@ -1101,7 +1141,6 @@ AudioMixer::UpdateParameterWeb()
} }
} }
#endif
fCore->Unlock(); fCore->Unlock();
@@ -24,7 +24,7 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrame
fLastDataAvailableTime(-1), fLastDataAvailableTime(-1),
fResampler(0), fResampler(0),
fRtmPool(0), fRtmPool(0),
fUserOverridesChannelDesignations(false) fUserOverridesChannelDestinations(false)
{ {
fix_multiaudio_format(&fInput.format.u.raw_audio); fix_multiaudio_format(&fInput.format.u.raw_audio);
PRINT_INPUT("MixerInput::MixerInput", fInput); PRINT_INPUT("MixerInput::MixerInput", fInput);
@@ -32,6 +32,9 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrame
ASSERT(fInput.format.u.raw_audio.channel_count > 0); ASSERT(fInput.format.u.raw_audio.channel_count > 0);
for (int i = 0; i < MAX_CHANNEL_TYPES; i++)
fChannelTypeGain[i] = 1.0f;
fInputChannelCount = fInput.format.u.raw_audio.channel_count; fInputChannelCount = fInput.format.u.raw_audio.channel_count;
fInputChannelMask = fInput.format.u.raw_audio.channel_mask; fInputChannelMask = fInput.format.u.raw_audio.channel_mask;
fInputChannelInfo = new input_chan_info[fInputChannelCount]; fInputChannelInfo = new input_chan_info[fInputChannelCount];
@@ -48,7 +51,7 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrame
// initialize fInputChannelInfo // initialize fInputChannelInfo
for (int i = 0; i < fInputChannelCount; i++) { for (int i = 0; i < fInputChannelCount; i++) {
fInputChannelInfo[i].buffer_base = 0; // will be set by SetMixBufferFormat() fInputChannelInfo[i].buffer_base = 0; // will be set by SetMixBufferFormat()
fInputChannelInfo[i].designations = 0; // will be set by UpdateChannelDesignations() fInputChannelInfo[i].destination_mask = 0; // will be set by UpdateInputChannelDestinationMask()
fInputChannelInfo[i].gain = 1.0; fInputChannelInfo[i].gain = 1.0;
} }
@@ -57,18 +60,9 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrame
for (int i = 0; i < fInputChannelCount; i++) for (int i = 0; i < fInputChannelCount; i++)
fResampler[i] = new Resampler(fInput.format.u.raw_audio.format, media_raw_audio_format::B_AUDIO_FLOAT); fResampler[i] = new Resampler(fInput.format.u.raw_audio.format, media_raw_audio_format::B_AUDIO_FLOAT);
// fMixerChannelInfo and fMixerChannelCount will be initialized by UpdateMixerChannels() // fMixerChannelInfo and fMixerChannelCount will be initialized by UpdateInputChannelDestinations()
SetMixBufferFormat(mixFrameRate, mixFrameCount); SetMixBufferFormat(mixFrameRate, mixFrameCount);
// XXX a test:
/*
SetMixerChannelGain(0, 0.222);
SetMixerChannelGain(1, 0.444);
AddInputChannelDesignation(0, B_CHANNEL_REARRIGHT);
SetMixerChannelGain(2, 0.666);
AddInputChannelDesignation(1, B_CHANNEL_REARLEFT);
*/
} }
MixerInput::~MixerInput() MixerInput::~MixerInput()
@@ -196,65 +190,81 @@ MixerInput::GetInputChannelCount()
} }
void void
MixerInput::AddInputChannelDesignation(int channel, uint32 des) MixerInput::AddInputChannelDestination(int channel, int destination_type)
{ {
ASSERT(count_nonzero_bits(des) == 1); uint32 mask = ChannelTypeToChannelMask(destination_type);
// test if the channel is valid // test if the channel is valid
if (channel < 0 || channel >= fInputChannelCount) if (channel < 0 || channel >= fInputChannelCount)
return; return;
// test if it is already set // test if it is already set
if (fInputChannelInfo[channel].designations & des) if (fInputChannelInfo[channel].destination_mask & mask)
return; return;
// remove it from all other channels that might have it // verify that no other channel has id
for (int i = 0; i < fInputChannelCount; i++) if (-1 != GetInputChannelForDestination(destination_type)) {
fInputChannelInfo[i].designations &= ~des; ERROR("MixerInput::AddInputChannelDestination: destination_type %d already assigned to channel %d\n", destination_type, GetInputChannelForDestination(destination_type));
return;
// add it to specified channel }
fInputChannelInfo[channel].designations |= des;
fUserOverridesChannelDesignations = true; // add it to specified channel
UpdateMixerChannels(); fInputChannelInfo[channel].destination_mask |= mask;
fUserOverridesChannelDestinations = true;
UpdateInputChannelDestinations();
} }
void void
MixerInput::RemoveInputChannelDesignation(int channel, uint32 des) MixerInput::RemoveInputChannelDestination(int channel, int destination_type)
{ {
ASSERT(count_nonzero_bits(des) == 1); uint32 mask = ChannelTypeToChannelMask(destination_type);
// test if the channel is valid // test if the channel is valid
if (channel < 0 || channel >= fInputChannelCount) if (channel < 0 || channel >= fInputChannelCount)
return; return;
// test if it is really set // test if it is really set
if ((fInputChannelInfo[channel].designations & des) == 0) if ((fInputChannelInfo[channel].destination_mask & mask) == 0)
return; return;
// remove it from specified channel // remove it from specified channel
fInputChannelInfo[channel].designations &= ~des; fInputChannelInfo[channel].destination_mask &= ~mask;
fUserOverridesChannelDesignations = true; fUserOverridesChannelDestinations = true;
UpdateMixerChannels(); UpdateInputChannelDestinations();
} }
uint32 bool
MixerInput::GetInputChannelDesignations(int channel) MixerInput::HasInputChannelDestination(int channel, int destination_type)
{ {
// test if the channel is valid
if (channel < 0 || channel >= fInputChannelCount) if (channel < 0 || channel >= fInputChannelCount)
return 0; return false;
return fInputChannelInfo[channel].designations; if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
return false;
return fInputChannelInfo[channel].destination_mask & ChannelTypeToChannelMask(destination_type);
} }
uint32 int
MixerInput::GetInputChannelForDestination(int destination_type)
{
if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
return -1;
uint32 mask = ChannelTypeToChannelMask(destination_type);
for (int chan = 0; chan < fInputChannelCount; chan++) {
if (fInputChannelInfo[chan].destination_mask & mask)
return chan;
}
return -1;
}
int
MixerInput::GetInputChannelType(int channel) MixerInput::GetInputChannelType(int channel)
{ {
// test if the channel is valid // test if the channel is valid
if (channel < 0 || channel >= fInputChannelCount) if (channel < 0 || channel >= fInputChannelCount)
return 0; return 0;
return GetChannelMask(channel, fInputChannelMask); return GetChannelType(channel, fInputChannelMask);
} }
void void
@@ -279,17 +289,17 @@ MixerInput::GetInputChannelGain(int channel)
} }
void void
MixerInput::UpdateChannelDesignations() MixerInput::UpdateInputChannelDestinationMask()
{ {
// is the user already messed with the assignmens, don't do anything. // is the user already messed with the assignmens, don't do anything.
if (fUserOverridesChannelDesignations) if (fUserOverridesChannelDestinations)
return; return;
TRACE("UpdateChannelDesignations: enter\n"); TRACE("UpdateInputChannelDestinationMask: enter\n");
// first apply a 1:1 mapping // first apply a 1:1 mapping
for (int i = 0; i < fInputChannelCount; i++) for (int i = 0; i < fInputChannelCount; i++)
fInputChannelInfo[i].designations = GetChannelMask(i, fInputChannelMask); fInputChannelInfo[i].destination_mask = GetChannelMask(i, fInputChannelMask);
// specialize this, depending on the available physical output channels // specialize this, depending on the available physical output channels
switch (fCore->OutputChannelCount()) { switch (fCore->OutputChannelCount()) {
@@ -299,80 +309,70 @@ MixerInput::UpdateChannelDesignations()
case 2: case 2:
if (fInputChannelCount == 1 && (GetChannelMask(0, fInputChannelMask) & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) { if (fInputChannelCount == 1 && (GetChannelMask(0, fInputChannelMask) & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) {
fInputChannelInfo[0].designations = B_CHANNEL_LEFT | B_CHANNEL_RIGHT; fInputChannelInfo[0].destination_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT;
} }
break; break;
default: default:
if (fInputChannelCount == 1 && (GetChannelMask(0, fInputChannelMask) & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) { if (fInputChannelCount == 1 && (GetChannelMask(0, fInputChannelMask) & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) {
fInputChannelInfo[0].designations = B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT; fInputChannelInfo[0].destination_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT;
} }
if (fInputChannelCount == 2 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_LEFT)) { if (fInputChannelCount == 2 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_LEFT)) {
fInputChannelInfo[0].designations = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT; fInputChannelInfo[0].destination_mask = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT;
} }
if (fInputChannelCount == 2 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_RIGHT)) { if (fInputChannelCount == 2 && (GetChannelMask(0, fInputChannelMask) & B_CHANNEL_RIGHT)) {
fInputChannelInfo[0].designations = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT; fInputChannelInfo[0].destination_mask = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT;
} }
if (fInputChannelCount == 2 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_LEFT)) { if (fInputChannelCount == 2 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_LEFT)) {
fInputChannelInfo[1].designations = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT; fInputChannelInfo[1].destination_mask = B_CHANNEL_LEFT | B_CHANNEL_REARLEFT;
} }
if (fInputChannelCount == 2 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_RIGHT)) { if (fInputChannelCount == 2 && (GetChannelMask(1, fInputChannelMask) & B_CHANNEL_RIGHT)) {
fInputChannelInfo[1].designations = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT; fInputChannelInfo[1].destination_mask = B_CHANNEL_RIGHT | B_CHANNEL_REARRIGHT;
} }
break; break;
} }
for (int i = 0; i < fInputChannelCount; i++) for (int i = 0; i < fInputChannelCount; i++)
TRACE("UpdateChannelDesignations: input channel %d, designations 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].designations, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); TRACE("UpdateInputChannelDestinationMask: input channel %d, destination_mask 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].destination_mask, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
TRACE("UpdateChannelDesignations: leave\n"); TRACE("UpdateInputChannelDestinationMask: leave\n");
} }
void void
MixerInput::UpdateMixerChannels() MixerInput::UpdateInputChannelDestinations()
{ {
uint32 channel_count; uint32 channel_count;
uint32 all_bits; uint32 all_bits;
uint32 mask; uint32 mask;
mixer_chan_info *old_mixer_channel_info; TRACE("UpdateInputChannelDestinations: enter\n");
uint32 old_mixer_channel_count;
TRACE("UpdateMixerChannels: enter\n");
for (int i = 0; i < fInputChannelCount; i++) for (int i = 0; i < fInputChannelCount; i++)
TRACE("UpdateMixerChannels: input channel %d, designations 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].designations, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); TRACE("UpdateInputChannelDestinations: input channel %d, destination_mask 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].destination_mask, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain);
all_bits = 0; all_bits = 0;
for (int i = 0; i < fInputChannelCount; i++) for (int i = 0; i < fInputChannelCount; i++)
all_bits |= fInputChannelInfo[i].designations; all_bits |= fInputChannelInfo[i].destination_mask;
TRACE("UpdateMixerChannels: all_bits = %08x\n", all_bits); TRACE("UpdateInputChannelDestinations: all_bits = %08x\n", all_bits);
channel_count = count_nonzero_bits(all_bits); channel_count = count_nonzero_bits(all_bits);
TRACE("UpdateMixerChannels: %ld input channels, %ld mixer channels (%ld old)\n", fInputChannelCount, channel_count, fMixerChannelCount); TRACE("UpdateInputChannelDestinations: %ld input channels, %ld mixer channels (%ld old)\n", fInputChannelCount, channel_count, fMixerChannelCount);
// If we resize the channel info array, we preserve the gain setting
// by saving the old array until new assignments are finished, and
// then applying the old gains. New gains are set to 1.0
if (channel_count != fMixerChannelCount) { if (channel_count != fMixerChannelCount) {
old_mixer_channel_info = fMixerChannelInfo; delete [] fMixerChannelInfo;
old_mixer_channel_count = fMixerChannelCount;
fMixerChannelInfo = new mixer_chan_info[channel_count]; fMixerChannelInfo = new mixer_chan_info[channel_count];
fMixerChannelCount = channel_count; fMixerChannelCount = channel_count;
for (int i = 0; i < fMixerChannelCount; i++)
fMixerChannelInfo[i].gain = 1.0;
} else {
old_mixer_channel_info = 0;
old_mixer_channel_count = 0;
} }
// assign each mixer channel one type // assign each mixer channel one type
// and the gain from the fChannelTypeGain[]
for (int i = 0, mask = 1; i < fMixerChannelCount; i++) { for (int i = 0, mask = 1; i < fMixerChannelCount; i++) {
while (mask != 0 && (all_bits & mask) == 0) while (mask != 0 && (all_bits & mask) == 0)
mask <<= 1; mask <<= 1;
fMixerChannelInfo[i].type = ChannelMaskToChannelType(mask); fMixerChannelInfo[i].destination_type = ChannelMaskToChannelType(mask);
fMixerChannelInfo[i].destination_gain = fChannelTypeGain[fMixerChannelInfo[i].destination_type];
mask <<= 1; mask <<= 1;
} }
@@ -380,7 +380,7 @@ MixerInput::UpdateMixerChannels()
for (int i = 0; i < fMixerChannelCount; i++) { for (int i = 0; i < fMixerChannelCount; i++) {
int j; int j;
for (j = 0; j < fInputChannelCount; j++) { for (j = 0; j < fInputChannelCount; j++) {
if (fInputChannelInfo[j].designations & ChannelTypeToChannelMask(fMixerChannelInfo[i].type)) { if (fInputChannelInfo[j].destination_mask & ChannelTypeToChannelMask(fMixerChannelInfo[i].destination_type)) {
fMixerChannelInfo[i].buffer_base = fMixBuffer ? &fMixBuffer[j] : 0; fMixerChannelInfo[i].buffer_base = fMixBuffer ? &fMixBuffer[j] : 0;
break; break;
} }
@@ -390,50 +390,46 @@ MixerInput::UpdateMixerChannels()
fMixerChannelInfo[i].buffer_base = fMixBuffer; fMixerChannelInfo[i].buffer_base = fMixBuffer;
} }
} }
// apply old gains, overriding the 1.0 defaults for the old channels
if (old_mixer_channel_info != 0) {
for (int i = 0; i < fMixerChannelCount; i++) {
for (int j = 0; j < old_mixer_channel_count; j++) {
if (fMixerChannelInfo[i].type == old_mixer_channel_info[j].type) {
fMixerChannelInfo[i].gain = old_mixer_channel_info[j].gain;
break;
}
}
}
// also delete the old info array
delete [] old_mixer_channel_info;
}
for (int i = 0; i < fMixerChannelCount; i++) for (int i = 0; i < fMixerChannelCount; i++)
TRACE("UpdateMixerChannels: mixer channel %d, type %2d, des 0x%08X, base %p, gain %.3f\n", i, fMixerChannelInfo[i].type, ChannelTypeToChannelMask(fMixerChannelInfo[i].type), fMixerChannelInfo[i].buffer_base, fMixerChannelInfo[i].gain); TRACE("UpdateInputChannelDestinations: mixer channel %d, type %2d, base %p, gain %.3f\n", i, fMixerChannelInfo[i].destination_type, fMixerChannelInfo[i].buffer_base, fMixerChannelInfo[i].destination_gain);
TRACE("UpdateMixerChannels: leave\n"); TRACE("UpdateInputChannelDestinations: leave\n");
}
uint32
MixerInput::GetMixerChannelCount()
{
return fMixerChannelCount;
} }
void void
MixerInput::SetMixerChannelGain(int channel, float gain) MixerInput::SetInputChannelDestinationGain(int channel, int destination_type, float gain)
{ {
TRACE("SetMixerChannelGain chan %d, gain %.5f\n", channel, gain); TRACE("SetInputChannelDestinationGain: channel %d, destination_type %d, gain %.4f\n", channel, destination_type, gain);
// we don't need the channel, as each destination_type can only exist
// once for each MixerInput, but we use it for parameter validation
// and to have a interface similar to MixerOutput
if (channel < 0 || channel >= fMixerChannelCount) if (channel < 0 || channel >= fMixerChannelCount)
return; return;
if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
return;
if (gain < 0.0f) if (gain < 0.0f)
gain = 0.0f; gain = 0.0f;
fMixerChannelInfo[channel].gain = gain; fChannelTypeGain[destination_type] = gain;
for (int i = 0; i < fMixerChannelCount; i++) {
if (fMixerChannelInfo[i].destination_type == destination_type) {
fMixerChannelInfo[i].destination_gain = gain;
return;
}
}
} }
float float
MixerInput::GetMixerChannelGain(int channel) MixerInput::GetInputChannelDestinationGain(int channel, int destination_type)
{ {
// we don't need the channel, as each destination_type can only exist
// once for each MixerInput, but we use it for parameter validation
// and to have a interface similar to MixerOutput
if (channel < 0 || channel >= fMixerChannelCount) if (channel < 0 || channel >= fMixerChannelCount)
return 1.0; return 0.0f;
return fMixerChannelInfo[channel].gain; if (destination_type < 0 || destination_type >= MAX_CHANNEL_TYPES)
return 0.0f;
return fChannelTypeGain[destination_type];
} }
void void
@@ -466,8 +462,8 @@ MixerInput::SetMixBufferFormat(int32 framerate, int32 frames)
fInputChannelInfo[i].buffer_base = 0; fInputChannelInfo[i].buffer_base = 0;
fMixBufferFrameCount = 0; fMixBufferFrameCount = 0;
UpdateChannelDesignations(); UpdateInputChannelDestinationMask();
UpdateMixerChannels(); UpdateInputChannelDestinations();
return; return;
} }
@@ -502,6 +498,6 @@ MixerInput::SetMixBufferFormat(int32 framerate, int32 frames)
for (int i = 0; i < fInputChannelCount; i++) for (int i = 0; i < fInputChannelCount; i++)
fInputChannelInfo[i].buffer_base = &fMixBuffer[i]; fInputChannelInfo[i].buffer_base = &fMixBuffer[i];
UpdateChannelDesignations(); UpdateInputChannelDestinationMask();
UpdateMixerChannels(); UpdateInputChannelDestinations();
} }
@@ -3,9 +3,9 @@
#include <RealtimeAlloc.h> #include <RealtimeAlloc.h>
#include <MediaNode.h> #include <MediaNode.h>
#include "MixerCore.h"
#include "debug.h" #include "debug.h"
class MixerCore;
class ByteSwap; class ByteSwap;
class Resampler; class Resampler;
@@ -20,44 +20,46 @@ public:
void BufferReceived(BBuffer *buffer); void BufferReceived(BBuffer *buffer);
media_input & MediaInput(); media_input & MediaInput();
uint32 GetMixerChannelCount(); // The physical input channels
void SetMixerChannelGain(int channel, float gain); uint32 GetInputChannelCount();
float GetMixerChannelGain(int channel); int GetInputChannelType(int channel);
void SetInputChannelGain(int channel, float gain);
uint32 GetInputChannelCount(); float GetInputChannelGain(int channel);
void AddInputChannelDesignation(int channel, uint32 des);
void RemoveInputChannelDesignation(int channel, uint32 des); // The destinations for each channel
uint32 GetInputChannelDesignations(int channel); void AddInputChannelDestination(int channel, int destination_type);
uint32 GetInputChannelType(int channel); void RemoveInputChannelDestination(int channel, int destination_type);
void SetInputChannelGain(int channel, float gain); void SetInputChannelDestinationGain(int channel, int destination_type, float gain);
float GetInputChannelGain(int channel); float GetInputChannelDestinationGain(int channel, int destination_type);
bool HasInputChannelDestination(int channel, int destination_type);
int GetInputChannelForDestination(int destination_type); // returns -1 if not found
void SetEnabled(bool yesno); void SetEnabled(bool yesno);
bool IsEnabled(); bool IsEnabled();
// only for use by MixerCore // only for use by MixerCore
bool GetMixerChannelInfo(int channel, int64 framepos, bigtime_t time, const float **buffer, uint32 *sample_offset, int *type, float *gain); uint32 GetMixerChannelCount();
int GetMixerChannelType(int channel); bool GetMixerChannelInfo(int mixer_channel, int64 framepos, bigtime_t time, const float **buffer, uint32 *sample_offset, int *type, float *gain);
protected: protected:
friend class MixerCore; friend class MixerCore;
void SetMixBufferFormat(int32 framerate, int32 frames); void SetMixBufferFormat(int32 framerate, int32 frames);
private: private:
void UpdateChannelDesignations(); void UpdateInputChannelDestinationMask();
void UpdateMixerChannels(); void UpdateInputChannelDestinations();
private: private:
struct input_chan_info { struct input_chan_info {
float *buffer_base; float *buffer_base;
uint32 designations; // multiple or no bits sets uint32 destination_mask; // multiple or no bits sets
float gain; float gain;
}; };
struct mixer_chan_info { struct mixer_chan_info {
float *buffer_base; float *buffer_base;
int type; int destination_type;
float gain; float destination_gain;
}; };
private: private:
@@ -65,6 +67,8 @@ private:
media_input fInput; media_input fInput;
ByteSwap *fInputByteSwap; ByteSwap *fInputByteSwap;
float fChannelTypeGain[MAX_CHANNEL_TYPES];
bool fEnabled; bool fEnabled;
input_chan_info *fInputChannelInfo; // array input_chan_info *fInputChannelInfo; // array
@@ -84,34 +88,32 @@ private:
Resampler **fResampler; // array Resampler **fResampler; // array
rtm_pool *fRtmPool; rtm_pool *fRtmPool;
bool fUserOverridesChannelDesignations; bool fUserOverridesChannelDestinations;
int32 debugMixBufferFrames; int32 debugMixBufferFrames;
}; };
inline uint32
MixerInput::GetMixerChannelCount()
{
return fMixerChannelCount;
}
inline bool inline bool
MixerInput::GetMixerChannelInfo(int channel, int64 framepos, bigtime_t time, const float **buffer, uint32 *sample_offset, int *type, float *gain) MixerInput::GetMixerChannelInfo(int mixer_channel, int64 framepos, bigtime_t time, const float **buffer, uint32 *sample_offset, int *type, float *gain)
{ {
ASSERT(fMixBuffer); // this function should not be called if we don't have a mix buffer! ASSERT(fMixBuffer); // this function should not be called if we don't have a mix buffer!
ASSERT(channel >= 0 && channel < fMixerChannelCount); ASSERT(mixer_channel >= 0 && mixer_channel < fMixerChannelCount);
if (time > fLastDataAvailableTime || !fEnabled) if (time > fLastDataAvailableTime || !fEnabled)
return false; return false;
int32 offset = framepos % fMixBufferFrameCount; int32 offset = framepos % fMixBufferFrameCount;
if (channel == 0) PRINT(3, "GetMixerChannelInfo: frames %ld to %ld\n", offset, offset + debugMixBufferFrames - 1); if (mixer_channel == 0) PRINT(3, "GetMixerChannelInfo: frames %ld to %ld\n", offset, offset + debugMixBufferFrames - 1);
*buffer = reinterpret_cast<float *>(reinterpret_cast<char *>(fMixerChannelInfo[channel].buffer_base) + (offset * sizeof(float) * fInputChannelCount)); *buffer = reinterpret_cast<float *>(reinterpret_cast<char *>(fMixerChannelInfo[mixer_channel].buffer_base) + (offset * sizeof(float) * fInputChannelCount));
*sample_offset = sizeof(float) * fInputChannelCount; *sample_offset = sizeof(float) * fInputChannelCount;
*type = fMixerChannelInfo[channel].type; *type = fMixerChannelInfo[mixer_channel].destination_type;
*gain = fMixerChannelInfo[channel].gain; *gain = fMixerChannelInfo[mixer_channel].destination_gain;
return true; return true;
} }
inline int
MixerInput::GetMixerChannelType(int channel)
{
ASSERT(fMixBuffer); // this function should not be called if we don't have a mix buffer!
ASSERT(channel >= 0 && channel < fMixerChannelCount);
return fMixerChannelInfo[channel].type;
}
#endif #endif
@@ -104,7 +104,7 @@ MixerOutput::UpdateOutputChannels()
delete [] oldInfo; delete [] oldInfo;
} }
for (int i = 0; i < fOutputChannelCount; i++) for (int i = 0; i < fOutputChannelCount; i++)
TRACE("UpdateOutputChannels: output channel %d, des 0x%08X (type %2d), gain %.3f\n", i, fOutputChannelInfo[i].designation, ChannelMaskToChannelType(fOutputChannelInfo[i].designation), fOutputChannelInfo[i].gain); TRACE("UpdateOutputChannels: output channel %d, type %2d, gain %.3f\n", i, fOutputChannelInfo[i].channel_type, fOutputChannelInfo[i].channel_gain);
} }
void void
@@ -229,7 +229,7 @@ MixerOutput::AssignDefaultSources()
} }
} }
uint32 int
MixerOutput::GetOutputChannelType(int channel) MixerOutput::GetOutputChannelType(int channel)
{ {
if (channel < 0 || channel >= fOutputChannelCount) if (channel < 0 || channel >= fOutputChannelCount)
@@ -29,18 +29,18 @@ public:
// The physical output channels // The physical output channels
uint32 GetOutputChannelCount(); uint32 GetOutputChannelCount();
uint32 GetOutputChannelType(int channel); int GetOutputChannelType(int channel);
void SetOutputChannelGain(int channel, float gain); void SetOutputChannelGain(int channel, float gain);
float GetOutputChannelGain(int channel); float GetOutputChannelGain(int channel);
// The Sources for each channel // The sources for each channel
void AddOutputChannelSource(int channel, int source_type); void AddOutputChannelSource(int channel, int source_type);
void RemoveOutputChannelSource(int channel, int source_type); void RemoveOutputChannelSource(int channel, int source_type);
void SetOutputChannelSourceGain(int channel, int source_type, float source_gain); void SetOutputChannelSourceGain(int channel, int source_type, float source_gain);
float GetOutputChannelSourceGain(int channel, int source_type); float GetOutputChannelSourceGain(int channel, int source_type);
bool HasOutputChannelSource(int channel, int source_type); bool HasOutputChannelSource(int channel, int source_type);
// The Output can be muted // The output can be muted
void SetMuted(bool yesno); void SetMuted(bool yesno);
bool IsMuted(); bool IsMuted();
@@ -61,7 +61,7 @@ private:
private: private:
/* An entry in the source array is not the same as the /* An entry in the source array is not the same as the
* channel type, but the number should be the same * channel type, but the count should be the same
*/ */
enum { enum {
MAX_SOURCE_ENTRIES = MAX_CHANNEL_TYPES MAX_SOURCE_ENTRIES = MAX_CHANNEL_TYPES
@@ -100,15 +100,14 @@ inline float MixerOutput::GetOutputChannelGain(int channel)
inline uint32 MixerOutput::GetOutputChannelSourceCount(int channel) inline uint32 MixerOutput::GetOutputChannelSourceCount(int channel)
{ {
if (channel < 0 || channel >= fOutputChannelCount) ASSERT(channel >= 0 && channel < fOutputChannelCount);
return 0;
return fOutputChannelInfo[channel].source_count; return fOutputChannelInfo[channel].source_count;
} }
inline void MixerOutput::GetOutputChannelSourceInfoAt(int channel, int source_index, int *source_type, float *source_gain) inline void MixerOutput::GetOutputChannelSourceInfoAt(int channel, int source_index, int *source_type, float *source_gain)
{ {
ASSERT(channel >= 0 && channel < fOutputChannelCount); ASSERT(channel >= 0 && channel < fOutputChannelCount);
ASSERT(index >= 0 && source_index < fOutputChannelInfo[channel].source_count); ASSERT(source_index >= 0 && source_index < fOutputChannelInfo[channel].source_count);
*source_type = fOutputChannelInfo[channel].source_type[source_index]; *source_type = fOutputChannelInfo[channel].source_type[source_index];
*source_gain = fOutputChannelInfo[channel].source_gain[source_index]; *source_gain = fOutputChannelInfo[channel].source_gain[source_index];
} }