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