allocate mixer buffers of the correct size,
place incoming data in input specific mix buffer git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3646 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -334,7 +334,7 @@ AudioMixer::FormatChanged(const media_source &producer, const media_destination
|
|||||||
|
|
||||||
// tell core about format change
|
// tell core about format change
|
||||||
fCore->Lock();
|
fCore->Lock();
|
||||||
fCore->InputFormatChanged(consumer.id, &format);
|
fCore->InputFormatChanged(consumer.id, format.u.raw_audio);
|
||||||
fCore->Unlock();
|
fCore->Unlock();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -420,7 +420,7 @@ AudioMixer::FormatChangeRequested(const media_source &source, const media_destin
|
|||||||
|
|
||||||
// apply format change
|
// apply format change
|
||||||
fCore->Lock();
|
fCore->Lock();
|
||||||
fCore->OutputFormatChanged(io_format);
|
fCore->OutputFormatChanged(io_format->u.raw_audio);
|
||||||
fCore->Unlock();
|
fCore->Unlock();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -617,7 +617,7 @@ AudioMixer::Connect(status_t error, const media_source &source, const media_dest
|
|||||||
fCore->Output()->MediaOutput().destination = dest;
|
fCore->Output()->MediaOutput().destination = dest;
|
||||||
|
|
||||||
fCore->EnableOutput(true);
|
fCore->EnableOutput(true);
|
||||||
fCore->SetTimeSource(TimeSource()->ID());
|
fCore->SetTimeSource(TimeSource());
|
||||||
fCore->SetOutputBufferGroup(fBufferGroup);
|
fCore->SetOutputBufferGroup(fBufferGroup);
|
||||||
fCore->Unlock();
|
fCore->Unlock();
|
||||||
}
|
}
|
||||||
@@ -710,7 +710,7 @@ AudioMixer::SetTimeSource(BTimeSource * time_source)
|
|||||||
{
|
{
|
||||||
printf("AudioMixer::SetTimeSource: timesource is now %ld\n", time_source->ID());
|
printf("AudioMixer::SetTimeSource: timesource is now %ld\n", time_source->ID());
|
||||||
fCore->Lock();
|
fCore->Lock();
|
||||||
fCore->SetTimeSource(time_source->ID());
|
fCore->SetTimeSource(time_source);
|
||||||
fCore->Unlock();
|
fCore->Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,46 @@
|
|||||||
|
#include <RealtimeAlloc.h>
|
||||||
#include <MediaNode.h>
|
#include <MediaNode.h>
|
||||||
|
#include <TimeSource.h>
|
||||||
#include <Buffer.h>
|
#include <Buffer.h>
|
||||||
|
#include <BufferGroup.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 "Debug.h"
|
#include "Debug.h"
|
||||||
|
|
||||||
#define MAX_OUTPUT_BUFFER_LENGTH 50000LL /* 50 ms */
|
#define DOUBLE_RATE_MIXING 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")
|
||||||
|
|
||||||
/* 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
|
||||||
|
* output buffer, or the double frame rate and frame count.
|
||||||
|
*
|
||||||
|
* All mixer input ring buffers must be an exact multiple of the mixer buffer size,
|
||||||
|
* so that we do not get any buffer wrap around during reading from the input buffers.
|
||||||
|
* The mixer input is told by constructor (or after a format change by SetMixBufferFormat())
|
||||||
|
* of the current mixer buffer propertys, and must allocate a buffer that is an exact multiple,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
MixerCore::MixerCore()
|
MixerCore::MixerCore()
|
||||||
: fLocker(new BLocker),
|
: fLocker(new BLocker),
|
||||||
fOutputBufferLength(MAX_OUTPUT_BUFFER_LENGTH),
|
|
||||||
fInputBufferLength(3 * MAX_OUTPUT_BUFFER_LENGTH),
|
|
||||||
fMixFrameRate(96000),
|
|
||||||
fMixStartTime(0),
|
|
||||||
fInputs(new BList),
|
fInputs(new BList),
|
||||||
fOutput(0),
|
fOutput(0),
|
||||||
fNextInputID(1),
|
fNextInputID(1),
|
||||||
fRunning(false)
|
fRunning(false),
|
||||||
|
fMixBuffer(0),
|
||||||
|
fMixBufferFrameRate(0),
|
||||||
|
fMixBufferFrameCount(0),
|
||||||
|
fMixBufferChannelTypes(0),
|
||||||
|
fMixBufferChannelCount(0),
|
||||||
|
fDoubleRateMixing(DOUBLE_RATE_MIXING),
|
||||||
|
fLastMixStartTime(0),
|
||||||
|
fBufferGroup(0),
|
||||||
|
fTimeSource(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,13 +48,21 @@ MixerCore::~MixerCore()
|
|||||||
{
|
{
|
||||||
delete fLocker;
|
delete fLocker;
|
||||||
delete fInputs;
|
delete fInputs;
|
||||||
|
|
||||||
|
if (fMixBuffer)
|
||||||
|
rtm_free(fMixBuffer);
|
||||||
|
|
||||||
|
if (fTimeSource)
|
||||||
|
fTimeSource->Release();
|
||||||
|
|
||||||
|
delete fMixBufferChannelTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MixerCore::AddInput(const media_input &input)
|
MixerCore::AddInput(const media_input &input)
|
||||||
{
|
{
|
||||||
ASSERT_LOCKED();
|
ASSERT_LOCKED();
|
||||||
fInputs->AddItem(new MixerInput(this, input, fMixFrameRate, frames_for_duration(fMixFrameRate, fInputBufferLength), fMixStartTime));
|
fInputs->AddItem(new MixerInput(this, input, fMixBufferFrameRate, fMixBufferFrameCount, fLastMixStartTime));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +73,8 @@ MixerCore::AddOutput(const media_output &output)
|
|||||||
if (fOutput)
|
if (fOutput)
|
||||||
return false;
|
return false;
|
||||||
fOutput = new MixerOutput(this, output);
|
fOutput = new MixerOutput(this, output);
|
||||||
|
// the output format might have been adjusted inside MixerOutput
|
||||||
|
OutputFormatChanged(fOutput->MediaOutput().format.u.raw_audio);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -114,36 +140,77 @@ MixerCore::BufferReceived(BBuffer *buffer, bigtime_t lateness)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MixerCore::InputFormatChanged(int32 inputID, const media_format *format)
|
MixerCore::InputFormatChanged(int32 inputID, const media_multi_audio_format &format)
|
||||||
{
|
{
|
||||||
ASSERT_LOCKED();
|
ASSERT_LOCKED();
|
||||||
|
printf("MixerCore::InputFormatChanged not handled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MixerCore::OutputFormatChanged(const media_format *format)
|
MixerCore::OutputFormatChanged(const media_multi_audio_format &format)
|
||||||
{
|
{
|
||||||
ASSERT_LOCKED();
|
ASSERT_LOCKED();
|
||||||
|
|
||||||
// void ChangeMixBufferFormat(float samplerate, int32 frames, int32 channelcount, uint32 channel_mask);
|
|
||||||
|
|
||||||
|
if (fMixBuffer)
|
||||||
|
rtm_free(fMixBuffer);
|
||||||
|
|
||||||
|
delete fMixBufferChannelTypes;
|
||||||
|
|
||||||
|
fMixBufferFrameRate = (int32)format.frame_rate;
|
||||||
|
fMixBufferFrameCount = frames_per_buffer(format);
|
||||||
|
if (fDoubleRateMixing) {
|
||||||
|
fMixBufferFrameRate *= 2;
|
||||||
|
fMixBufferFrameCount *= 2;
|
||||||
|
}
|
||||||
|
fMixBufferChannelCount = format.channel_count;
|
||||||
|
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);
|
||||||
|
|
||||||
|
printf("MixerCore::OutputFormatChanged:\n");
|
||||||
|
printf(" fMixBufferFrameRate %ld\n", fMixBufferFrameRate);
|
||||||
|
printf(" fMixBufferFrameCount %ld\n", fMixBufferFrameCount);
|
||||||
|
printf(" fMixBufferChannelCount %ld\n", fMixBufferChannelCount);
|
||||||
|
for (int i = 0; i < fMixBufferChannelCount; i++)
|
||||||
|
printf(" fMixBufferChannelTypes[%i] %ld\n", i, fMixBufferChannelTypes[i]);
|
||||||
|
|
||||||
|
MixerInput *input;
|
||||||
|
for (int i = 0; (input = Input(i)); i++)
|
||||||
|
input->SetMixBufferFormat(fMixBufferFrameRate, fMixBufferFrameCount, fLastMixStartTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MixerCore::SetOutputBufferGroup(BBufferGroup *group)
|
MixerCore::SetOutputBufferGroup(BBufferGroup *group)
|
||||||
{
|
{
|
||||||
ASSERT_LOCKED();
|
ASSERT_LOCKED();
|
||||||
|
|
||||||
|
fBufferGroup = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MixerCore::SetTimeSource(media_node_id id)
|
MixerCore::SetTimeSource(BTimeSource *ts)
|
||||||
{
|
{
|
||||||
ASSERT_LOCKED();
|
ASSERT_LOCKED();
|
||||||
|
|
||||||
|
if (fTimeSource)
|
||||||
|
fTimeSource->Release();
|
||||||
|
|
||||||
|
fTimeSource = dynamic_cast<BTimeSource *>(ts->Acquire());
|
||||||
|
fLastMixStartTime = fTimeSource->Now();
|
||||||
|
|
||||||
|
MixerInput *input;
|
||||||
|
for (int i = 0; (input = Input(i)); i++)
|
||||||
|
input->SetMixBufferFormat(fMixBufferFrameRate, fMixBufferFrameCount, fLastMixStartTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MixerCore::EnableOutput(bool enabled)
|
MixerCore::EnableOutput(bool enabled)
|
||||||
{
|
{
|
||||||
ASSERT_LOCKED();
|
ASSERT_LOCKED();
|
||||||
|
printf("MixerCore::EnableOutput %d\n", enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -170,7 +237,9 @@ uint32
|
|||||||
MixerCore::OutputBufferSize()
|
MixerCore::OutputBufferSize()
|
||||||
{
|
{
|
||||||
ASSERT_LOCKED();
|
ASSERT_LOCKED();
|
||||||
return 1;
|
|
||||||
|
uint32 size = sizeof(float) * fMixBufferFrameCount * fMixBufferChannelCount;
|
||||||
|
return fDoubleRateMixing ? (size / 2) : size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -180,11 +249,6 @@ MixerCore::IsStarted()
|
|||||||
return fRunning;
|
return fRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
MixerCore::OutputBufferLengthChanged(bigtime_t length)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void BufferReceived(BBuffer *buffer, bigtime_t lateness);
|
void BufferReceived(BBuffer *buffer, bigtime_t lateness);
|
||||||
@@ -225,4 +289,4 @@ AudioMixer::MixThread()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ public:
|
|||||||
|
|
||||||
void BufferReceived(BBuffer *buffer, bigtime_t lateness);
|
void BufferReceived(BBuffer *buffer, bigtime_t lateness);
|
||||||
|
|
||||||
void InputFormatChanged(int32 inputID, const media_format *format);
|
void InputFormatChanged(int32 inputID, const media_multi_audio_format &format);
|
||||||
void OutputFormatChanged(const media_format *format);
|
void OutputFormatChanged(const media_multi_audio_format &format);
|
||||||
|
|
||||||
void SetOutputBufferGroup(BBufferGroup *group);
|
void SetOutputBufferGroup(BBufferGroup *group);
|
||||||
void SetTimeSource(media_node_id id);
|
void SetTimeSource(BTimeSource *ts);
|
||||||
void EnableOutput(bool enabled);
|
void EnableOutput(bool enabled);
|
||||||
void Start(bigtime_t time);
|
void Start(bigtime_t time);
|
||||||
void Stop();
|
void Stop();
|
||||||
@@ -43,7 +43,6 @@ public:
|
|||||||
uint32 OutputChannelCount();
|
uint32 OutputChannelCount();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OutputBufferLengthChanged(bigtime_t length);
|
|
||||||
// handle mixing in separate thread
|
// handle mixing in separate thread
|
||||||
// not implemented (yet)
|
// not implemented (yet)
|
||||||
|
|
||||||
@@ -54,15 +53,21 @@ private:
|
|||||||
private:
|
private:
|
||||||
BLocker *fLocker;
|
BLocker *fLocker;
|
||||||
|
|
||||||
bigtime_t fOutputBufferLength;
|
|
||||||
bigtime_t fInputBufferLength;
|
|
||||||
float fMixFrameRate;
|
|
||||||
bigtime_t fMixStartTime;
|
|
||||||
|
|
||||||
BList *fInputs;
|
BList *fInputs;
|
||||||
MixerOutput *fOutput;
|
MixerOutput *fOutput;
|
||||||
int32 fNextInputID;
|
int32 fNextInputID;
|
||||||
bool fRunning;
|
bool fRunning;
|
||||||
|
|
||||||
|
float *fMixBuffer;
|
||||||
|
int32 fMixBufferFrameRate;
|
||||||
|
int32 fMixBufferFrameCount;
|
||||||
|
int32 fMixBufferChannelCount;
|
||||||
|
int32 *fMixBufferChannelTypes; //array
|
||||||
|
bool fDoubleRateMixing;
|
||||||
|
bigtime_t fLastMixStartTime;
|
||||||
|
|
||||||
|
BBufferGroup *fBufferGroup;
|
||||||
|
BTimeSource *fTimeSource;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -77,4 +82,3 @@ inline void MixerCore::Unlock()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
#include <MediaNode.h>
|
#include <MediaNode.h>
|
||||||
#include <Buffer.h>
|
#include <Buffer.h>
|
||||||
#include <RealtimeAlloc.h>
|
#include <RealtimeAlloc.h>
|
||||||
|
#include <string.h>
|
||||||
#include "MixerInput.h"
|
#include "MixerInput.h"
|
||||||
#include "MixerCore.h"
|
#include "MixerCore.h"
|
||||||
#include "MixerUtils.h"
|
#include "MixerUtils.h"
|
||||||
|
#include "Resampler.h"
|
||||||
#include "ByteSwap.h"
|
#include "ByteSwap.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
template<class t> const t & max(const t &t1, const t &t2) { return (t1 > t2) ? t1 : t2; }
|
||||||
|
|
||||||
MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixSampleRate, int32 mixFramesCount, bigtime_t mixStartTime)
|
MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixSampleRate, int32 mixFramesCount, bigtime_t mixStartTime)
|
||||||
: fCore(core),
|
: fCore(core),
|
||||||
fInput(input),
|
fInput(input),
|
||||||
@@ -17,9 +21,10 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixSampl
|
|||||||
fMixerChannelInfo(0),
|
fMixerChannelInfo(0),
|
||||||
fMixerChannelCount(0),
|
fMixerChannelCount(0),
|
||||||
fMixBuffer(0),
|
fMixBuffer(0),
|
||||||
fMixBufferSampleRate(0),
|
fMixBufferFrameRate(0),
|
||||||
fMixBufferFrames(0),
|
fMixBufferFrameCount(0),
|
||||||
fMixBufferStartTime(0),
|
fMixBufferStartTime(0),
|
||||||
|
fResampler(0),
|
||||||
fUserOverridesChannelDesignations(false)
|
fUserOverridesChannelDesignations(false)
|
||||||
{
|
{
|
||||||
fix_multiaudio_format(&fInput.format.u.raw_audio);
|
fix_multiaudio_format(&fInput.format.u.raw_audio);
|
||||||
@@ -47,6 +52,11 @@ MixerInput::MixerInput(MixerCore *core, const media_input &input, float mixSampl
|
|||||||
fInputChannelInfo[i].designations = 0; // will be set by UpdateChannelDesignations()
|
fInputChannelInfo[i].designations = 0; // will be set by UpdateChannelDesignations()
|
||||||
fInputChannelInfo[i].gain = 1.0;
|
fInputChannelInfo[i].gain = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create resamplers
|
||||||
|
fResampler = new Resampler * [fInputChannelCount];
|
||||||
|
for (int i = 0; i < fInputChannelCount; i++)
|
||||||
|
fResampler[i] = new Resampler(fInput.format.u.raw_audio.format, media_raw_audio_format::B_AUDIO_FLOAT);
|
||||||
|
|
||||||
// fMixerChannelInfo and fMixerChannelCount will be initialized by UpdateMixerChannels()
|
// fMixerChannelInfo and fMixerChannelCount will be initialized by UpdateMixerChannels()
|
||||||
|
|
||||||
@@ -69,6 +79,11 @@ MixerInput::~MixerInput()
|
|||||||
rtm_free(fMixBuffer);
|
rtm_free(fMixBuffer);
|
||||||
delete [] fInputChannelInfo;
|
delete [] fInputChannelInfo;
|
||||||
delete [] fMixerChannelInfo;
|
delete [] fMixerChannelInfo;
|
||||||
|
|
||||||
|
// delete resamplers
|
||||||
|
for (int i = 0; i < fInputChannelCount; i++)
|
||||||
|
delete fResampler[i];
|
||||||
|
delete [] fResampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -88,8 +103,54 @@ MixerInput::BufferReceived(BBuffer *buffer)
|
|||||||
if (fInputByteSwap)
|
if (fInputByteSwap)
|
||||||
fInputByteSwap->Swap(data, size);
|
fInputByteSwap->Swap(data, size);
|
||||||
|
|
||||||
|
int32 offset = frames_for_duration(fMixBufferFrameRate, start - fMixBufferStartTime) % fMixBufferFrameCount;
|
||||||
|
|
||||||
|
printf("MixerInput::BufferReceived: mix buffer start %14Ld, buffer start %14Ld, offset %6d\n", fMixBufferStartTime, start, offset);
|
||||||
|
|
||||||
|
int in_frames = frames_per_buffer(fInput.format.u.raw_audio); // XXX use size
|
||||||
|
int out_frames = (int)((in_frames * fMixBufferFrameRate) / fInput.format.u.raw_audio.frame_rate); // XXX losing fractions
|
||||||
|
|
||||||
printf("mix buffer start %14Ld, buffer start %14Ld\n", fMixBufferStartTime, start);
|
if (offset + out_frames > fMixBufferFrameCount) {
|
||||||
|
|
||||||
|
int out_frames1 = fMixBufferFrameCount - offset;
|
||||||
|
int out_frames2 = out_frames - out_frames1;
|
||||||
|
int in_frames1 = (out_frames1 * in_frames) / out_frames;
|
||||||
|
int in_frames2 = in_frames - in_frames1;
|
||||||
|
|
||||||
|
printf(" in_frames %5d, out_frames %5d, in_frames1 %5d, out_frames1 %5d, in_frames2 %5d, out_frames2 %5d\n",
|
||||||
|
in_frames, out_frames, in_frames1, out_frames1, in_frames2, out_frames2);
|
||||||
|
|
||||||
|
for (int i = 0; i < fInputChannelCount; i++) {
|
||||||
|
fResampler[i]->Resample(reinterpret_cast<char *>(data) + i * bytes_per_frame(fInput.format.u.raw_audio),
|
||||||
|
fInputChannelCount * bytes_per_frame(fInput.format.u.raw_audio),
|
||||||
|
in_frames1,
|
||||||
|
reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base) + (offset * sizeof(float) * fInputChannelCount),
|
||||||
|
fInputChannelCount * sizeof(float),
|
||||||
|
out_frames1,
|
||||||
|
fInputChannelInfo[i].gain);
|
||||||
|
|
||||||
|
fResampler[i]->Resample(reinterpret_cast<char *>(data) + i * bytes_per_frame(fInput.format.u.raw_audio),
|
||||||
|
fInputChannelCount * bytes_per_frame(fInput.format.u.raw_audio),
|
||||||
|
in_frames2,
|
||||||
|
reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base),
|
||||||
|
fInputChannelCount * sizeof(float),
|
||||||
|
out_frames2,
|
||||||
|
fInputChannelInfo[i].gain);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
printf(" in_frames %5d, out_frames %5d\n", in_frames, out_frames);
|
||||||
|
|
||||||
|
for (int i = 0; i < fInputChannelCount; i++) {
|
||||||
|
fResampler[i]->Resample(reinterpret_cast<char *>(data) + i * bytes_per_frame(fInput.format.u.raw_audio),
|
||||||
|
fInputChannelCount * bytes_per_frame(fInput.format.u.raw_audio),
|
||||||
|
in_frames,
|
||||||
|
reinterpret_cast<char *>(fInputChannelInfo[i].buffer_base) + (offset * sizeof(float) * fInputChannelCount),
|
||||||
|
fInputChannelCount * sizeof(float),
|
||||||
|
out_frames,
|
||||||
|
fInputChannelInfo[i].gain);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
media_input &
|
media_input &
|
||||||
@@ -303,11 +364,12 @@ MixerInput::GetMixerChannelCount()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MixerInput::GetMixerChannelInfo(int channel, const float **buffer, uint32 *sample_offset, int *type, float *gain)
|
MixerInput::GetMixerChannelInfo(int channel, int64 framepos, const float **buffer, uint32 *sample_offset, int *type, float *gain)
|
||||||
{
|
{
|
||||||
ASSERT(fMixBuffer);
|
ASSERT(fMixBuffer);
|
||||||
ASSERT(channel >= 0 && channel < fMixerChannelCount);
|
ASSERT(channel >= 0 && channel < fMixerChannelCount);
|
||||||
*buffer = fMixerChannelInfo[channel].buffer_base;
|
int32 offset = framepos % fMixBufferFrameCount;
|
||||||
|
*buffer = reinterpret_cast<float *>(reinterpret_cast<char *>(fMixerChannelInfo[channel].buffer_base) + (offset * sizeof(float) * fInputChannelCount));
|
||||||
*sample_offset = sizeof(float) * fInputChannelCount;
|
*sample_offset = sizeof(float) * fInputChannelCount;
|
||||||
*type = fMixerChannelInfo[channel].type;
|
*type = fMixerChannelInfo[channel].type;
|
||||||
*gain = fMixerChannelInfo[channel].gain;
|
*gain = fMixerChannelInfo[channel].gain;
|
||||||
@@ -332,16 +394,35 @@ MixerInput::GetMixerChannelGain(int channel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MixerInput::SetMixBufferFormat(float samplerate, int32 frames, bigtime_t starttime)
|
MixerInput::SetMixBufferFormat(int32 framerate, int32 frames, bigtime_t starttime)
|
||||||
{
|
{
|
||||||
fMixBufferSampleRate = samplerate;
|
fMixBufferFrameRate = framerate;
|
||||||
fMixBufferFrames = frames;
|
|
||||||
fMixBufferStartTime = starttime;
|
fMixBufferStartTime = starttime;
|
||||||
|
|
||||||
|
printf("MixerInput::SetMixBufferFormat: framerate %ld, frames %ld, starttime %Ld\n", framerate, frames, starttime);
|
||||||
|
|
||||||
|
// make fMixBufferFrameCount an integral multiple of frames,
|
||||||
|
// but at least 3 times duration of our input buffer
|
||||||
|
// and at least 2 times duration of the output buffer
|
||||||
|
bigtime_t inputBufferLength = duration_for_frames(fInput.format.u.raw_audio.frame_rate, frames_per_buffer(fInput.format.u.raw_audio));
|
||||||
|
bigtime_t outputBufferLength = duration_for_frames(framerate, frames);
|
||||||
|
bigtime_t mixerBufferLength = max_c(3 * inputBufferLength, 2 * outputBufferLength);
|
||||||
|
int temp = frames_for_duration(framerate, mixerBufferLength);
|
||||||
|
fMixBufferFrameCount = ((temp / frames) + 1) * frames;
|
||||||
|
|
||||||
|
printf(" inputBufferLength %10Ld\n", inputBufferLength);
|
||||||
|
printf(" outputBufferLength %10Ld\n", outputBufferLength);
|
||||||
|
printf(" mixerBufferLength %10Ld\n", mixerBufferLength);
|
||||||
|
printf(" fMixBufferFrameCount %10ld\n", fMixBufferFrameCount);
|
||||||
|
|
||||||
if (fMixBuffer)
|
if (fMixBuffer)
|
||||||
rtm_free(fMixBuffer);
|
rtm_free(fMixBuffer);
|
||||||
fMixBuffer = (float *)rtm_alloc(NULL, sizeof(float) * fInputChannelCount * fMixBufferFrames);
|
int size = sizeof(float) * fInputChannelCount * fMixBufferFrameCount;
|
||||||
|
fMixBuffer = (float *)rtm_alloc(NULL, size);
|
||||||
|
ASSERT(fMixBuffer);
|
||||||
|
|
||||||
|
memset(fMixBuffer, 0, size);
|
||||||
|
|
||||||
for (int i = 0; i < fInputChannelCount; i++)
|
for (int i = 0; i < fInputChannelCount; i++)
|
||||||
fInputChannelInfo[i].buffer_base = &fMixBuffer[i * fMixBufferFrames];
|
fInputChannelInfo[i].buffer_base = &fMixBuffer[i];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
class MixerCore;
|
class MixerCore;
|
||||||
class ByteSwap;
|
class ByteSwap;
|
||||||
|
class Resampler;
|
||||||
|
|
||||||
class MixerInput
|
class MixerInput
|
||||||
{
|
{
|
||||||
@@ -17,7 +18,7 @@ public:
|
|||||||
media_input & MediaInput();
|
media_input & MediaInput();
|
||||||
|
|
||||||
uint32 GetMixerChannelCount();
|
uint32 GetMixerChannelCount();
|
||||||
void GetMixerChannelInfo(int channel, const float **buffer, uint32 *sample_offset, int *type, float *gain);
|
void GetMixerChannelInfo(int channel, int64 framepos, const float **buffer, uint32 *sample_offset, int *type, float *gain);
|
||||||
void SetMixerChannelGain(int channel, float gain);
|
void SetMixerChannelGain(int channel, float gain);
|
||||||
float GetMixerChannelGain(int channel);
|
float GetMixerChannelGain(int channel);
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class MixerCore;
|
friend class MixerCore;
|
||||||
void SetMixBufferFormat(float samplerate, int32 frames, bigtime_t starttime);
|
void SetMixBufferFormat(int32 framerate, int32 frames, bigtime_t starttime);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateChannelDesignations();
|
void UpdateChannelDesignations();
|
||||||
@@ -62,9 +63,11 @@ private:
|
|||||||
|
|
||||||
float *fMixBuffer;
|
float *fMixBuffer;
|
||||||
|
|
||||||
float fMixBufferSampleRate;
|
float fMixBufferFrameRate;
|
||||||
uint32 fMixBufferFrames;
|
uint32 fMixBufferFrameCount;
|
||||||
bigtime_t fMixBufferStartTime;
|
bigtime_t fMixBufferStartTime;
|
||||||
|
|
||||||
|
Resampler **fResampler; // array
|
||||||
|
|
||||||
bool fUserOverridesChannelDesignations;
|
bool fUserOverridesChannelDesignations;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user