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 1000477acd..8e316f2074 100644 --- a/src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp +++ b/src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp @@ -1475,7 +1475,7 @@ AudioMixer::SetParameterValue(int32 id, bigtime_t when, const void *value, if (size != sizeof(int32)) goto err; fCore->Settings()->SetResamplingAlgorithm(static_cast(value)[0]); - // XXX tell the core to change the algorithm + fCore->UpdateResamplingAlgorithm(); break; case 80: // Refuse output format changes if (size != sizeof(int32)) 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 3b5bdefd35..3ff2a8fecc 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp @@ -120,6 +120,21 @@ MixerCore::Settings() } +void +MixerCore::UpdateResamplingAlgorithm() +{ + ASSERT_LOCKED(); + + _UpdateResamplers(fOutput->MediaOutput().format.u.raw_audio); + + for (int32 i = fInputs->CountItems() - 1; i >= 0; i--) { + MixerInput* input + = reinterpret_cast(fInputs->ItemAtFast(i)); + input->UpdateResamplingAlgorithm(); + } +} + + void MixerCore::SetOutputAttenuation(float gain) { @@ -133,7 +148,7 @@ MixerCore::AddInput(const media_input& input) { ASSERT_LOCKED(); MixerInput* in = new MixerInput(this, input, fMixBufferFrameRate, - fMixBufferFrameCount, Settings()->ResamplingAlgorithm()); + fMixBufferFrameCount); fInputs->AddItem(in); return in; } @@ -149,7 +164,7 @@ MixerCore::AddOutput(const media_output& output) } fOutput = new MixerOutput(this, output); // the output format might have been adjusted inside MixerOutput - ApplyOutputFormat(); + _ApplyOutputFormat(); ASSERT(!fRunning); if (fStarted && fOutputEnabled) @@ -252,76 +267,13 @@ MixerCore::OutputFormatChanged(const media_multi_audio_format &format) Stop(); fOutput->ChangeFormat(format); - ApplyOutputFormat(); + _ApplyOutputFormat(); if (was_started) Start(); } -void -MixerCore::ApplyOutputFormat() -{ - ASSERT_LOCKED(); - - media_multi_audio_format format = fOutput->MediaOutput().format.u.raw_audio; - - if (fMixBuffer != NULL) - rtm_free(fMixBuffer); - - delete fMixBufferChannelTypes; - - fMixBufferFrameRate = (int32)(0.5 + format.frame_rate); - fMixBufferFrameCount = frames_per_buffer(format); - if (fDoubleRateMixing) { - fMixBufferFrameRate *= 2; - fMixBufferFrameCount *= 2; - } - fMixBufferChannelCount = format.channel_count; - ASSERT(fMixBufferChannelCount == fOutput->GetOutputChannelCount()); - fMixBufferChannelTypes = new int32 [format.channel_count]; - - for (int i = 0; i < fMixBufferChannelCount; i++) { - fMixBufferChannelTypes[i] - = ChannelMaskToChannelType(GetChannelMask(i, format.channel_mask)); - } - - fMixBuffer = (float*)rtm_alloc(NULL, sizeof(float) * fMixBufferFrameCount - * fMixBufferChannelCount); - ASSERT(fMixBuffer != NULL); - - if (fResampler != NULL) { - for (int i = 0; i < fMixBufferChannelCount; i++) - delete fResampler[i]; - delete[] fResampler; - } - - fResampler = new Resampler*[fMixBufferChannelCount]; - for (int i = 0; i < fMixBufferChannelCount; i++) { - switch (Settings()->ResamplingAlgorithm()) { - case 2: - fResampler[i] = new Interpolate( - media_raw_audio_format::B_AUDIO_FLOAT, format.format); - break; - default: - fResampler[i] = new Resampler( - media_raw_audio_format::B_AUDIO_FLOAT, format.format); - } - } - - TRACE("MixerCore::OutputFormatChanged:\n"); - TRACE(" fMixBufferFrameRate %ld\n", fMixBufferFrameRate); - TRACE(" fMixBufferFrameCount %ld\n", fMixBufferFrameCount); - TRACE(" fMixBufferChannelCount %ld\n", fMixBufferChannelCount); - for (int i = 0; i < fMixBufferChannelCount; i++) - TRACE(" fMixBufferChannelTypes[%i] %ld\n", i, fMixBufferChannelTypes[i]); - - MixerInput *input; - for (int i = 0; (input = Input(i)); i++) - input->SetMixBufferFormat(fMixBufferFrameRate, fMixBufferFrameCount); -} - - void MixerCore::SetOutputBufferGroup(BBufferGroup *group) { @@ -411,8 +363,8 @@ MixerCore::StartMixThread() ASSERT(fOutput); fRunning = true; fMixThreadWaitSem = create_sem(0, "mix thread wait"); - fMixThread = spawn_thread(MixThreadEntry, "Yeah baby, very shagadelic", 120, - this); + fMixThread = spawn_thread(_MixThreadEntry, "Yeah baby, very shagadelic", + 120, this); resume_thread(fMixThread); } @@ -434,16 +386,92 @@ MixerCore::StopMixThread() } -int32 -MixerCore::MixThreadEntry(void* arg) +// #pragma mark - private + + +void +MixerCore::_UpdateResamplers(const media_multi_audio_format& format) { - static_cast(arg)->MixThread(); + ASSERT_LOCKED(); + + if (fResampler != NULL) { + for (int i = 0; i < fMixBufferChannelCount; i++) + delete fResampler[i]; + delete[] fResampler; + } + + fResampler = new Resampler*[fMixBufferChannelCount]; + for (int i = 0; i < fMixBufferChannelCount; i++) { + switch (Settings()->ResamplingAlgorithm()) { + case 2: + fResampler[i] = new Interpolate( + media_raw_audio_format::B_AUDIO_FLOAT, format.format); + break; + default: + fResampler[i] = new Resampler( + media_raw_audio_format::B_AUDIO_FLOAT, format.format); + } + } +} + + +void +MixerCore::_ApplyOutputFormat() +{ + ASSERT_LOCKED(); + + const media_multi_audio_format& format + = fOutput->MediaOutput().format.u.raw_audio; + + if (fMixBuffer != NULL) + rtm_free(fMixBuffer); + + delete fMixBufferChannelTypes; + + fMixBufferFrameRate = (int32)(0.5 + format.frame_rate); + fMixBufferFrameCount = frames_per_buffer(format); + if (fDoubleRateMixing) { + fMixBufferFrameRate *= 2; + fMixBufferFrameCount *= 2; + } + fMixBufferChannelCount = format.channel_count; + ASSERT(fMixBufferChannelCount == fOutput->GetOutputChannelCount()); + fMixBufferChannelTypes = new int32 [format.channel_count]; + + for (int i = 0; i < fMixBufferChannelCount; i++) { + fMixBufferChannelTypes[i] + = ChannelMaskToChannelType(GetChannelMask(i, format.channel_mask)); + } + + fMixBuffer = (float*)rtm_alloc(NULL, sizeof(float) * fMixBufferFrameCount + * fMixBufferChannelCount); + ASSERT(fMixBuffer != NULL); + + _UpdateResamplers(format); + + TRACE("MixerCore::OutputFormatChanged:\n"); + TRACE(" fMixBufferFrameRate %ld\n", fMixBufferFrameRate); + TRACE(" fMixBufferFrameCount %ld\n", fMixBufferFrameCount); + TRACE(" fMixBufferChannelCount %ld\n", fMixBufferChannelCount); + for (int i = 0; i < fMixBufferChannelCount; i++) + TRACE(" fMixBufferChannelTypes[%i] %ld\n", i, fMixBufferChannelTypes[i]); + + MixerInput *input; + for (int i = 0; (input = Input(i)); i++) + input->SetMixBufferFormat(fMixBufferFrameRate, fMixBufferFrameCount); +} + + +int32 +MixerCore::_MixThreadEntry(void* arg) +{ + static_cast(arg)->_MixThread(); return 0; } void -MixerCore::MixThread() +MixerCore::_MixThread() { // The broken BeOS R5 multiaudio node starts with time 0, // then publishes negative times for about 50ms, publishes 0 @@ -453,7 +481,7 @@ MixerCore::MixThread() bigtime_t start = fTimeSource->Now(); Unlock(); while (start <= 0) { - TRACE("MixerCore: delaying MixThread start, timesource is at %Ld\n", + TRACE("MixerCore: delaying _MixThread start, timesource is at %Ld\n", start); snooze(5000); if (!LockFromMixThread()) @@ -471,7 +499,7 @@ MixerCore::MixThread() bigtime_t bufferRequestTimeout = buffer_duration( fOutput->MediaOutput().format.u.raw_audio) / 2; - TRACE("MixerCore: starting MixThread at %Ld with latency %Ld and " + TRACE("MixerCore: starting _MixThread at %Ld with latency %Ld and " "downstream latency %Ld, bufferRequestTimeout %Ld\n", start, latency, fDownstreamLatency, bufferRequestTimeout); @@ -483,7 +511,7 @@ MixerCore::MixThread() bigtime_t timeBase = duration_for_frames(fMixBufferFrameRate, frameBase); Unlock(); - TRACE("MixerCore: starting MixThread, start %Ld, timeBase %Ld, " + TRACE("MixerCore: starting _MixThread, start %Ld, timeBase %Ld, " "frameBase %Ld\n", start, timeBase, frameBase); ASSERT(fMixBufferFrameCount > 0); @@ -603,13 +631,13 @@ MixerCore::MixThread() memset(fMixBuffer, 0, fMixBufferChannelCount * fMixBufferFrameCount * sizeof(float)); for (int channel = 0; channel < fMixBufferChannelCount; channel++) { - PRINT(5, "MixThread: channel %d has %d sources\n", channel, + PRINT(5, "_MixThread: channel %d has %d sources\n", channel, mixChanInfos[channel].CountItems()); int count = mixChanInfos[channel].CountItems(); for (int i = 0; i < count; i++) { chan_info* info = mixChanInfos[channel].ItemAt(i); - PRINT(5, "MixThread: base %p, sample-offset %2d, gain %.3f\n", + PRINT(5, "_MixThread: base %p, sample-offset %2d, gain %.3f\n", info->base, info->sample_offset, info->gain); // This looks slightly ugly, but the current GCC will generate // the fastest code this way. diff --git a/src/add-ons/media/media-add-ons/mixer/MixerCore.h b/src/add-ons/media/media-add-ons/mixer/MixerCore.h index 09bf56faa5..5a5c7e233d 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerCore.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerCore.h @@ -36,6 +36,7 @@ public: virtual ~MixerCore(); MixerSettings* Settings(); + void UpdateResamplingAlgorithm(); // To avoid calling Settings()->AttenuateOutput() for every outgoing // buffer, this setting is cached in fOutputGain and must be set by @@ -77,9 +78,11 @@ public: uint32 OutputChannelCount(); private: - void ApplyOutputFormat(); - static int32 MixThreadEntry(void* arg); - void MixThread(); + void _UpdateResamplers( + const media_multi_audio_format& format); + void _ApplyOutputFormat(); + static int32 _MixThreadEntry(void* arg); + void _MixThread(); private: BLocker* fLocker; 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 5f0ebc3fd8..ec4126516d 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp @@ -20,26 +20,26 @@ #include "Resampler.h" -MixerInput::MixerInput(MixerCore *core, const media_input &input, - float mixFrameRate, int32 mixFrameCount, int resamplingAlgorithm) +MixerInput::MixerInput(MixerCore* core, const media_input& input, + float mixFrameRate, int32 mixFrameCount) : fCore(core), fInput(input), - fInputByteSwap(0), + fInputByteSwap(NULL), fEnabled(true), - fInputChannelInfo(0), + fInputChannelInfo(NULL), fInputChannelCount(0), fInputChannelMask(0), fMixerChannelInfo(0), fMixerChannelCount(0), - fMixBuffer(0), + fMixBuffer(NULL), fMixBufferFrameRate(0), fMixBufferFrameCount(0), fLastDataFrameWritten(-1), fLastDataAvailableTime(-1), fFractionalFrames(0.0), - fResampler(0), - fRtmPool(0), + fResampler(NULL), + fRtmPool(NULL), fUserOverridesChannelDestinations(false) { fix_multiaudio_format(&fInput.format.u.raw_audio); @@ -72,28 +72,14 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, fInputChannelInfo[i].buffer_base = 0; // will be set by SetMixBufferFormat() fInputChannelInfo[i].destination_mask = 0; - // will be set by UpdateInputChannelDestinationMask() + // will be set by _UpdateInputChannelDestinationMask() fInputChannelInfo[i].gain = 1.0; } - // create resamplers - fResampler = new Resampler * [fInputChannelCount]; - for (int i = 0; i < fInputChannelCount; i++) { - switch (resamplingAlgorithm) { - case 2: - fResampler[i] = new Interpolate( - fInput.format.u.raw_audio.format, - media_raw_audio_format::B_AUDIO_FLOAT); - break; - default: - fResampler[i] = new Resampler( - fInput.format.u.raw_audio.format, - media_raw_audio_format::B_AUDIO_FLOAT); - } - } + UpdateResamplingAlgorithm(); // fMixerChannelInfo and fMixerChannelCount will be initialized by - // UpdateInputChannelDestinations() + // _UpdateInputChannelDestinations() SetMixBufferFormat((int32)mixFrameRate, mixFrameCount); } @@ -104,21 +90,37 @@ MixerInput::~MixerInput() rtm_free(fMixBuffer); if (fRtmPool) rtm_delete_pool(fRtmPool); - delete [] fInputChannelInfo; - delete [] fMixerChannelInfo; + delete[] fInputChannelInfo; + delete[] fMixerChannelInfo; // delete resamplers - for (int i = 0; i < fInputChannelCount; i++) - delete fResampler[i]; - delete [] fResampler; + if (fResampler != NULL) { + for (int i = 0; i < fInputChannelCount; i++) + delete fResampler[i]; + delete[] fResampler; + } delete fInputByteSwap; } -void -MixerInput::BufferReceived(BBuffer *buffer) +int32 +MixerInput::ID() { - void *data; + return fInput.destination.id; +} + + +media_input& +MixerInput::MediaInput() +{ + return fInput; +} + + +void +MixerInput::BufferReceived(BBuffer* buffer) +{ + void* data; size_t size; bigtime_t start; bigtime_t buffer_duration; @@ -255,19 +257,19 @@ MixerInput::BufferReceived(BBuffer *buffer) for (int i = 0; i < fInputChannelCount; i++) { fResampler[i]->Resample( - reinterpret_cast(data) + reinterpret_cast(data) + i * bytes_per_sample(fInput.format.u.raw_audio), bytes_per_frame(fInput.format.u.raw_audio), in_frames1, - reinterpret_cast(fInputChannelInfo[i].buffer_base) + reinterpret_cast(fInputChannelInfo[i].buffer_base) + offset, fInputChannelCount * sizeof(float), out_frames1, fInputChannelInfo[i].gain); fResampler[i]->Resample( - reinterpret_cast(data) + reinterpret_cast(data) + i * bytes_per_sample(fInput.format.u.raw_audio) + in_frames1 * bytes_per_frame(fInput.format.u.raw_audio), bytes_per_frame(fInput.format.u.raw_audio), in_frames2, - reinterpret_cast(fInputChannelInfo[i].buffer_base), + reinterpret_cast(fInputChannelInfo[i].buffer_base), fInputChannelCount * sizeof(float), out_frames2, fInputChannelInfo[i].gain); @@ -290,10 +292,10 @@ MixerInput::BufferReceived(BBuffer *buffer) offset *= sizeof(float) * fInputChannelCount; for (int i = 0; i < fInputChannelCount; i++) { fResampler[i]->Resample( - reinterpret_cast(data) + reinterpret_cast(data) + i * bytes_per_sample(fInput.format.u.raw_audio), bytes_per_frame(fInput.format.u.raw_audio), in_frames, - reinterpret_cast(fInputChannelInfo[i].buffer_base) + reinterpret_cast(fInputChannelInfo[i].buffer_base) + offset, fInputChannelCount * sizeof(float), out_frames, fInputChannelInfo[i].gain); } @@ -302,17 +304,29 @@ MixerInput::BufferReceived(BBuffer *buffer) } -media_input & -MixerInput::MediaInput() +void +MixerInput::UpdateResamplingAlgorithm() { - return fInput; -} - - -int32 -MixerInput::ID() -{ - return fInput.destination.id; + if (fResampler != NULL) { + for (int i = 0; i < fInputChannelCount; i++) + delete fResampler[i]; + delete[] fResampler; + } + // create resamplers + fResampler = new Resampler*[fInputChannelCount]; + for (int i = 0; i < fInputChannelCount; i++) { + switch (fCore->Settings()->ResamplingAlgorithm()) { + case 2: + fResampler[i] = new Interpolate( + fInput.format.u.raw_audio.format, + media_raw_audio_format::B_AUDIO_FLOAT); + break; + default: + fResampler[i] = new Resampler( + fInput.format.u.raw_audio.format, + media_raw_audio_format::B_AUDIO_FLOAT); + } + } } @@ -347,7 +361,7 @@ MixerInput::AddInputChannelDestination(int channel, int destination_type) fInputChannelInfo[channel].destination_mask |= mask; fUserOverridesChannelDestinations = true; - UpdateInputChannelDestinations(); + _UpdateInputChannelDestinations(); } @@ -367,7 +381,7 @@ MixerInput::RemoveInputChannelDestination(int channel, int destination_type) fInputChannelInfo[channel].destination_mask &= ~mask; fUserOverridesChannelDestinations = true; - UpdateInputChannelDestinations(); + _UpdateInputChannelDestinations(); } @@ -428,13 +442,13 @@ MixerInput::GetInputChannelGain(int channel) void -MixerInput::UpdateInputChannelDestinationMask() +MixerInput::_UpdateInputChannelDestinationMask() { // is the user already messed with the assignmens, don't do anything. if (fUserOverridesChannelDestinations) return; - TRACE("UpdateInputChannelDestinationMask: enter\n"); + TRACE("_UpdateInputChannelDestinationMask: enter\n"); // first apply a 1:1 mapping for (int i = 0; i < fInputChannelCount; i++) { @@ -480,25 +494,25 @@ MixerInput::UpdateInputChannelDestinationMask() } for (int i = 0; i < fInputChannelCount; i++) { - TRACE("UpdateInputChannelDestinationMask: input channel %d, " + TRACE("_UpdateInputChannelDestinationMask: input channel %d, " "destination_mask 0x%08lX, base %p, gain %.3f\n", i, fInputChannelInfo[i].destination_mask, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); } - TRACE("UpdateInputChannelDestinationMask: leave\n"); + TRACE("_UpdateInputChannelDestinationMask: leave\n"); } void -MixerInput::UpdateInputChannelDestinations() +MixerInput::_UpdateInputChannelDestinations() { int channel_count; uint32 all_bits; uint32 mask; - TRACE("UpdateInputChannelDestinations: enter\n"); + TRACE("_UpdateInputChannelDestinations: enter\n"); for (int i = 0; i < fInputChannelCount; i++) { - TRACE("UpdateInputChannelDestinations: input channel %d, " + TRACE("_UpdateInputChannelDestinations: input channel %d, " "destination_mask 0x%08lX, base %p, gain %.3f\n", i, fInputChannelInfo[i].destination_mask, fInputChannelInfo[i].buffer_base, fInputChannelInfo[i].gain); @@ -508,10 +522,10 @@ MixerInput::UpdateInputChannelDestinations() for (int i = 0; i < fInputChannelCount; i++) all_bits |= fInputChannelInfo[i].destination_mask; - TRACE("UpdateInputChannelDestinations: all_bits = %08lx\n", all_bits); + TRACE("_UpdateInputChannelDestinations: all_bits = %08lx\n", all_bits); channel_count = count_nonzero_bits(all_bits); - TRACE("UpdateInputChannelDestinations: %d input channels, %d mixer " + TRACE("_UpdateInputChannelDestinations: %d input channels, %d mixer " "channels (%d old)\n", fInputChannelCount, channel_count, fMixerChannelCount); if (channel_count != fMixerChannelCount) { @@ -551,13 +565,13 @@ MixerInput::UpdateInputChannelDestinations() } for (int i = 0; i < fMixerChannelCount; i++) { - TRACE("UpdateInputChannelDestinations: mixer channel %d, type %2d, " + 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("UpdateInputChannelDestinations: leave\n"); + TRACE("_UpdateInputChannelDestinations: leave\n"); } @@ -668,8 +682,8 @@ MixerInput::SetMixBufferFormat(int32 framerate, int32 frames) fInputChannelInfo[i].buffer_base = 0; fMixBufferFrameCount = 0; - UpdateInputChannelDestinationMask(); - UpdateInputChannelDestinations(); + _UpdateInputChannelDestinationMask(); + _UpdateInputChannelDestinations(); return; } @@ -711,6 +725,6 @@ MixerInput::SetMixBufferFormat(int32 framerate, int32 frames) for (int i = 0; i < fInputChannelCount; i++) fInputChannelInfo[i].buffer_base = &fMixBuffer[i]; - UpdateInputChannelDestinationMask(); - UpdateInputChannelDestinations(); + _UpdateInputChannelDestinationMask(); + _UpdateInputChannelDestinations(); } 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 a6ade9b8fc..361ca1efe1 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerInput.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerInput.h @@ -25,14 +25,16 @@ class MixerInput { public: MixerInput(MixerCore* core, const media_input& input, - float mixFrameRate, int32 mixFrameCount, - int resamplingAlgorithm); + float mixFrameRate, int32 mixFrameCount); ~MixerInput(); int32 ID(); - void BufferReceived(BBuffer* buffer); media_input& MediaInput(); + void BufferReceived(BBuffer* buffer); + + void UpdateResamplingAlgorithm(); + // The physical input channels int GetInputChannelCount(); int GetInputChannelType(int channel); @@ -74,8 +76,8 @@ protected: int32 frames); private: - void UpdateInputChannelDestinationMask(); - void UpdateInputChannelDestinations(); + void _UpdateInputChannelDestinationMask(); + void _UpdateInputChannelDestinations(); struct input_chan_info { float* buffer_base;