diff --git a/src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp b/src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp index 736a4d8ddf..cb8b8b7031 100644 --- a/src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp +++ b/src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp @@ -465,19 +465,19 @@ AudioMixer::FormatChangeRequested(const media_source &source, const media_destin //printf("AudioMixer: SendLatencyChange %Ld\n", EventLatency()); //SendLatencyChange(source, destination, EventLatency()); - delete fBufferGroup; - fBufferGroup = CreateBufferGroup(); - fCore->SetOutputBufferGroup(fBufferGroup); - // apply latency change fCore->SetTimingInfo(TimeSource(), fDownstreamLatency); // apply format change fCore->OutputFormatChanged(io_format->u.raw_audio); + delete fBufferGroup; + fBufferGroup = CreateBufferGroup(); + fCore->SetOutputBufferGroup(fBufferGroup); + fCore->Unlock(); return B_OK; - + err: fCore->Unlock(); return B_ERROR; diff --git a/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp b/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp index e8732176eb..7fa011a495 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp @@ -204,7 +204,7 @@ MixerCore::ApplyOutputFormat() delete fMixBufferChannelTypes; - fMixBufferFrameRate = (int32)format.frame_rate; + fMixBufferFrameRate = (int32)(0.5 + format.frame_rate); fMixBufferFrameCount = frames_per_buffer(format); if (fDoubleRateMixing) { fMixBufferFrameRate *= 2; diff --git a/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp b/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp index 6b82500c7e..619112b338 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp @@ -189,6 +189,12 @@ MixerInput::ID() return fInput.destination.id; } +uint32 +MixerInput::GetInputChannelCount() +{ + return fInputChannelCount; +} + void MixerInput::AddInputChannelDesignation(int channel, uint32 des) { @@ -385,19 +391,6 @@ MixerInput::GetMixerChannelCount() return fMixerChannelCount; } -void -MixerInput::GetMixerChannelInfo(int channel, int64 framepos, 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(channel >= 0 && channel < fMixerChannelCount); - int32 offset = framepos % fMixBufferFrameCount; - if (channel == 0) PRINT(3, "GetMixerChannelInfo: frames %ld to %ld\n", offset, offset + debugMixBufferFrames - 1); - *buffer = reinterpret_cast(reinterpret_cast(fMixerChannelInfo[channel].buffer_base) + (offset * sizeof(float) * fInputChannelCount)); - *sample_offset = sizeof(float) * fInputChannelCount; - *type = fMixerChannelInfo[channel].type; - *gain = fMixerChannelInfo[channel].gain; -} - void MixerInput::SetMixerChannelGain(int channel, float gain) { diff --git a/src/add-ons/media/media-add-ons/mixer/MixerInput.h b/src/add-ons/media/media-add-ons/mixer/MixerInput.h index 1c10ff0261..31ee9bd7ee 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerInput.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerInput.h @@ -1,6 +1,8 @@ #ifndef _MIXER_INPUT_H #define _MIXER_INPUT_H +#include "debug.h" + class MixerCore; class ByteSwap; class Resampler; @@ -18,10 +20,10 @@ public: media_input & MediaInput(); uint32 GetMixerChannelCount(); - void GetMixerChannelInfo(int channel, int64 framepos, const float **buffer, uint32 *sample_offset, int *type, float *gain); void SetMixerChannelGain(int channel, float gain); float GetMixerChannelGain(int channel); + uint32 GetInputChannelCount(); void AddInputChannelDesignation(int channel, uint32 des); void RemoveInputChannelDesignation(int channel, uint32 des); uint32 GetInputChannelDesignations(int channel); @@ -29,6 +31,10 @@ public: void SetInputChannelGain(int channel, float gain); float GetInputChannelGain(int channel); + // only for use by MixerCore + void GetMixerChannelInfo(int channel, int64 framepos, const float **buffer, uint32 *sample_offset, int *type, float *gain); + int GetMixerChannelType(int channel); + protected: friend class MixerCore; void SetMixBufferFormat(int32 framerate, int32 frames); @@ -74,4 +80,25 @@ private: int32 debugMixBufferFrames; }; +inline void +MixerInput::GetMixerChannelInfo(int channel, int64 framepos, 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(channel >= 0 && channel < fMixerChannelCount); + int32 offset = framepos % fMixBufferFrameCount; + if (channel == 0) PRINT(3, "GetMixerChannelInfo: frames %ld to %ld\n", offset, offset + debugMixBufferFrames - 1); + *buffer = reinterpret_cast(reinterpret_cast(fMixerChannelInfo[channel].buffer_base) + (offset * sizeof(float) * fInputChannelCount)); + *sample_offset = sizeof(float) * fInputChannelCount; + *type = fMixerChannelInfo[channel].type; + *gain = fMixerChannelInfo[channel].gain; +} + +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 diff --git a/src/add-ons/media/media-add-ons/mixer/MixerOutput.cpp b/src/add-ons/media/media-add-ons/mixer/MixerOutput.cpp index b8b2e353ff..e3f39eed78 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerOutput.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerOutput.cpp @@ -6,15 +6,20 @@ MixerOutput::MixerOutput(MixerCore *core, const media_output &output) : fCore(core), - fOutput(output) + fOutput(output), + fOutputChannelCount(0), + fOutputChannelInfo(0) { fix_multiaudio_format(&fOutput.format.u.raw_audio); PRINT_OUTPUT("MixerOutput::MixerOutput", fOutput); PRINT_CHANNEL_MASK(fOutput.format); + + UpdateOutputChannels(); } MixerOutput::~MixerOutput() { + delete fOutputChannelInfo; } media_output & @@ -31,4 +36,148 @@ MixerOutput::ChangeFormat(const media_multi_audio_format &format) PRINT_OUTPUT("MixerOutput::ChangeFormat", fOutput); PRINT_CHANNEL_MASK(fOutput.format); + + UpdateOutputChannels(); +} + +void +MixerOutput::UpdateOutputChannels() +{ + output_chan_info *oldInfo = fOutputChannelInfo; + uint32 oldCount = fOutputChannelCount; + + fOutputChannelCount = fOutput.format.u.raw_audio.channel_count; + fOutputChannelInfo = new output_chan_info[fOutputChannelCount]; + for (int i = 0; i < fOutputChannelCount; i++) { + fOutputChannelInfo[i].designation = GetChannelMask(i, fOutput.format.u.raw_audio.channel_mask); + fOutputChannelInfo[i].gain = 1.0; + fOutputChannelInfo[i].source_count = 1; + fOutputChannelInfo[i].source_gain[0] = 1.0; + fOutputChannelInfo[i].source_type[0] = ChannelMaskToChannelType(fOutputChannelInfo[i].designation); + } + AssignDefaultSources(); + + // apply old gains and sources, overriding the 1.0 gain defaults for the old channels + if (oldInfo != 0 && oldCount != 0) { + for (int i = 0; i < fOutputChannelCount; i++) { + for (int j = 0; j < oldCount; j++) { + if (fOutputChannelInfo[i].designation == oldInfo[j].designation) { + fOutputChannelInfo[i].gain == oldInfo[j].gain; + fOutputChannelInfo[i].source_count == oldInfo[j].source_count; + for (int k = 0; k < fOutputChannelInfo[i].source_count; k++) { + fOutputChannelInfo[i].source_gain[k] == oldInfo[j].source_gain[k]; + fOutputChannelInfo[i].source_type[k] == oldInfo[j].source_type[k]; + } + break; + } + } + } + // also delete the old info array + delete [] oldInfo; + } + for (int i = 0; i < fOutputChannelCount; i++) + printf("UpdateOutputChannels: output channel %d, des 0x%08X (type %2d), gain %.3f\n", i, fOutputChannelInfo[i].designation, ChannelMaskToChannelType(fOutputChannelInfo[i].designation), fOutputChannelInfo[i].gain); +} + +void +MixerOutput::AssignDefaultSources() +{ + // XXX assign default sources + for (int i = 0; i < fOutputChannelCount; i++) { + for (int j = 0; j < fOutputChannelInfo[i].source_count; j++) { + printf("AssignDefaultSources: output channel %d, source %d: des 0x%08X (type %2d), gain %.3f\n", i, j, ChannelTypeToChannelMask(fOutputChannelInfo[i].source_type[j]), fOutputChannelInfo[i].source_type[j], fOutputChannelInfo[i].source_gain[j]); + } + } +} + +uint32 +MixerOutput::GetOutputChannelDesignation(int channel) +{ + if (channel < 0 || channel >= fOutputChannelCount) + return 0; + return fOutputChannelInfo[channel].designation; +} + +void +MixerOutput::SetOutputChannelGain(int channel, float gain) +{ + if (channel < 0 || channel >= fOutputChannelCount) + return; + fOutputChannelInfo[channel].gain = gain; +} + +void +MixerOutput::AddOutputChannelSource(int channel, uint32 source_designation, float source_gain) +{ + if (channel < 0 || channel >= fOutputChannelCount) + return; + if (fOutputChannelInfo[channel].source_count == MAX_SOURCES) + return; + int source_type = ChannelMaskToChannelType(source_designation); + for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) { + if (fOutputChannelInfo[channel].source_type[i] == source_type) + return; + } + fOutputChannelInfo[channel].source_type[fOutputChannelInfo[channel].source_count] = source_type; + fOutputChannelInfo[channel].source_gain[fOutputChannelInfo[channel].source_count] = source_gain; + fOutputChannelInfo[channel].source_count++; +} + +void +MixerOutput::RemoveOutputChannelSource(int channel, uint32 source_designation) +{ + if (channel < 0 || channel >= fOutputChannelCount) + return; + int source_type = ChannelMaskToChannelType(source_designation); + for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) { + if (fOutputChannelInfo[channel].source_type[i] == source_type) { + fOutputChannelInfo[channel].source_type[i] = fOutputChannelInfo[channel].source_type[fOutputChannelInfo[channel].source_count - 1]; + fOutputChannelInfo[channel].source_gain[i] = fOutputChannelInfo[channel].source_gain[fOutputChannelInfo[channel].source_count - 1]; + fOutputChannelInfo[channel].source_count--; + return; + } + } +} + +void +MixerOutput::SetOutputChannelSourceGain(int channel, uint32 source_designation, float source_gain) +{ + if (channel < 0 || channel >= fOutputChannelCount) + return; + int source_type = ChannelMaskToChannelType(source_designation); + for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) { + if (fOutputChannelInfo[channel].source_type[i] == source_type) { + fOutputChannelInfo[channel].source_gain[i] = source_gain; + return; + } + } +} + +float +MixerOutput::GetOutputChannelSourceGain(int channel, uint32 source_designation) +{ + if (channel < 0 || channel >= fOutputChannelCount) + return 1.0; + int source_type = ChannelMaskToChannelType(source_designation); + for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) { + if (fOutputChannelInfo[channel].source_type[i] == source_type) { + return fOutputChannelInfo[channel].source_gain[i]; + } + } + return 1.0; +} + +void +MixerOutput::GetOutputChannelSourceAt(int channel, int index, uint32 *source_designation, float *source_gain) +{ + if (channel < 0 || channel >= fOutputChannelCount) + return; + if (index >= fOutputChannelInfo[channel].source_count) { + // ERROR + *source_gain = 1.0; + *source_designation = 0; + return; + } + *source_gain = fOutputChannelInfo[channel].source_gain[index]; + *source_designation = ChannelTypeToChannelMask(fOutputChannelInfo[channel].source_type[index]); } diff --git a/src/add-ons/media/media-add-ons/mixer/MixerOutput.h b/src/add-ons/media/media-add-ons/mixer/MixerOutput.h index 19f15b6b05..3db8625f83 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerOutput.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerOutput.h @@ -1,6 +1,10 @@ #ifndef _MIXER_OUTPUT_H #define _MIXER_OUTPUT_H +#include "debug.h" + +#define MAX_SOURCES 20 + class MixerCore; class MixerOutput @@ -13,9 +17,66 @@ public: void ChangeFormat(const media_multi_audio_format &format); + uint32 GetOutputChannelCount(); + uint32 GetOutputChannelDesignation(int channel); + void SetOutputChannelGain(int channel, float gain); + float GetOutputChannelGain(int channel); + + uint32 GetOutputChannelSourceCount(int channel); + void AddOutputChannelSource(int channel, uint32 source_designation, float source_gain); + void RemoveOutputChannelSource(int channel, uint32 source_designation); + void SetOutputChannelSourceGain(int channel, uint32 source_designation, float source_gain); + float GetOutputChannelSourceGain(int channel, uint32 source_designation); + void GetOutputChannelSourceAt(int channel, int index, uint32 *source_designation, float *source_gain); + + // only for use by MixerCore + void GetMixerChannelInfo(int channel, int index, int *type, float *gain); + private: - MixerCore *fCore; - media_output fOutput; + void UpdateOutputChannels(); + void AssignDefaultSources(); + +private: + struct output_chan_info { + uint32 designation; // only one bit set + float gain; + int source_count; + float source_gain[MAX_SOURCES]; + int source_type[MAX_SOURCES]; + }; + + MixerCore *fCore; + media_output fOutput; + + uint32 fOutputChannelCount; + output_chan_info *fOutputChannelInfo; //array }; +inline uint32 MixerOutput::GetOutputChannelCount() +{ + return fOutputChannelCount; +} + +inline float MixerOutput::GetOutputChannelGain(int channel) +{ + if (channel < 0 || channel >= fOutputChannelCount) + return 1.0; + return fOutputChannelInfo[channel].gain; +} + +inline uint32 MixerOutput::GetOutputChannelSourceCount(int channel) +{ + if (channel < 0 || channel >= fOutputChannelCount) + return 0; + return fOutputChannelInfo[channel].source_count; +} + +inline void MixerOutput::GetMixerChannelInfo(int channel, int index, int *type, float *gain) +{ + ASSERT (channel >= 0 && channel < fOutputChannelCount); + ASSERT(index >= 0 && index < fOutputChannelInfo[channel].source_count); + *type = fOutputChannelInfo[channel].source_type[index]; + *gain = fOutputChannelInfo[channel].source_gain[index]; +} + #endif