// FixedSizeAudioBuffer.cpp: implementation of the FixedSizeAudioBuffer class.
|
//
|
//////////////////////////////////////////////////////////////////////
|
|
#include "FixedSizeAudioBuffer.h"
|
#include "AudioSample.h"
|
#include "AudioSampleManager.h"
|
|
using namespace std;
|
|
//////////////////////////////////////////////////////////////////////
|
// Construction/Destruction
|
//////////////////////////////////////////////////////////////////////
|
|
FixedSizeAudioBuffer::FixedSizeAudioBuffer()
|
{
|
char subFacilityName[100];
|
sprintf(subFacilityName, "FixedSizeAudioBuffer:%x", this);
|
tracer.SetSubFacilityName(subFacilityName);
|
SetTraceLevel();
|
outputDuration = 20;
|
minFrameSize = 1;
|
minFrameDuration = 1;
|
outputSize = 1000; // any high number
|
bRunning = false;
|
InitializeCriticalSection(&audioBufferMutex);
|
}
|
|
FixedSizeAudioBuffer::~FixedSizeAudioBuffer()
|
{
|
DeleteCriticalSection(&audioBufferMutex);
|
}
|
|
int
|
FixedSizeAudioBuffer::SetTraceLevel()
|
{
|
long SystemMask = 0;
|
if ((SystemMask = GetRegKeyLong(HKEY_CURRENT_USER, "Software\\Cisco Systems\\MTC\\Tracing", "AllComponents", 0x0)) == 0)
|
{
|
SystemMask = GetRegKeyLong(HKEY_CURRENT_USER, "Software\\Cisco Systems\\MTC\\Tracing", "FixedSizeAudioBuffer", 0x100000);
|
}
|
tracer.SetSystemMask(SystemMask);
|
return 0;
|
}
|
|
int
|
FixedSizeAudioBuffer::SetOutputDuration(int duration)
|
{
|
outputDuration = duration;
|
return 0;
|
}
|
|
int
|
FixedSizeAudioBuffer::EnqueuePacket(std::vector<std::pair<AudioSample *, AudioSource *> > &data)
|
{
|
AudioSample *audioSample = NULL;
|
if (data.size() > 0)
|
{
|
audioSample = data[0].first;
|
}
|
if (audioSample)
|
{
|
minFrameDuration = audioSample->MinFrameDuration();
|
minFrameSize = audioSample->MinFrameSize();
|
audioSample->GetFormat(&audioFormat);
|
outputSize = (outputDuration * 1000 * minFrameSize) / minFrameDuration;
|
if (audioSample->DataSize() > 0)
|
{
|
EnterCriticalSection(&audioBufferMutex);
|
audioBuffer.insert(audioBuffer.end(), audioSample->Data(), audioSample->Data() + audioSample->DataSize());
|
LeaveCriticalSection(&audioBufferMutex);
|
}
|
else if (audioSample->GetSilenceDuration() > 0)
|
{
|
EnterCriticalSection(&audioBufferMutex);
|
for (int i=0; i<audioSample->SilenceSize(); i++)
|
{
|
audioBuffer.push_back(0);
|
}
|
LeaveCriticalSection(&audioBufferMutex);
|
}
|
}
|
else
|
{
|
tracer.tracef(ERR, "EnquePacket : asked to enqueue NULL packet\n");
|
Sleep(5);
|
}
|
return 0;
|
}
|
|
int
|
FixedSizeAudioBuffer::TransformStarted()
|
{
|
EnterCriticalSection(&audioBufferMutex);
|
audioBuffer.clear();
|
audioFormat = WaveFormat::GetWaveFormat(WaveFormat_PCM_16_8_1);
|
LeaveCriticalSection(&audioBufferMutex);
|
bRunning = true;
|
return 0;
|
}
|
|
int
|
FixedSizeAudioBuffer::TransformStopped()
|
{
|
bRunning = false;
|
return 0;
|
}
|
|
int
|
FixedSizeAudioBuffer::RenderAudioSamples(std::vector<std::pair<AudioSample *, AudioSource *> > &data)
|
{
|
if (bRunning)
|
{
|
EnqueuePacket(data);
|
int outputSize = (outputDuration * 1000 * minFrameSize) / minFrameDuration;
|
EnterCriticalSection(&audioBufferMutex);
|
while (audioBuffer.size() >= outputSize)
|
{
|
AudioSample *outputSample = NULL;
|
(AudioSampleManager::GetInstance())->GetAudioSample(&outputSample, this);
|
outputSample->SetFormat(audioFormat);
|
char *outputData = outputSample->Data();
|
for (int i=0; i<outputSize; i++)
|
{
|
*outputData = audioBuffer[0];
|
audioBuffer.erase(audioBuffer.begin());
|
}
|
outputSample->SetDataSize(outputSize);
|
EnterCriticalSection(&audioSinksMutex);
|
std::vector<AudioSink *>::iterator iter;
|
for (iter = audioSinks.begin(); iter != audioSinks.end(); iter++)
|
{
|
SendAudioSample(outputSample, *iter);
|
}
|
LeaveCriticalSection(&audioSinksMutex);
|
outputSample->Release(this);
|
outputSample = NULL;
|
}
|
LeaveCriticalSection(&audioBufferMutex);
|
}
|
return 0;
|
}
|
|
int
|
FixedSizeAudioBuffer::GenerateData(AudioSample **ppAudioSample)
|
{
|
tracer.tracef(DET, "GenerateData\n");
|
tracer.tracef(DET, "GenerateData : filling data\n");
|
int result(0);
|
*ppAudioSample = NULL;
|
while(audioBuffer.size() < outputSize)
|
{
|
tracer.tracef(DET, "GenerateData : audioBuffer.size = %d, outputSize = %d\n", audioBuffer.size(), outputSize);
|
if (!bRunning)
|
{
|
break;
|
}
|
// get data from all sources
|
inputData.clear();
|
EnterCriticalSection(&audioSourcesMutex);
|
vector<AudioSource *>::iterator iter = audioSources.begin();
|
for (iter = audioSources.begin(); iter != audioSources.end(); iter++)
|
{
|
AudioSample *pAudioSample = NULL;
|
// tracer.tracef(DET, "GenerateData : calling GiveNextAudioSample\n");
|
result = (*iter)->GiveNextAudioSample(&pAudioSample, this);
|
if (result != 0)
|
{
|
if (pAudioSample)
|
{
|
pAudioSample->Release(this);
|
pAudioSample = NULL;
|
}
|
}
|
else
|
{
|
if (pAudioSample)
|
{
|
inputData.push_back(make_pair(pAudioSample, *iter));
|
}
|
}
|
}
|
LeaveCriticalSection(&audioSourcesMutex);
|
|
// add the data to the queue
|
EnqueuePacket(inputData);
|
|
// release all the input samples
|
// (since they were obtained by GiveNextAudioSample, they will not be released by the corresponding source
|
for (int i = 0; i < inputData.size(); i++)
|
{
|
AudioSample *sample = (inputData[i]).first;
|
if (sample)
|
{
|
sample->Release(this);
|
sample = NULL;
|
}
|
}
|
}
|
tracer.tracef(DET, "GenerateData : transmitting data\n");
|
if (bRunning && audioBuffer.size() >= outputSize)
|
{
|
AudioSample *outputSample = NULL;
|
(AudioSampleManager::GetInstance())->GetAudioSample(&outputSample, this);
|
outputSample->SetFormat(audioFormat);
|
char *outputData = outputSample->Data();
|
for (int i=0; i<outputSize; i++)
|
{
|
*outputData = audioBuffer[0];
|
outputData++;
|
audioBuffer.erase(audioBuffer.begin());
|
}
|
outputSample->SetDataSize(outputSize);
|
*ppAudioSample = outputSample;
|
}
|
if (*ppAudioSample == NULL)
|
{
|
(AudioSampleManager::GetInstance())->GetAudioSample(ppAudioSample, this);
|
(*ppAudioSample)->SetFormat(audioFormat);
|
(*ppAudioSample)->SetDataSize(0);
|
(*ppAudioSample)->SetSilenceDuration(outputDuration);
|
}
|
tracer.tracef(DET, "~GenerateData\n");
|
return 0;
|
}
|
|
int
|
FixedSizeAudioBuffer::TransformAudioSamples(std::vector<std::pair<AudioSample *, AudioSource *> > &data, AudioSample **ppAudioSample)
|
{
|
return 0;
|
}
|