From a9cf57cff5dfe040f74a96705d98d6711b6b1b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 2 Dec 2009 09:21:28 +0000 Subject: [PATCH] * Cleanup, no functional change. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34437 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../media/media-add-ons/mixer/AudioMixer.cpp | 29 +- .../media/media-add-ons/mixer/AudioMixer.h | 28 +- .../media/media-add-ons/mixer/ByteSwap.cpp | 25 +- .../media/media-add-ons/mixer/ByteSwap.h | 23 +- .../media/media-add-ons/mixer/MixerAddOn.cpp | 39 +- .../media/media-add-ons/mixer/MixerAddOn.h | 46 +- .../media/media-add-ons/mixer/MixerCore.cpp | 310 ++++++++----- .../media/media-add-ons/mixer/MixerCore.h | 40 +- .../media/media-add-ons/mixer/MixerDebug.h | 41 +- .../media/media-add-ons/mixer/MixerInput.cpp | 121 +++-- .../media/media-add-ons/mixer/MixerInput.h | 205 ++++----- .../media/media-add-ons/mixer/MixerOutput.cpp | 35 +- .../media-add-ons/mixer/MixerSettings.cpp | 135 +++--- .../media/media-add-ons/mixer/MixerUtils.cpp | 11 +- .../media/media-add-ons/mixer/MixerUtils.h | 11 +- .../media/media-add-ons/mixer/Resampler.cpp | 412 ++++++++++-------- .../media/media-add-ons/mixer/Resampler.h | 101 +++-- .../media/media-add-ons/mixer/RtList.h | 54 ++- 18 files changed, 970 insertions(+), 696 deletions(-) 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 e4e0c7c749..c5c24e0fb9 100644 --- a/src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp +++ b/src/add-ons/media/media-add-ons/mixer/AudioMixer.cpp @@ -6,23 +6,27 @@ * Distributed under the terms of the MIT License. */ + #include "AudioMixer.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + #include "MixerCore.h" #include "MixerInput.h" #include "MixerOutput.h" #include "MixerUtils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // the range of the gain sliders (in dB) #define DB_MAX 18.0 @@ -84,7 +88,8 @@ multi_audio_format_specialize(media_multi_audio_format *format, AudioMixer::AudioMixer(BMediaAddOn *addOn, bool isSystemMixer) - : BMediaNode("Audio Mixer"), + : + BMediaNode("Audio Mixer"), BBufferConsumer(B_MEDIA_RAW_AUDIO), BBufferProducer(B_MEDIA_RAW_AUDIO), BControllable(), diff --git a/src/add-ons/media/media-add-ons/mixer/AudioMixer.h b/src/add-ons/media/media-add-ons/mixer/AudioMixer.h index b7d407ceb7..bcb1f24c0c 100644 --- a/src/add-ons/media/media-add-ons/mixer/AudioMixer.h +++ b/src/add-ons/media/media-add-ons/mixer/AudioMixer.h @@ -7,6 +7,7 @@ #ifndef _AUDIOMIXER_H #define _AUDIOMIXER_H + #include #include #include @@ -14,20 +15,18 @@ #include #include + class MixerCore; -class AudioMixer : - public BBufferConsumer, - public BBufferProducer, - public BControllable, - public BMediaEventLooper -{ - public: + +class AudioMixer : public BBufferConsumer, public BBufferProducer, + public BControllable, public BMediaEventLooper { +public: AudioMixer(BMediaAddOn *addOn, bool isSystemMixer); ~AudioMixer(); void DisableNodeStop(); - + // AudioMixer support void ApplySettings(); @@ -48,9 +47,9 @@ class AudioMixer : void SetTimeSource(BTimeSource * time_source); using BBufferProducer::SendBuffer; - protected: +protected: // BControllable methods - status_t GetParameterValue(int32 id, + status_t GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *ioSize); @@ -69,10 +68,10 @@ class AudioMixer : void DisposeInputCookie(int32 cookie); void BufferReceived(BBuffer *buffer); void ProducerDataStatus(const media_destination &for_whom, - int32 status, + int32 status, bigtime_t at_performance_time); status_t GetLatencyFor(const media_destination &for_whom, - bigtime_t *out_latency, + bigtime_t *out_latency, media_node_id *out_timesource); status_t Connected(const media_source &producer, const media_destination &where, @@ -128,7 +127,7 @@ class AudioMixer : bigtime_t lateness, bool realTimeEvent = false); - private: +private: BMediaAddOn *fAddOn; MixerCore *fCore; BParameterWeb *fWeb; // local pointer to parameterweb @@ -138,4 +137,5 @@ class AudioMixer : bool fDisableStop; media_format fDefaultFormat; }; -#endif + +#endif // _AUDIOMIXER_H diff --git a/src/add-ons/media/media-add-ons/mixer/ByteSwap.cpp b/src/add-ons/media/media-add-ons/mixer/ByteSwap.cpp index 6edadb0fb5..9620e48110 100644 --- a/src/add-ons/media/media-add-ons/mixer/ByteSwap.cpp +++ b/src/add-ons/media/media-add-ons/mixer/ByteSwap.cpp @@ -3,17 +3,22 @@ * Copyright 2007 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. */ + + #include "ByteSwap.h" -#include "MixerDebug.h" #include #include +#include "MixerDebug.h" + + static void swap_float(void *buffer, size_t bytecount); static void swap_int32(void *buffer, size_t bytecount); static void swap_int16(void *buffer, size_t bytecount); static void do_nothing(void *buffer, size_t bytecount); + ByteSwap::ByteSwap(uint32 format) { switch (format) { @@ -32,18 +37,21 @@ ByteSwap::ByteSwap(uint32 format) } } + ByteSwap::~ByteSwap() { } + void do_nothing(void *buffer, size_t bytecount) { } -#if __INTEL__ -// optimized for IA32 platform +#if __INTEL__ +// #pragma mark - optimized for IA32 platform + void swap_float(void *buffer, size_t bytecount) @@ -52,6 +60,7 @@ swap_float(void *buffer, size_t bytecount) swap_data(B_FLOAT_TYPE, buffer, bytecount, B_SWAP_ALWAYS); } + void swap_int32(void *buffer, size_t bytecount) { @@ -59,6 +68,7 @@ swap_int32(void *buffer, size_t bytecount) swap_data(B_INT32_TYPE, buffer, bytecount, B_SWAP_ALWAYS); } + void swap_int16(void *buffer, size_t bytecount) { @@ -111,9 +121,10 @@ swap_int16(void *buffer, size_t bytecount) : "cc", "memory"); } -#else -// non optimized default versions, do not remove +#else // !__INTEL__ +// #pragma mark - generic versions + void swap_float(void *buffer, size_t bytecount) @@ -121,15 +132,19 @@ swap_float(void *buffer, size_t bytecount) swap_data(B_FLOAT_TYPE, buffer, bytecount, B_SWAP_ALWAYS); } + void swap_int32(void *buffer, size_t bytecount) { swap_data(B_INT32_TYPE, buffer, bytecount, B_SWAP_ALWAYS); } + void swap_int16(void *buffer, size_t bytecount) { swap_data(B_INT16_TYPE, buffer, bytecount, B_SWAP_ALWAYS); } + + #endif diff --git a/src/add-ons/media/media-add-ons/mixer/ByteSwap.h b/src/add-ons/media/media-add-ons/mixer/ByteSwap.h index b0f115042a..bba176a0d1 100644 --- a/src/add-ons/media/media-add-ons/mixer/ByteSwap.h +++ b/src/add-ons/media/media-add-ons/mixer/ByteSwap.h @@ -6,23 +6,26 @@ #ifndef _BYTE_SWAP_H #define _BYTE_SWAP_H + #include -class ByteSwap -{ - public: - ByteSwap(uint32 format); - ~ByteSwap(); - - void Swap(void *buffer, size_t bytecount); - private: - void (*fFunc)(void *, size_t); +class ByteSwap { +public: + ByteSwap(uint32 format); + ~ByteSwap(); + + void Swap(void *buffer, size_t bytecount); + +private: + void (*fFunc)(void *, size_t); }; + inline void ByteSwap::Swap(void *buffer, size_t bytecount) { (*fFunc)(buffer, bytecount); } -#endif + +#endif // _BYTE_SWAP_H diff --git a/src/add-ons/media/media-add-ons/mixer/MixerAddOn.cpp b/src/add-ons/media/media-add-ons/mixer/MixerAddOn.cpp index 88c58c58bb..cb66ab0998 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerAddOn.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerAddOn.cpp @@ -4,21 +4,28 @@ * Copyright 2007 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. */ + + +#include "MixerAddOn.h" + +#include +#include + #include #include -#include -#include #include "AudioMixer.h" -#include "MixerAddOn.h" + // instantiation function extern "C" _EXPORT BMediaAddOn* make_media_addon(image_id image) { return new AudioMixerAddon(image); } + AudioMixerAddon::AudioMixerAddon(image_id image) - : BMediaAddOn(image), + : + BMediaAddOn(image), fFormat(new media_format), fInfo(new flavor_info) { @@ -38,15 +45,16 @@ AudioMixerAddon::AudioMixerAddon(image_id image) fInfo->out_formats = fFormat; } + AudioMixerAddon::~AudioMixerAddon() { delete fFormat; delete fInfo; } -// -------------------------------------------------------- // -// BMediaAddOn impl -// -------------------------------------------------------- // + +// #pragma mark - BMediaAddOn implementation + status_t AudioMixerAddon::InitCheck(const char** out_failure_text) @@ -54,46 +62,53 @@ AudioMixerAddon::InitCheck(const char** out_failure_text) return B_OK; } + int32 AudioMixerAddon::CountFlavors() { return 1; } + status_t AudioMixerAddon::GetFlavorAt(int32 n, const flavor_info** out_info) { // only the 0th flavor exists if (n != 0) return B_ERROR; - + *out_info = fInfo; return B_OK; } + BMediaNode * AudioMixerAddon::InstantiateNodeFor(const flavor_info* info, BMessage* config, - status_t* out_error) + status_t* out_error) { return new AudioMixer(this, false); } + status_t -AudioMixerAddon::GetConfigurationFor(BMediaNode* your_node, BMessage* into_message) +AudioMixerAddon::GetConfigurationFor(BMediaNode* your_node, + BMessage* into_message) { // no config yet return B_ERROR; } + bool AudioMixerAddon::WantsAutoStart() { return true; } + status_t AudioMixerAddon::AutoStart(int in_index, BMediaNode **out_node, - int32 *out_internal_id, bool *out_has_more) + int32 *out_internal_id, bool *out_has_more) { *out_has_more = false; @@ -103,6 +118,6 @@ AudioMixerAddon::AutoStart(int in_index, BMediaNode **out_node, *out_internal_id = 0; AudioMixer *mixer = new AudioMixer(this, true); *out_node = mixer; - + return B_OK; } diff --git a/src/add-ons/media/media-add-ons/mixer/MixerAddOn.h b/src/add-ons/media/media-add-ons/mixer/MixerAddOn.h index 910b646c84..494f09d9a6 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerAddOn.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerAddOn.h @@ -7,33 +7,31 @@ #ifndef _AUDIOMIXER_ADDON_H #define _AUDIOMIXER_ADDON_H + #include + class AudioMixerAddon : public BMediaAddOn { - public: - virtual ~AudioMixerAddon(); - explicit AudioMixerAddon(image_id image); - - virtual status_t InitCheck(const char** out_failure_text); - virtual int32 CountFlavors(); - virtual status_t GetFlavorAt(int32 n, - const flavor_info ** out_info); - virtual BMediaNode * InstantiateNodeFor( - const flavor_info *info, - BMessage *config, - status_t *out_error); - virtual status_t GetConfigurationFor( - BMediaNode *your_node, - BMessage *into_message); +public: + virtual ~AudioMixerAddon(); + explicit AudioMixerAddon(image_id image); - virtual bool WantsAutoStart(); - virtual status_t AutoStart(int in_index, - BMediaNode **out_node, - int32 *out_internal_id, - bool *out_has_more); + virtual status_t InitCheck(const char** _failureText); + virtual int32 CountFlavors(); + virtual status_t GetFlavorAt(int32 n, + const flavor_info** _info); + virtual BMediaNode * InstantiateNodeFor(const flavor_info* info, + BMessage* config, status_t* _error); + virtual status_t GetConfigurationFor(BMediaNode* node, + BMessage* toMmessage); - private: - media_format *fFormat; - flavor_info *fInfo; + virtual bool WantsAutoStart(); + virtual status_t AutoStart(int index, BMediaNode** _node, + int32* _internalID, bool* _hasMore); + +private: + media_format* fFormat; + flavor_info* fInfo; }; -#endif + +#endif // _AUDIOMIXER_ADDON_H 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 18791a444a..be68e16174 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerCore.cpp @@ -1,17 +1,15 @@ /* - * Copyright 2007 Haiku Inc. All rights reserved. + * Copyright 2003-2009 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: - * Marcus Overhagen + * Marcus Overhagen */ -#include "AudioMixer.h" + + #include "MixerCore.h" -#include "MixerInput.h" -#include "MixerOutput.h" -#include "MixerUtils.h" -#include "Resampler.h" -#include "RtList.h" + +#include #include #include @@ -20,31 +18,49 @@ #include #include #include -#include + +#include "AudioMixer.h" +#include "MixerInput.h" +#include "MixerOutput.h" +#include "MixerUtils.h" +#include "Resampler.h" +#include "RtList.h" + #define DOUBLE_RATE_MIXING 0 #if DEBUG > 1 - #define ASSERT_LOCKED() if (fLocker->IsLocked()) {} else debugger("core not locked, meltdown occurred") +# define ASSERT_LOCKED() if (fLocker->IsLocked()) {} \ + else debugger("core not locked, meltdown occurred") #else - #define ASSERT_LOCKED() ((void)0) +# define ASSERT_LOCKED() ((void)0) #endif -/* Mixer channels are identified by a type number, each type number corresponds - * to the one of the channel masks of enum media_multi_channels. - * - * The mixer buffer uses either the same frame rate and same count of frames as the - * output buffer, or the double frame rate and frame count. - * - * All mixer input ring buffers must be an exact multiple of the mixer buffer size, - * so that we do not get any buffer wrap around during reading from the input buffers. - * The mixer input is told by constructor (or after a format change by SetMixBufferFormat()) - * of the current mixer buffer propertys, and must allocate a buffer that is an exact multiple, - */ +/*! Mixer channels are identified by a type number, each type number corresponds + to the one of the channel masks of enum media_multi_channels. + + The mixer buffer uses either the same frame rate and same count of frames as + the output buffer, or the double frame rate and frame count. + + All mixer input ring buffers must be an exact multiple of the mixer buffer + size, so that we do not get any buffer wrap around during reading from the + input buffers. + The mixer input is told by constructor (or after a format change by + SetMixBufferFormat() of the current mixer buffer propertys, and must + allocate a buffer that is an exact multiple, +*/ + + +struct chan_info { + const char *base; + uint32 sample_offset; + float gain; +}; MixerCore::MixerCore(AudioMixer *node) - : fLocker(new BLocker("mixer core lock")), + : + fLocker(new BLocker("mixer core lock")), fInputs(new BList), fOutput(0), fNextInputID(1), @@ -69,6 +85,7 @@ MixerCore::MixerCore(AudioMixer *node) { } + MixerCore::~MixerCore() { delete fSettings; @@ -90,16 +107,18 @@ MixerCore::~MixerCore() delete fResampler[i]; delete [] fResampler; } - + delete fMixBufferChannelTypes; } + MixerSettings * MixerCore::Settings() { return fSettings; } + void MixerCore::SetOutputAttenuation(float gain) { @@ -107,16 +126,18 @@ MixerCore::SetOutputAttenuation(float gain) fOutputGain = gain; } + MixerInput * MixerCore::AddInput(const media_input &input) { ASSERT_LOCKED(); MixerInput *in = new MixerInput(this, input, fMixBufferFrameRate, - fMixBufferFrameCount); + fMixBufferFrameCount); fInputs->AddItem(in); return in; } + MixerOutput * MixerCore::AddOutput(const media_output &output) { @@ -132,10 +153,11 @@ MixerCore::AddOutput(const media_output &output) ASSERT(!fRunning); if (fStarted && fOutputEnabled) StartMixThread(); - + return fOutput; } + bool MixerCore::RemoveInput(int32 inputID) { @@ -151,6 +173,7 @@ MixerCore::RemoveInput(int32 inputID) return false; } + bool MixerCore::RemoveOutput() { @@ -167,6 +190,7 @@ MixerCore::RemoveOutput() return true; } + int32 MixerCore::CreateInputID() { @@ -174,6 +198,7 @@ MixerCore::CreateInputID() return fNextInputID++; } + MixerInput * MixerCore::Input(int i) { @@ -181,6 +206,7 @@ MixerCore::Input(int i) return (MixerInput *)fInputs->ItemAt(i); } + MixerOutput * MixerCore::Output() { @@ -188,6 +214,7 @@ MixerCore::Output() return fOutput; } + void MixerCore::BufferReceived(BBuffer *buffer, bigtime_t lateness) { @@ -200,16 +227,20 @@ MixerCore::BufferReceived(BBuffer *buffer, bigtime_t lateness) return; } } - ERROR("MixerCore::BufferReceived: received buffer for unknown id %ld\n", id); + ERROR("MixerCore::BufferReceived: received buffer for unknown id %ld\n", + id); } - + + void -MixerCore::InputFormatChanged(int32 inputID, const media_multi_audio_format &format) +MixerCore::InputFormatChanged(int32 inputID, + const media_multi_audio_format &format) { ASSERT_LOCKED(); ERROR("MixerCore::InputFormatChanged not handled\n"); } + void MixerCore::OutputFormatChanged(const media_multi_audio_format &format) { @@ -226,16 +257,17 @@ MixerCore::OutputFormatChanged(const media_multi_audio_format &format) Start(); } + void MixerCore::ApplyOutputFormat() { ASSERT_LOCKED(); - + media_multi_audio_format format = fOutput->MediaOutput().format.u.raw_audio; - - if (fMixBuffer) + + if (fMixBuffer != NULL) rtm_free(fMixBuffer); - + delete fMixBufferChannelTypes; fMixBufferFrameRate = (int32)(0.5 + format.frame_rate); @@ -247,9 +279,11 @@ MixerCore::ApplyOutputFormat() 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)); + + 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); @@ -261,10 +295,11 @@ MixerCore::ApplyOutputFormat() } fResampler = new Resampler * [fMixBufferChannelCount]; - for (int i = 0; i < fMixBufferChannelCount; i++) - fResampler[i] = new Resampler(media_raw_audio_format::B_AUDIO_FLOAT, - format.format); - + for (int i = 0; i < fMixBufferChannelCount; i++) { + 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); @@ -277,6 +312,7 @@ MixerCore::ApplyOutputFormat() input->SetMixBufferFormat(fMixBufferFrameRate, fMixBufferFrameCount); } + void MixerCore::SetOutputBufferGroup(BBufferGroup *group) { @@ -284,21 +320,22 @@ MixerCore::SetOutputBufferGroup(BBufferGroup *group) fBufferGroup = group; } + void MixerCore::SetTimingInfo(BTimeSource *ts, bigtime_t downstream_latency) { ASSERT_LOCKED(); if (fTimeSource) fTimeSource->Release(); - + fTimeSource = dynamic_cast(ts->Acquire()); fDownstreamLatency = downstream_latency; - TRACE("MixerCore::SetTimingInfo, now = %Ld, downstream latency %Ld\n", - fTimeSource->Now(), - fDownstreamLatency); + TRACE("MixerCore::SetTimingInfo, now = %Ld, downstream latency %Ld\n", + fTimeSource->Now(), fDownstreamLatency); } + void MixerCore::EnableOutput(bool enabled) { @@ -328,11 +365,11 @@ MixerCore::Start() TRACE("MixerCore::Start\n"); if (fStarted) return false; - + fStarted = true; - + ASSERT(!fRunning); - + // only start the mix thread if we have an output if (fOutput && fOutputEnabled) StartMixThread(); @@ -340,6 +377,7 @@ MixerCore::Start() return true; } + bool MixerCore::Stop() { @@ -347,7 +385,7 @@ MixerCore::Stop() TRACE("MixerCore::Stop\n"); if (!fStarted) return false; - + if (fRunning) StopMixThread(); @@ -355,6 +393,7 @@ MixerCore::Stop() return true; } + void MixerCore::StartMixThread() { @@ -363,26 +402,29 @@ MixerCore::StartMixThread() ASSERT(fOutput); fRunning = true; fMixThreadWaitSem = create_sem(0, "mix thread wait"); - fMixThread = spawn_thread(_mix_thread_, "Yeah baby, very shagadelic", 120, this); + fMixThread = spawn_thread(_mix_thread_, "Yeah baby, very shagadelic", 120, + this); resume_thread(fMixThread); } + void MixerCore::StopMixThread() { ASSERT(fRunning == true); ASSERT(fMixThread > 0); ASSERT(fMixThreadWaitSem > 0); - + status_t unused; delete_sem(fMixThreadWaitSem); - wait_for_thread(fMixThread, &unused); - + wait_for_thread(fMixThread, &unused); + fMixThread = -1; fMixThreadWaitSem = -1; fRunning = false; } + int32 MixerCore::_mix_thread_(void *arg) { @@ -390,23 +432,18 @@ MixerCore::_mix_thread_(void *arg) return 0; } -struct chan_info { - const char *base; - uint32 sample_offset; - float gain; -}; void MixerCore::MixThread() { - bigtime_t event_time; - bigtime_t time_base; - bigtime_t latency; - bigtime_t start; - bigtime_t buffer_request_timeout; - int64 frame_base; - int64 frame_pos; - + bigtime_t event_time; + bigtime_t time_base; + bigtime_t latency; + bigtime_t start; + bigtime_t buffer_request_timeout; + int64 frame_base; + int64 frame_pos; + // The broken BeOS R5 multiaudio node starts with time 0, // then publishes negative times for about 50ms, publishes 0 // again until it finally reaches time values > 0 @@ -415,7 +452,8 @@ MixerCore::MixThread() start = fTimeSource->Now(); Unlock(); while (start <= 0) { - TRACE("MixerCore: delaying MixThread start, timesource is at %Ld\n", start); + TRACE("MixerCore: delaying MixThread start, timesource is at %Ld\n", + start); snooze(5000); if (!LockFromMixThread()) return; @@ -425,55 +463,65 @@ MixerCore::MixThread() if (!LockFromMixThread()) return; - latency = max(3600LL, bigtime_t(0.4 * buffer_duration(fOutput->MediaOutput().format.u.raw_audio))); - - // XXX when the format changes while running, everything is wrong! - buffer_request_timeout = buffer_duration(fOutput->MediaOutput().format.u.raw_audio) / 2; - - TRACE("MixerCore: starting MixThread at %Ld with latency %Ld and downstream latency %Ld, buffer_request_timeout %Ld\n", start, latency, fDownstreamLatency, buffer_request_timeout); + latency = max(3600LL, bigtime_t(0.4 * buffer_duration( + fOutput->MediaOutput().format.u.raw_audio))); - /* We must read from the input buffer at a position (pos) that is always a multiple of fMixBufferFrameCount. - */ + // TODO: when the format changes while running, everything is wrong! + buffer_request_timeout = buffer_duration( + fOutput->MediaOutput().format.u.raw_audio) / 2; + + TRACE("MixerCore: starting MixThread at %Ld with latency %Ld and " + "downstream latency %Ld, buffer_request_timeout %Ld\n", start, latency, + fDownstreamLatency, buffer_request_timeout); + + // We must read from the input buffer at a position (pos) that is always + // a multiple of fMixBufferFrameCount. int64 temp = frames_for_duration(fMixBufferFrameRate, start); frame_base = ((temp / fMixBufferFrameCount) + 1) * fMixBufferFrameCount; time_base = duration_for_frames(fMixBufferFrameRate, frame_base); Unlock(); - - TRACE("MixerCore: starting MixThread, start %Ld, time_base %Ld, frame_base %Ld\n", start, time_base, frame_base); - + + TRACE("MixerCore: starting MixThread, start %Ld, time_base %Ld, " + "frame_base %Ld\n", start, time_base, frame_base); + ASSERT(fMixBufferFrameCount > 0); - + #if DEBUG uint64 buffer_num = 0; #endif RtList InputChanInfos[MAX_CHANNEL_TYPES]; - RtList MixChanInfos[fMixBufferChannelCount]; // XXX this does not support changing output channel count - + RtList MixChanInfos[fMixBufferChannelCount]; + // TODO: this does not support changing output channel count + event_time = time_base; frame_pos = 0; for (;;) { bigtime_t wait_until; if (!LockFromMixThread()) return; - wait_until = fTimeSource->RealTimeFor(event_time, 0) - latency - fDownstreamLatency; + wait_until = fTimeSource->RealTimeFor(event_time, 0) + - latency - fDownstreamLatency; Unlock(); status_t rv; - rv = acquire_sem_etc(fMixThreadWaitSem, 1, B_ABSOLUTE_TIMEOUT, wait_until); + rv = acquire_sem_etc(fMixThreadWaitSem, 1, B_ABSOLUTE_TIMEOUT, + wait_until); if (rv == B_INTERRUPTED) continue; if (rv != B_TIMED_OUT && rv < B_OK) return; - + if (!LockWithTimeout(10000)) { ERROR("MixerCore: LockWithTimeout failed\n"); continue; } - - // no inputs or output muted, skip further processing and just send an empty buffer + + // no inputs or output muted, skip further processing and just send an + // empty buffer if (fInputs->IsEmpty() || fOutput->IsMuted()) { int size = fOutput->MediaOutput().format.u.raw_audio.buffer_size; - BBuffer* buf = fBufferGroup->RequestBuffer(size, buffer_request_timeout); + BBuffer* buf = fBufferGroup->RequestBuffer(size, + buffer_request_timeout); if (buf) { memset(buf->Data(), 0, size); // fill in the buffer header @@ -482,9 +530,11 @@ MixerCore::MixThread() hdr->size_used = size; hdr->time_source = fTimeSource->ID(); hdr->start_time = event_time; - if (B_OK != fNode->SendBuffer(buf, fOutput->MediaOutput().destination)) { + if (fNode->SendBuffer(buf, fOutput->MediaOutput().destination) + != B_OK) { #if DEBUG - ERROR("MixerCore: SendBuffer failed for buffer %Ld\n", buffer_num); + ERROR("MixerCore: SendBuffer failed for buffer %Ld\n", + buffer_num); #else ERROR("MixerCore: SendBuffer failed\n"); #endif @@ -492,7 +542,8 @@ MixerCore::MixThread() } } else { #if DEBUG - ERROR("MixerCore: RequestBuffer failed for buffer %Ld\n", buffer_num); + ERROR("MixerCore: RequestBuffer failed for buffer %Ld\n", + buffer_num); #else ERROR("MixerCore: RequestBuffer failed\n"); #endif @@ -502,12 +553,13 @@ MixerCore::MixThread() int64 cur_framepos; cur_framepos = frame_base + frame_pos; - + // mix all data from all inputs into the mix buffer ASSERT(cur_framepos % fMixBufferFrameCount == 0); - PRINT(4, "create new buffer event at %Ld, reading input frames at %Ld\n", event_time, cur_framepos); - + PRINT(4, "create new buffer event at %Ld, reading input frames at " + "%Ld\n", event_time, cur_framepos); + MixerInput *input; for (int i = 0; (input = Input(i)) != 0; i++) { int count = input->GetMixerChannelCount(); @@ -516,7 +568,8 @@ MixerCore::MixThread() const float *base; uint32 sample_offset; float gain; - if (!input->GetMixerChannelInfo(chan, cur_framepos, event_time, &base, &sample_offset, &type, &gain)) + if (!input->GetMixerChannelInfo(chan, cur_framepos, event_time, + &base, &sample_offset, &type, &gain)) continue; if (type < 0 || type >= MAX_CHANNEL_TYPES) continue; @@ -526,7 +579,7 @@ MixerCore::MixThread() info->gain = gain; } } - + for (int chan = 0; chan < fMixBufferChannelCount; chan++) { int sourcecount = fOutput->GetOutputChannelSourceCount(chan); for (int i = 0; i < sourcecount; i++) { @@ -546,16 +599,22 @@ MixerCore::MixThread() } } - memset(fMixBuffer, 0, fMixBufferChannelCount * fMixBufferFrameCount * sizeof(float)); + memset(fMixBuffer, 0, + fMixBufferChannelCount * fMixBufferFrameCount * sizeof(float)); for (int chan = 0; chan < fMixBufferChannelCount; chan++) { - PRINT(5, "MixThread: chan %d has %d sources\n", chan, MixChanInfos[chan].CountItems()); + PRINT(5, "MixThread: chan %d has %d sources\n", chan, + MixChanInfos[chan].CountItems()); + int count = MixChanInfos[chan].CountItems(); for (int i = 0; i < count; i++) { chan_info *info = MixChanInfos[chan].ItemAt(i); - 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. fMixBufferFrameCount is always > 0. - uint32 dst_sample_offset = fMixBufferChannelCount * sizeof(float); + 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. + // fMixBufferFrameCount is always > 0. + uint32 dst_sample_offset + = fMixBufferChannelCount * sizeof(float); uint32 src_sample_offset = info->sample_offset; register char *dst = (char *)&fMixBuffer[chan]; register char *src = (char *)info->base; @@ -572,36 +631,45 @@ MixerCore::MixThread() // request a buffer BBuffer *buf; buf = fBufferGroup->RequestBuffer( - fOutput->MediaOutput().format.u.raw_audio.buffer_size, - buffer_request_timeout); + fOutput->MediaOutput().format.u.raw_audio.buffer_size, + buffer_request_timeout); if (buf) { // copy data from mix buffer into output buffer for (int i = 0; i < fMixBufferChannelCount; i++) { - fResampler[i]->Resample(reinterpret_cast(fMixBuffer) + i * sizeof(float), - fMixBufferChannelCount * sizeof(float), - fMixBufferFrameCount, - reinterpret_cast(buf->Data()) + (i * bytes_per_sample(fOutput->MediaOutput().format.u.raw_audio)), - bytes_per_frame(fOutput->MediaOutput().format.u.raw_audio), - frames_per_buffer(fOutput->MediaOutput().format.u.raw_audio), - fOutputGain * fOutput->GetOutputChannelGain(i)); + fResampler[i]->Resample( + reinterpret_cast(fMixBuffer) + i * sizeof(float), + fMixBufferChannelCount * sizeof(float), + fMixBufferFrameCount, + reinterpret_cast(buf->Data()) + + (i * bytes_per_sample( + fOutput->MediaOutput().format.u.raw_audio)), + bytes_per_frame(fOutput->MediaOutput().format.u.raw_audio), + frames_per_buffer( + fOutput->MediaOutput().format.u.raw_audio), + fOutputGain * fOutput->GetOutputChannelGain(i)); } - PRINT(4, "send buffer, inframes %ld, outframes %ld\n", fMixBufferFrameCount, frames_per_buffer(fOutput->MediaOutput().format.u.raw_audio)); - + PRINT(4, "send buffer, inframes %ld, outframes %ld\n", + fMixBufferFrameCount, + frames_per_buffer(fOutput->MediaOutput().format.u.raw_audio)); + // fill in the buffer header media_header* hdr = buf->Header(); hdr->type = B_MEDIA_RAW_AUDIO; - hdr->size_used = fOutput->MediaOutput().format.u.raw_audio.buffer_size; + hdr->size_used + = fOutput->MediaOutput().format.u.raw_audio.buffer_size; hdr->time_source = fTimeSource->ID(); hdr->start_time = event_time; - + // swap byte order if necessary fOutput->AdjustByteOrder(buf); - + // send the buffer - status_t res = fNode->SendBuffer(buf, fOutput->MediaOutput().destination); - if (B_OK != res) { + status_t res = fNode->SendBuffer(buf, + fOutput->MediaOutput().destination); + if (res != B_OK) { #if DEBUG - ERROR("MixerCore: SendBuffer failed for buffer %Ld\n", buffer_num); + ERROR("MixerCore: SendBuffer failed for buffer %Ld\n", + buffer_num); #else ERROR("MixerCore: SendBuffer failed\n"); #endif @@ -609,7 +677,8 @@ MixerCore::MixThread() } } else { #if DEBUG - ERROR("MixerCore: RequestBuffer failed for buffer %Ld\n", buffer_num); + ERROR("MixerCore: RequestBuffer failed for buffer %Ld\n", + buffer_num); #else ERROR("MixerCore: RequestBuffer failed\n"); #endif @@ -621,10 +690,11 @@ MixerCore::MixThread() for (int i = 0; i < fOutput->GetOutputChannelCount(); i++) MixChanInfos[i].MakeEmpty(); -schedule_next_event: +schedule_next_event: // schedule next event frame_pos += fMixBufferFrameCount; - event_time = time_base + bigtime_t((1000000LL * frame_pos) / fMixBufferFrameRate); + event_time = time_base + bigtime_t((1000000LL * frame_pos) + / fMixBufferFrameRate); Unlock(); #if DEBUG buffer_num++; 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 7fde50cba1..e808ee5882 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerCore.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerCore.h @@ -1,34 +1,40 @@ /* - * Copyright 2007-2009 Haiku Inc. All rights reserved. + * Copyright 2003-2009 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. + * + * Authors: + * Marcus Overhagen */ #ifndef _MIXER_CORE_H #define _MIXER_CORE_H + #include "MixerSettings.h" #include #include #include + class AudioMixer; class BBufferGroup; class MixerInput; class MixerOutput; class Resampler; + // The number of "enum media_multi_channels" types from MediaDefs.h // XXX should be 18, but limited to 12 here #define MAX_CHANNEL_TYPES 12 // XXX using a dedicated mono channel, this should be channel type 31 -// but for now we redefine type 12 +// but for now we redefine type 12 #define B_CHANNEL_MONO B_CHANNEL_TOP_CENTER class MixerCore { public: MixerCore(AudioMixer *node); virtual ~MixerCore(); - + MixerSettings* Settings(); // To avoid calling Settings()->AttenuateOutput() for every outgoing @@ -41,11 +47,11 @@ public: bool RemoveInput(int32 inputID); bool RemoveOutput(); int32 CreateInputID(); - + // index = 0 to count-1, NOT inputID MixerInput* Input(int index); MixerOutput* Output(); - + void Lock(); bool LockWithTimeout(bigtime_t timeout); bool LockFromMixThread(); @@ -53,28 +59,28 @@ public: void BufferReceived(BBuffer* buffer, bigtime_t lateness); - - void InputFormatChanged(int32 inputID, + + void InputFormatChanged(int32 inputID, const media_multi_audio_format& format); void OutputFormatChanged( const media_multi_audio_format& format); void SetOutputBufferGroup(BBufferGroup* group); - void SetTimingInfo(BTimeSource* timeSource, + void SetTimingInfo(BTimeSource* timeSource, bigtime_t downstream_latency); void EnableOutput(bool enabled); bool Start(); bool Stop(); - + void StartMixThread(); - void StopMixThread(); + void StopMixThread(); uint32 OutputChannelCount(); private: void ApplyOutputFormat(); static int32 _mix_thread_(void* arg); void MixThread(); - + private: BLocker* fLocker; BList* fInputs; @@ -84,7 +90,7 @@ private: // true = the mix thread is running bool fStarted; - // true = mix thread should be + // true = mix thread should be // started of it is not running bool fOutputEnabled; @@ -104,7 +110,7 @@ private: BBufferGroup* fBufferGroup; BTimeSource* fTimeSource; thread_id fMixThread; - sem_id fMixThreadWaitSem; + sem_id fMixThreadWaitSem; float fOutputGain; friend class MixerInput; @@ -112,28 +118,28 @@ private: }; -inline void +inline void MixerCore::Lock() { fLocker->Lock(); } -inline bool +inline bool MixerCore::LockWithTimeout(bigtime_t timeout) { return fLocker->LockWithTimeout(timeout) == B_OK; } -inline void +inline void MixerCore::Unlock() { fLocker->Unlock(); } -inline bool +inline bool MixerCore::LockFromMixThread() { for (;;) { diff --git a/src/add-ons/media/media-add-ons/mixer/MixerDebug.h b/src/add-ons/media/media-add-ons/mixer/MixerDebug.h index c721157c1b..41af2e9684 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerDebug.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerDebug.h @@ -7,42 +7,41 @@ #ifndef _MIXER_DEBUG_H_ #define _MIXER_DEBUG_H_ + #ifndef DEBUG - #define DEBUG 0 +# define DEBUG 0 #endif #include #include + #undef TRACE #undef PRINT -#if DEBUG > 0 +#if DEBUG > 0 inline void ERROR(const char *fmt, ...) { va_list ap; va_start(ap, fmt); printf("### ERROR: "); vprintf(fmt, ap); va_end(ap); } inline void PRINT(int level, const char *fmt, ...) { va_list ap; if (level > DEBUG) return; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); } - #define PRINT_FORMAT(_text, _fmt) do { char _buf[300]; string_for_format((_fmt), _buf, sizeof(_buf)); printf("%s %s\n", (_text), (_buf)); } while (0) - #define PRINT_INPUT(_text, _in) do { char _buf[300]; string_for_format((_in).format, _buf, sizeof(_buf)); printf("%s node(node %ld, port %ld); source(port %ld, id %ld); dest(port %ld, id %ld); fmt(%s); name(%s)\n", (_text), (_in).node.node, (_in).node.port, (_in).source.port, (_in).source.id, (_in).destination.port, (_in).destination.id, _buf, (_in).name); } while (0) - #define PRINT_OUTPUT(_text, _out) do { char _buf[300]; string_for_format((_out).format, _buf, sizeof(_buf)); printf("%s node(node %ld, port %ld); source(port %ld, id %ld); dest(port %ld, id %ld); fmt(%s); name(%s)\n", (_text), (_out).node.node, (_out).node.port, (_out).source.port, (_out).source.id, (_out).destination.port, (_out).destination.id, _buf, (_out).name); } while (0) - #define PRINT_CHANNEL_MASK(fmt) do { char s[200]; StringForChannelMask(s, (fmt).u.raw_audio.channel_mask); printf(" channel_mask 0x%08lX %s\n", (fmt).u.raw_audio.channel_mask, s); } while (0) - - #if DEBUG >= 2 - #define TRACE printf - #else - #define TRACE(a...) ((void)0) - #endif +# define PRINT_FORMAT(_text, _fmt) do { char _buf[300]; string_for_format((_fmt), _buf, sizeof(_buf)); printf("%s %s\n", (_text), (_buf)); } while (0) +# define PRINT_INPUT(_text, _in) do { char _buf[300]; string_for_format((_in).format, _buf, sizeof(_buf)); printf("%s node(node %ld, port %ld); source(port %ld, id %ld); dest(port %ld, id %ld); fmt(%s); name(%s)\n", (_text), (_in).node.node, (_in).node.port, (_in).source.port, (_in).source.id, (_in).destination.port, (_in).destination.id, _buf, (_in).name); } while (0) +# define PRINT_OUTPUT(_text, _out) do { char _buf[300]; string_for_format((_out).format, _buf, sizeof(_buf)); printf("%s node(node %ld, port %ld); source(port %ld, id %ld); dest(port %ld, id %ld); fmt(%s); name(%s)\n", (_text), (_out).node.node, (_out).node.port, (_out).source.port, (_out).source.id, (_out).destination.port, (_out).destination.id, _buf, (_out).name); } while (0) +# define PRINT_CHANNEL_MASK(fmt) do { char s[200]; StringForChannelMask(s, (fmt).u.raw_audio.channel_mask); printf(" channel_mask 0x%08lX %s\n", (fmt).u.raw_audio.channel_mask, s); } while (0) +# if DEBUG >= 2 +# define TRACE printf +# else +# define TRACE(a...) ((void)0) +# endif #else - - #define PRINT_FORMAT(_text, _fmt) ((void)0) - #define PRINT_INPUT(_text, _in) ((void)0) - #define PRINT_OUTPUT(_text, _out) ((void)0) - #define PRINT_CHANNEL_MASK(fmt) ((void)0) - #define PRINT(l, a...) ((void)0) - #define ERROR(a...) ((void)0) - #define TRACE(a...) ((void)0) - +# define PRINT_FORMAT(_text, _fmt) ((void)0) +# define PRINT_INPUT(_text, _in) ((void)0) +# define PRINT_OUTPUT(_text, _out) ((void)0) +# define PRINT_CHANNEL_MASK(fmt) ((void)0) +# define PRINT(l, a...) ((void)0) +# define ERROR(a...) ((void)0) +# define TRACE(a...) ((void)0) #endif #endif /* _MIXER_DEBUG_H_ */ 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 c10e7d84ef..0306cdd9ce 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerInput.cpp @@ -1,22 +1,28 @@ /* - * Copyright 2007 Haiku Inc. All rights reserved. + * Copyright 2003-2009 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: - * Marcus Overhagen + * Marcus Overhagen */ -#include "ByteSwap.h" + + #include "MixerCore.h" + +#include +#include +#include // TODO: debug only + +#include "ByteSwap.h" #include "MixerInput.h" #include "MixerUtils.h" #include "Resampler.h" -#include -#include -#include // XXX debug only -MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrameRate, int32 mixFrameCount) - : fCore(core), +MixerInput::MixerInput(MixerCore *core, const media_input &input, + float mixFrameRate, int32 mixFrameCount) + : + fCore(core), fInput(input), fInputByteSwap(0), fEnabled(true), @@ -38,7 +44,7 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrame 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); for (int i = 0; i < MAX_CHANNEL_TYPES; i++) @@ -47,16 +53,19 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrame 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) { + 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() @@ -68,11 +77,12 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrame fResampler = new Resampler * [fInputChannelCount]; for (int i = 0; i < fInputChannelCount; i++) fResampler[i] = new Resampler(fInput.format.u.raw_audio.format, media_raw_audio_format::B_AUDIO_FLOAT); - + // fMixerChannelInfo and fMixerChannelCount will be initialized by UpdateInputChannelDestinations() SetMixBufferFormat((int32)mixFrameRate, mixFrameCount); } + MixerInput::~MixerInput() { if (fMixBuffer) @@ -87,7 +97,8 @@ MixerInput::~MixerInput() delete fResampler[i]; delete [] fResampler; } - + + void MixerInput::BufferReceived(BBuffer *buffer) { @@ -95,12 +106,12 @@ MixerInput::BufferReceived(BBuffer *buffer) size_t size; bigtime_t start; bigtime_t buffer_duration; - + if (!fMixBuffer) { ERROR("MixerInput::BufferReceived: dropped incoming buffer as we don't have a mix buffer\n"); return; } - + data = buffer->Data(); size = buffer->SizeUsed(); start = buffer->Header()->start_time; @@ -109,15 +120,15 @@ MixerInput::BufferReceived(BBuffer *buffer) ERROR("MixerInput::BufferReceived: buffer with negative start time of %Ld dropped\n", start); return; } - + // swap the byte order of this buffer, if necessary if (fInputByteSwap) fInputByteSwap->Swap(data, size); int offset = frames_for_duration(fMixBufferFrameRate, start) % fMixBufferFrameCount; - + PRINT(4, "MixerInput::BufferReceived: buffer start %10Ld, offset %6d\n", start, offset); - + int in_frames = size / bytes_per_frame(fInput.format.u.raw_audio); double frames = double(in_frames * fMixBufferFrameRate) / fInput.format.u.raw_audio.frame_rate; int out_frames = int(frames); @@ -197,7 +208,7 @@ MixerInput::BufferReceived(BBuffer *buffer) fInputChannelCount * sizeof(float), out_frames1, fInputChannelInfo[i].gain); - + fResampler[i]->Resample(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, @@ -205,7 +216,7 @@ MixerInput::BufferReceived(BBuffer *buffer) fInputChannelCount * sizeof(float), out_frames2, fInputChannelInfo[i].gain); - + } } else { //printf("at %10Ld, data arrived for %10Ld to %10Ld, storing at frames %ld to %ld\n", fCore->fTimeSource->Now(), start, start + duration_for_frames(fInput.format.u.raw_audio.frame_rate, frames_per_buffer(fInput.format.u.raw_audio)), offset, offset + out_frames - 1); @@ -265,7 +276,7 @@ MixerInput::AddInputChannelDestination(int channel, int destination_type) if (-1 != GetInputChannelForDestination(destination_type)) { 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].destination_mask |= mask; @@ -274,6 +285,7 @@ MixerInput::AddInputChannelDestination(int channel, int destination_type) UpdateInputChannelDestinations(); } + void MixerInput::RemoveInputChannelDestination(int channel, int destination_type) { @@ -293,6 +305,7 @@ MixerInput::RemoveInputChannelDestination(int channel, int destination_type) UpdateInputChannelDestinations(); } + bool MixerInput::HasInputChannelDestination(int channel, int destination_type) { @@ -303,6 +316,7 @@ MixerInput::HasInputChannelDestination(int channel, int destination_type) return fInputChannelInfo[channel].destination_mask & ChannelTypeToChannelMask(destination_type); } + int MixerInput::GetInputChannelForDestination(int destination_type) { @@ -316,6 +330,7 @@ MixerInput::GetInputChannelForDestination(int destination_type) return -1; } + int MixerInput::GetInputChannelType(int channel) { @@ -324,6 +339,7 @@ MixerInput::GetInputChannelType(int channel) return GetChannelType(channel, fInputChannelMask); } + void MixerInput::SetInputChannelGain(int channel, float gain) { @@ -331,10 +347,11 @@ MixerInput::SetInputChannelGain(int channel, float gain) return; if (gain < 0.0f) gain = 0.0f; - + fInputChannelInfo[channel].gain = gain; } + float MixerInput::GetInputChannelGain(int channel) { @@ -343,6 +360,7 @@ MixerInput::GetInputChannelGain(int channel) return fInputChannelInfo[channel].gain; } + void MixerInput::UpdateInputChannelDestinationMask() { @@ -355,7 +373,7 @@ MixerInput::UpdateInputChannelDestinationMask() // first apply a 1:1 mapping for (int i = 0; i < fInputChannelCount; i++) fInputChannelInfo[i].destination_mask = GetChannelMask(i, fInputChannelMask); - + // specialize this, depending on the available physical output channels if (fCore->OutputChannelCount() <= 2) { // less or equal two channels @@ -386,23 +404,24 @@ MixerInput::UpdateInputChannelDestinationMask() TRACE("UpdateInputChannelDestinationMask: leave\n"); } + void MixerInput::UpdateInputChannelDestinations() { int channel_count; uint32 all_bits; uint32 mask; - + TRACE("UpdateInputChannelDestinations: enter\n"); for (int i = 0; i < fInputChannelCount; i++) 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); - + all_bits = 0; for (int i = 0; i < fInputChannelCount; i++) all_bits |= fInputChannelInfo[i].destination_mask; TRACE("UpdateInputChannelDestinations: all_bits = %08lx\n", all_bits); - + channel_count = count_nonzero_bits(all_bits); TRACE("UpdateInputChannelDestinations: %d input channels, %d mixer channels (%d old)\n", fInputChannelCount, channel_count, fMixerChannelCount); if (channel_count != fMixerChannelCount) { @@ -410,7 +429,7 @@ MixerInput::UpdateInputChannelDestinations() fMixerChannelInfo = new mixer_chan_info[channel_count]; fMixerChannelCount = channel_count; } - + // assign each mixer channel one type // and the gain from the fChannelTypeGain[] mask = 1; @@ -443,6 +462,7 @@ MixerInput::UpdateInputChannelDestinations() TRACE("UpdateInputChannelDestinations: leave\n"); } + // Note: The following code is outcommented on purpose // and is about to be modified at a later point /* @@ -468,6 +488,7 @@ MixerInput::SetInputChannelDestinationGain(int channel, int destination_type, fl } } + float MixerInput::GetInputChannelDestinationGain(int channel, int destination_type) { @@ -482,6 +503,7 @@ MixerInput::GetInputChannelDestinationGain(int channel, int destination_type) } */ + void MixerInput::SetMixerChannelGain(int mixer_channel, float gain) { @@ -494,6 +516,7 @@ MixerInput::SetMixerChannelGain(int mixer_channel, float gain) fChannelTypeGain[fMixerChannelInfo[mixer_channel].destination_type] = gain; } + float MixerInput::GetMixerChannelGain(int mixer_channel) { @@ -502,6 +525,7 @@ MixerInput::GetMixerChannelGain(int mixer_channel) return fMixerChannelInfo[mixer_channel].destination_gain; } + int MixerInput::GetMixerChannelType(int mixer_channel) { @@ -510,31 +534,35 @@ MixerInput::GetMixerChannelType(int mixer_channel) return fMixerChannelInfo[mixer_channel].destination_type; } + void MixerInput::SetEnabled(bool yesno) { fEnabled = yesno; } + bool MixerInput::IsEnabled() { return fEnabled; } + void MixerInput::SetMixBufferFormat(int32 framerate, int32 frames) { - TRACE("MixerInput::SetMixBufferFormat: framerate %ld, frames %ld\n", framerate, frames); + TRACE("MixerInput::SetMixBufferFormat: framerate %ld, frames %ld\n", + framerate, frames); fMixBufferFrameRate = framerate; - debugMixBufferFrames = frames; + fDebugMixBufferFrames = frames; // frames and/or framerate can be 0 (if no output is connected) if (framerate == 0 || frames == 0) { - if (fMixBuffer) { + if (fMixBuffer != NULL) { rtm_free(fMixBuffer); - fMixBuffer = 0; + fMixBuffer = NULL; } for (int i = 0; i < fInputChannelCount; i++) fInputChannelInfo[i].buffer_base = 0; @@ -553,28 +581,29 @@ MixerInput::SetMixBufferFormat(int32 framerate, int32 frames) bigtime_t mixerBufferLength = max_c(3 * inputBufferLength, 2 * outputBufferLength); int temp = frames_for_duration(framerate, mixerBufferLength); fMixBufferFrameCount = ((temp / frames) + 1) * frames; - + TRACE(" inputBufferLength %10Ld\n", inputBufferLength); TRACE(" outputBufferLength %10Ld\n", outputBufferLength); TRACE(" mixerBufferLength %10Ld\n", mixerBufferLength); TRACE(" fMixBufferFrameCount %10d\n", fMixBufferFrameCount); ASSERT((fMixBufferFrameCount % frames) == 0); - + fLastDataFrameWritten = -1; fFractionalFrames = 0.0; - - if (fMixBuffer) - rtm_free(fMixBuffer); - if (fRtmPool) - rtm_delete_pool(fRtmPool); + + rtm_free(fMixBuffer); + rtm_delete_pool(fRtmPool); + int size = sizeof(float) * fInputChannelCount * fMixBufferFrameCount; - if (B_OK != rtm_create_pool(&fRtmPool, size)) - fRtmPool = 0; + if (rtm_create_pool(&fRtmPool, size) != B_OK) + fRtmPool = NULL; + fMixBuffer = (float *)rtm_alloc(fRtmPool, size); - ASSERT(fMixBuffer); - - memset(fMixBuffer, 0, size); + if (fMixBuffer == NULL) + return; + + memset(fMixBuffer, 0, size); for (int i = 0; i < fInputChannelCount; i++) fInputChannelInfo[i].buffer_base = &fMixBuffer[i]; 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 ae080a5a7f..6503d2e28d 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerInput.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerInput.h @@ -1,149 +1,152 @@ /* - * Copyright 2007 Haiku Inc. All rights reserved. + * Copyright 2003-2009 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. + * + * Authors: + * Marcus Overhagen */ #ifndef _MIXER_INPUT_H #define _MIXER_INPUT_H + +#include +#include + #include "MixerCore.h" #include "MixerDebug.h" #include "MixerUtils.h" -#include -#include class ByteSwap; class Resampler; -class MixerInput -{ - public: - MixerInput(MixerCore *core, - const media_input &input, - float mixFrameRate, - int32 mixFrameCount); - ~MixerInput(); - - int32 ID(); - void BufferReceived(BBuffer *buffer); - media_input& MediaInput(); - // The physical input channels - int GetInputChannelCount(); - int GetInputChannelType(int channel); - void SetInputChannelGain(int channel, - float gain); - float GetInputChannelGain(int channel); +class MixerInput { +public: + MixerInput(MixerCore* core, + const media_input& input, + float mixFrameRate, int32 mixFrameCount); + ~MixerInput(); - // The destinations for each channel - void AddInputChannelDestination( - int channel, - int destination_type); - void RemoveInputChannelDestination( - int channel, - int destination_type); - bool HasInputChannelDestination( - int channel, - int destination_type); - int GetInputChannelForDestination( - int destination_type); - // returns -1 if not found - - // The virtual mixer channels that are generated from destinations - int GetMixerChannelCount(); - void SetMixerChannelGain(int mixer_channel, - float gain); - float GetMixerChannelGain(int mixer_channel); - int GetMixerChannelType(int mixer_channel); - - void SetEnabled(bool yesno); - bool IsEnabled(); + int32 ID(); + void BufferReceived(BBuffer* buffer); + media_input& MediaInput(); - // only for use by MixerCore - bool GetMixerChannelInfo(int mixer_channel, - int64 framepos, - bigtime_t time, - const float **buffer, - uint32 *sample_offset, - int *type, - float *gain); + // The physical input channels + int GetInputChannelCount(); + int GetInputChannelType(int channel); + void SetInputChannelGain(int channel, float gain); + float GetInputChannelGain(int channel); - protected: - friend class MixerCore; - void SetMixBufferFormat(int32 framerate, - int32 frames); - - private: - void UpdateInputChannelDestinationMask(); - void UpdateInputChannelDestinations(); + // The destinations for each channel + void AddInputChannelDestination(int channel, + int destinationType); + void RemoveInputChannelDestination(int channel, + int destinationType); + bool HasInputChannelDestination(int channel, + int destinationType); + int GetInputChannelForDestination( + int destinationType); + // returns -1 if not found - struct input_chan_info { - float *buffer_base; - uint32 destination_mask; // multiple or no bits sets - float gain; - }; - struct mixer_chan_info { - float *buffer_base; - int destination_type; - float destination_gain; - }; - - private: - MixerCore *fCore; - media_input fInput; - ByteSwap *fInputByteSwap; - float fChannelTypeGain[MAX_CHANNEL_TYPES]; - bool fEnabled; - input_chan_info *fInputChannelInfo; // array - int fInputChannelCount; - uint32 fInputChannelMask; - mixer_chan_info *fMixerChannelInfo; // array - int fMixerChannelCount; - float *fMixBuffer; - int32 fMixBufferFrameRate; - int fMixBufferFrameCount; - int32 fLastDataFrameWritten; - bigtime_t fLastDataAvailableTime; - double fFractionalFrames; - Resampler **fResampler; // array - rtm_pool *fRtmPool; - bool fUserOverridesChannelDestinations; - int32 debugMixBufferFrames; + // The virtual mixer channels that are generated from destinations + int GetMixerChannelCount(); + void SetMixerChannelGain(int mixerChannel, + float gain); + float GetMixerChannelGain(int mixerChannel); + int GetMixerChannelType(int mixerChannel); + + void SetEnabled(bool enabled); + bool IsEnabled(); + + // only for use by MixerCore + bool GetMixerChannelInfo(int mixerChannel, + int64 framepos, bigtime_t time, + const float** _buffer, + uint32* _sampleOffset, int* _type, + float* _gain); + +protected: + friend class MixerCore; + + void SetMixBufferFormat(int32 framerate, + int32 frames); + +private: + void UpdateInputChannelDestinationMask(); + void UpdateInputChannelDestinations(); + + struct input_chan_info { + float* buffer_base; + uint32 destination_mask; // multiple or no bits sets + float gain; + }; + + struct mixer_chan_info { + float* buffer_base; + int destination_type; + float destination_gain; + }; + +private: + MixerCore* fCore; + media_input fInput; + ByteSwap* fInputByteSwap; + float fChannelTypeGain[MAX_CHANNEL_TYPES]; + bool fEnabled; + input_chan_info* fInputChannelInfo; // array + int fInputChannelCount; + uint32 fInputChannelMask; + mixer_chan_info* fMixerChannelInfo; // array + int fMixerChannelCount; + float* fMixBuffer; + int32 fMixBufferFrameRate; + int fMixBufferFrameCount; + int32 fLastDataFrameWritten; + bigtime_t fLastDataAvailableTime; + double fFractionalFrames; + Resampler** fResampler; // array + rtm_pool* fRtmPool; + bool fUserOverridesChannelDestinations; + int32 fDebugMixBufferFrames; }; + inline int MixerInput::GetMixerChannelCount() { return fMixerChannelCount; } + inline bool -MixerInput::GetMixerChannelInfo(int mixer_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) { // this function should not be called if we don't have a mix buffer! - ASSERT(fMixBuffer); + ASSERT(fMixBuffer); ASSERT(mixer_channel >= 0 && mixer_channel < fMixerChannelCount); if (!fEnabled) return false; #if 1 if (time < (fLastDataAvailableTime - duration_for_frames(fMixBufferFrameRate, fMixBufferFrameCount)) - || (time + duration_for_frames(fMixBufferFrameRate, debugMixBufferFrames)) >= fLastDataAvailableTime) + || (time + duration_for_frames(fMixBufferFrameRate, fDebugMixBufferFrames)) >= fLastDataAvailableTime) ERROR("MixerInput::GetMixerChannelInfo: reading wrong data, have %Ld to %Ld, reading from %Ld to %Ld\n", - fLastDataAvailableTime - duration_for_frames(fMixBufferFrameRate, fMixBufferFrameCount), fLastDataAvailableTime, time, time + duration_for_frames(fMixBufferFrameRate, debugMixBufferFrames)); + fLastDataAvailableTime - duration_for_frames(fMixBufferFrameRate, fMixBufferFrameCount), fLastDataAvailableTime, time, time + duration_for_frames(fMixBufferFrameRate, fDebugMixBufferFrames)); #endif if (time > fLastDataAvailableTime) return false; - + int32 offset = framepos % fMixBufferFrameCount; - if (mixer_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 + fDebugMixBufferFrames - 1); *buffer = reinterpret_cast(reinterpret_cast(fMixerChannelInfo[mixer_channel].buffer_base) + (offset * sizeof(float) * fInputChannelCount)); *sample_offset = sizeof(float) * fInputChannelCount; *type = fMixerChannelInfo[mixer_channel].destination_type; *gain = fMixerChannelInfo[mixer_channel].destination_gain; return true; } -#endif + +#endif // _MIXER_INPUT_H 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 9de9b20801..9827e5e6a5 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerOutput.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerOutput.cpp @@ -1,19 +1,24 @@ /* - * Copyright 2007 Haiku Inc. All rights reserved. + * Copyright 2003-2009 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: - * probably Marcus Overhagen + * Marcus Overhagen */ -#include "MixerCore.h" -#include "MixerDebug.h" + + #include "MixerOutput.h" -#include "MixerUtils.h" #include +#include "MixerCore.h" +#include "MixerDebug.h" +#include "MixerUtils.h" + + MixerOutput::MixerOutput(MixerCore *core, const media_output &output) - : fCore(core), + : + fCore(core), fOutput(output), fOutputChannelCount(0), fOutputChannelInfo(0), @@ -28,24 +33,27 @@ MixerOutput::MixerOutput(MixerCore *core, const media_output &output) UpdateByteOrderSwap(); } + MixerOutput::~MixerOutput() { delete fOutputChannelInfo; delete fOutputByteSwap; } + media_output & MixerOutput::MediaOutput() { return fOutput; } + void MixerOutput::ChangeFormat(const media_multi_audio_format &format) { fOutput.format.u.raw_audio = format; fix_multiaudio_format(&fOutput.format.u.raw_audio); - + PRINT_OUTPUT("MixerOutput::ChangeFormat", fOutput); PRINT_CHANNEL_MASK(fOutput.format); @@ -53,6 +61,7 @@ MixerOutput::ChangeFormat(const media_multi_audio_format &format) UpdateByteOrderSwap(); } + void MixerOutput::UpdateByteOrderSwap() { @@ -69,6 +78,7 @@ MixerOutput::UpdateByteOrderSwap() } } + void MixerOutput::UpdateOutputChannels() { @@ -115,12 +125,13 @@ MixerOutput::UpdateOutputChannels() TRACE("UpdateOutputChannels: output channel %d, type %2d, gain %.3f\n", i, fOutputChannelInfo[i].channel_type, fOutputChannelInfo[i].channel_gain); } + void MixerOutput::AssignDefaultSources() { uint32 mask = fOutput.format.u.raw_audio.channel_mask; int count = fOutputChannelCount; - + // assign default sources for a few known setups, // everything else is left unchanged (it already is 1:1) if (count == 1 && mask & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT)) { @@ -296,6 +307,7 @@ MixerOutput::AssignDefaultSources() } } + int MixerOutput::GetOutputChannelType(int channel) { @@ -304,6 +316,7 @@ MixerOutput::GetOutputChannelType(int channel) return fOutputChannelInfo[channel].channel_type; } + void MixerOutput::SetOutputChannelGain(int channel, float gain) { @@ -313,6 +326,7 @@ MixerOutput::SetOutputChannelGain(int channel, float gain) fOutputChannelInfo[channel].channel_gain = gain; } + void MixerOutput::AddOutputChannelSource(int channel, int source_type) { @@ -333,6 +347,7 @@ MixerOutput::AddOutputChannelSource(int channel, int source_type) fOutputChannelInfo[channel].source_count++; } + void MixerOutput::RemoveOutputChannelSource(int channel, int source_type) { @@ -351,6 +366,7 @@ MixerOutput::RemoveOutputChannelSource(int channel, int source_type) } } + void MixerOutput::SetOutputChannelSourceGain(int channel, int source_type, float source_gain) { @@ -369,6 +385,7 @@ MixerOutput::SetOutputChannelSourceGain(int channel, int source_type, float sour fOutputChannelInfo[channel].source_gain_cache[source_type] = source_gain; } + float MixerOutput::GetOutputChannelSourceGain(int channel, int source_type) { @@ -386,6 +403,7 @@ MixerOutput::GetOutputChannelSourceGain(int channel, int source_type) return fOutputChannelInfo[channel].source_gain_cache[source_type]; } + bool MixerOutput::HasOutputChannelSource(int channel, int source_type) { @@ -399,6 +417,7 @@ MixerOutput::HasOutputChannelSource(int channel, int source_type) return false; } + void MixerOutput::SetMuted(bool yesno) { diff --git a/src/add-ons/media/media-add-ons/mixer/MixerSettings.cpp b/src/add-ons/media/media-add-ons/mixer/MixerSettings.cpp index 8602ed257c..f7ea2b6f44 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerSettings.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerSettings.cpp @@ -1,30 +1,37 @@ /* - * Copyright 2007 Haiku Inc. All rights reserved. + * Copyright 2003-2009 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: - * probably Marcus Overhagen + * Marcus Overhagen */ -#include "MixerCore.h" -#include "MixerDebug.h" -#include "MixerInput.h" -#include "MixerOutput.h" + + #include "MixerSettings.h" +#include + #include #include #include #include #include -#include + +#include "MixerCore.h" +#include "MixerDebug.h" +#include "MixerInput.h" +#include "MixerOutput.h" + #define SAVE_DELAY 5000000 // delay saving of settings for 5s #define SAVE_RUNTIME 30000000 // stop save thread after 30s inactivity #define SETTINGS_VERSION ((int32)0x94251601) + MixerSettings::MixerSettings() - : fLocker(new BLocker("mixer settings lock")), + : + fLocker(new BLocker("mixer settings lock")), fSettingsFile(0), fSettingsDirty(false), fSettingsLastChange(0), @@ -35,6 +42,7 @@ MixerSettings::MixerSettings() Load(); } + MixerSettings::~MixerSettings() { StopDeferredSave(); @@ -44,6 +52,7 @@ MixerSettings::~MixerSettings() delete fSettingsFile; } + void MixerSettings::SetSettingsFile(const char *file) { @@ -54,6 +63,7 @@ MixerSettings::SetSettingsFile(const char *file) Load(); } + bool MixerSettings::AttenuateOutput() { @@ -64,6 +74,7 @@ MixerSettings::AttenuateOutput() return temp; } + void MixerSettings::SetAttenuateOutput(bool yesno) { @@ -73,6 +84,7 @@ MixerSettings::SetAttenuateOutput(bool yesno) StartDeferredSave(); } + bool MixerSettings::NonLinearGainSlider() { @@ -83,6 +95,7 @@ MixerSettings::NonLinearGainSlider() return temp; } + void MixerSettings::SetNonLinearGainSlider(bool yesno) { @@ -92,6 +105,7 @@ MixerSettings::SetNonLinearGainSlider(bool yesno) StartDeferredSave(); } + bool MixerSettings::UseBalanceControl() { @@ -102,6 +116,7 @@ MixerSettings::UseBalanceControl() return temp; } + void MixerSettings::SetUseBalanceControl(bool yesno) { @@ -111,6 +126,7 @@ MixerSettings::SetUseBalanceControl(bool yesno) StartDeferredSave(); } + bool MixerSettings::AllowOutputChannelRemapping() { @@ -121,6 +137,7 @@ MixerSettings::AllowOutputChannelRemapping() return temp; } + void MixerSettings::SetAllowOutputChannelRemapping(bool yesno) { @@ -130,6 +147,7 @@ MixerSettings::SetAllowOutputChannelRemapping(bool yesno) StartDeferredSave(); } + bool MixerSettings::AllowInputChannelRemapping() { @@ -140,6 +158,7 @@ MixerSettings::AllowInputChannelRemapping() return temp; } + void MixerSettings::SetAllowInputChannelRemapping(bool yesno) { @@ -149,6 +168,7 @@ MixerSettings::SetAllowInputChannelRemapping(bool yesno) StartDeferredSave(); } + int MixerSettings::InputGainControls() { @@ -159,6 +179,7 @@ MixerSettings::InputGainControls() return temp; } + void MixerSettings::SetInputGainControls(int value) { @@ -168,6 +189,7 @@ MixerSettings::SetInputGainControls(int value) StartDeferredSave(); } + int MixerSettings::ResamplingAlgorithm() { @@ -178,6 +200,7 @@ MixerSettings::ResamplingAlgorithm() return temp; } + void MixerSettings::SetResamplingAlgorithm(int value) { @@ -187,6 +210,7 @@ MixerSettings::SetResamplingAlgorithm(int value) StartDeferredSave(); } + bool MixerSettings::RefuseOutputFormatChange() { @@ -197,6 +221,7 @@ MixerSettings::RefuseOutputFormatChange() return temp; } + void MixerSettings::SetRefuseOutputFormatChange(bool yesno) { @@ -206,6 +231,7 @@ MixerSettings::SetRefuseOutputFormatChange(bool yesno) StartDeferredSave(); } + bool MixerSettings::RefuseInputFormatChange() { @@ -216,6 +242,7 @@ MixerSettings::RefuseInputFormatChange() return temp; } + void MixerSettings::SetRefuseInputFormatChange(bool yesno) { @@ -225,17 +252,18 @@ MixerSettings::SetRefuseInputFormatChange(bool yesno) StartDeferredSave(); } + void MixerSettings::SaveConnectionSettings(MixerInput *input) { fLocker->Lock(); int index = -1; - + // try to find matching name first for (int i = 0; i < MAX_INPUT_SETTINGS; i++) { if (fInputSetting[i].IsEmpty()) continue; - if (0 == strcmp(fInputSetting[i].FindString("name"), input->MediaInput().name)) { + if (!strcmp(fInputSetting[i].FindString("name"), input->MediaInput().name)) { index = i; break; } @@ -267,7 +295,7 @@ MixerSettings::SaveConnectionSettings(MixerInput *input) int count = input->GetInputChannelCount(); fInputSetting[index].AddInt32("InputChannelCount", count); fInputSetting[index].AddBool("InputIsEnabled", input->IsEnabled()); - + for (int i = 0; i < count; i++) fInputSetting[index].AddFloat("InputChannelGain", input->GetInputChannelGain(i)); @@ -277,6 +305,7 @@ MixerSettings::SaveConnectionSettings(MixerInput *input) StartDeferredSave(); } + void MixerSettings::LoadConnectionSettings(MixerInput *input) { @@ -285,7 +314,7 @@ MixerSettings::LoadConnectionSettings(MixerInput *input) for (index = 0; index < MAX_INPUT_SETTINGS; index++) { if (fInputSetting[index].IsEmpty()) continue; - if (0 == strcmp(fInputSetting[index].FindString("name"), input->MediaInput().name)) + if (!strcmp(fInputSetting[index].FindString("name"), input->MediaInput().name)) break; } if (index == MAX_INPUT_SETTINGS) { @@ -293,58 +322,61 @@ MixerSettings::LoadConnectionSettings(MixerInput *input) fLocker->Unlock(); return; } - + TRACE("LoadConnectionSettings: found entry %d\n", index); - + int count = input->GetInputChannelCount(); if (fInputSetting[index].FindInt32("InputChannelCount") == count) { for (int i = 0; i < count; i++) input->SetInputChannelGain(i, fInputSetting[index].FindFloat("InputChannelGain", i)); input->SetEnabled(fInputSetting[index].FindBool("InputIsEnabled")); } - + // XXX should load channel destinations and mixer channels - + fInputSetting[index].ReplaceInt64("lru", system_time()); fLocker->Unlock(); StartDeferredSave(); } + void MixerSettings::SaveConnectionSettings(MixerOutput *output) { fLocker->Lock(); - + fOutputSetting.MakeEmpty(); - + int count = output->GetOutputChannelCount(); fOutputSetting.AddInt32("OutputChannelCount", count); for (int i = 0; i < count; i++) fOutputSetting.AddFloat("OutputChannelGain", output->GetOutputChannelGain(i)); fOutputSetting.AddBool("OutputIsMuted", output->IsMuted()); - + // XXX should save channel sources and source gains - + fLocker->Unlock(); StartDeferredSave(); } + void MixerSettings::LoadConnectionSettings(MixerOutput *output) { fLocker->Lock(); - + int count = output->GetOutputChannelCount(); if (fOutputSetting.FindInt32("OutputChannelCount") == count) { for (int i = 0; i < count; i++) output->SetOutputChannelGain(i, fOutputSetting.FindFloat("OutputChannelGain", i)); output->SetMuted(fOutputSetting.FindBool("OutputIsMuted")); } - + // XXX should load channel sources and source gains fLocker->Unlock(); } + void MixerSettings::Save() { @@ -355,30 +387,31 @@ MixerSettings::Save() return; } TRACE("MixerSettings: SAVE!\n"); - + BMessage msg; msg.AddInt32("version", SETTINGS_VERSION); msg.AddData("settings", B_RAW_TYPE, (void *)&fSettings, sizeof(fSettings)); msg.AddMessage("output", &fOutputSetting); for (int i = 0; i < MAX_INPUT_SETTINGS; i++) msg.AddMessage("input", &fInputSetting[i]); - + char *buffer; - size_t length; - + size_t length; + length = msg.FlattenedSize(); buffer = new char [length]; msg.Flatten(buffer, length); BFile file(fSettingsFile->Path(), B_READ_WRITE | B_CREATE_FILE); file.Write(buffer, length); - + delete [] buffer; - + fSettingsDirty = false; fLocker->Unlock(); } + void MixerSettings::Load() { @@ -393,13 +426,13 @@ MixerSettings::Load() fSettings.ResamplingAlgorithm = 0; fSettings.RefuseOutputFormatChange = true; fSettings.RefuseInputFormatChange = true; - + // if we don't have a settings file, don't continue if (!fSettingsFile) { fLocker->Unlock(); return; } - + BFile file(fSettingsFile->Path(), B_READ_WRITE); off_t size = 0; file.GetSize(&size); @@ -432,10 +465,10 @@ MixerSettings::Load() TRACE("MixerSettings: settings have wrong version\n"); return; } - + const void *data; ssize_t datasize = 0; - + msg.FindData("settings", B_RAW_TYPE, &data, &datasize); if (datasize != sizeof(fSettings)) { fLocker->Unlock(); @@ -443,19 +476,20 @@ MixerSettings::Load() return; } memcpy((void *)&fSettings, data, sizeof(fSettings)); - + msg.FindMessage("output", &fOutputSetting); for (int i = 0; i < MAX_INPUT_SETTINGS; i++) msg.FindMessage("input", i, &fInputSetting[i]); - + fLocker->Unlock(); } + void MixerSettings::StartDeferredSave() { fLocker->Lock(); - + // if we don't have a settings file, don't save the settings if (!fSettingsFile) { fLocker->Unlock(); @@ -464,14 +498,14 @@ MixerSettings::StartDeferredSave() fSettingsDirty = true; fSettingsLastChange = system_time(); - + if (fSaveThreadRunning) { fLocker->Unlock(); return; } - + StopDeferredSave(); - + ASSERT(fSaveThreadWaitSem < 0); fSaveThreadWaitSem = create_sem(0, "save thread wait"); if (fSaveThreadWaitSem < B_OK) { @@ -491,42 +525,44 @@ MixerSettings::StartDeferredSave() return; } resume_thread(fSaveThread); - + fSaveThreadRunning = true; fLocker->Unlock(); } + void MixerSettings::StopDeferredSave() { fLocker->Lock(); - if (fSaveThread > 0) { + if (fSaveThread >= 0) { ASSERT(fSaveThreadWaitSem > 0); status_t unused; delete_sem(fSaveThreadWaitSem); wait_for_thread(fSaveThread, &unused); - + fSaveThread = -1; fSaveThreadWaitSem = -1; } - + fLocker->Unlock(); } + void MixerSettings::SaveThread() { bigtime_t timeout; status_t rv; - + TRACE("MixerSettings: save thread started\n"); fLocker->Lock(); timeout = fSettingsLastChange + SAVE_DELAY; fLocker->Unlock(); - + for (;;) { rv = acquire_sem_etc(fSaveThreadWaitSem, 1, B_ABSOLUTE_TIMEOUT, timeout); if (rv == B_INTERRUPTED) @@ -535,11 +571,11 @@ MixerSettings::SaveThread() break; if (B_OK != fLocker->LockWithTimeout(200000)) continue; - + TRACE("MixerSettings: save thread running\n"); - + bigtime_t delta = system_time() - fSettingsLastChange; - + if (fSettingsDirty && delta > SAVE_DELAY) { Save(); } @@ -553,10 +589,11 @@ MixerSettings::SaveThread() timeout = system_time() + SAVE_DELAY; fLocker->Unlock(); } - + TRACE("MixerSettings: save thread ended\n"); } - + + int32 MixerSettings::_save_thread_(void *arg) { diff --git a/src/add-ons/media/media-add-ons/mixer/MixerUtils.cpp b/src/add-ons/media/media-add-ons/mixer/MixerUtils.cpp index e8a225b180..ce28d01de6 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerUtils.cpp +++ b/src/add-ons/media/media-add-ons/mixer/MixerUtils.cpp @@ -1,3 +1,12 @@ +/* + * Copyright 2003-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Marcus Overhagen + */ + + #include #include #include @@ -119,7 +128,7 @@ fix_multiaudio_format(media_multi_audio_format *format) format->matrix_mask = 0; } break; - + default: if (count_nonzero_bits(format->channel_mask) != (int)format->channel_count) { format->channel_mask = 0xffffffff; diff --git a/src/add-ons/media/media-add-ons/mixer/MixerUtils.h b/src/add-ons/media/media-add-ons/mixer/MixerUtils.h index 4ecb79b9cb..cc01a9b43c 100644 --- a/src/add-ons/media/media-add-ons/mixer/MixerUtils.h +++ b/src/add-ons/media/media-add-ons/mixer/MixerUtils.h @@ -1,12 +1,21 @@ +/* + * Copyright 2003-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Marcus Overhagen + */ #ifndef _MIXER_UTILS_H #define _MIXER_UTILS_H + #ifndef __SGI_STL_INTERNAL_ALGOBASE_H template const t & max(const t &t1, const t &t2) { return (t1 > t2) ? t1 : t2; } template const t & min(const t &t1, const t &t2) { return (t1 < t2) ? t1 : t2; } #endif template const t abs(const t t1) { return (t1 < 0) ? - t1 : t1; } + void fix_multiaudio_format(media_multi_audio_format *format); int count_nonzero_bits(uint32 value); @@ -42,4 +51,4 @@ const char *StringForFormat(char *buf, MixerInput *input); const char *StringForChannelMask(char *buf, uint32 mask); const char *StringForChannelType(char *buf, int type); -#endif //_MIXER_UTILS_H +#endif // _MIXER_UTILS_H diff --git a/src/add-ons/media/media-add-ons/mixer/Resampler.cpp b/src/add-ons/media/media-add-ons/mixer/Resampler.cpp index 2aa78a65b7..1a758c23b4 100644 --- a/src/add-ons/media/media-add-ons/mixer/Resampler.cpp +++ b/src/add-ons/media/media-add-ons/mixer/Resampler.cpp @@ -1,20 +1,27 @@ -/* Copyright (C) 2003 Marcus Overhagen - * Released under terms of the MIT license. - * - * A simple resampling class for the audio mixer. - * You pick the conversion function on object creation, - * and then call the Resample() function, specifying data pointer, - * offset (in bytes) to the next sample, and count of samples for - * both source and destination. - * +/* + * Copyright 2003 Marcus Overhagen + * Distributed under the terms of the MIT License. */ -#include + #include "Resampler.h" + +#include + #include "MixerDebug.h" + +/*! A simple resampling class for the audio mixer. + You pick the conversion function on object creation, + and then call the Resample() function, specifying data pointer, + offset (in bytes) to the next sample, and count of samples for + both source and destination. +*/ + + Resampler::Resampler(uint32 src_format, uint32 dst_format) - : fFunc(0) + : + fFunc(0) { if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) { switch (src_format) { @@ -34,7 +41,8 @@ Resampler::Resampler(uint32 src_format, uint32 dst_format) fFunc = &Resampler::uint8_to_float; return; default: - ERROR("Resampler::Resampler: unknown source format 0x%x\n", src_format); + ERROR("Resampler::Resampler: unknown source format 0x%x\n", + src_format); return; } } @@ -60,275 +68,290 @@ Resampler::Resampler(uint32 src_format, uint32 dst_format) } } - ERROR("Resampler::Resampler: source or destination format must be B_AUDIO_FLOAT\n"); + ERROR("Resampler::Resampler: source or destination format must be " + "B_AUDIO_FLOAT\n"); } + Resampler::~Resampler() { } + status_t -Resampler::InitCheck() +Resampler::InitCheck() const { - return (fFunc != 0) ? B_OK : B_ERROR; + return fFunc != 0 ? B_OK : B_ERROR; } + void -Resampler::float_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, - void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) +Resampler::float_to_float(const void *_src, int32 srcSampleOffset, + int32 srcSampleCount, void *_dest, int32 destSampleOffset, + int32 destSampleCount, float _gain) { - register const char * src = (const char *) _src; - register char * dst = (char *) _dst; - register int32 count = dst_sample_count; + register const char * src = (const char *)_src; + register char * dest = (char *)_dest; + register int32 count = destSampleCount; register float gain = _gain; - - if (src_sample_count == dst_sample_count) { + + if (srcSampleCount == destSampleCount) { // optimized case for no resampling while (count--) { - *(float *)dst = *(const float *)src * gain; - src += src_sample_offset; - dst += dst_sample_offset; + *(float *)dest = *(const float *)src * gain; + src += srcSampleOffset; + dest += destSampleOffset; } return; } - register float delta = float(src_sample_count) / float(dst_sample_count); + register float delta = float(srcSampleCount) / float(destSampleCount); register float current = 0.0f; if (delta < 1.0) { // upsample while (count--) { - *(float *)dst = *(const float *)src * gain; - dst += dst_sample_offset; + *(float *)dest = *(const float *)src * gain; + dest += destSampleOffset; current += delta; if (current >= 1.0f) { current -= 1.0f; - src += src_sample_offset; + src += srcSampleOffset; } } } else { // downsample while (count--) { - *(float *)dst = *(const float *)src * gain; - dst += dst_sample_offset; + *(float *)dest = *(const float *)src * gain; + dest += destSampleOffset; current += delta; register int32 skipcount = (int32)current; current -= skipcount; - src += skipcount * src_sample_offset; + src += skipcount * srcSampleOffset; } } } + void -Resampler::int32_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, - void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) +Resampler::int32_to_float(const void *_src, int32 srcSampleOffset, + int32 srcSampleCount, void *_dest, int32 destSampleOffset, + int32 destSampleCount, float _gain) { - register const char * src = (const char *) _src; - register char * dst = (char *) _dst; - register int32 count = dst_sample_count; + register const char * src = (const char *)_src; + register char * dest = (char *)_dest; + register int32 count = destSampleCount; register float gain = _gain / 2147483647.0; - - if (src_sample_count == dst_sample_count) { + + if (srcSampleCount == destSampleCount) { // optimized case for no resampling while (count--) { - *(float *)dst = *(const int32 *)src * gain; - src += src_sample_offset; - dst += dst_sample_offset; + *(float *)dest = *(const int32 *)src * gain; + src += srcSampleOffset; + dest += destSampleOffset; } return; } - register float delta = float(src_sample_count) / float(dst_sample_count); + register float delta = float(srcSampleCount) / float(destSampleCount); register float current = 0.0f; if (delta < 1.0) { // upsample while (count--) { - *(float *)dst = *(const int32 *)src * gain; - dst += dst_sample_offset; + *(float *)dest = *(const int32 *)src * gain; + dest += destSampleOffset; current += delta; if (current >= 1.0f) { current -= 1.0f; - src += src_sample_offset; + src += srcSampleOffset; } } } else { // downsample while (count--) { - *(float *)dst = *(const int32 *)src * gain; - dst += dst_sample_offset; + *(float *)dest = *(const int32 *)src * gain; + dest += destSampleOffset; current += delta; register int32 skipcount = (int32)current; current -= skipcount; - src += skipcount * src_sample_offset; + src += skipcount * srcSampleOffset; } } } + void -Resampler::int16_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, - void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) +Resampler::int16_to_float(const void *_src, int32 srcSampleOffset, + int32 srcSampleCount, void *_dest, int32 destSampleOffset, + int32 destSampleCount, float _gain) { - register const char * src = (const char *) _src; - register char * dst = (char *) _dst; - register int32 count = dst_sample_count; + register const char * src = (const char *)_src; + register char * dest = (char *)_dest; + register int32 count = destSampleCount; register float gain = _gain / 32767.0; - - if (src_sample_count == dst_sample_count) { + + if (srcSampleCount == destSampleCount) { // optimized case for no resampling while (count--) { - *(float *)dst = *(const int16 *)src * gain; - src += src_sample_offset; - dst += dst_sample_offset; + *(float *)dest = *(const int16 *)src * gain; + src += srcSampleOffset; + dest += destSampleOffset; } return; } - register float delta = float(src_sample_count) / float(dst_sample_count); + register float delta = float(srcSampleCount) / float(destSampleCount); register float current = 0.0f; if (delta < 1.0) { // upsample while (count--) { - *(float *)dst = *(const int16 *)src * gain; - dst += dst_sample_offset; + *(float *)dest = *(const int16 *)src * gain; + dest += destSampleOffset; current += delta; if (current >= 1.0f) { current -= 1.0f; - src += src_sample_offset; + src += srcSampleOffset; } } } else { // downsample while (count--) { - *(float *)dst = *(const int16 *)src * gain; - dst += dst_sample_offset; + *(float *)dest = *(const int16 *)src * gain; + dest += destSampleOffset; current += delta; register int32 skipcount = (int32)current; current -= skipcount; - src += skipcount * src_sample_offset; + src += skipcount * srcSampleOffset; } } } + void -Resampler::int8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, - void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) +Resampler::int8_to_float(const void *_src, int32 srcSampleOffset, + int32 srcSampleCount, void *_dest, int32 destSampleOffset, + int32 destSampleCount, float _gain) { - register const char * src = (const char *) _src; - register char * dst = (char *) _dst; - register int32 count = dst_sample_count; + register const char * src = (const char *)_src; + register char * dest = (char *)_dest; + register int32 count = destSampleCount; register float gain = _gain / 127.0; - - if (src_sample_count == dst_sample_count) { + + if (srcSampleCount == destSampleCount) { // optimized case for no resampling while (count--) { - *(float *)dst = *(const int8 *)src * gain; - src += src_sample_offset; - dst += dst_sample_offset; + *(float *)dest = *(const int8 *)src * gain; + src += srcSampleOffset; + dest += destSampleOffset; } return; } - register float delta = float(src_sample_count) / float(dst_sample_count); + register float delta = float(srcSampleCount) / float(destSampleCount); register float current = 0.0f; if (delta < 1.0) { // upsample while (count--) { - *(float *)dst = *(const int8 *)src * gain; - dst += dst_sample_offset; + *(float *)dest = *(const int8 *)src * gain; + dest += destSampleOffset; current += delta; if (current >= 1.0f) { current -= 1.0f; - src += src_sample_offset; + src += srcSampleOffset; } } } else { // downsample while (count--) { - *(float *)dst = *(const int8 *)src * gain; - dst += dst_sample_offset; + *(float *)dest = *(const int8 *)src * gain; + dest += destSampleOffset; current += delta; register int32 skipcount = (int32)current; current -= skipcount; - src += skipcount * src_sample_offset; + src += skipcount * srcSampleOffset; } } } + void -Resampler::uint8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, - void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) +Resampler::uint8_to_float(const void *_src, int32 srcSampleOffset, + int32 srcSampleCount, void *_dest, int32 destSampleOffset, + int32 destSampleCount, float _gain) { - register const char * src = (const char *) _src; - register char * dst = (char *) _dst; - register int32 count = dst_sample_count; + register const char * src = (const char *)_src; + register char * dest = (char *)_dest; + register int32 count = destSampleCount; register float gain = _gain / 127.0; - - if (src_sample_count == dst_sample_count) { + + if (srcSampleCount == destSampleCount) { // optimized case for no resampling while (count--) { - *(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; - src += src_sample_offset; - dst += dst_sample_offset; + *(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain; + src += srcSampleOffset; + dest += destSampleOffset; } return; } - register float delta = float(src_sample_count) / float(dst_sample_count); + register float delta = float(srcSampleCount) / float(destSampleCount); register float current = 0.0f; if (delta < 1.0) { // upsample while (count--) { - *(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; - dst += dst_sample_offset; + *(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain; + dest += destSampleOffset; current += delta; if (current >= 1.0f) { current -= 1.0f; - src += src_sample_offset; + src += srcSampleOffset; } } } else { // downsample while (count--) { - *(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; - dst += dst_sample_offset; + *(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain; + dest += destSampleOffset; current += delta; register int32 skipcount = (int32)current; current -= skipcount; - src += skipcount * src_sample_offset; + src += skipcount * srcSampleOffset; } } } + void -Resampler::float_to_int32(const void *_src, int32 src_sample_offset, int32 src_sample_count, - void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) +Resampler::float_to_int32(const void *_src, int32 srcSampleOffset, + int32 srcSampleCount, void *_dest, int32 destSampleOffset, + int32 destSampleCount, float _gain) { - register const char * src = (const char *) _src; - register char * dst = (char *) _dst; - register int32 count = dst_sample_count; + register const char * src = (const char *)_src; + register char * dest = (char *)_dest; + register int32 count = destSampleCount; register float gain = _gain * 2147483647.0; - - if (src_sample_count == dst_sample_count) { + + if (srcSampleCount == destSampleCount) { // optimized case for no resampling while (count--) { register float sample = *(const float *)src * gain; if (sample > 2147483647.0f) - *(int32 *)dst = 2147483647L; + *(int32 *)dest = 2147483647L; else if (sample < -2147483647.0f) - *(int32 *)dst = -2147483647L; + *(int32 *)dest = -2147483647L; else - *(int32 *)dst = (int32)sample; - src += src_sample_offset; - dst += dst_sample_offset; + *(int32 *)dest = (int32)sample; + src += srcSampleOffset; + dest += destSampleOffset; } return; } - register float delta = float(src_sample_count) / float(dst_sample_count); + register float delta = float(srcSampleCount) / float(destSampleCount); register float current = 0.0f; if (delta < 1.0) { @@ -336,16 +359,16 @@ Resampler::float_to_int32(const void *_src, int32 src_sample_offset, int32 src_s while (count--) { register float sample = *(const float *)src * gain; if (sample > 2147483647.0f) - *(int32 *)dst = 2147483647L; + *(int32 *)dest = 2147483647L; else if (sample < -2147483647.0f) - *(int32 *)dst = -2147483647L; + *(int32 *)dest = -2147483647L; else - *(int32 *)dst = (int32)sample; - dst += dst_sample_offset; + *(int32 *)dest = (int32)sample; + dest += destSampleOffset; current += delta; if (current >= 1.0f) { current -= 1.0f; - src += src_sample_offset; + src += srcSampleOffset; } } } else { @@ -353,47 +376,48 @@ Resampler::float_to_int32(const void *_src, int32 src_sample_offset, int32 src_s while (count--) { register float sample = *(const float *)src * gain; if (sample > 2147483647.0f) - *(int32 *)dst = 2147483647L; + *(int32 *)dest = 2147483647L; else if (sample < -2147483647.0f) - *(int32 *)dst = -2147483647L; + *(int32 *)dest = -2147483647L; else - *(int32 *)dst = (int32)sample; - dst += dst_sample_offset; + *(int32 *)dest = (int32)sample; + dest += destSampleOffset; current += delta; register int32 skipcount = (int32)current; current -= skipcount; - src += skipcount * src_sample_offset; + src += skipcount * srcSampleOffset; } } } void -Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_sample_count, - void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) +Resampler::float_to_int16(const void *_src, int32 srcSampleOffset, + int32 srcSampleCount, void *_dest, int32 destSampleOffset, + int32 destSampleCount, float _gain) { - register const char * src = (const char *) _src; - register char * dst = (char *) _dst; - register int32 count = dst_sample_count; + register const char * src = (const char *)_src; + register char * dest = (char *)_dest; + register int32 count = destSampleCount; register float gain = _gain * 32767.0; - - if (src_sample_count == dst_sample_count) { + + if (srcSampleCount == destSampleCount) { // optimized case for no resampling while (count--) { register float sample = *(const float *)src * gain; if (sample > 32767.0f) - *(int16 *)dst = 32767; + *(int16 *)dest = 32767; else if (sample < -32767.0f) - *(int16 *)dst = -32767; + *(int16 *)dest = -32767; else - *(int16 *)dst = (int16)sample; - src += src_sample_offset; - dst += dst_sample_offset; + *(int16 *)dest = (int16)sample; + src += srcSampleOffset; + dest += destSampleOffset; } return; } - register float delta = float(src_sample_count) / float(dst_sample_count); + register float delta = float(srcSampleCount) / float(destSampleCount); register float current = 0.0f; if (delta < 1.0) { @@ -401,16 +425,16 @@ Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_s while (count--) { register float sample = *(const float *)src * gain; if (sample > 32767.0f) - *(int16 *)dst = 32767; + *(int16 *)dest = 32767; else if (sample < -32767.0f) - *(int16 *)dst = -32767; + *(int16 *)dest = -32767; else - *(int16 *)dst = (int16)sample; - dst += dst_sample_offset; + *(int16 *)dest = (int16)sample; + dest += destSampleOffset; current += delta; if (current >= 1.0f) { current -= 1.0f; - src += src_sample_offset; + src += srcSampleOffset; } } } else { @@ -418,46 +442,48 @@ Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_s while (count--) { register float sample = *(const float *)src * gain; if (sample > 32767.0f) - *(int16 *)dst = 32767; + *(int16 *)dest = 32767; else if (sample < -32767.0f) - *(int16 *)dst = -32767; + *(int16 *)dest = -32767; else - *(int16 *)dst = (int16)sample; - dst += dst_sample_offset; + *(int16 *)dest = (int16)sample; + dest += destSampleOffset; current += delta; register int32 skipcount = (int32)current; current -= skipcount; - src += skipcount * src_sample_offset; + src += skipcount * srcSampleOffset; } } } + void -Resampler::float_to_int8(const void *_src, int32 src_sample_offset, int32 src_sample_count, - void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) +Resampler::float_to_int8(const void *_src, int32 srcSampleOffset, + int32 srcSampleCount, void *_dest, int32 destSampleOffset, + int32 destSampleCount, float _gain) { - register const char * src = (const char *) _src; - register char * dst = (char *) _dst; - register int32 count = dst_sample_count; + register const char * src = (const char *)_src; + register char * dest = (char *)_dest; + register int32 count = destSampleCount; register float gain = _gain * 127.0; - - if (src_sample_count == dst_sample_count) { + + if (srcSampleCount == destSampleCount) { // optimized case for no resampling while (count--) { register float sample = *(const float *)src * gain; if (sample > 127.0f) - *(int8 *)dst = 127; + *(int8 *)dest = 127; else if (sample < -127.0f) - *(int8 *)dst = -127; + *(int8 *)dest = -127; else - *(int8 *)dst = (int8)sample; - src += src_sample_offset; - dst += dst_sample_offset; + *(int8 *)dest = (int8)sample; + src += srcSampleOffset; + dest += destSampleOffset; } return; } - register float delta = float(src_sample_count) / float(dst_sample_count); + register float delta = float(srcSampleCount) / float(destSampleCount); register float current = 0.0f; if (delta < 1.0) { @@ -465,16 +491,16 @@ Resampler::float_to_int8(const void *_src, int32 src_sample_offset, int32 src_sa while (count--) { register float sample = *(const float *)src * gain; if (sample > 127.0f) - *(int8 *)dst = 127; + *(int8 *)dest = 127; else if (sample < -127.0f) - *(int8 *)dst = -127; + *(int8 *)dest = -127; else - *(int8 *)dst = (int8)sample; - dst += dst_sample_offset; + *(int8 *)dest = (int8)sample; + dest += destSampleOffset; current += delta; if (current >= 1.0f) { current -= 1.0f; - src += src_sample_offset; + src += srcSampleOffset; } } } else { @@ -482,46 +508,48 @@ Resampler::float_to_int8(const void *_src, int32 src_sample_offset, int32 src_sa while (count--) { register float sample = *(const float *)src * gain; if (sample > 127.0f) - *(int8 *)dst = 127; + *(int8 *)dest = 127; else if (sample < -127.0f) - *(int8 *)dst = -127; + *(int8 *)dest = -127; else - *(int8 *)dst = (int8)sample; - dst += dst_sample_offset; + *(int8 *)dest = (int8)sample; + dest += destSampleOffset; current += delta; register int32 skipcount = (int32)current; current -= skipcount; - src += skipcount * src_sample_offset; + src += skipcount * srcSampleOffset; } } } + void -Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_sample_count, - void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) +Resampler::float_to_uint8(const void *_src, int32 srcSampleOffset, + int32 srcSampleCount, void *_dest, int32 destSampleOffset, + int32 destSampleCount, float _gain) { - register const char * src = (const char *) _src; - register char * dst = (char *) _dst; - register int32 count = dst_sample_count; + register const char * src = (const char *)_src; + register char * dest = (char *)_dest; + register int32 count = destSampleCount; register float gain = _gain * 127.0; - - if (src_sample_count == dst_sample_count) { + + if (srcSampleCount == destSampleCount) { // optimized case for no resampling while (count--) { register float sample = 128.0f + *(const float *)src * gain; if (sample > 255.0f) - *(uint8 *)dst = 255; + *(uint8 *)dest = 255; else if (sample < 1.0f) - *(uint8 *)dst = 1; + *(uint8 *)dest = 1; else - *(uint8 *)dst = (uint8)sample; - src += src_sample_offset; - dst += dst_sample_offset; + *(uint8 *)dest = (uint8)sample; + src += srcSampleOffset; + dest += destSampleOffset; } return; } - register float delta = float(src_sample_count) / float(dst_sample_count); + register float delta = float(srcSampleCount) / float(destSampleCount); register float current = 0.0f; if (delta < 1.0) { @@ -529,16 +557,16 @@ Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_s while (count--) { register float sample = 128.0f + *(const float *)src * gain; if (sample > 255.0f) - *(uint8 *)dst = 255; + *(uint8 *)dest = 255; else if (sample < 1.0f) - *(uint8 *)dst = 1; + *(uint8 *)dest = 1; else - *(uint8 *)dst = (uint8)sample; - dst += dst_sample_offset; + *(uint8 *)dest = (uint8)sample; + dest += destSampleOffset; current += delta; if (current >= 1.0f) { current -= 1.0f; - src += src_sample_offset; + src += srcSampleOffset; } } } else { @@ -546,16 +574,16 @@ Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_s while (count--) { register float sample = 128.0f + *(const float *)src * gain; if (sample > 255.0f) - *(uint8 *)dst = 255; + *(uint8 *)dest = 255; else if (sample < 1.0f) - *(uint8 *)dst = 1; + *(uint8 *)dest = 1; else - *(uint8 *)dst = (uint8)sample; - dst += dst_sample_offset; + *(uint8 *)dest = (uint8)sample; + dest += destSampleOffset; current += delta; register int32 skipcount = (int32)current; current -= skipcount; - src += skipcount * src_sample_offset; + src += skipcount * srcSampleOffset; } } } diff --git a/src/add-ons/media/media-add-ons/mixer/Resampler.h b/src/add-ons/media/media-add-ons/mixer/Resampler.h index ce508bf0b8..9ad1b64b5f 100644 --- a/src/add-ons/media/media-add-ons/mixer/Resampler.h +++ b/src/add-ons/media/media-add-ons/mixer/Resampler.h @@ -1,59 +1,80 @@ -/* Copyright (C) 2003 Marcus Overhagen - * Released under terms of the MIT license. - * - * A simple resampling class for the audio mixer. - * You pick the conversion function on object creation, - * and then call the Resample() function, specifying data pointer, - * offset (in bytes) to the next sample, and count of samples for - * both source and destination. - * +/* + * Copyright 2003 Marcus Overhagen + * Distributed under the terms of the MIT License. */ #ifndef _RESAMPLER_H #define _RESAMPLER_H + #include -class Resampler -{ +class Resampler { public: - Resampler(uint32 sourceformat, uint32 destformat); - virtual ~Resampler(); - - status_t InitCheck(); - - void Resample(const void *src, int32 src_sample_offset, int32 src_sample_count, - void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); + Resampler(uint32 sourceFormat, + uint32 destFormat); + virtual ~Resampler(); + + status_t InitCheck() const; + + void Resample(const void* src, int32 srcSampleOffset, + int32 srcSampleCount, void* dest, + int32 destSampleOffset, + int32 destSampleCount, float gain); protected: - virtual void float_to_float (const void *src, int32 src_sample_offset, int32 src_sample_count, - void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); - virtual void int32_to_float (const void *src, int32 src_sample_offset, int32 src_sample_count, - void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); - virtual void int16_to_float (const void *src, int32 src_sample_offset, int32 src_sample_count, - void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); - virtual void int8_to_float (const void *src, int32 src_sample_offset, int32 src_sample_count, - void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); - virtual void uint8_to_float (const void *src, int32 src_sample_offset, int32 src_sample_count, - void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); - virtual void float_to_int32 (const void *src, int32 src_sample_offset, int32 src_sample_count, - void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); - virtual void float_to_int16 (const void *src, int32 src_sample_offset, int32 src_sample_count, - void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); - virtual void float_to_int8 (const void *src, int32 src_sample_offset, int32 src_sample_count, - void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); - virtual void float_to_uint8 (const void *src, int32 src_sample_offset, int32 src_sample_count, - void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); + virtual void float_to_float(const void* src, + int32 srcSampleOffset, int32 srcSampleCount, + void* dest, int32 destSampleOffset, + int32 destSampleCount, float gain); + virtual void int32_to_float(const void* src, + int32 srcSampleOffset, int32 srcSampleCount, + void* dest, int32 destSampleOffset, + int32 destSampleCount, float gain); + virtual void int16_to_float(const void* src, + int32 srcSampleOffset, int32 srcSampleCount, + void* dest, int32 destSampleOffset, + int32 destSampleCount, float gain); + virtual void int8_to_float(const void* src, + int32 srcSampleOffset, int32 srcSampleCount, + void* dest, int32 destSampleOffset, + int32 destSampleCount, float gain); + virtual void uint8_to_float(const void* src, + int32 srcSampleOffset, int32 srcSampleCount, + void* dest, int32 destSampleOffset, + int32 destSampleCount, float gain); + virtual void float_to_int32(const void* src, + int32 srcSampleOffset, int32 srcSampleCount, + void* dest, int32 destSampleOffset, + int32 destSampleCount, float gain); + virtual void float_to_int16(const void* src, + int32 srcSampleOffset, int32 srcSampleCount, + void* dest, int32 destSampleOffset, + int32 destSampleCount, float gain); + virtual void float_to_int8(const void* src, + int32 srcSampleOffset, int32 srcSampleCount, + void* dest, int32 destSampleOffset, + int32 destSampleCount, float gain); + virtual void float_to_uint8(const void* src, + int32 srcSampleOffset, int32 srcSampleCount, + void* dest, int32 destSampleOffset, + int32 destSampleCount, float gain); + private: - void (Resampler::*fFunc) (const void *, int32, int32, void *, int32, int32, float); + void (Resampler::*fFunc)(const void* src, + int32 srcSampleOffset, int32 srcSampleCount, + void* dest, int32 destSampleOffset, + int32 destSampleCount, float gain); }; inline void -Resampler::Resample(const void *src, int32 src_sample_offset, int32 src_sample_count, - void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain) +Resampler::Resample(const void *src, int32 srcSampleOffset, + int32 srcSampleCount, void *dest, int32 destSampleOffset, + int32 destSampleCount, float gain) { - (this->*fFunc)(src, src_sample_offset, src_sample_count, dst, dst_sample_offset, dst_sample_count, gain); + (this->*fFunc)(src, srcSampleOffset, srcSampleCount, dest, destSampleOffset, + destSampleCount, gain); } #endif // _RESAMPLER_H diff --git a/src/add-ons/media/media-add-ons/mixer/RtList.h b/src/add-ons/media/media-add-ons/mixer/RtList.h index 40fd70f045..9ad1889d1a 100644 --- a/src/add-ons/media/media-add-ons/mixer/RtList.h +++ b/src/add-ons/media/media-add-ons/mixer/RtList.h @@ -1,41 +1,48 @@ +/* + * Copyright 2003 Marcus Overhagen + * Distributed under the terms of the MIT License. + */ #ifndef _MEDIA_RT_LIST_H #define _MEDIA_RT_LIST_H -/* Copyright (C) 2003 Marcus Overhagen - * Released under terms of the MIT license. - * - * A simple list template that uses realtime - * memory and does no error checking. Since - * it doesn't call constructors or destructors, - * don't use it to store objects. - */ - + + +/*! A simple list template that uses realtime + memory and does no error checking. Since + it doesn't call constructors or destructors, + don't use it to store objects. + + // TODO: no error checking? Great. +*/ + + #include -template class RtList -{ + +template class RtList { public: RtList() - : item_max(INIT_COUNT), + : + item_max(INIT_COUNT), item_count(0), - items((value *)rtm_alloc(NULL, sizeof(value) * INIT_COUNT)) + items((value*)rtm_alloc(NULL, sizeof(value) * INIT_COUNT)) { } - + ~RtList() { rtm_free(items); } - value *Create() + value* Create() { if (item_count == item_max) { item_max += INC_COUNT; - rtm_realloc((void **)&items, sizeof(value) * item_max); + rtm_realloc((void**)&items, sizeof(value) * item_max); } return &items[item_count++]; } - - value *ItemAt(int index) + + value* ItemAt(int index) { return &items[index]; } @@ -51,14 +58,15 @@ public: } private: - RtList(const RtList &other); - RtList &operator=(const RtList &other); + RtList(const RtList& other); + RtList &operator=(const RtList& other); private: enum { INIT_COUNT = 8, INC_COUNT = 16 }; - int item_max; - int item_count; - value *items; + + int item_max; + int item_count; + value* items; }; #endif // _MEDIA_RT_LIST_H