#include #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(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(); segment->channelCount = this->channelCount; segment->sampleSize = this->segmentSize; segment->full = true; auto bufLen = this->segmentSize * this->channelCount * sizeof(float); segment->samples = static_cast(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(); segment->channelCount = this->channelCount; segment->sampleSize = overhead; segment->full = false; auto bufLen = overhead * this->channelCount * sizeof(float); segment->samples = static_cast(malloc(bufLen)); memcpy(segment->samples, &pcm[pcmIndex], bufLen); this->segments.push_back(segment); } } std::shared_ptr 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; }