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:
@@ -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
|
// add it to specified channel
|
||||||
fInputChannelInfo[channel].designations |= des;
|
fInputChannelInfo[channel].destination_mask |= mask;
|
||||||
|
|
||||||
fUserOverridesChannelDesignations = true;
|
fUserOverridesChannelDestinations = true;
|
||||||
UpdateMixerChannels();
|
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;
|
||||||
}
|
}
|
||||||
@@ -391,49 +391,45 @@ MixerInput::UpdateMixerChannels()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
||||||
@@ -21,43 +21,45 @@ public:
|
|||||||
|
|
||||||
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);
|
||||||
|
float GetInputChannelGain(int channel);
|
||||||
|
|
||||||
uint32 GetInputChannelCount();
|
// The destinations for each channel
|
||||||
void AddInputChannelDesignation(int channel, uint32 des);
|
void AddInputChannelDestination(int channel, int destination_type);
|
||||||
void RemoveInputChannelDesignation(int channel, uint32 des);
|
void RemoveInputChannelDestination(int channel, int destination_type);
|
||||||
uint32 GetInputChannelDesignations(int channel);
|
void SetInputChannelDestinationGain(int channel, int destination_type, float gain);
|
||||||
uint32 GetInputChannelType(int channel);
|
float GetInputChannelDestinationGain(int channel, int destination_type);
|
||||||
void SetInputChannelGain(int channel, float gain);
|
bool HasInputChannelDestination(int channel, int destination_type);
|
||||||
float GetInputChannelGain(int channel);
|
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];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user