* Cleanup, no functional change.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34437 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-12-02 09:21:28 +00:00
parent 1fd264a18e
commit a9cf57cff5
18 changed files with 970 additions and 696 deletions
@@ -6,23 +6,27 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "AudioMixer.h" #include "AudioMixer.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Buffer.h>
#include <FindDirectory.h>
#include <MediaRoster.h>
#include <ParameterWeb.h>
#include <Path.h>
#include <RealtimeAlloc.h>
#include <TimeSource.h>
#include "MixerCore.h" #include "MixerCore.h"
#include "MixerInput.h" #include "MixerInput.h"
#include "MixerOutput.h" #include "MixerOutput.h"
#include "MixerUtils.h" #include "MixerUtils.h"
#include <Buffer.h>
#include <FindDirectory.h>
#include <math.h>
#include <MediaRoster.h>
#include <ParameterWeb.h>
#include <Path.h>
#include <RealtimeAlloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <TimeSource.h>
// the range of the gain sliders (in dB) // the range of the gain sliders (in dB)
#define DB_MAX 18.0 #define DB_MAX 18.0
@@ -84,7 +88,8 @@ multi_audio_format_specialize(media_multi_audio_format *format,
AudioMixer::AudioMixer(BMediaAddOn *addOn, bool isSystemMixer) AudioMixer::AudioMixer(BMediaAddOn *addOn, bool isSystemMixer)
: BMediaNode("Audio Mixer"), :
BMediaNode("Audio Mixer"),
BBufferConsumer(B_MEDIA_RAW_AUDIO), BBufferConsumer(B_MEDIA_RAW_AUDIO),
BBufferProducer(B_MEDIA_RAW_AUDIO), BBufferProducer(B_MEDIA_RAW_AUDIO),
BControllable(), BControllable(),
@@ -7,6 +7,7 @@
#ifndef _AUDIOMIXER_H #ifndef _AUDIOMIXER_H
#define _AUDIOMIXER_H #define _AUDIOMIXER_H
#include <BufferConsumer.h> #include <BufferConsumer.h>
#include <BufferGroup.h> #include <BufferGroup.h>
#include <BufferProducer.h> #include <BufferProducer.h>
@@ -14,15 +15,13 @@
#include <MediaEventLooper.h> #include <MediaEventLooper.h>
#include <MediaNode.h> #include <MediaNode.h>
class MixerCore; class MixerCore;
class AudioMixer :
public BBufferConsumer, class AudioMixer : public BBufferConsumer, public BBufferProducer,
public BBufferProducer, public BControllable, public BMediaEventLooper {
public BControllable, public:
public BMediaEventLooper
{
public:
AudioMixer(BMediaAddOn *addOn, bool isSystemMixer); AudioMixer(BMediaAddOn *addOn, bool isSystemMixer);
~AudioMixer(); ~AudioMixer();
@@ -48,7 +47,7 @@ class AudioMixer :
void SetTimeSource(BTimeSource * time_source); void SetTimeSource(BTimeSource * time_source);
using BBufferProducer::SendBuffer; using BBufferProducer::SendBuffer;
protected: protected:
// BControllable methods // BControllable methods
status_t GetParameterValue(int32 id, status_t GetParameterValue(int32 id,
bigtime_t *last_change, bigtime_t *last_change,
@@ -128,7 +127,7 @@ class AudioMixer :
bigtime_t lateness, bigtime_t lateness,
bool realTimeEvent = false); bool realTimeEvent = false);
private: private:
BMediaAddOn *fAddOn; BMediaAddOn *fAddOn;
MixerCore *fCore; MixerCore *fCore;
BParameterWeb *fWeb; // local pointer to parameterweb BParameterWeb *fWeb; // local pointer to parameterweb
@@ -138,4 +137,5 @@ class AudioMixer :
bool fDisableStop; bool fDisableStop;
media_format fDefaultFormat; media_format fDefaultFormat;
}; };
#endif
#endif // _AUDIOMIXER_H
@@ -3,17 +3,22 @@
* Copyright 2007 Haiku Inc. All rights reserved. * Copyright 2007 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "ByteSwap.h" #include "ByteSwap.h"
#include "MixerDebug.h"
#include <ByteOrder.h> #include <ByteOrder.h>
#include <MediaDefs.h> #include <MediaDefs.h>
#include "MixerDebug.h"
static void swap_float(void *buffer, size_t bytecount); static void swap_float(void *buffer, size_t bytecount);
static void swap_int32(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 swap_int16(void *buffer, size_t bytecount);
static void do_nothing(void *buffer, size_t bytecount); static void do_nothing(void *buffer, size_t bytecount);
ByteSwap::ByteSwap(uint32 format) ByteSwap::ByteSwap(uint32 format)
{ {
switch (format) { switch (format) {
@@ -32,18 +37,21 @@ ByteSwap::ByteSwap(uint32 format)
} }
} }
ByteSwap::~ByteSwap() ByteSwap::~ByteSwap()
{ {
} }
void void
do_nothing(void *buffer, size_t bytecount) do_nothing(void *buffer, size_t bytecount)
{ {
} }
#if __INTEL__
// optimized for IA32 platform #if __INTEL__
// #pragma mark - optimized for IA32 platform
void void
swap_float(void *buffer, size_t bytecount) 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); swap_data(B_FLOAT_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
} }
void void
swap_int32(void *buffer, size_t bytecount) 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); swap_data(B_INT32_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
} }
void void
swap_int16(void *buffer, size_t bytecount) swap_int16(void *buffer, size_t bytecount)
{ {
@@ -111,9 +121,10 @@ swap_int16(void *buffer, size_t bytecount)
: "cc", "memory"); : "cc", "memory");
} }
#else
// non optimized default versions, do not remove #else // !__INTEL__
// #pragma mark - generic versions
void void
swap_float(void *buffer, size_t bytecount) 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); swap_data(B_FLOAT_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
} }
void void
swap_int32(void *buffer, size_t bytecount) swap_int32(void *buffer, size_t bytecount)
{ {
swap_data(B_INT32_TYPE, buffer, bytecount, B_SWAP_ALWAYS); swap_data(B_INT32_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
} }
void void
swap_int16(void *buffer, size_t bytecount) swap_int16(void *buffer, size_t bytecount)
{ {
swap_data(B_INT16_TYPE, buffer, bytecount, B_SWAP_ALWAYS); swap_data(B_INT16_TYPE, buffer, bytecount, B_SWAP_ALWAYS);
} }
#endif #endif
@@ -6,23 +6,26 @@
#ifndef _BYTE_SWAP_H #ifndef _BYTE_SWAP_H
#define _BYTE_SWAP_H #define _BYTE_SWAP_H
#include <SupportDefs.h> #include <SupportDefs.h>
class ByteSwap
{ class ByteSwap {
public: public:
ByteSwap(uint32 format); ByteSwap(uint32 format);
~ByteSwap(); ~ByteSwap();
void Swap(void *buffer, size_t bytecount); void Swap(void *buffer, size_t bytecount);
private: private:
void (*fFunc)(void *, size_t); void (*fFunc)(void *, size_t);
}; };
inline void inline void
ByteSwap::Swap(void *buffer, size_t bytecount) ByteSwap::Swap(void *buffer, size_t bytecount)
{ {
(*fFunc)(buffer, bytecount); (*fFunc)(buffer, bytecount);
} }
#endif
#endif // _BYTE_SWAP_H
@@ -4,21 +4,28 @@
* Copyright 2007 Haiku Inc. All rights reserved. * Copyright 2007 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "MixerAddOn.h"
#include <stdio.h>
#include <string.h>
#include <MediaRoster.h> #include <MediaRoster.h>
#include <MediaNode.h> #include <MediaNode.h>
#include <cstring>
#include <cstdio>
#include "AudioMixer.h" #include "AudioMixer.h"
#include "MixerAddOn.h"
// instantiation function // instantiation function
extern "C" _EXPORT BMediaAddOn* make_media_addon(image_id image) { extern "C" _EXPORT BMediaAddOn* make_media_addon(image_id image) {
return new AudioMixerAddon(image); return new AudioMixerAddon(image);
} }
AudioMixerAddon::AudioMixerAddon(image_id image) AudioMixerAddon::AudioMixerAddon(image_id image)
: BMediaAddOn(image), :
BMediaAddOn(image),
fFormat(new media_format), fFormat(new media_format),
fInfo(new flavor_info) fInfo(new flavor_info)
{ {
@@ -38,15 +45,16 @@ AudioMixerAddon::AudioMixerAddon(image_id image)
fInfo->out_formats = fFormat; fInfo->out_formats = fFormat;
} }
AudioMixerAddon::~AudioMixerAddon() AudioMixerAddon::~AudioMixerAddon()
{ {
delete fFormat; delete fFormat;
delete fInfo; delete fInfo;
} }
// -------------------------------------------------------- //
// BMediaAddOn impl // #pragma mark - BMediaAddOn implementation
// -------------------------------------------------------- //
status_t status_t
AudioMixerAddon::InitCheck(const char** out_failure_text) AudioMixerAddon::InitCheck(const char** out_failure_text)
@@ -54,12 +62,14 @@ AudioMixerAddon::InitCheck(const char** out_failure_text)
return B_OK; return B_OK;
} }
int32 int32
AudioMixerAddon::CountFlavors() AudioMixerAddon::CountFlavors()
{ {
return 1; return 1;
} }
status_t status_t
AudioMixerAddon::GetFlavorAt(int32 n, const flavor_info** out_info) AudioMixerAddon::GetFlavorAt(int32 n, const flavor_info** out_info)
{ {
@@ -71,6 +81,7 @@ AudioMixerAddon::GetFlavorAt(int32 n, const flavor_info** out_info)
return B_OK; return B_OK;
} }
BMediaNode * BMediaNode *
AudioMixerAddon::InstantiateNodeFor(const flavor_info* info, BMessage* config, AudioMixerAddon::InstantiateNodeFor(const flavor_info* info, BMessage* config,
status_t* out_error) status_t* out_error)
@@ -78,19 +89,23 @@ AudioMixerAddon::InstantiateNodeFor(const flavor_info* info, BMessage* config,
return new AudioMixer(this, false); return new AudioMixer(this, false);
} }
status_t status_t
AudioMixerAddon::GetConfigurationFor(BMediaNode* your_node, BMessage* into_message) AudioMixerAddon::GetConfigurationFor(BMediaNode* your_node,
BMessage* into_message)
{ {
// no config yet // no config yet
return B_ERROR; return B_ERROR;
} }
bool bool
AudioMixerAddon::WantsAutoStart() AudioMixerAddon::WantsAutoStart()
{ {
return true; return true;
} }
status_t status_t
AudioMixerAddon::AutoStart(int in_index, BMediaNode **out_node, AudioMixerAddon::AutoStart(int in_index, BMediaNode **out_node,
int32 *out_internal_id, bool *out_has_more) int32 *out_internal_id, bool *out_has_more)
@@ -7,33 +7,31 @@
#ifndef _AUDIOMIXER_ADDON_H #ifndef _AUDIOMIXER_ADDON_H
#define _AUDIOMIXER_ADDON_H #define _AUDIOMIXER_ADDON_H
#include <MediaAddOn.h> #include <MediaAddOn.h>
class AudioMixerAddon : public BMediaAddOn { class AudioMixerAddon : public BMediaAddOn {
public: public:
virtual ~AudioMixerAddon(); virtual ~AudioMixerAddon();
explicit AudioMixerAddon(image_id image); explicit AudioMixerAddon(image_id image);
virtual status_t InitCheck(const char** out_failure_text); virtual status_t InitCheck(const char** _failureText);
virtual int32 CountFlavors(); virtual int32 CountFlavors();
virtual status_t GetFlavorAt(int32 n, virtual status_t GetFlavorAt(int32 n,
const flavor_info ** out_info); const flavor_info** _info);
virtual BMediaNode * InstantiateNodeFor( virtual BMediaNode * InstantiateNodeFor(const flavor_info* info,
const flavor_info *info, BMessage* config, status_t* _error);
BMessage *config, virtual status_t GetConfigurationFor(BMediaNode* node,
status_t *out_error); BMessage* toMmessage);
virtual status_t GetConfigurationFor(
BMediaNode *your_node,
BMessage *into_message);
virtual bool WantsAutoStart(); virtual bool WantsAutoStart();
virtual status_t AutoStart(int in_index, virtual status_t AutoStart(int index, BMediaNode** _node,
BMediaNode **out_node, int32* _internalID, bool* _hasMore);
int32 *out_internal_id,
bool *out_has_more);
private: private:
media_format *fFormat; media_format* fFormat;
flavor_info *fInfo; flavor_info* fInfo;
}; };
#endif
#endif // _AUDIOMIXER_ADDON_H
@@ -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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Marcus Overhagen * Marcus Overhagen
*/ */
#include "AudioMixer.h"
#include "MixerCore.h" #include "MixerCore.h"
#include "MixerInput.h"
#include "MixerOutput.h" #include <string.h>
#include "MixerUtils.h"
#include "Resampler.h"
#include "RtList.h"
#include <Buffer.h> #include <Buffer.h>
#include <BufferGroup.h> #include <BufferGroup.h>
@@ -20,31 +18,49 @@
#include <RealtimeAlloc.h> #include <RealtimeAlloc.h>
#include <StopWatch.h> #include <StopWatch.h>
#include <TimeSource.h> #include <TimeSource.h>
#include <string.h>
#include "AudioMixer.h"
#include "MixerInput.h"
#include "MixerOutput.h"
#include "MixerUtils.h"
#include "Resampler.h"
#include "RtList.h"
#define DOUBLE_RATE_MIXING 0 #define DOUBLE_RATE_MIXING 0
#if DEBUG > 1 #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 #else
#define ASSERT_LOCKED() ((void)0) # define ASSERT_LOCKED() ((void)0)
#endif #endif
/* Mixer channels are identified by a type number, each type number corresponds /*! Mixer channels are identified by a type number, each type number corresponds
* to the one of the channel masks of enum media_multi_channels. 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 The mixer buffer uses either the same frame rate and same count of frames as
* output buffer, or the double frame rate and frame count. 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, All mixer input ring buffers must be an exact multiple of the mixer buffer
* so that we do not get any buffer wrap around during reading from the input buffers. size, so that we do not get any buffer wrap around during reading from the
* The mixer input is told by constructor (or after a format change by SetMixBufferFormat()) input buffers.
* of the current mixer buffer propertys, and must allocate a buffer that is an exact multiple, 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) MixerCore::MixerCore(AudioMixer *node)
: fLocker(new BLocker("mixer core lock")), :
fLocker(new BLocker("mixer core lock")),
fInputs(new BList), fInputs(new BList),
fOutput(0), fOutput(0),
fNextInputID(1), fNextInputID(1),
@@ -69,6 +85,7 @@ MixerCore::MixerCore(AudioMixer *node)
{ {
} }
MixerCore::~MixerCore() MixerCore::~MixerCore()
{ {
delete fSettings; delete fSettings;
@@ -94,12 +111,14 @@ MixerCore::~MixerCore()
delete fMixBufferChannelTypes; delete fMixBufferChannelTypes;
} }
MixerSettings * MixerSettings *
MixerCore::Settings() MixerCore::Settings()
{ {
return fSettings; return fSettings;
} }
void void
MixerCore::SetOutputAttenuation(float gain) MixerCore::SetOutputAttenuation(float gain)
{ {
@@ -107,6 +126,7 @@ MixerCore::SetOutputAttenuation(float gain)
fOutputGain = gain; fOutputGain = gain;
} }
MixerInput * MixerInput *
MixerCore::AddInput(const media_input &input) MixerCore::AddInput(const media_input &input)
{ {
@@ -117,6 +137,7 @@ MixerCore::AddInput(const media_input &input)
return in; return in;
} }
MixerOutput * MixerOutput *
MixerCore::AddOutput(const media_output &output) MixerCore::AddOutput(const media_output &output)
{ {
@@ -136,6 +157,7 @@ MixerCore::AddOutput(const media_output &output)
return fOutput; return fOutput;
} }
bool bool
MixerCore::RemoveInput(int32 inputID) MixerCore::RemoveInput(int32 inputID)
{ {
@@ -151,6 +173,7 @@ MixerCore::RemoveInput(int32 inputID)
return false; return false;
} }
bool bool
MixerCore::RemoveOutput() MixerCore::RemoveOutput()
{ {
@@ -167,6 +190,7 @@ MixerCore::RemoveOutput()
return true; return true;
} }
int32 int32
MixerCore::CreateInputID() MixerCore::CreateInputID()
{ {
@@ -174,6 +198,7 @@ MixerCore::CreateInputID()
return fNextInputID++; return fNextInputID++;
} }
MixerInput * MixerInput *
MixerCore::Input(int i) MixerCore::Input(int i)
{ {
@@ -181,6 +206,7 @@ MixerCore::Input(int i)
return (MixerInput *)fInputs->ItemAt(i); return (MixerInput *)fInputs->ItemAt(i);
} }
MixerOutput * MixerOutput *
MixerCore::Output() MixerCore::Output()
{ {
@@ -188,6 +214,7 @@ MixerCore::Output()
return fOutput; return fOutput;
} }
void void
MixerCore::BufferReceived(BBuffer *buffer, bigtime_t lateness) MixerCore::BufferReceived(BBuffer *buffer, bigtime_t lateness)
{ {
@@ -200,16 +227,20 @@ MixerCore::BufferReceived(BBuffer *buffer, bigtime_t lateness)
return; return;
} }
} }
ERROR("MixerCore::BufferReceived: received buffer for unknown id %ld\n", id); ERROR("MixerCore::BufferReceived: received buffer for unknown id %ld\n",
id);
} }
void void
MixerCore::InputFormatChanged(int32 inputID, const media_multi_audio_format &format) MixerCore::InputFormatChanged(int32 inputID,
const media_multi_audio_format &format)
{ {
ASSERT_LOCKED(); ASSERT_LOCKED();
ERROR("MixerCore::InputFormatChanged not handled\n"); ERROR("MixerCore::InputFormatChanged not handled\n");
} }
void void
MixerCore::OutputFormatChanged(const media_multi_audio_format &format) MixerCore::OutputFormatChanged(const media_multi_audio_format &format)
{ {
@@ -226,6 +257,7 @@ MixerCore::OutputFormatChanged(const media_multi_audio_format &format)
Start(); Start();
} }
void void
MixerCore::ApplyOutputFormat() MixerCore::ApplyOutputFormat()
{ {
@@ -233,7 +265,7 @@ MixerCore::ApplyOutputFormat()
media_multi_audio_format format = fOutput->MediaOutput().format.u.raw_audio; media_multi_audio_format format = fOutput->MediaOutput().format.u.raw_audio;
if (fMixBuffer) if (fMixBuffer != NULL)
rtm_free(fMixBuffer); rtm_free(fMixBuffer);
delete fMixBufferChannelTypes; delete fMixBufferChannelTypes;
@@ -248,8 +280,10 @@ MixerCore::ApplyOutputFormat()
ASSERT(fMixBufferChannelCount == fOutput->GetOutputChannelCount()); ASSERT(fMixBufferChannelCount == fOutput->GetOutputChannelCount());
fMixBufferChannelTypes = new int32 [format.channel_count]; fMixBufferChannelTypes = new int32 [format.channel_count];
for (int i = 0; i < fMixBufferChannelCount; i++) for (int i = 0; i < fMixBufferChannelCount; i++) {
fMixBufferChannelTypes[i] = ChannelMaskToChannelType(GetChannelMask(i, format.channel_mask)); fMixBufferChannelTypes[i]
= ChannelMaskToChannelType(GetChannelMask(i, format.channel_mask));
}
fMixBuffer = (float *)rtm_alloc(NULL, sizeof(float) * fMixBufferFrameCount * fMixBufferChannelCount); fMixBuffer = (float *)rtm_alloc(NULL, sizeof(float) * fMixBufferFrameCount * fMixBufferChannelCount);
ASSERT(fMixBuffer); ASSERT(fMixBuffer);
@@ -261,9 +295,10 @@ MixerCore::ApplyOutputFormat()
} }
fResampler = new Resampler * [fMixBufferChannelCount]; fResampler = new Resampler * [fMixBufferChannelCount];
for (int i = 0; i < fMixBufferChannelCount; i++) for (int i = 0; i < fMixBufferChannelCount; i++) {
fResampler[i] = new Resampler(media_raw_audio_format::B_AUDIO_FLOAT, fResampler[i] = new Resampler(media_raw_audio_format::B_AUDIO_FLOAT,
format.format); format.format);
}
TRACE("MixerCore::OutputFormatChanged:\n"); TRACE("MixerCore::OutputFormatChanged:\n");
TRACE(" fMixBufferFrameRate %ld\n", fMixBufferFrameRate); TRACE(" fMixBufferFrameRate %ld\n", fMixBufferFrameRate);
@@ -277,6 +312,7 @@ MixerCore::ApplyOutputFormat()
input->SetMixBufferFormat(fMixBufferFrameRate, fMixBufferFrameCount); input->SetMixBufferFormat(fMixBufferFrameRate, fMixBufferFrameCount);
} }
void void
MixerCore::SetOutputBufferGroup(BBufferGroup *group) MixerCore::SetOutputBufferGroup(BBufferGroup *group)
{ {
@@ -284,6 +320,7 @@ MixerCore::SetOutputBufferGroup(BBufferGroup *group)
fBufferGroup = group; fBufferGroup = group;
} }
void void
MixerCore::SetTimingInfo(BTimeSource *ts, bigtime_t downstream_latency) MixerCore::SetTimingInfo(BTimeSource *ts, bigtime_t downstream_latency)
{ {
@@ -295,10 +332,10 @@ MixerCore::SetTimingInfo(BTimeSource *ts, bigtime_t downstream_latency)
fDownstreamLatency = downstream_latency; fDownstreamLatency = downstream_latency;
TRACE("MixerCore::SetTimingInfo, now = %Ld, downstream latency %Ld\n", TRACE("MixerCore::SetTimingInfo, now = %Ld, downstream latency %Ld\n",
fTimeSource->Now(), fTimeSource->Now(), fDownstreamLatency);
fDownstreamLatency);
} }
void void
MixerCore::EnableOutput(bool enabled) MixerCore::EnableOutput(bool enabled)
{ {
@@ -340,6 +377,7 @@ MixerCore::Start()
return true; return true;
} }
bool bool
MixerCore::Stop() MixerCore::Stop()
{ {
@@ -355,6 +393,7 @@ MixerCore::Stop()
return true; return true;
} }
void void
MixerCore::StartMixThread() MixerCore::StartMixThread()
{ {
@@ -363,10 +402,12 @@ MixerCore::StartMixThread()
ASSERT(fOutput); ASSERT(fOutput);
fRunning = true; fRunning = true;
fMixThreadWaitSem = create_sem(0, "mix thread wait"); 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); resume_thread(fMixThread);
} }
void void
MixerCore::StopMixThread() MixerCore::StopMixThread()
{ {
@@ -383,6 +424,7 @@ MixerCore::StopMixThread()
fRunning = false; fRunning = false;
} }
int32 int32
MixerCore::_mix_thread_(void *arg) MixerCore::_mix_thread_(void *arg)
{ {
@@ -390,11 +432,6 @@ MixerCore::_mix_thread_(void *arg)
return 0; return 0;
} }
struct chan_info {
const char *base;
uint32 sample_offset;
float gain;
};
void void
MixerCore::MixThread() MixerCore::MixThread()
@@ -415,7 +452,8 @@ MixerCore::MixThread()
start = fTimeSource->Now(); start = fTimeSource->Now();
Unlock(); Unlock();
while (start <= 0) { 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); snooze(5000);
if (!LockFromMixThread()) if (!LockFromMixThread())
return; return;
@@ -425,21 +463,26 @@ MixerCore::MixThread()
if (!LockFromMixThread()) if (!LockFromMixThread())
return; return;
latency = max(3600LL, bigtime_t(0.4 * buffer_duration(fOutput->MediaOutput().format.u.raw_audio))); 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! // TODO: when the format changes while running, everything is wrong!
buffer_request_timeout = buffer_duration(fOutput->MediaOutput().format.u.raw_audio) / 2; 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); 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. // 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); int64 temp = frames_for_duration(fMixBufferFrameRate, start);
frame_base = ((temp / fMixBufferFrameCount) + 1) * fMixBufferFrameCount; frame_base = ((temp / fMixBufferFrameCount) + 1) * fMixBufferFrameCount;
time_base = duration_for_frames(fMixBufferFrameRate, frame_base); time_base = duration_for_frames(fMixBufferFrameRate, frame_base);
Unlock(); 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); ASSERT(fMixBufferFrameCount > 0);
@@ -448,7 +491,8 @@ MixerCore::MixThread()
#endif #endif
RtList<chan_info> InputChanInfos[MAX_CHANNEL_TYPES]; RtList<chan_info> InputChanInfos[MAX_CHANNEL_TYPES];
RtList<chan_info> MixChanInfos[fMixBufferChannelCount]; // XXX this does not support changing output channel count RtList<chan_info> MixChanInfos[fMixBufferChannelCount];
// TODO: this does not support changing output channel count
event_time = time_base; event_time = time_base;
frame_pos = 0; frame_pos = 0;
@@ -456,10 +500,12 @@ MixerCore::MixThread()
bigtime_t wait_until; bigtime_t wait_until;
if (!LockFromMixThread()) if (!LockFromMixThread())
return; return;
wait_until = fTimeSource->RealTimeFor(event_time, 0) - latency - fDownstreamLatency; wait_until = fTimeSource->RealTimeFor(event_time, 0)
- latency - fDownstreamLatency;
Unlock(); Unlock();
status_t rv; 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) if (rv == B_INTERRUPTED)
continue; continue;
if (rv != B_TIMED_OUT && rv < B_OK) if (rv != B_TIMED_OUT && rv < B_OK)
@@ -470,10 +516,12 @@ MixerCore::MixThread()
continue; 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()) { if (fInputs->IsEmpty() || fOutput->IsMuted()) {
int size = fOutput->MediaOutput().format.u.raw_audio.buffer_size; 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) { if (buf) {
memset(buf->Data(), 0, size); memset(buf->Data(), 0, size);
// fill in the buffer header // fill in the buffer header
@@ -482,9 +530,11 @@ MixerCore::MixThread()
hdr->size_used = size; hdr->size_used = size;
hdr->time_source = fTimeSource->ID(); hdr->time_source = fTimeSource->ID();
hdr->start_time = event_time; 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 #if DEBUG
ERROR("MixerCore: SendBuffer failed for buffer %Ld\n", buffer_num); ERROR("MixerCore: SendBuffer failed for buffer %Ld\n",
buffer_num);
#else #else
ERROR("MixerCore: SendBuffer failed\n"); ERROR("MixerCore: SendBuffer failed\n");
#endif #endif
@@ -492,7 +542,8 @@ MixerCore::MixThread()
} }
} else { } else {
#if DEBUG #if DEBUG
ERROR("MixerCore: RequestBuffer failed for buffer %Ld\n", buffer_num); ERROR("MixerCore: RequestBuffer failed for buffer %Ld\n",
buffer_num);
#else #else
ERROR("MixerCore: RequestBuffer failed\n"); ERROR("MixerCore: RequestBuffer failed\n");
#endif #endif
@@ -506,7 +557,8 @@ MixerCore::MixThread()
// mix all data from all inputs into the mix buffer // mix all data from all inputs into the mix buffer
ASSERT(cur_framepos % fMixBufferFrameCount == 0); 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; MixerInput *input;
for (int i = 0; (input = Input(i)) != 0; i++) { for (int i = 0; (input = Input(i)) != 0; i++) {
@@ -516,7 +568,8 @@ MixerCore::MixThread()
const float *base; const float *base;
uint32 sample_offset; uint32 sample_offset;
float gain; 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; continue;
if (type < 0 || type >= MAX_CHANNEL_TYPES) if (type < 0 || type >= MAX_CHANNEL_TYPES)
continue; continue;
@@ -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++) { 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(); int count = MixChanInfos[chan].CountItems();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
chan_info *info = MixChanInfos[chan].ItemAt(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); PRINT(5, "MixThread: base %p, sample-offset %2d, gain %.3f\n",
// This looks slightly ugly, but the current GCC will generate the fastest info->base, info->sample_offset, info->gain);
// code this way. fMixBufferFrameCount is always > 0. // This looks slightly ugly, but the current GCC will generate
uint32 dst_sample_offset = fMixBufferChannelCount * sizeof(float); // the fastest code this way.
// fMixBufferFrameCount is always > 0.
uint32 dst_sample_offset
= fMixBufferChannelCount * sizeof(float);
uint32 src_sample_offset = info->sample_offset; uint32 src_sample_offset = info->sample_offset;
register char *dst = (char *)&fMixBuffer[chan]; register char *dst = (char *)&fMixBuffer[chan];
register char *src = (char *)info->base; register char *src = (char *)info->base;
@@ -577,20 +636,27 @@ MixerCore::MixThread()
if (buf) { if (buf) {
// copy data from mix buffer into output buffer // copy data from mix buffer into output buffer
for (int i = 0; i < fMixBufferChannelCount; i++) { for (int i = 0; i < fMixBufferChannelCount; i++) {
fResampler[i]->Resample(reinterpret_cast<char *>(fMixBuffer) + i * sizeof(float), fResampler[i]->Resample(
reinterpret_cast<char *>(fMixBuffer) + i * sizeof(float),
fMixBufferChannelCount * sizeof(float), fMixBufferChannelCount * sizeof(float),
fMixBufferFrameCount, fMixBufferFrameCount,
reinterpret_cast<char *>(buf->Data()) + (i * bytes_per_sample(fOutput->MediaOutput().format.u.raw_audio)), reinterpret_cast<char *>(buf->Data())
+ (i * bytes_per_sample(
fOutput->MediaOutput().format.u.raw_audio)),
bytes_per_frame(fOutput->MediaOutput().format.u.raw_audio), bytes_per_frame(fOutput->MediaOutput().format.u.raw_audio),
frames_per_buffer(fOutput->MediaOutput().format.u.raw_audio), frames_per_buffer(
fOutput->MediaOutput().format.u.raw_audio),
fOutputGain * fOutput->GetOutputChannelGain(i)); 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 // fill in the buffer header
media_header* hdr = buf->Header(); media_header* hdr = buf->Header();
hdr->type = B_MEDIA_RAW_AUDIO; 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->time_source = fTimeSource->ID();
hdr->start_time = event_time; hdr->start_time = event_time;
@@ -598,10 +664,12 @@ MixerCore::MixThread()
fOutput->AdjustByteOrder(buf); fOutput->AdjustByteOrder(buf);
// send the buffer // send the buffer
status_t res = fNode->SendBuffer(buf, fOutput->MediaOutput().destination); status_t res = fNode->SendBuffer(buf,
if (B_OK != res) { fOutput->MediaOutput().destination);
if (res != B_OK) {
#if DEBUG #if DEBUG
ERROR("MixerCore: SendBuffer failed for buffer %Ld\n", buffer_num); ERROR("MixerCore: SendBuffer failed for buffer %Ld\n",
buffer_num);
#else #else
ERROR("MixerCore: SendBuffer failed\n"); ERROR("MixerCore: SendBuffer failed\n");
#endif #endif
@@ -609,7 +677,8 @@ MixerCore::MixThread()
} }
} else { } else {
#if DEBUG #if DEBUG
ERROR("MixerCore: RequestBuffer failed for buffer %Ld\n", buffer_num); ERROR("MixerCore: RequestBuffer failed for buffer %Ld\n",
buffer_num);
#else #else
ERROR("MixerCore: RequestBuffer failed\n"); ERROR("MixerCore: RequestBuffer failed\n");
#endif #endif
@@ -624,7 +693,8 @@ MixerCore::MixThread()
schedule_next_event: schedule_next_event:
// schedule next event // schedule next event
frame_pos += fMixBufferFrameCount; frame_pos += fMixBufferFrameCount;
event_time = time_base + bigtime_t((1000000LL * frame_pos) / fMixBufferFrameRate); event_time = time_base + bigtime_t((1000000LL * frame_pos)
/ fMixBufferFrameRate);
Unlock(); Unlock();
#if DEBUG #if DEBUG
buffer_num++; buffer_num++;
@@ -1,22 +1,28 @@
/* /*
* Copyright 2007-2009 Haiku Inc. All rights reserved. * Copyright 2003-2009 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*
* Authors:
* Marcus Overhagen
*/ */
#ifndef _MIXER_CORE_H #ifndef _MIXER_CORE_H
#define _MIXER_CORE_H #define _MIXER_CORE_H
#include "MixerSettings.h" #include "MixerSettings.h"
#include <Buffer.h> #include <Buffer.h>
#include <Locker.h> #include <Locker.h>
#include <TimeSource.h> #include <TimeSource.h>
class AudioMixer; class AudioMixer;
class BBufferGroup; class BBufferGroup;
class MixerInput; class MixerInput;
class MixerOutput; class MixerOutput;
class Resampler; class Resampler;
// The number of "enum media_multi_channels" types from MediaDefs.h // The number of "enum media_multi_channels" types from MediaDefs.h
// XXX should be 18, but limited to 12 here // XXX should be 18, but limited to 12 here
#define MAX_CHANNEL_TYPES 12 #define MAX_CHANNEL_TYPES 12
@@ -7,42 +7,41 @@
#ifndef _MIXER_DEBUG_H_ #ifndef _MIXER_DEBUG_H_
#define _MIXER_DEBUG_H_ #define _MIXER_DEBUG_H_
#ifndef DEBUG #ifndef DEBUG
#define DEBUG 0 # define DEBUG 0
#endif #endif
#include <Debug.h> #include <Debug.h>
#include <stdio.h> #include <stdio.h>
#undef TRACE #undef TRACE
#undef PRINT #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 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); } 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_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_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_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) # 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
# if DEBUG >= 2
# define TRACE printf
# else
# define TRACE(a...) ((void)0)
# endif
#else #else
# define PRINT_FORMAT(_text, _fmt) ((void)0)
#define PRINT_FORMAT(_text, _fmt) ((void)0) # define PRINT_INPUT(_text, _in) ((void)0)
#define PRINT_INPUT(_text, _in) ((void)0) # define PRINT_OUTPUT(_text, _out) ((void)0)
#define PRINT_OUTPUT(_text, _out) ((void)0) # define PRINT_CHANNEL_MASK(fmt) ((void)0)
#define PRINT_CHANNEL_MASK(fmt) ((void)0) # define PRINT(l, a...) ((void)0)
#define PRINT(l, a...) ((void)0) # define ERROR(a...) ((void)0)
#define ERROR(a...) ((void)0) # define TRACE(a...) ((void)0)
#define TRACE(a...) ((void)0)
#endif #endif
#endif /* _MIXER_DEBUG_H_ */ #endif /* _MIXER_DEBUG_H_ */
@@ -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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Marcus Overhagen * Marcus Overhagen
*/ */
#include "ByteSwap.h"
#include "MixerCore.h" #include "MixerCore.h"
#include <Buffer.h>
#include <string.h>
#include <TimeSource.h> // TODO: debug only
#include "ByteSwap.h"
#include "MixerInput.h" #include "MixerInput.h"
#include "MixerUtils.h" #include "MixerUtils.h"
#include "Resampler.h" #include "Resampler.h"
#include <Buffer.h>
#include <string.h>
#include <TimeSource.h> // XXX debug only
MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrameRate, int32 mixFrameCount) MixerInput::MixerInput(MixerCore *core, const media_input &input,
: fCore(core), float mixFrameRate, int32 mixFrameCount)
:
fCore(core),
fInput(input), fInput(input),
fInputByteSwap(0), fInputByteSwap(0),
fEnabled(true), fEnabled(true),
@@ -50,9 +56,12 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrame
// perhaps we need byte swapping // perhaps we need byte swapping
if (fInput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) { 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 if (fInput.format.u.raw_audio.format
|| fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_INT == media_raw_audio_format::B_AUDIO_FLOAT
|| fInput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_SHORT) { || 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); fInputByteSwap = new ByteSwap(fInput.format.u.raw_audio.format);
} }
} }
@@ -73,6 +82,7 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixFrame
SetMixBufferFormat((int32)mixFrameRate, mixFrameCount); SetMixBufferFormat((int32)mixFrameRate, mixFrameCount);
} }
MixerInput::~MixerInput() MixerInput::~MixerInput()
{ {
if (fMixBuffer) if (fMixBuffer)
@@ -88,6 +98,7 @@ MixerInput::~MixerInput()
delete [] fResampler; delete [] fResampler;
} }
void void
MixerInput::BufferReceived(BBuffer *buffer) MixerInput::BufferReceived(BBuffer *buffer)
{ {
@@ -274,6 +285,7 @@ MixerInput::AddInputChannelDestination(int channel, int destination_type)
UpdateInputChannelDestinations(); UpdateInputChannelDestinations();
} }
void void
MixerInput::RemoveInputChannelDestination(int channel, int destination_type) MixerInput::RemoveInputChannelDestination(int channel, int destination_type)
{ {
@@ -293,6 +305,7 @@ MixerInput::RemoveInputChannelDestination(int channel, int destination_type)
UpdateInputChannelDestinations(); UpdateInputChannelDestinations();
} }
bool bool
MixerInput::HasInputChannelDestination(int channel, int destination_type) 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); return fInputChannelInfo[channel].destination_mask & ChannelTypeToChannelMask(destination_type);
} }
int int
MixerInput::GetInputChannelForDestination(int destination_type) MixerInput::GetInputChannelForDestination(int destination_type)
{ {
@@ -316,6 +330,7 @@ MixerInput::GetInputChannelForDestination(int destination_type)
return -1; return -1;
} }
int int
MixerInput::GetInputChannelType(int channel) MixerInput::GetInputChannelType(int channel)
{ {
@@ -324,6 +339,7 @@ MixerInput::GetInputChannelType(int channel)
return GetChannelType(channel, fInputChannelMask); return GetChannelType(channel, fInputChannelMask);
} }
void void
MixerInput::SetInputChannelGain(int channel, float gain) MixerInput::SetInputChannelGain(int channel, float gain)
{ {
@@ -335,6 +351,7 @@ MixerInput::SetInputChannelGain(int channel, float gain)
fInputChannelInfo[channel].gain = gain; fInputChannelInfo[channel].gain = gain;
} }
float float
MixerInput::GetInputChannelGain(int channel) MixerInput::GetInputChannelGain(int channel)
{ {
@@ -343,6 +360,7 @@ MixerInput::GetInputChannelGain(int channel)
return fInputChannelInfo[channel].gain; return fInputChannelInfo[channel].gain;
} }
void void
MixerInput::UpdateInputChannelDestinationMask() MixerInput::UpdateInputChannelDestinationMask()
{ {
@@ -386,6 +404,7 @@ MixerInput::UpdateInputChannelDestinationMask()
TRACE("UpdateInputChannelDestinationMask: leave\n"); TRACE("UpdateInputChannelDestinationMask: leave\n");
} }
void void
MixerInput::UpdateInputChannelDestinations() MixerInput::UpdateInputChannelDestinations()
{ {
@@ -443,6 +462,7 @@ MixerInput::UpdateInputChannelDestinations()
TRACE("UpdateInputChannelDestinations: leave\n"); TRACE("UpdateInputChannelDestinations: leave\n");
} }
// Note: The following code is outcommented on purpose // Note: The following code is outcommented on purpose
// and is about to be modified at a later point // and is about to be modified at a later point
/* /*
@@ -468,6 +488,7 @@ MixerInput::SetInputChannelDestinationGain(int channel, int destination_type, fl
} }
} }
float float
MixerInput::GetInputChannelDestinationGain(int channel, int destination_type) MixerInput::GetInputChannelDestinationGain(int channel, int destination_type)
{ {
@@ -482,6 +503,7 @@ MixerInput::GetInputChannelDestinationGain(int channel, int destination_type)
} }
*/ */
void void
MixerInput::SetMixerChannelGain(int mixer_channel, float gain) 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; fChannelTypeGain[fMixerChannelInfo[mixer_channel].destination_type] = gain;
} }
float float
MixerInput::GetMixerChannelGain(int mixer_channel) MixerInput::GetMixerChannelGain(int mixer_channel)
{ {
@@ -502,6 +525,7 @@ MixerInput::GetMixerChannelGain(int mixer_channel)
return fMixerChannelInfo[mixer_channel].destination_gain; return fMixerChannelInfo[mixer_channel].destination_gain;
} }
int int
MixerInput::GetMixerChannelType(int mixer_channel) MixerInput::GetMixerChannelType(int mixer_channel)
{ {
@@ -510,31 +534,35 @@ MixerInput::GetMixerChannelType(int mixer_channel)
return fMixerChannelInfo[mixer_channel].destination_type; return fMixerChannelInfo[mixer_channel].destination_type;
} }
void void
MixerInput::SetEnabled(bool yesno) MixerInput::SetEnabled(bool yesno)
{ {
fEnabled = yesno; fEnabled = yesno;
} }
bool bool
MixerInput::IsEnabled() MixerInput::IsEnabled()
{ {
return fEnabled; return fEnabled;
} }
void void
MixerInput::SetMixBufferFormat(int32 framerate, int32 frames) 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; fMixBufferFrameRate = framerate;
debugMixBufferFrames = frames; fDebugMixBufferFrames = frames;
// frames and/or framerate can be 0 (if no output is connected) // frames and/or framerate can be 0 (if no output is connected)
if (framerate == 0 || frames == 0) { if (framerate == 0 || frames == 0) {
if (fMixBuffer) { if (fMixBuffer != NULL) {
rtm_free(fMixBuffer); rtm_free(fMixBuffer);
fMixBuffer = 0; fMixBuffer = NULL;
} }
for (int i = 0; i < fInputChannelCount; i++) for (int i = 0; i < fInputChannelCount; i++)
fInputChannelInfo[i].buffer_base = 0; fInputChannelInfo[i].buffer_base = 0;
@@ -564,15 +592,16 @@ MixerInput::SetMixBufferFormat(int32 framerate, int32 frames)
fLastDataFrameWritten = -1; fLastDataFrameWritten = -1;
fFractionalFrames = 0.0; fFractionalFrames = 0.0;
if (fMixBuffer)
rtm_free(fMixBuffer); rtm_free(fMixBuffer);
if (fRtmPool)
rtm_delete_pool(fRtmPool); rtm_delete_pool(fRtmPool);
int size = sizeof(float) * fInputChannelCount * fMixBufferFrameCount; int size = sizeof(float) * fInputChannelCount * fMixBufferFrameCount;
if (B_OK != rtm_create_pool(&fRtmPool, size)) if (rtm_create_pool(&fRtmPool, size) != B_OK)
fRtmPool = 0; fRtmPool = NULL;
fMixBuffer = (float *)rtm_alloc(fRtmPool, size); fMixBuffer = (float *)rtm_alloc(fRtmPool, size);
ASSERT(fMixBuffer); if (fMixBuffer == NULL)
return;
memset(fMixBuffer, 0, size); memset(fMixBuffer, 0, size);
@@ -1,126 +1,128 @@
/* /*
* Copyright 2007 Haiku Inc. All rights reserved. * Copyright 2003-2009 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*
* Authors:
* Marcus Overhagen
*/ */
#ifndef _MIXER_INPUT_H #ifndef _MIXER_INPUT_H
#define _MIXER_INPUT_H #define _MIXER_INPUT_H
#include <MediaNode.h>
#include <RealtimeAlloc.h>
#include "MixerCore.h" #include "MixerCore.h"
#include "MixerDebug.h" #include "MixerDebug.h"
#include "MixerUtils.h" #include "MixerUtils.h"
#include <MediaNode.h>
#include <RealtimeAlloc.h>
class ByteSwap; class ByteSwap;
class Resampler; class Resampler;
class MixerInput
{ class MixerInput {
public: public:
MixerInput(MixerCore *core, MixerInput(MixerCore* core,
const media_input &input, const media_input& input,
float mixFrameRate, float mixFrameRate, int32 mixFrameCount);
int32 mixFrameCount);
~MixerInput(); ~MixerInput();
int32 ID(); int32 ID();
void BufferReceived(BBuffer *buffer); void BufferReceived(BBuffer* buffer);
media_input& MediaInput(); media_input& MediaInput();
// The physical input channels // The physical input channels
int GetInputChannelCount(); int GetInputChannelCount();
int GetInputChannelType(int channel); int GetInputChannelType(int channel);
void SetInputChannelGain(int channel, void SetInputChannelGain(int channel, float gain);
float gain);
float GetInputChannelGain(int channel); float GetInputChannelGain(int channel);
// The destinations for each channel // The destinations for each channel
void AddInputChannelDestination( void AddInputChannelDestination(int channel,
int channel, int destinationType);
int destination_type); void RemoveInputChannelDestination(int channel,
void RemoveInputChannelDestination( int destinationType);
int channel, bool HasInputChannelDestination(int channel,
int destination_type); int destinationType);
bool HasInputChannelDestination(
int channel,
int destination_type);
int GetInputChannelForDestination( int GetInputChannelForDestination(
int destination_type); int destinationType);
// returns -1 if not found // returns -1 if not found
// The virtual mixer channels that are generated from destinations // The virtual mixer channels that are generated from destinations
int GetMixerChannelCount(); int GetMixerChannelCount();
void SetMixerChannelGain(int mixer_channel, void SetMixerChannelGain(int mixerChannel,
float gain); float gain);
float GetMixerChannelGain(int mixer_channel); float GetMixerChannelGain(int mixerChannel);
int GetMixerChannelType(int mixer_channel); int GetMixerChannelType(int mixerChannel);
void SetEnabled(bool yesno); void SetEnabled(bool enabled);
bool IsEnabled(); bool IsEnabled();
// only for use by MixerCore // only for use by MixerCore
bool GetMixerChannelInfo(int mixer_channel, bool GetMixerChannelInfo(int mixerChannel,
int64 framepos, int64 framepos, bigtime_t time,
bigtime_t time, const float** _buffer,
const float **buffer, uint32* _sampleOffset, int* _type,
uint32 *sample_offset, float* _gain);
int *type,
float *gain);
protected: protected:
friend class MixerCore; friend class MixerCore;
void SetMixBufferFormat(int32 framerate, void SetMixBufferFormat(int32 framerate,
int32 frames); int32 frames);
private: private:
void UpdateInputChannelDestinationMask(); void UpdateInputChannelDestinationMask();
void UpdateInputChannelDestinations(); void UpdateInputChannelDestinations();
struct input_chan_info { struct input_chan_info {
float *buffer_base; float* buffer_base;
uint32 destination_mask; // multiple or no bits sets uint32 destination_mask; // multiple or no bits sets
float gain; float gain;
}; };
struct mixer_chan_info { struct mixer_chan_info {
float *buffer_base; float* buffer_base;
int destination_type; int destination_type;
float destination_gain; float destination_gain;
}; };
private: private:
MixerCore *fCore; MixerCore* fCore;
media_input fInput; media_input fInput;
ByteSwap *fInputByteSwap; ByteSwap* fInputByteSwap;
float fChannelTypeGain[MAX_CHANNEL_TYPES]; float fChannelTypeGain[MAX_CHANNEL_TYPES];
bool fEnabled; bool fEnabled;
input_chan_info *fInputChannelInfo; // array input_chan_info* fInputChannelInfo; // array
int fInputChannelCount; int fInputChannelCount;
uint32 fInputChannelMask; uint32 fInputChannelMask;
mixer_chan_info *fMixerChannelInfo; // array mixer_chan_info* fMixerChannelInfo; // array
int fMixerChannelCount; int fMixerChannelCount;
float *fMixBuffer; float* fMixBuffer;
int32 fMixBufferFrameRate; int32 fMixBufferFrameRate;
int fMixBufferFrameCount; int fMixBufferFrameCount;
int32 fLastDataFrameWritten; int32 fLastDataFrameWritten;
bigtime_t fLastDataAvailableTime; bigtime_t fLastDataAvailableTime;
double fFractionalFrames; double fFractionalFrames;
Resampler **fResampler; // array Resampler** fResampler; // array
rtm_pool *fRtmPool; rtm_pool* fRtmPool;
bool fUserOverridesChannelDestinations; bool fUserOverridesChannelDestinations;
int32 debugMixBufferFrames; int32 fDebugMixBufferFrames;
}; };
inline int inline int
MixerInput::GetMixerChannelCount() MixerInput::GetMixerChannelCount()
{ {
return fMixerChannelCount; return fMixerChannelCount;
} }
inline bool inline bool
MixerInput::GetMixerChannelInfo(int mixer_channel, int64 framepos, MixerInput::GetMixerChannelInfo(int mixer_channel, int64 framepos,
bigtime_t time, const float **buffer, bigtime_t time, const float **buffer, uint32 *sample_offset, int *type,
uint32 *sample_offset, int *type, float *gain) float *gain)
{ {
// this function should not be called if we don't have a mix buffer! // this function should not be called if we don't have a mix buffer!
ASSERT(fMixBuffer); ASSERT(fMixBuffer);
@@ -130,20 +132,21 @@ MixerInput::GetMixerChannelInfo(int mixer_channel, int64 framepos,
#if 1 #if 1
if (time < (fLastDataAvailableTime - duration_for_frames(fMixBufferFrameRate, fMixBufferFrameCount)) 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", 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 #endif
if (time > fLastDataAvailableTime) if (time > fLastDataAvailableTime)
return false; return false;
int32 offset = framepos % fMixBufferFrameCount; 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<float *>(reinterpret_cast<char *>(fMixerChannelInfo[mixer_channel].buffer_base) + (offset * sizeof(float) * fInputChannelCount)); *buffer = reinterpret_cast<float *>(reinterpret_cast<char *>(fMixerChannelInfo[mixer_channel].buffer_base) + (offset * sizeof(float) * fInputChannelCount));
*sample_offset = sizeof(float) * fInputChannelCount; *sample_offset = sizeof(float) * fInputChannelCount;
*type = fMixerChannelInfo[mixer_channel].destination_type; *type = fMixerChannelInfo[mixer_channel].destination_type;
*gain = fMixerChannelInfo[mixer_channel].destination_gain; *gain = fMixerChannelInfo[mixer_channel].destination_gain;
return true; return true;
} }
#endif
#endif // _MIXER_INPUT_H
@@ -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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* probably Marcus Overhagen * Marcus Overhagen
*/ */
#include "MixerCore.h"
#include "MixerDebug.h"
#include "MixerOutput.h" #include "MixerOutput.h"
#include "MixerUtils.h"
#include <MediaNode.h> #include <MediaNode.h>
#include "MixerCore.h"
#include "MixerDebug.h"
#include "MixerUtils.h"
MixerOutput::MixerOutput(MixerCore *core, const media_output &output) MixerOutput::MixerOutput(MixerCore *core, const media_output &output)
: fCore(core), :
fCore(core),
fOutput(output), fOutput(output),
fOutputChannelCount(0), fOutputChannelCount(0),
fOutputChannelInfo(0), fOutputChannelInfo(0),
@@ -28,18 +33,21 @@ MixerOutput::MixerOutput(MixerCore *core, const media_output &output)
UpdateByteOrderSwap(); UpdateByteOrderSwap();
} }
MixerOutput::~MixerOutput() MixerOutput::~MixerOutput()
{ {
delete fOutputChannelInfo; delete fOutputChannelInfo;
delete fOutputByteSwap; delete fOutputByteSwap;
} }
media_output & media_output &
MixerOutput::MediaOutput() MixerOutput::MediaOutput()
{ {
return fOutput; return fOutput;
} }
void void
MixerOutput::ChangeFormat(const media_multi_audio_format &format) MixerOutput::ChangeFormat(const media_multi_audio_format &format)
{ {
@@ -53,6 +61,7 @@ MixerOutput::ChangeFormat(const media_multi_audio_format &format)
UpdateByteOrderSwap(); UpdateByteOrderSwap();
} }
void void
MixerOutput::UpdateByteOrderSwap() MixerOutput::UpdateByteOrderSwap()
{ {
@@ -69,6 +78,7 @@ MixerOutput::UpdateByteOrderSwap()
} }
} }
void void
MixerOutput::UpdateOutputChannels() MixerOutput::UpdateOutputChannels()
{ {
@@ -115,6 +125,7 @@ MixerOutput::UpdateOutputChannels()
TRACE("UpdateOutputChannels: output channel %d, type %2d, gain %.3f\n", i, fOutputChannelInfo[i].channel_type, fOutputChannelInfo[i].channel_gain); TRACE("UpdateOutputChannels: output channel %d, type %2d, gain %.3f\n", i, fOutputChannelInfo[i].channel_type, fOutputChannelInfo[i].channel_gain);
} }
void void
MixerOutput::AssignDefaultSources() MixerOutput::AssignDefaultSources()
{ {
@@ -296,6 +307,7 @@ MixerOutput::AssignDefaultSources()
} }
} }
int int
MixerOutput::GetOutputChannelType(int channel) MixerOutput::GetOutputChannelType(int channel)
{ {
@@ -304,6 +316,7 @@ MixerOutput::GetOutputChannelType(int channel)
return fOutputChannelInfo[channel].channel_type; return fOutputChannelInfo[channel].channel_type;
} }
void void
MixerOutput::SetOutputChannelGain(int channel, float gain) MixerOutput::SetOutputChannelGain(int channel, float gain)
{ {
@@ -313,6 +326,7 @@ MixerOutput::SetOutputChannelGain(int channel, float gain)
fOutputChannelInfo[channel].channel_gain = gain; fOutputChannelInfo[channel].channel_gain = gain;
} }
void void
MixerOutput::AddOutputChannelSource(int channel, int source_type) MixerOutput::AddOutputChannelSource(int channel, int source_type)
{ {
@@ -333,6 +347,7 @@ MixerOutput::AddOutputChannelSource(int channel, int source_type)
fOutputChannelInfo[channel].source_count++; fOutputChannelInfo[channel].source_count++;
} }
void void
MixerOutput::RemoveOutputChannelSource(int channel, int source_type) MixerOutput::RemoveOutputChannelSource(int channel, int source_type)
{ {
@@ -351,6 +366,7 @@ MixerOutput::RemoveOutputChannelSource(int channel, int source_type)
} }
} }
void void
MixerOutput::SetOutputChannelSourceGain(int channel, int source_type, float source_gain) 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; fOutputChannelInfo[channel].source_gain_cache[source_type] = source_gain;
} }
float float
MixerOutput::GetOutputChannelSourceGain(int channel, int source_type) 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]; return fOutputChannelInfo[channel].source_gain_cache[source_type];
} }
bool bool
MixerOutput::HasOutputChannelSource(int channel, int source_type) MixerOutput::HasOutputChannelSource(int channel, int source_type)
{ {
@@ -399,6 +417,7 @@ MixerOutput::HasOutputChannelSource(int channel, int source_type)
return false; return false;
} }
void void
MixerOutput::SetMuted(bool yesno) MixerOutput::SetMuted(bool yesno)
{ {
@@ -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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* probably Marcus Overhagen * Marcus Overhagen
*/ */
#include "MixerCore.h"
#include "MixerDebug.h"
#include "MixerInput.h"
#include "MixerOutput.h"
#include "MixerSettings.h" #include "MixerSettings.h"
#include <string.h>
#include <File.h> #include <File.h>
#include <Locker.h> #include <Locker.h>
#include <MediaDefs.h> #include <MediaDefs.h>
#include <OS.h> #include <OS.h>
#include <Path.h> #include <Path.h>
#include <string.h>
#include "MixerCore.h"
#include "MixerDebug.h"
#include "MixerInput.h"
#include "MixerOutput.h"
#define SAVE_DELAY 5000000 // delay saving of settings for 5s #define SAVE_DELAY 5000000 // delay saving of settings for 5s
#define SAVE_RUNTIME 30000000 // stop save thread after 30s inactivity #define SAVE_RUNTIME 30000000 // stop save thread after 30s inactivity
#define SETTINGS_VERSION ((int32)0x94251601) #define SETTINGS_VERSION ((int32)0x94251601)
MixerSettings::MixerSettings() MixerSettings::MixerSettings()
: fLocker(new BLocker("mixer settings lock")), :
fLocker(new BLocker("mixer settings lock")),
fSettingsFile(0), fSettingsFile(0),
fSettingsDirty(false), fSettingsDirty(false),
fSettingsLastChange(0), fSettingsLastChange(0),
@@ -35,6 +42,7 @@ MixerSettings::MixerSettings()
Load(); Load();
} }
MixerSettings::~MixerSettings() MixerSettings::~MixerSettings()
{ {
StopDeferredSave(); StopDeferredSave();
@@ -44,6 +52,7 @@ MixerSettings::~MixerSettings()
delete fSettingsFile; delete fSettingsFile;
} }
void void
MixerSettings::SetSettingsFile(const char *file) MixerSettings::SetSettingsFile(const char *file)
{ {
@@ -54,6 +63,7 @@ MixerSettings::SetSettingsFile(const char *file)
Load(); Load();
} }
bool bool
MixerSettings::AttenuateOutput() MixerSettings::AttenuateOutput()
{ {
@@ -64,6 +74,7 @@ MixerSettings::AttenuateOutput()
return temp; return temp;
} }
void void
MixerSettings::SetAttenuateOutput(bool yesno) MixerSettings::SetAttenuateOutput(bool yesno)
{ {
@@ -73,6 +84,7 @@ MixerSettings::SetAttenuateOutput(bool yesno)
StartDeferredSave(); StartDeferredSave();
} }
bool bool
MixerSettings::NonLinearGainSlider() MixerSettings::NonLinearGainSlider()
{ {
@@ -83,6 +95,7 @@ MixerSettings::NonLinearGainSlider()
return temp; return temp;
} }
void void
MixerSettings::SetNonLinearGainSlider(bool yesno) MixerSettings::SetNonLinearGainSlider(bool yesno)
{ {
@@ -92,6 +105,7 @@ MixerSettings::SetNonLinearGainSlider(bool yesno)
StartDeferredSave(); StartDeferredSave();
} }
bool bool
MixerSettings::UseBalanceControl() MixerSettings::UseBalanceControl()
{ {
@@ -102,6 +116,7 @@ MixerSettings::UseBalanceControl()
return temp; return temp;
} }
void void
MixerSettings::SetUseBalanceControl(bool yesno) MixerSettings::SetUseBalanceControl(bool yesno)
{ {
@@ -111,6 +126,7 @@ MixerSettings::SetUseBalanceControl(bool yesno)
StartDeferredSave(); StartDeferredSave();
} }
bool bool
MixerSettings::AllowOutputChannelRemapping() MixerSettings::AllowOutputChannelRemapping()
{ {
@@ -121,6 +137,7 @@ MixerSettings::AllowOutputChannelRemapping()
return temp; return temp;
} }
void void
MixerSettings::SetAllowOutputChannelRemapping(bool yesno) MixerSettings::SetAllowOutputChannelRemapping(bool yesno)
{ {
@@ -130,6 +147,7 @@ MixerSettings::SetAllowOutputChannelRemapping(bool yesno)
StartDeferredSave(); StartDeferredSave();
} }
bool bool
MixerSettings::AllowInputChannelRemapping() MixerSettings::AllowInputChannelRemapping()
{ {
@@ -140,6 +158,7 @@ MixerSettings::AllowInputChannelRemapping()
return temp; return temp;
} }
void void
MixerSettings::SetAllowInputChannelRemapping(bool yesno) MixerSettings::SetAllowInputChannelRemapping(bool yesno)
{ {
@@ -149,6 +168,7 @@ MixerSettings::SetAllowInputChannelRemapping(bool yesno)
StartDeferredSave(); StartDeferredSave();
} }
int int
MixerSettings::InputGainControls() MixerSettings::InputGainControls()
{ {
@@ -159,6 +179,7 @@ MixerSettings::InputGainControls()
return temp; return temp;
} }
void void
MixerSettings::SetInputGainControls(int value) MixerSettings::SetInputGainControls(int value)
{ {
@@ -168,6 +189,7 @@ MixerSettings::SetInputGainControls(int value)
StartDeferredSave(); StartDeferredSave();
} }
int int
MixerSettings::ResamplingAlgorithm() MixerSettings::ResamplingAlgorithm()
{ {
@@ -178,6 +200,7 @@ MixerSettings::ResamplingAlgorithm()
return temp; return temp;
} }
void void
MixerSettings::SetResamplingAlgorithm(int value) MixerSettings::SetResamplingAlgorithm(int value)
{ {
@@ -187,6 +210,7 @@ MixerSettings::SetResamplingAlgorithm(int value)
StartDeferredSave(); StartDeferredSave();
} }
bool bool
MixerSettings::RefuseOutputFormatChange() MixerSettings::RefuseOutputFormatChange()
{ {
@@ -197,6 +221,7 @@ MixerSettings::RefuseOutputFormatChange()
return temp; return temp;
} }
void void
MixerSettings::SetRefuseOutputFormatChange(bool yesno) MixerSettings::SetRefuseOutputFormatChange(bool yesno)
{ {
@@ -206,6 +231,7 @@ MixerSettings::SetRefuseOutputFormatChange(bool yesno)
StartDeferredSave(); StartDeferredSave();
} }
bool bool
MixerSettings::RefuseInputFormatChange() MixerSettings::RefuseInputFormatChange()
{ {
@@ -216,6 +242,7 @@ MixerSettings::RefuseInputFormatChange()
return temp; return temp;
} }
void void
MixerSettings::SetRefuseInputFormatChange(bool yesno) MixerSettings::SetRefuseInputFormatChange(bool yesno)
{ {
@@ -225,6 +252,7 @@ MixerSettings::SetRefuseInputFormatChange(bool yesno)
StartDeferredSave(); StartDeferredSave();
} }
void void
MixerSettings::SaveConnectionSettings(MixerInput *input) MixerSettings::SaveConnectionSettings(MixerInput *input)
{ {
@@ -235,7 +263,7 @@ MixerSettings::SaveConnectionSettings(MixerInput *input)
for (int i = 0; i < MAX_INPUT_SETTINGS; i++) { for (int i = 0; i < MAX_INPUT_SETTINGS; i++) {
if (fInputSetting[i].IsEmpty()) if (fInputSetting[i].IsEmpty())
continue; continue;
if (0 == strcmp(fInputSetting[i].FindString("name"), input->MediaInput().name)) { if (!strcmp(fInputSetting[i].FindString("name"), input->MediaInput().name)) {
index = i; index = i;
break; break;
} }
@@ -277,6 +305,7 @@ MixerSettings::SaveConnectionSettings(MixerInput *input)
StartDeferredSave(); StartDeferredSave();
} }
void void
MixerSettings::LoadConnectionSettings(MixerInput *input) MixerSettings::LoadConnectionSettings(MixerInput *input)
{ {
@@ -285,7 +314,7 @@ MixerSettings::LoadConnectionSettings(MixerInput *input)
for (index = 0; index < MAX_INPUT_SETTINGS; index++) { for (index = 0; index < MAX_INPUT_SETTINGS; index++) {
if (fInputSetting[index].IsEmpty()) if (fInputSetting[index].IsEmpty())
continue; continue;
if (0 == strcmp(fInputSetting[index].FindString("name"), input->MediaInput().name)) if (!strcmp(fInputSetting[index].FindString("name"), input->MediaInput().name))
break; break;
} }
if (index == MAX_INPUT_SETTINGS) { if (index == MAX_INPUT_SETTINGS) {
@@ -310,6 +339,7 @@ MixerSettings::LoadConnectionSettings(MixerInput *input)
StartDeferredSave(); StartDeferredSave();
} }
void void
MixerSettings::SaveConnectionSettings(MixerOutput *output) MixerSettings::SaveConnectionSettings(MixerOutput *output)
{ {
@@ -329,6 +359,7 @@ MixerSettings::SaveConnectionSettings(MixerOutput *output)
StartDeferredSave(); StartDeferredSave();
} }
void void
MixerSettings::LoadConnectionSettings(MixerOutput *output) MixerSettings::LoadConnectionSettings(MixerOutput *output)
{ {
@@ -345,6 +376,7 @@ MixerSettings::LoadConnectionSettings(MixerOutput *output)
fLocker->Unlock(); fLocker->Unlock();
} }
void void
MixerSettings::Save() MixerSettings::Save()
{ {
@@ -379,6 +411,7 @@ MixerSettings::Save()
fLocker->Unlock(); fLocker->Unlock();
} }
void void
MixerSettings::Load() MixerSettings::Load()
{ {
@@ -451,6 +484,7 @@ MixerSettings::Load()
fLocker->Unlock(); fLocker->Unlock();
} }
void void
MixerSettings::StartDeferredSave() MixerSettings::StartDeferredSave()
{ {
@@ -496,12 +530,13 @@ MixerSettings::StartDeferredSave()
fLocker->Unlock(); fLocker->Unlock();
} }
void void
MixerSettings::StopDeferredSave() MixerSettings::StopDeferredSave()
{ {
fLocker->Lock(); fLocker->Lock();
if (fSaveThread > 0) { if (fSaveThread >= 0) {
ASSERT(fSaveThreadWaitSem > 0); ASSERT(fSaveThreadWaitSem > 0);
status_t unused; status_t unused;
@@ -515,6 +550,7 @@ MixerSettings::StopDeferredSave()
fLocker->Unlock(); fLocker->Unlock();
} }
void void
MixerSettings::SaveThread() MixerSettings::SaveThread()
{ {
@@ -557,6 +593,7 @@ MixerSettings::SaveThread()
TRACE("MixerSettings: save thread ended\n"); TRACE("MixerSettings: save thread ended\n");
} }
int32 int32
MixerSettings::_save_thread_(void *arg) MixerSettings::_save_thread_(void *arg)
{ {
@@ -1,3 +1,12 @@
/*
* Copyright 2003-2009 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Marcus Overhagen
*/
#include <MediaDefs.h> #include <MediaDefs.h>
#include <OS.h> #include <OS.h>
#include <stdio.h> #include <stdio.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 #ifndef _MIXER_UTILS_H
#define _MIXER_UTILS_H #define _MIXER_UTILS_H
#ifndef __SGI_STL_INTERNAL_ALGOBASE_H #ifndef __SGI_STL_INTERNAL_ALGOBASE_H
template<class t> const t & max(const t &t1, const t &t2) { return (t1 > t2) ? t1 : t2; } template<class t> const t & max(const t &t1, const t &t2) { return (t1 > t2) ? t1 : t2; }
template<class t> const t & min(const t &t1, const t &t2) { return (t1 < t2) ? t1 : t2; } template<class t> const t & min(const t &t1, const t &t2) { return (t1 < t2) ? t1 : t2; }
#endif #endif
template<class t> const t abs(const t t1) { return (t1 < 0) ? - t1 : t1; } template<class t> const t abs(const t t1) { return (t1 < 0) ? - t1 : t1; }
void fix_multiaudio_format(media_multi_audio_format *format); void fix_multiaudio_format(media_multi_audio_format *format);
int count_nonzero_bits(uint32 value); 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 *StringForChannelMask(char *buf, uint32 mask);
const char *StringForChannelType(char *buf, int type); const char *StringForChannelType(char *buf, int type);
#endif //_MIXER_UTILS_H #endif // _MIXER_UTILS_H
@@ -1,20 +1,27 @@
/* Copyright (C) 2003 Marcus Overhagen /*
* Released under terms of the MIT license. * Copyright 2003 Marcus Overhagen
* * Distributed under the 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.
*
*/ */
#include <MediaDefs.h>
#include "Resampler.h" #include "Resampler.h"
#include <MediaDefs.h>
#include "MixerDebug.h" #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) Resampler::Resampler(uint32 src_format, uint32 dst_format)
: fFunc(0) :
fFunc(0)
{ {
if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) { if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) {
switch (src_format) { switch (src_format) {
@@ -34,7 +41,8 @@ Resampler::Resampler(uint32 src_format, uint32 dst_format)
fFunc = &Resampler::uint8_to_float; fFunc = &Resampler::uint8_to_float;
return; return;
default: default:
ERROR("Resampler::Resampler: unknown source format 0x%x\n", src_format); ERROR("Resampler::Resampler: unknown source format 0x%x\n",
src_format);
return; 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() Resampler::~Resampler()
{ {
} }
status_t status_t
Resampler::InitCheck() Resampler::InitCheck() const
{ {
return (fFunc != 0) ? B_OK : B_ERROR; return fFunc != 0 ? B_OK : B_ERROR;
} }
void void
Resampler::float_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, Resampler::float_to_float(const void *_src, int32 srcSampleOffset,
void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) int32 srcSampleCount, void *_dest, int32 destSampleOffset,
int32 destSampleCount, float _gain)
{ {
register const char * src = (const char *) _src; register const char * src = (const char *)_src;
register char * dst = (char *) _dst; register char * dest = (char *)_dest;
register int32 count = dst_sample_count; register int32 count = destSampleCount;
register float gain = _gain; register float gain = _gain;
if (src_sample_count == dst_sample_count) { if (srcSampleCount == destSampleCount) {
// optimized case for no resampling // optimized case for no resampling
while (count--) { while (count--) {
*(float *)dst = *(const float *)src * gain; *(float *)dest = *(const float *)src * gain;
src += src_sample_offset; src += srcSampleOffset;
dst += dst_sample_offset; dest += destSampleOffset;
} }
return; return;
} }
register float delta = float(src_sample_count) / float(dst_sample_count); register float delta = float(srcSampleCount) / float(destSampleCount);
register float current = 0.0f; register float current = 0.0f;
if (delta < 1.0) { if (delta < 1.0) {
// upsample // upsample
while (count--) { while (count--) {
*(float *)dst = *(const float *)src * gain; *(float *)dest = *(const float *)src * gain;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
if (current >= 1.0f) { if (current >= 1.0f) {
current -= 1.0f; current -= 1.0f;
src += src_sample_offset; src += srcSampleOffset;
} }
} }
} else { } else {
// downsample // downsample
while (count--) { while (count--) {
*(float *)dst = *(const float *)src * gain; *(float *)dest = *(const float *)src * gain;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
register int32 skipcount = (int32)current; register int32 skipcount = (int32)current;
current -= skipcount; current -= skipcount;
src += skipcount * src_sample_offset; src += skipcount * srcSampleOffset;
} }
} }
} }
void void
Resampler::int32_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, Resampler::int32_to_float(const void *_src, int32 srcSampleOffset,
void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) int32 srcSampleCount, void *_dest, int32 destSampleOffset,
int32 destSampleCount, float _gain)
{ {
register const char * src = (const char *) _src; register const char * src = (const char *)_src;
register char * dst = (char *) _dst; register char * dest = (char *)_dest;
register int32 count = dst_sample_count; register int32 count = destSampleCount;
register float gain = _gain / 2147483647.0; register float gain = _gain / 2147483647.0;
if (src_sample_count == dst_sample_count) { if (srcSampleCount == destSampleCount) {
// optimized case for no resampling // optimized case for no resampling
while (count--) { while (count--) {
*(float *)dst = *(const int32 *)src * gain; *(float *)dest = *(const int32 *)src * gain;
src += src_sample_offset; src += srcSampleOffset;
dst += dst_sample_offset; dest += destSampleOffset;
} }
return; return;
} }
register float delta = float(src_sample_count) / float(dst_sample_count); register float delta = float(srcSampleCount) / float(destSampleCount);
register float current = 0.0f; register float current = 0.0f;
if (delta < 1.0) { if (delta < 1.0) {
// upsample // upsample
while (count--) { while (count--) {
*(float *)dst = *(const int32 *)src * gain; *(float *)dest = *(const int32 *)src * gain;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
if (current >= 1.0f) { if (current >= 1.0f) {
current -= 1.0f; current -= 1.0f;
src += src_sample_offset; src += srcSampleOffset;
} }
} }
} else { } else {
// downsample // downsample
while (count--) { while (count--) {
*(float *)dst = *(const int32 *)src * gain; *(float *)dest = *(const int32 *)src * gain;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
register int32 skipcount = (int32)current; register int32 skipcount = (int32)current;
current -= skipcount; current -= skipcount;
src += skipcount * src_sample_offset; src += skipcount * srcSampleOffset;
} }
} }
} }
void void
Resampler::int16_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, Resampler::int16_to_float(const void *_src, int32 srcSampleOffset,
void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) int32 srcSampleCount, void *_dest, int32 destSampleOffset,
int32 destSampleCount, float _gain)
{ {
register const char * src = (const char *) _src; register const char * src = (const char *)_src;
register char * dst = (char *) _dst; register char * dest = (char *)_dest;
register int32 count = dst_sample_count; register int32 count = destSampleCount;
register float gain = _gain / 32767.0; register float gain = _gain / 32767.0;
if (src_sample_count == dst_sample_count) { if (srcSampleCount == destSampleCount) {
// optimized case for no resampling // optimized case for no resampling
while (count--) { while (count--) {
*(float *)dst = *(const int16 *)src * gain; *(float *)dest = *(const int16 *)src * gain;
src += src_sample_offset; src += srcSampleOffset;
dst += dst_sample_offset; dest += destSampleOffset;
} }
return; return;
} }
register float delta = float(src_sample_count) / float(dst_sample_count); register float delta = float(srcSampleCount) / float(destSampleCount);
register float current = 0.0f; register float current = 0.0f;
if (delta < 1.0) { if (delta < 1.0) {
// upsample // upsample
while (count--) { while (count--) {
*(float *)dst = *(const int16 *)src * gain; *(float *)dest = *(const int16 *)src * gain;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
if (current >= 1.0f) { if (current >= 1.0f) {
current -= 1.0f; current -= 1.0f;
src += src_sample_offset; src += srcSampleOffset;
} }
} }
} else { } else {
// downsample // downsample
while (count--) { while (count--) {
*(float *)dst = *(const int16 *)src * gain; *(float *)dest = *(const int16 *)src * gain;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
register int32 skipcount = (int32)current; register int32 skipcount = (int32)current;
current -= skipcount; current -= skipcount;
src += skipcount * src_sample_offset; src += skipcount * srcSampleOffset;
} }
} }
} }
void void
Resampler::int8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, Resampler::int8_to_float(const void *_src, int32 srcSampleOffset,
void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) int32 srcSampleCount, void *_dest, int32 destSampleOffset,
int32 destSampleCount, float _gain)
{ {
register const char * src = (const char *) _src; register const char * src = (const char *)_src;
register char * dst = (char *) _dst; register char * dest = (char *)_dest;
register int32 count = dst_sample_count; register int32 count = destSampleCount;
register float gain = _gain / 127.0; register float gain = _gain / 127.0;
if (src_sample_count == dst_sample_count) { if (srcSampleCount == destSampleCount) {
// optimized case for no resampling // optimized case for no resampling
while (count--) { while (count--) {
*(float *)dst = *(const int8 *)src * gain; *(float *)dest = *(const int8 *)src * gain;
src += src_sample_offset; src += srcSampleOffset;
dst += dst_sample_offset; dest += destSampleOffset;
} }
return; return;
} }
register float delta = float(src_sample_count) / float(dst_sample_count); register float delta = float(srcSampleCount) / float(destSampleCount);
register float current = 0.0f; register float current = 0.0f;
if (delta < 1.0) { if (delta < 1.0) {
// upsample // upsample
while (count--) { while (count--) {
*(float *)dst = *(const int8 *)src * gain; *(float *)dest = *(const int8 *)src * gain;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
if (current >= 1.0f) { if (current >= 1.0f) {
current -= 1.0f; current -= 1.0f;
src += src_sample_offset; src += srcSampleOffset;
} }
} }
} else { } else {
// downsample // downsample
while (count--) { while (count--) {
*(float *)dst = *(const int8 *)src * gain; *(float *)dest = *(const int8 *)src * gain;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
register int32 skipcount = (int32)current; register int32 skipcount = (int32)current;
current -= skipcount; current -= skipcount;
src += skipcount * src_sample_offset; src += skipcount * srcSampleOffset;
} }
} }
} }
void void
Resampler::uint8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, Resampler::uint8_to_float(const void *_src, int32 srcSampleOffset,
void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) int32 srcSampleCount, void *_dest, int32 destSampleOffset,
int32 destSampleCount, float _gain)
{ {
register const char * src = (const char *) _src; register const char * src = (const char *)_src;
register char * dst = (char *) _dst; register char * dest = (char *)_dest;
register int32 count = dst_sample_count; register int32 count = destSampleCount;
register float gain = _gain / 127.0; register float gain = _gain / 127.0;
if (src_sample_count == dst_sample_count) { if (srcSampleCount == destSampleCount) {
// optimized case for no resampling // optimized case for no resampling
while (count--) { while (count--) {
*(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; *(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain;
src += src_sample_offset; src += srcSampleOffset;
dst += dst_sample_offset; dest += destSampleOffset;
} }
return; return;
} }
register float delta = float(src_sample_count) / float(dst_sample_count); register float delta = float(srcSampleCount) / float(destSampleCount);
register float current = 0.0f; register float current = 0.0f;
if (delta < 1.0) { if (delta < 1.0) {
// upsample // upsample
while (count--) { while (count--) {
*(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; *(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
if (current >= 1.0f) { if (current >= 1.0f) {
current -= 1.0f; current -= 1.0f;
src += src_sample_offset; src += srcSampleOffset;
} }
} }
} else { } else {
// downsample // downsample
while (count--) { while (count--) {
*(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; *(float *)dest = (((int32) *(const uint8 *)src) - 128) * gain;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
register int32 skipcount = (int32)current; register int32 skipcount = (int32)current;
current -= skipcount; current -= skipcount;
src += skipcount * src_sample_offset; src += skipcount * srcSampleOffset;
} }
} }
} }
void void
Resampler::float_to_int32(const void *_src, int32 src_sample_offset, int32 src_sample_count, Resampler::float_to_int32(const void *_src, int32 srcSampleOffset,
void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) int32 srcSampleCount, void *_dest, int32 destSampleOffset,
int32 destSampleCount, float _gain)
{ {
register const char * src = (const char *) _src; register const char * src = (const char *)_src;
register char * dst = (char *) _dst; register char * dest = (char *)_dest;
register int32 count = dst_sample_count; register int32 count = destSampleCount;
register float gain = _gain * 2147483647.0; register float gain = _gain * 2147483647.0;
if (src_sample_count == dst_sample_count) { if (srcSampleCount == destSampleCount) {
// optimized case for no resampling // optimized case for no resampling
while (count--) { while (count--) {
register float sample = *(const float *)src * gain; register float sample = *(const float *)src * gain;
if (sample > 2147483647.0f) if (sample > 2147483647.0f)
*(int32 *)dst = 2147483647L; *(int32 *)dest = 2147483647L;
else if (sample < -2147483647.0f) else if (sample < -2147483647.0f)
*(int32 *)dst = -2147483647L; *(int32 *)dest = -2147483647L;
else else
*(int32 *)dst = (int32)sample; *(int32 *)dest = (int32)sample;
src += src_sample_offset; src += srcSampleOffset;
dst += dst_sample_offset; dest += destSampleOffset;
} }
return; return;
} }
register float delta = float(src_sample_count) / float(dst_sample_count); register float delta = float(srcSampleCount) / float(destSampleCount);
register float current = 0.0f; register float current = 0.0f;
if (delta < 1.0) { if (delta < 1.0) {
@@ -336,16 +359,16 @@ Resampler::float_to_int32(const void *_src, int32 src_sample_offset, int32 src_s
while (count--) { while (count--) {
register float sample = *(const float *)src * gain; register float sample = *(const float *)src * gain;
if (sample > 2147483647.0f) if (sample > 2147483647.0f)
*(int32 *)dst = 2147483647L; *(int32 *)dest = 2147483647L;
else if (sample < -2147483647.0f) else if (sample < -2147483647.0f)
*(int32 *)dst = -2147483647L; *(int32 *)dest = -2147483647L;
else else
*(int32 *)dst = (int32)sample; *(int32 *)dest = (int32)sample;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
if (current >= 1.0f) { if (current >= 1.0f) {
current -= 1.0f; current -= 1.0f;
src += src_sample_offset; src += srcSampleOffset;
} }
} }
} else { } else {
@@ -353,47 +376,48 @@ Resampler::float_to_int32(const void *_src, int32 src_sample_offset, int32 src_s
while (count--) { while (count--) {
register float sample = *(const float *)src * gain; register float sample = *(const float *)src * gain;
if (sample > 2147483647.0f) if (sample > 2147483647.0f)
*(int32 *)dst = 2147483647L; *(int32 *)dest = 2147483647L;
else if (sample < -2147483647.0f) else if (sample < -2147483647.0f)
*(int32 *)dst = -2147483647L; *(int32 *)dest = -2147483647L;
else else
*(int32 *)dst = (int32)sample; *(int32 *)dest = (int32)sample;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
register int32 skipcount = (int32)current; register int32 skipcount = (int32)current;
current -= skipcount; current -= skipcount;
src += skipcount * src_sample_offset; src += skipcount * srcSampleOffset;
} }
} }
} }
void void
Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_sample_count, Resampler::float_to_int16(const void *_src, int32 srcSampleOffset,
void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) int32 srcSampleCount, void *_dest, int32 destSampleOffset,
int32 destSampleCount, float _gain)
{ {
register const char * src = (const char *) _src; register const char * src = (const char *)_src;
register char * dst = (char *) _dst; register char * dest = (char *)_dest;
register int32 count = dst_sample_count; register int32 count = destSampleCount;
register float gain = _gain * 32767.0; register float gain = _gain * 32767.0;
if (src_sample_count == dst_sample_count) { if (srcSampleCount == destSampleCount) {
// optimized case for no resampling // optimized case for no resampling
while (count--) { while (count--) {
register float sample = *(const float *)src * gain; register float sample = *(const float *)src * gain;
if (sample > 32767.0f) if (sample > 32767.0f)
*(int16 *)dst = 32767; *(int16 *)dest = 32767;
else if (sample < -32767.0f) else if (sample < -32767.0f)
*(int16 *)dst = -32767; *(int16 *)dest = -32767;
else else
*(int16 *)dst = (int16)sample; *(int16 *)dest = (int16)sample;
src += src_sample_offset; src += srcSampleOffset;
dst += dst_sample_offset; dest += destSampleOffset;
} }
return; return;
} }
register float delta = float(src_sample_count) / float(dst_sample_count); register float delta = float(srcSampleCount) / float(destSampleCount);
register float current = 0.0f; register float current = 0.0f;
if (delta < 1.0) { if (delta < 1.0) {
@@ -401,16 +425,16 @@ Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_s
while (count--) { while (count--) {
register float sample = *(const float *)src * gain; register float sample = *(const float *)src * gain;
if (sample > 32767.0f) if (sample > 32767.0f)
*(int16 *)dst = 32767; *(int16 *)dest = 32767;
else if (sample < -32767.0f) else if (sample < -32767.0f)
*(int16 *)dst = -32767; *(int16 *)dest = -32767;
else else
*(int16 *)dst = (int16)sample; *(int16 *)dest = (int16)sample;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
if (current >= 1.0f) { if (current >= 1.0f) {
current -= 1.0f; current -= 1.0f;
src += src_sample_offset; src += srcSampleOffset;
} }
} }
} else { } else {
@@ -418,46 +442,48 @@ Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_s
while (count--) { while (count--) {
register float sample = *(const float *)src * gain; register float sample = *(const float *)src * gain;
if (sample > 32767.0f) if (sample > 32767.0f)
*(int16 *)dst = 32767; *(int16 *)dest = 32767;
else if (sample < -32767.0f) else if (sample < -32767.0f)
*(int16 *)dst = -32767; *(int16 *)dest = -32767;
else else
*(int16 *)dst = (int16)sample; *(int16 *)dest = (int16)sample;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
register int32 skipcount = (int32)current; register int32 skipcount = (int32)current;
current -= skipcount; current -= skipcount;
src += skipcount * src_sample_offset; src += skipcount * srcSampleOffset;
} }
} }
} }
void void
Resampler::float_to_int8(const void *_src, int32 src_sample_offset, int32 src_sample_count, Resampler::float_to_int8(const void *_src, int32 srcSampleOffset,
void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) int32 srcSampleCount, void *_dest, int32 destSampleOffset,
int32 destSampleCount, float _gain)
{ {
register const char * src = (const char *) _src; register const char * src = (const char *)_src;
register char * dst = (char *) _dst; register char * dest = (char *)_dest;
register int32 count = dst_sample_count; register int32 count = destSampleCount;
register float gain = _gain * 127.0; register float gain = _gain * 127.0;
if (src_sample_count == dst_sample_count) { if (srcSampleCount == destSampleCount) {
// optimized case for no resampling // optimized case for no resampling
while (count--) { while (count--) {
register float sample = *(const float *)src * gain; register float sample = *(const float *)src * gain;
if (sample > 127.0f) if (sample > 127.0f)
*(int8 *)dst = 127; *(int8 *)dest = 127;
else if (sample < -127.0f) else if (sample < -127.0f)
*(int8 *)dst = -127; *(int8 *)dest = -127;
else else
*(int8 *)dst = (int8)sample; *(int8 *)dest = (int8)sample;
src += src_sample_offset; src += srcSampleOffset;
dst += dst_sample_offset; dest += destSampleOffset;
} }
return; return;
} }
register float delta = float(src_sample_count) / float(dst_sample_count); register float delta = float(srcSampleCount) / float(destSampleCount);
register float current = 0.0f; register float current = 0.0f;
if (delta < 1.0) { if (delta < 1.0) {
@@ -465,16 +491,16 @@ Resampler::float_to_int8(const void *_src, int32 src_sample_offset, int32 src_sa
while (count--) { while (count--) {
register float sample = *(const float *)src * gain; register float sample = *(const float *)src * gain;
if (sample > 127.0f) if (sample > 127.0f)
*(int8 *)dst = 127; *(int8 *)dest = 127;
else if (sample < -127.0f) else if (sample < -127.0f)
*(int8 *)dst = -127; *(int8 *)dest = -127;
else else
*(int8 *)dst = (int8)sample; *(int8 *)dest = (int8)sample;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
if (current >= 1.0f) { if (current >= 1.0f) {
current -= 1.0f; current -= 1.0f;
src += src_sample_offset; src += srcSampleOffset;
} }
} }
} else { } else {
@@ -482,46 +508,48 @@ Resampler::float_to_int8(const void *_src, int32 src_sample_offset, int32 src_sa
while (count--) { while (count--) {
register float sample = *(const float *)src * gain; register float sample = *(const float *)src * gain;
if (sample > 127.0f) if (sample > 127.0f)
*(int8 *)dst = 127; *(int8 *)dest = 127;
else if (sample < -127.0f) else if (sample < -127.0f)
*(int8 *)dst = -127; *(int8 *)dest = -127;
else else
*(int8 *)dst = (int8)sample; *(int8 *)dest = (int8)sample;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
register int32 skipcount = (int32)current; register int32 skipcount = (int32)current;
current -= skipcount; current -= skipcount;
src += skipcount * src_sample_offset; src += skipcount * srcSampleOffset;
} }
} }
} }
void void
Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_sample_count, Resampler::float_to_uint8(const void *_src, int32 srcSampleOffset,
void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) int32 srcSampleCount, void *_dest, int32 destSampleOffset,
int32 destSampleCount, float _gain)
{ {
register const char * src = (const char *) _src; register const char * src = (const char *)_src;
register char * dst = (char *) _dst; register char * dest = (char *)_dest;
register int32 count = dst_sample_count; register int32 count = destSampleCount;
register float gain = _gain * 127.0; register float gain = _gain * 127.0;
if (src_sample_count == dst_sample_count) { if (srcSampleCount == destSampleCount) {
// optimized case for no resampling // optimized case for no resampling
while (count--) { while (count--) {
register float sample = 128.0f + *(const float *)src * gain; register float sample = 128.0f + *(const float *)src * gain;
if (sample > 255.0f) if (sample > 255.0f)
*(uint8 *)dst = 255; *(uint8 *)dest = 255;
else if (sample < 1.0f) else if (sample < 1.0f)
*(uint8 *)dst = 1; *(uint8 *)dest = 1;
else else
*(uint8 *)dst = (uint8)sample; *(uint8 *)dest = (uint8)sample;
src += src_sample_offset; src += srcSampleOffset;
dst += dst_sample_offset; dest += destSampleOffset;
} }
return; return;
} }
register float delta = float(src_sample_count) / float(dst_sample_count); register float delta = float(srcSampleCount) / float(destSampleCount);
register float current = 0.0f; register float current = 0.0f;
if (delta < 1.0) { if (delta < 1.0) {
@@ -529,16 +557,16 @@ Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_s
while (count--) { while (count--) {
register float sample = 128.0f + *(const float *)src * gain; register float sample = 128.0f + *(const float *)src * gain;
if (sample > 255.0f) if (sample > 255.0f)
*(uint8 *)dst = 255; *(uint8 *)dest = 255;
else if (sample < 1.0f) else if (sample < 1.0f)
*(uint8 *)dst = 1; *(uint8 *)dest = 1;
else else
*(uint8 *)dst = (uint8)sample; *(uint8 *)dest = (uint8)sample;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
if (current >= 1.0f) { if (current >= 1.0f) {
current -= 1.0f; current -= 1.0f;
src += src_sample_offset; src += srcSampleOffset;
} }
} }
} else { } else {
@@ -546,16 +574,16 @@ Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_s
while (count--) { while (count--) {
register float sample = 128.0f + *(const float *)src * gain; register float sample = 128.0f + *(const float *)src * gain;
if (sample > 255.0f) if (sample > 255.0f)
*(uint8 *)dst = 255; *(uint8 *)dest = 255;
else if (sample < 1.0f) else if (sample < 1.0f)
*(uint8 *)dst = 1; *(uint8 *)dest = 1;
else else
*(uint8 *)dst = (uint8)sample; *(uint8 *)dest = (uint8)sample;
dst += dst_sample_offset; dest += destSampleOffset;
current += delta; current += delta;
register int32 skipcount = (int32)current; register int32 skipcount = (int32)current;
current -= skipcount; current -= skipcount;
src += skipcount * src_sample_offset; src += skipcount * srcSampleOffset;
} }
} }
} }
@@ -1,59 +1,80 @@
/* Copyright (C) 2003 Marcus Overhagen /*
* Released under terms of the MIT license. * Copyright 2003 Marcus Overhagen
* * Distributed under the 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.
*
*/ */
#ifndef _RESAMPLER_H #ifndef _RESAMPLER_H
#define _RESAMPLER_H #define _RESAMPLER_H
#include <SupportDefs.h> #include <SupportDefs.h>
class Resampler class Resampler {
{
public: public:
Resampler(uint32 sourceformat, uint32 destformat); Resampler(uint32 sourceFormat,
uint32 destFormat);
virtual ~Resampler(); virtual ~Resampler();
status_t InitCheck(); status_t InitCheck() const;
void Resample(const void *src, int32 src_sample_offset, int32 src_sample_count, void Resample(const void* src, int32 srcSampleOffset,
void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); int32 srcSampleCount, void* dest,
int32 destSampleOffset,
int32 destSampleCount, float gain);
protected: protected:
virtual void float_to_float (const void *src, int32 src_sample_offset, int32 src_sample_count, virtual void float_to_float(const void* src,
void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); int32 srcSampleOffset, int32 srcSampleCount,
virtual void int32_to_float (const void *src, int32 src_sample_offset, int32 src_sample_count, void* dest, int32 destSampleOffset,
void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); int32 destSampleCount, float gain);
virtual void int16_to_float (const void *src, int32 src_sample_offset, int32 src_sample_count, virtual void int32_to_float(const void* src,
void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); int32 srcSampleOffset, int32 srcSampleCount,
virtual void int8_to_float (const void *src, int32 src_sample_offset, int32 src_sample_count, void* dest, int32 destSampleOffset,
void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); int32 destSampleCount, float gain);
virtual void uint8_to_float (const void *src, int32 src_sample_offset, int32 src_sample_count, virtual void int16_to_float(const void* src,
void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); int32 srcSampleOffset, int32 srcSampleCount,
virtual void float_to_int32 (const void *src, int32 src_sample_offset, int32 src_sample_count, void* dest, int32 destSampleOffset,
void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); int32 destSampleCount, float gain);
virtual void float_to_int16 (const void *src, int32 src_sample_offset, int32 src_sample_count, virtual void int8_to_float(const void* src,
void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); int32 srcSampleOffset, int32 srcSampleCount,
virtual void float_to_int8 (const void *src, int32 src_sample_offset, int32 src_sample_count, void* dest, int32 destSampleOffset,
void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); int32 destSampleCount, float gain);
virtual void float_to_uint8 (const void *src, int32 src_sample_offset, int32 src_sample_count, virtual void uint8_to_float(const void* src,
void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain); 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: 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 inline void
Resampler::Resample(const void *src, int32 src_sample_offset, int32 src_sample_count, Resampler::Resample(const void *src, int32 srcSampleOffset,
void *dst, int32 dst_sample_offset, int32 dst_sample_count, float gain) 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 #endif // _RESAMPLER_H
+26 -18
View File
@@ -1,23 +1,30 @@
/*
* Copyright 2003 Marcus Overhagen
* Distributed under the terms of the MIT License.
*/
#ifndef _MEDIA_RT_LIST_H #ifndef _MEDIA_RT_LIST_H
#define _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
* A simple list template that uses realtime memory and does no error checking. Since
* memory and does no error checking. Since it doesn't call constructors or destructors,
* it doesn't call constructors or destructors, don't use it to store objects.
* don't use it to store objects.
*/ // TODO: no error checking? Great.
*/
#include <RealtimeAlloc.h> #include <RealtimeAlloc.h>
template<class value> class RtList
{ template<class value> class RtList {
public: public:
RtList() RtList()
: item_max(INIT_COUNT), :
item_max(INIT_COUNT),
item_count(0), item_count(0),
items((value *)rtm_alloc(NULL, sizeof(value) * INIT_COUNT)) items((value*)rtm_alloc(NULL, sizeof(value) * INIT_COUNT))
{ {
} }
@@ -26,16 +33,16 @@ public:
rtm_free(items); rtm_free(items);
} }
value *Create() value* Create()
{ {
if (item_count == item_max) { if (item_count == item_max) {
item_max += INC_COUNT; item_max += INC_COUNT;
rtm_realloc((void **)&items, sizeof(value) * item_max); rtm_realloc((void**)&items, sizeof(value) * item_max);
} }
return &items[item_count++]; return &items[item_count++];
} }
value *ItemAt(int index) value* ItemAt(int index)
{ {
return &items[index]; return &items[index];
} }
@@ -51,14 +58,15 @@ public:
} }
private: private:
RtList(const RtList<value> &other); RtList(const RtList<value>& other);
RtList<value> &operator=(const RtList<value> &other); RtList<value> &operator=(const RtList<value>& other);
private: private:
enum { INIT_COUNT = 8, INC_COUNT = 16 }; enum { INIT_COUNT = 8, INC_COUNT = 16 };
int item_max; int item_max;
int item_count; int item_count;
value *items; value* items;
}; };
#endif // _MEDIA_RT_LIST_H #endif // _MEDIA_RT_LIST_H