#include #include #include #include "MixerInput.h" #include "MixerCore.h" #include "MixerUtils.h" #include "ByteSwap.h" #include "debug.h" MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixSampleRate, int32 mixFramesCount, bigtime_t mixStartTime) : fCore(core), fInput(input), fInputByteSwap(0), fInputChannelInfo(0), fInputChannelCount(0), fInputChannelMask(0), fMixerChannelInfo(0), fMixerChannelCount(0), fMixBuffer(0), fMixBufferSampleRate(0), fMixBufferFrames(0), fMixBufferStartTime(0), fUserOverridesChannelDesignations(false) { fix_multiaudio_format(&fInput.format.u.raw_audio); PRINT_INPUT("MixerInput::MixerInput", fInput); PRINT_CHANNEL_MASK(fInput.format); ASSERT(fInput.format.u.raw_audio.channel_count > 0); fInputChannelCount = fInput.format.u.raw_audio.channel_count; fInputChannelMask = fInput.format.u.raw_audio.channel_mask; fInputChannelInfo = new input_chan_info[fInputChannelCount]; // perhaps we need byte swapping if (fInput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) { if ( fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT || fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_INT || fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_SHORT) { fInputByteSwap = new ByteSwap(fInput.format.u.raw_audio.format); } } // initialize fInputChannelInfo for (int i = 0; i < fInputChannelCount; i++) { fInputChannelInfo[i].buffer_base = 0; // will be set by SetMixBufferFormat() fInputChannelInfo[i].designations = 0; // will be set by UpdateChannelDesignations() fInputChannelInfo[i].gain = 1.0; } // fMixerChannelInfo and fMixerChannelCount will be initialized by UpdateMixerChannels() SetMixBufferFormat(mixSampleRate, mixFramesCount, mixStartTime); UpdateChannelDesignations(); UpdateMixerChannels(); // 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() { if (fMixBuffer) rtm_free(fMixBuffer); delete [] fInputChannelInfo; delete [] fMixerChannelInfo; } void MixerInput::BufferReceived(BBuffer *buffer) { void *data; size_t size; bigtime_t start; ASSERT(fMixBuffer); data = buffer->Data(); size = buffer->SizeUsed(); start = buffer->Header()->start_time; // swap the byte order of this buffer, if necessary if (fInputByteSwap) fInputByteSwap->Swap(data, size); printf("mix buffer start %14Ld, buffer start %14Ld\n", fMixBufferStartTime, start); } media_input & MixerInput::MediaInput() { return fInput; } int32 MixerInput::ID() { return fInput.destination.id; } void MixerInput::AddInputChannelDesignation(int channel, uint32 des) { ASSERT(count_nonzero_bits(des) == 1); // test if the channel is valid if (channel < 0 || channel >= fInputChannelCount) return; // test if it is already set if (fInputChannelInfo[channel].designations & des) return; // remove it from all other channels that might have it for (int i = 0; i < fInputChannelCount; i++) fInputChannelInfo[i].designations &= ~des; // add it to specified channel fInputChannelInfo[channel].designations |= des; fUserOverridesChannelDesignations = true; UpdateMixerChannels(); } void MixerInput::RemoveInputChannelDesignation(int channel, uint32 des) { ASSERT(count_nonzero_bits(des) == 1); // test if the channel is valid if (channel < 0 || channel >= fInputChannelCount) return; // test if it is really set if ((fInputChannelInfo[channel].designations & des) == 0) return; // remove it from specified channel fInputChannelInfo[channel].designations &= ~des; fUserOverridesChannelDesignations = true; UpdateMixerChannels(); } uint32 MixerInput::GetInputChannelDesignations(int channel) { // test if the channel is valid if (channel < 0 || channel >= fInputChannelCount) return 0; return fInputChannelInfo[channel].designations; } uint32 MixerInput::GetInputChannelType(int channel) { // test if the channel is valid if (channel < 0 || channel >= fInputChannelCount) return 0; return GetChannelMask(channel, fInputChannelMask); } void MixerInput::SetInputChannelGain(int channel, float gain) { // test if the channel is valid if (channel < 0 || channel >= fInputChannelCount) return; if (gain < 0.0f) gain = 0.0f; fInputChannelInfo[channel].gain = gain; } float MixerInput::GetInputChannelGain(int channel) { // test if the channel is valid if (channel < 0 || channel >= fInputChannelCount) return 0.0f; return fInputChannelInfo[channel].gain; } void MixerInput::UpdateChannelDesignations() { // is the user already messed with the assignmens, don't do anything. if (fUserOverridesChannelDesignations) return; printf("UpdateChannelDesignations: enter\n"); if (fInputChannelCount == 1 && (GetChannelMask(0, fInputChannelMask) & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT))) { // a left or right channel get's output as stereo on both fInputChannelInfo[0].designations = B_CHANNEL_LEFT | B_CHANNEL_RIGHT; } else { // everything else get's mapped 1:1 for (int i = 0; i < fInputChannelCount; i++) fInputChannelInfo[i].designations = GetChannelMask(i, fInputChannelMask); } for (int i = 0; i < fInputChannelCount; i++) printf("UpdateChannelDesignations: input channel %d, designations 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].designations, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); printf("UpdateChannelDesignations: enter\n"); } void MixerInput::UpdateMixerChannels() { uint32 channel_count; uint32 all_bits; uint32 mask; mixer_chan_info *old_mixer_channel_info; uint32 old_mixer_channel_count; ASSERT(fMixBuffer); printf("UpdateMixerChannels: enter\n"); for (int i = 0; i < fInputChannelCount; i++) printf("UpdateMixerChannels: input channel %d, designations 0x%08X, base %p, gain %.3f\n", i, fInputChannelInfo[i].designations, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); all_bits = 0; for (int i = 0; i < fInputChannelCount; i++) all_bits |= fInputChannelInfo[i].designations; printf("UpdateMixerChannels: all_bits = %08x\n", all_bits); channel_count = count_nonzero_bits(all_bits); printf("UpdateMixerChannels: %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) { old_mixer_channel_info = fMixerChannelInfo; old_mixer_channel_count = fMixerChannelCount; fMixerChannelInfo = new mixer_chan_info[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 for (int i = 0, mask = 1; i < fMixerChannelCount; i++) { while (mask != 0 && (all_bits & mask) == 0) mask <<= 1; fMixerChannelInfo[i].type = ChannelMaskToChannelType(mask); mask <<= 1; } // assign buffer_base pointer for each mixer channel for (int i = 0; i < fMixerChannelCount; i++) { int j; for (j = 0; j < fInputChannelCount; j++) { if (fInputChannelInfo[j].designations & ChannelTypeToChannelMask(fMixerChannelInfo[i].type)) { fMixerChannelInfo[i].buffer_base = &fMixBuffer[j]; break; } } if (j == fInputChannelCount) { printf("buffer assignment failed for mixer chan %d\n", i); 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++) printf("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); printf("UpdateMixerChannels: leave\n"); } uint32 MixerInput::GetMixerChannelCount() { return fMixerChannelCount; } void MixerInput::GetMixerChannelInfo(int channel, const float **buffer, uint32 *sample_offset, int *type, float *gain) { ASSERT(fMixBuffer); ASSERT(channel >= 0 && channel < fMixerChannelCount); *buffer = fMixerChannelInfo[channel].buffer_base; *sample_offset = sizeof(float) * fInputChannelCount; *type = fMixerChannelInfo[channel].type; *gain = fMixerChannelInfo[channel].gain; } void MixerInput::SetMixerChannelGain(int channel, float gain) { if (channel < 0 || channel >= fMixerChannelCount) return; if (gain < 0.0f) gain = 0.0f; fMixerChannelInfo[channel].gain = gain; } float MixerInput::GetMixerChannelGain(int channel) { if (channel < 0 || channel >= fMixerChannelCount) return 1.0; return fMixerChannelInfo[channel].gain; } void MixerInput::SetMixBufferFormat(float samplerate, int32 frames, bigtime_t starttime) { fMixBufferSampleRate = samplerate; fMixBufferFrames = frames; fMixBufferStartTime = starttime; if (fMixBuffer) rtm_free(fMixBuffer); fMixBuffer = (float *)rtm_alloc(NULL, sizeof(float) * fInputChannelCount * fMixBufferFrames); for (int i = 0; i < fInputChannelCount; i++) fInputChannelInfo[i].buffer_base = &fMixBuffer[i * fMixBufferFrames]; }