* 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:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user