- clang format + naming improved
This commit is contained in:
+225
-232
@@ -17,341 +17,334 @@ using namespace Audio;
|
||||
|
||||
Mixer::Stream::Stream()
|
||||
{
|
||||
mResampler8.start(AUDIO_CHANNELS, 8000, AUDIO_SAMPLERATE);
|
||||
mResampler16.start(AUDIO_CHANNELS, 16000, AUDIO_SAMPLERATE);
|
||||
mResampler32.start(AUDIO_CHANNELS, 32000, AUDIO_SAMPLERATE);
|
||||
mResampler48.start(AUDIO_CHANNELS, 48000, AUDIO_SAMPLERATE);
|
||||
mActive = false;
|
||||
mContext = nullptr;
|
||||
mSSRC = 0;
|
||||
mFadeOutCounter = 0;
|
||||
mData.setCapacity(AUDIO_SPK_BUFFER_SIZE * AUDIO_SPK_BUFFER_COUNT);
|
||||
mResampler8.start(AUDIO_CHANNELS, 8000, AUDIO_SAMPLERATE);
|
||||
mResampler16.start(AUDIO_CHANNELS, 16000, AUDIO_SAMPLERATE);
|
||||
mResampler32.start(AUDIO_CHANNELS, 32000, AUDIO_SAMPLERATE);
|
||||
mResampler48.start(AUDIO_CHANNELS, 48000, AUDIO_SAMPLERATE);
|
||||
mActive = false;
|
||||
mContext = nullptr;
|
||||
mSSRC = 0;
|
||||
mFadeOutCounter = 0;
|
||||
mData.setCapacity(AUDIO_SPK_BUFFER_SIZE * AUDIO_SPK_BUFFER_COUNT);
|
||||
}
|
||||
|
||||
Mixer::Stream::~Stream()
|
||||
{
|
||||
}
|
||||
Mixer::Stream::~Stream() {}
|
||||
|
||||
void Mixer::Stream::setSsrc(unsigned ssrc)
|
||||
{
|
||||
mSSRC = ssrc;
|
||||
mSSRC = ssrc;
|
||||
}
|
||||
|
||||
unsigned Mixer::Stream::ssrc()
|
||||
{
|
||||
return mSSRC;
|
||||
return mSSRC;
|
||||
}
|
||||
|
||||
void Mixer::Stream::setContext(void* context)
|
||||
{
|
||||
mContext = context;
|
||||
mContext = context;
|
||||
}
|
||||
void* Mixer::Stream::context()
|
||||
{
|
||||
return mContext;
|
||||
return mContext;
|
||||
}
|
||||
|
||||
DataWindow& Mixer::Stream::data()
|
||||
{
|
||||
return mData;
|
||||
return mData;
|
||||
}
|
||||
|
||||
bool Mixer::Stream::active()
|
||||
{
|
||||
return mActive;
|
||||
return mActive;
|
||||
}
|
||||
|
||||
void Mixer::Stream::setActive(bool active)
|
||||
{
|
||||
mActive = active;
|
||||
mActive = active;
|
||||
}
|
||||
|
||||
void Mixer::Stream::addPcm(int rate, const void* input, int length)
|
||||
{
|
||||
// Resample to internal sample rate
|
||||
size_t outputSize = size_t(0.5 + length * ((float)AUDIO_SAMPLERATE / rate));
|
||||
if (mTempBuffer.size() < outputSize)
|
||||
mTempBuffer.resize(outputSize);
|
||||
|
||||
Resampler* resampler = (rate == 8000) ? &mResampler8 : ((rate == 16000) ? &mResampler16 : ((rate == 32000) ? &mResampler32 : &mResampler48));
|
||||
size_t inputProcessed = 0;
|
||||
resampler->processBuffer(input, length, inputProcessed, mTempBuffer.mutableData(), outputSize);
|
||||
// inputProcessed result value is ignored here - rate will be 8/16/32/48k, inputProcessed is equal to length
|
||||
// Resample to internal sample rate
|
||||
size_t outputSize = size_t(0.5 + length * ((float)AUDIO_SAMPLERATE / rate));
|
||||
if (mTempBuffer.size() < outputSize)
|
||||
mTempBuffer.resize(outputSize);
|
||||
|
||||
// Queue data
|
||||
mData.add(mTempBuffer.data(), outputSize);
|
||||
Resampler* resampler = (rate == 8000)
|
||||
? &mResampler8
|
||||
: ((rate == 16000) ? &mResampler16 : ((rate == 32000) ? &mResampler32 : &mResampler48));
|
||||
size_t inputProcessed = 0;
|
||||
resampler->processBuffer(input, length, inputProcessed, mTempBuffer.mutableData(), outputSize);
|
||||
// inputProcessed result value is ignored here - rate will be 8/16/32/48k, inputProcessed is equal to length
|
||||
|
||||
// Queue data
|
||||
mData.add(mTempBuffer.data(), outputSize);
|
||||
}
|
||||
|
||||
Mixer::Mixer()
|
||||
{
|
||||
mActiveCounter = 0;
|
||||
mOutput.setCapacity(32768);
|
||||
mActiveCounter = 0;
|
||||
mOutput.setCapacity(32768);
|
||||
}
|
||||
|
||||
Mixer::~Mixer()
|
||||
{
|
||||
}
|
||||
Mixer::~Mixer() {}
|
||||
|
||||
void Mixer::unregisterChannel(void* channel)
|
||||
{
|
||||
Lock l(mMutex);
|
||||
for (int i=0; i<AUDIO_MIX_CHANNEL_COUNT; i++)
|
||||
{
|
||||
Stream& c = mChannelList[i];
|
||||
if (c.active() && c.context() == channel)
|
||||
Lock l(mMutex);
|
||||
for (int i = 0; i < AUDIO_MIX_CHANNEL_COUNT; i++)
|
||||
{
|
||||
c.setActive(false); // stream is not active anymore
|
||||
c.data().clear(); // clear data
|
||||
mActiveCounter--;
|
||||
Stream& c = mChannelList[i];
|
||||
if (c.active() && c.context() == channel)
|
||||
{
|
||||
c.setActive(false); // stream is not active anymore
|
||||
c.data().clear(); // clear data
|
||||
mActiveCounter--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mixer::clear(void* context, unsigned ssrc)
|
||||
{
|
||||
Lock l(mMutex);
|
||||
for (int i=0; i<AUDIO_MIX_CHANNEL_COUNT; i++)
|
||||
{
|
||||
Stream& c = mChannelList[i];
|
||||
if (c.active() && c.context() == context && c.ssrc() == ssrc)
|
||||
Lock l(mMutex);
|
||||
for (int i = 0; i < AUDIO_MIX_CHANNEL_COUNT; i++)
|
||||
{
|
||||
c.setActive(false);
|
||||
c.data().clear();
|
||||
mActiveCounter--;
|
||||
Stream& c = mChannelList[i];
|
||||
if (c.active() && c.context() == context && c.ssrc() == ssrc)
|
||||
{
|
||||
c.setActive(false);
|
||||
c.data().clear();
|
||||
mActiveCounter--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Mixer::Stream* Mixer::allocateChannel(void* context, unsigned ssrc)
|
||||
{
|
||||
// Allocate new channel
|
||||
Lock l(mMutex);
|
||||
Stream* channel;
|
||||
for (int i=0; i<AUDIO_MIX_CHANNEL_COUNT;i++)
|
||||
{
|
||||
channel = &mChannelList[i];
|
||||
if (!channel->active())
|
||||
// Allocate new channel
|
||||
Lock l(mMutex);
|
||||
Stream* channel;
|
||||
for (int i = 0; i < AUDIO_MIX_CHANNEL_COUNT; i++)
|
||||
{
|
||||
channel->setSsrc(ssrc);
|
||||
channel->setContext(context);
|
||||
channel->data().clear();
|
||||
mActiveCounter++;
|
||||
channel->setActive(true);
|
||||
return channel;
|
||||
channel = &mChannelList[i];
|
||||
if (!channel->active())
|
||||
{
|
||||
channel->setSsrc(ssrc);
|
||||
channel->setContext(context);
|
||||
channel->data().clear();
|
||||
mActiveCounter++;
|
||||
channel->setActive(true);
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Mixer::addPcm(void* context, unsigned ssrc,
|
||||
const void* inputData, int inputLength,
|
||||
int inputRate, bool fadeOut)
|
||||
void Mixer::addPcm(void* context, unsigned ssrc, const void* inputData, int inputLength, int inputRate, bool fadeOut)
|
||||
{
|
||||
assert(inputRate == 8000 || inputRate == 16000 || inputRate == 32000);
|
||||
assert(inputRate == 8000 || inputRate == 16000 || inputRate == 32000);
|
||||
|
||||
Lock l(mMutex);
|
||||
int i;
|
||||
Lock l(mMutex);
|
||||
int i;
|
||||
|
||||
// Locate a channel
|
||||
Stream* channel = NULL;
|
||||
|
||||
for (i=0; i<AUDIO_MIX_CHANNEL_COUNT && !channel; i++)
|
||||
{
|
||||
Stream& c = mChannelList[i];
|
||||
if (c.active() && c.context() == context && c.ssrc() == ssrc)
|
||||
channel = &c;
|
||||
}
|
||||
if (!channel)
|
||||
{
|
||||
channel = allocateChannel(context, ssrc);
|
||||
// Locate a channel
|
||||
Stream* channel = NULL;
|
||||
|
||||
for (i = 0; i < AUDIO_MIX_CHANNEL_COUNT && !channel; i++)
|
||||
{
|
||||
Stream& c = mChannelList[i];
|
||||
if (c.active() && c.context() == context && c.ssrc() == ssrc)
|
||||
channel = &c;
|
||||
}
|
||||
if (!channel)
|
||||
throw Exception(ERR_MIXER_OVERFLOW);
|
||||
}
|
||||
|
||||
channel->addPcm(inputRate, inputData, inputLength);
|
||||
{
|
||||
channel = allocateChannel(context, ssrc);
|
||||
if (!channel)
|
||||
throw Exception(ERR_MIXER_OVERFLOW);
|
||||
}
|
||||
|
||||
channel->addPcm(inputRate, inputData, inputLength);
|
||||
}
|
||||
|
||||
void Mixer::addPcm(void* context, unsigned ssrc, Audio::DataWindow& w, int rate, bool fadeOut)
|
||||
{
|
||||
assert(rate == 8000 || rate == 16000 || rate == 32000 || rate == 48000);
|
||||
assert(rate == 8000 || rate == 16000 || rate == 32000 || rate == 48000);
|
||||
|
||||
Lock l(mMutex);
|
||||
int i;
|
||||
Lock l(mMutex);
|
||||
int i;
|
||||
|
||||
// Locate a channel
|
||||
Stream* channel = NULL;
|
||||
|
||||
for (i=0; i<AUDIO_MIX_CHANNEL_COUNT && !channel; i++)
|
||||
{
|
||||
Stream& c = mChannelList[i];
|
||||
if (c.active() && c.context() == context && c.ssrc() == ssrc)
|
||||
channel = &c;
|
||||
}
|
||||
if (!channel)
|
||||
{
|
||||
channel = allocateChannel(context, ssrc);
|
||||
// Locate a channel
|
||||
Stream* channel = NULL;
|
||||
|
||||
for (i = 0; i < AUDIO_MIX_CHANNEL_COUNT && !channel; i++)
|
||||
{
|
||||
Stream& c = mChannelList[i];
|
||||
if (c.active() && c.context() == context && c.ssrc() == ssrc)
|
||||
channel = &c;
|
||||
}
|
||||
if (!channel)
|
||||
throw Exception(ERR_MIXER_OVERFLOW);
|
||||
}
|
||||
|
||||
channel->addPcm(rate, w.data(), w.filled());
|
||||
//ICELogSpecial(<<"Mixer stream " << int(this) << " has " << w.filled() << " bytes");
|
||||
{
|
||||
channel = allocateChannel(context, ssrc);
|
||||
if (!channel)
|
||||
throw Exception(ERR_MIXER_OVERFLOW);
|
||||
}
|
||||
|
||||
channel->addPcm(rate, w.data(), w.filled());
|
||||
// ICELogSpecial(<<"Mixer stream " << int(this) << " has " << w.filled() << " bytes");
|
||||
}
|
||||
|
||||
void Mixer::mix()
|
||||
{
|
||||
Lock l(mMutex);
|
||||
Lock l(mMutex);
|
||||
|
||||
// Current sample
|
||||
int sample = 0;
|
||||
// Current sample
|
||||
int sample = 0;
|
||||
|
||||
// Counter of processed active channels
|
||||
int processed = 0;
|
||||
// Counter of processed active channels
|
||||
int processed = 0;
|
||||
|
||||
// Samples & sources counters
|
||||
unsigned sampleCounter = 0, sourceCounter;
|
||||
// Samples & sources counters
|
||||
unsigned sampleCounter = 0, sourceCounter;
|
||||
|
||||
short outputBuffer[512];
|
||||
unsigned outputCounter = 0;
|
||||
short outputBuffer[512];
|
||||
unsigned outputCounter = 0;
|
||||
|
||||
// Build active channel map
|
||||
Stream* channelList[AUDIO_MIX_CHANNEL_COUNT];
|
||||
int activeCounter = 0;
|
||||
for (int i=0; i<AUDIO_MIX_CHANNEL_COUNT; i++)
|
||||
if (mChannelList[i].active())
|
||||
channelList[activeCounter++] = &mChannelList[i];
|
||||
|
||||
// No active channels - nothing to mix - exit
|
||||
if (!activeCounter)
|
||||
{
|
||||
// ICELogDebug(<< "No active channel");
|
||||
return;
|
||||
}
|
||||
|
||||
// Optimized versions for 1& 2 active channels
|
||||
if (activeCounter == 1)
|
||||
{
|
||||
// Copy much samples as we have
|
||||
Stream& audio = *channelList[0];
|
||||
// Build active channel map
|
||||
Stream* channelList[AUDIO_MIX_CHANNEL_COUNT];
|
||||
int activeCounter = 0;
|
||||
for (int i = 0; i < AUDIO_MIX_CHANNEL_COUNT; i++)
|
||||
if (mChannelList[i].active())
|
||||
channelList[activeCounter++] = &mChannelList[i];
|
||||
|
||||
// Copy the decoded data
|
||||
mOutput.add(audio.data().data(), audio.data().filled());
|
||||
|
||||
// Erase copied audio samples
|
||||
audio.data().erase(audio.data().filled());
|
||||
//ICELogSpecial(<<"Length of mixer stream " << audio.data().filled());
|
||||
}
|
||||
else
|
||||
if (activeCounter == 2)
|
||||
{
|
||||
Stream& audio1 = *channelList[0];
|
||||
Stream& audio2 = *channelList[1];
|
||||
int filled1 = audio1.data().filled() / 2, filled2 = audio2.data().filled() / 2;
|
||||
int available = filled1 > filled2 ? filled1 : filled2;
|
||||
|
||||
// Find how much samples can be mixed
|
||||
int filled = mOutput.filled() / 2;
|
||||
|
||||
int maxsize = mOutput.capacity() / 2;
|
||||
if (maxsize - filled < available)
|
||||
available = maxsize - filled;
|
||||
|
||||
short sample = 0;
|
||||
for (int i=0; i<available; i++)
|
||||
{
|
||||
short sample1 = filled1 > i ? audio1.data().shortAt(i) : 0;
|
||||
short sample2 = filled2 > i ? audio2.data().shortAt(i) : 0;
|
||||
sample = (abs(sample1) > abs(sample2)) ? sample1 : sample2;
|
||||
|
||||
mOutput.add(sample);
|
||||
}
|
||||
audio1.data().erase(available*2);
|
||||
audio2.data().erase(available*2);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
// No active channels - nothing to mix - exit
|
||||
if (!activeCounter)
|
||||
{
|
||||
sample = 0;
|
||||
sourceCounter = 0;
|
||||
processed = 0;
|
||||
for (int i=0; i<activeCounter; i++)
|
||||
{
|
||||
Stream& audio = *channelList[i];
|
||||
processed++;
|
||||
// ICELogDebug(<< "No active channel");
|
||||
return;
|
||||
}
|
||||
|
||||
if (audio.data().filled() > (int)sampleCounter * 2)
|
||||
// Optimized versions for 1& 2 active channels
|
||||
if (activeCounter == 1)
|
||||
{
|
||||
// Copy much samples as we have
|
||||
Stream& audio = *channelList[0];
|
||||
|
||||
// Copy the decoded data
|
||||
mOutput.add(audio.data().data(), audio.data().filled());
|
||||
|
||||
// Erase copied audio samples
|
||||
audio.data().erase(audio.data().filled());
|
||||
// ICELogSpecial(<<"Length of mixer stream " << audio.data().filled());
|
||||
}
|
||||
else if (activeCounter == 2)
|
||||
{
|
||||
Stream& audio1 = *channelList[0];
|
||||
Stream& audio2 = *channelList[1];
|
||||
int filled1 = audio1.data().filled() / 2, filled2 = audio2.data().filled() / 2;
|
||||
int available = filled1 > filled2 ? filled1 : filled2;
|
||||
|
||||
// Find how much samples can be mixed
|
||||
int filled = mOutput.filled() / 2;
|
||||
|
||||
int maxsize = mOutput.capacity() / 2;
|
||||
if (maxsize - filled < available)
|
||||
available = maxsize - filled;
|
||||
|
||||
short sample = 0;
|
||||
for (int i = 0; i < available; i++)
|
||||
{
|
||||
short currentSample = audio.data().shortAt(sampleCounter);
|
||||
if (abs(currentSample) > abs(sample))
|
||||
sample = currentSample;
|
||||
sourceCounter++;
|
||||
short sample1 = filled1 > i ? audio1.data().shortAt(i) : 0;
|
||||
short sample2 = filled2 > i ? audio2.data().shortAt(i) : 0;
|
||||
sample = (abs(sample1) > abs(sample2)) ? sample1 : sample2;
|
||||
|
||||
mOutput.add(sample);
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceCounter)
|
||||
{
|
||||
outputBuffer[outputCounter++] = (short)sample;
|
||||
sampleCounter++;
|
||||
}
|
||||
|
||||
// Check if time to flash output buffer
|
||||
if ((!sourceCounter || outputCounter == 512) && outputCounter)
|
||||
{
|
||||
mOutput.add(outputBuffer, outputCounter * 2);
|
||||
outputCounter = 0;
|
||||
}
|
||||
audio1.data().erase(available * 2);
|
||||
audio2.data().erase(available * 2);
|
||||
}
|
||||
while (sourceCounter);
|
||||
|
||||
processed = 0;
|
||||
for (int i=0; i<activeCounter; i++)
|
||||
else
|
||||
{
|
||||
Stream& audio = *channelList[i];
|
||||
audio.data().erase(sampleCounter*2);
|
||||
do
|
||||
{
|
||||
sample = 0;
|
||||
sourceCounter = 0;
|
||||
processed = 0;
|
||||
for (int i = 0; i < activeCounter; i++)
|
||||
{
|
||||
Stream& audio = *channelList[i];
|
||||
processed++;
|
||||
|
||||
if (audio.data().filled() > (int)sampleCounter * 2)
|
||||
{
|
||||
short currentSample = audio.data().shortAt(sampleCounter);
|
||||
if (abs(currentSample) > abs(sample))
|
||||
sample = currentSample;
|
||||
sourceCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceCounter)
|
||||
{
|
||||
outputBuffer[outputCounter++] = (short)sample;
|
||||
sampleCounter++;
|
||||
}
|
||||
|
||||
// Check if time to flash output buffer
|
||||
if ((!sourceCounter || outputCounter == 512) && outputCounter)
|
||||
{
|
||||
mOutput.add(outputBuffer, outputCounter * 2);
|
||||
outputCounter = 0;
|
||||
}
|
||||
} while (sourceCounter);
|
||||
|
||||
processed = 0;
|
||||
for (int i = 0; i < activeCounter; i++)
|
||||
{
|
||||
Stream& audio = *channelList[i];
|
||||
audio.data().erase(sampleCounter * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Mixer::getPcm(void* outputData, int outputLength)
|
||||
{
|
||||
Lock l(mMutex);
|
||||
Lock l(mMutex);
|
||||
|
||||
if (mOutput.filled() < outputLength)
|
||||
mix();
|
||||
if (mOutput.filled() < outputLength)
|
||||
mix();
|
||||
|
||||
//ICELogSpecial(<<"Mixer has " << mOutput.filled() << " available bytes");
|
||||
memset(outputData, 0, outputLength);
|
||||
return mOutput.read(outputData, outputLength);
|
||||
// ICELogSpecial(<<"Mixer has " << mOutput.filled() << " available bytes");
|
||||
memset(outputData, 0, outputLength);
|
||||
return mOutput.read(outputData, outputLength);
|
||||
}
|
||||
|
||||
int Mixer::mixAndGetPcm(Audio::DataWindow& output)
|
||||
{
|
||||
Lock l(mMutex);
|
||||
Lock l(mMutex);
|
||||
|
||||
// Mix
|
||||
mix();
|
||||
// Mix
|
||||
mix();
|
||||
|
||||
size_t avail = mOutput.filled();
|
||||
if (!avail)
|
||||
{
|
||||
output.setFilled(0);
|
||||
return 0;
|
||||
}
|
||||
size_t avail = mOutput.filled();
|
||||
if (!avail)
|
||||
{
|
||||
output.setFilled(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Make sure output has enough space (setCapacity only ever grows the window)
|
||||
if (output.capacity() < avail)
|
||||
output.setCapacity(avail);
|
||||
// Make sure output has enough space (setCapacity only ever grows the window)
|
||||
if (output.capacity() < avail)
|
||||
output.setCapacity(avail);
|
||||
|
||||
// Read mixed data to output and publish the real byte count
|
||||
size_t got = mOutput.read(output.mutableData(), avail);
|
||||
output.setFilled(got);
|
||||
return static_cast<int>(got);
|
||||
// Read mixed data to output and publish the real byte count
|
||||
size_t got = mOutput.read(output.mutableData(), avail);
|
||||
output.setFilled(got);
|
||||
return static_cast<int>(got);
|
||||
}
|
||||
|
||||
int Mixer::available()
|
||||
{
|
||||
return mOutput.filled();
|
||||
return mOutput.filled();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user