Teaspeak-Server/server/src/client/web/SampleHandler.cpp

71 lines
2.7 KiB
C++

#include <cstring>
#include "SampleHandler.h"
using namespace std;
using namespace ts;
using namespace ts::sound;
SampleConverter::SampleConverter(size_t channelCount, size_t segmentSize) : channelCount(channelCount), segmentSize(segmentSize) { }
SampleConverter::~SampleConverter() = default;
void SampleConverter::pushSamples(float* pcm, size_t size) {
threads::MutexLock l(this->segmentLock);
size_t pcmIndex = 0;
if(!this->segments.empty()) {
if(!this->segments.back()->full) {
auto& last = this->segments.back();
if(last->sampleSize < this->segmentSize) { //Enought space
size_t pcmWrites = min(this->segmentSize - last->sampleSize, size);
auto buffer = static_cast<float *>(malloc(this->segmentSize * this->channelCount * sizeof(float)));
memcpy(buffer, last->samples, last->channelCount * last->sampleSize * sizeof(float));
free(last->samples);
memcpy((void*) &buffer[last->channelCount * last->sampleSize], pcm, pcmWrites * this->channelCount * sizeof(float));
pcmIndex += this->channelCount * pcmWrites;
last->sampleSize += pcmWrites * this->channelCount;
last->samples = buffer;
last->full = last->sampleSize == this->segmentSize;
}
}
}
while(size - (pcmIndex / this->channelCount) > this->segmentSize) {
auto segment = make_shared<SampleSegment>();
segment->channelCount = this->channelCount;
segment->sampleSize = this->segmentSize;
segment->full = true;
auto bufLen = this->segmentSize * this->channelCount * sizeof(float);
segment->samples = static_cast<float *>(malloc(bufLen));
memcpy(segment->samples, &pcm[pcmIndex], bufLen);
pcmIndex += bufLen / sizeof(float);
this->segments.push_back(segment);
}
auto overhead = size - (pcmIndex / this->channelCount);
if(overhead > 0){
auto segment = make_shared<SampleSegment>();
segment->channelCount = this->channelCount;
segment->sampleSize = overhead;
segment->full = false;
auto bufLen = overhead * this->channelCount * sizeof(float);
segment->samples = static_cast<float *>(malloc(bufLen));
memcpy(segment->samples, &pcm[pcmIndex], bufLen);
this->segments.push_back(segment);
}
}
std::shared_ptr<SampleSegment> SampleConverter::nextSegment() {
threads::MutexLock l(this->segmentLock);
if(this->segments.empty()) return nullptr;
if(!this->segments.front()->full && this->segments.size() == 1) return nullptr;
auto elm = std::move(this->segments.front());
this->segments.pop_front();
return elm;
}