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