Select Git revision
ExperimentsRandomTestsVarSystemFixedAcceptanceRatioFixedTestSize.java
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ITABufferedAudioFileWriter.cpp 3.20 KiB
#include <ITABufferedAudioFileWriter.h>
#include <ITAException.h>
#include <ITASampleFrame.h>
#include <algorithm>
#include <list>
#include <algorithm>
#include <math.h>
class ITABufferedAudiofileWriterImpl : public ITABufferedAudiofileWriter
{
public:
inline ITABufferedAudiofileWriterImpl( const std::string& sFilePath,
const ITAAudiofileProperties& props,
double dInitialBufferSizeSeconds,
double dGrowBufferSizeSeconds )
: m_pWriter( NULL )
{
// Zunächst versuchen den regulären (ungepufferten) Schreiber aufzusetzen
m_pWriter = ITAAudiofileWriter::create( sFilePath, props );
// Initialen Chunk anlegen
m_iInitialBufferSizeSamples = (int) ceil( dInitialBufferSizeSeconds*props.dSampleRate );
m_iGrowBufferSizeSamples = (int) ceil( dGrowBufferSizeSeconds*props.dSampleRate );
m_lpChunks.push_back( new Chunk( (int) props.iChannels, m_iInitialBufferSizeSamples ) );
}
inline virtual ~ITABufferedAudiofileWriterImpl()
{
// Alle Chunks schreiben und freigeben
for (std::list<Chunk*>::iterator it=m_lpChunks.begin(); it!=m_lpChunks.end(); ++it) {
Chunk* pChunk = (*it);
if (m_pWriter && (pChunk->m_iTail > 0))
m_pWriter->write(pChunk->m_iTail, pChunk->m_vpfData);
delete pChunk;
}
// Schreiber freigeben
delete m_pWriter;
}
inline virtual void write( int iLength, std::vector<const float*> vpfSource )
{
// Korrekte Anzahl Kanäle
int iChannels = m_lpChunks.back()->m_sfSamples.channels();
if ((int) vpfSource.size() != iChannels)
ITA_EXCEPT1(INVALID_PARAMETER, "Wrong number of channels in source data");
if( iLength == 0 ) return;
int iWritten = 0;
int iTotal = iLength;
int iRemain = iTotal;
while (iWritten < iTotal) {
Chunk* pTailChunk = m_lpChunks.back();
// Soviel in diesen Chunk schreiben wie möglich
int iChunkRemain = pTailChunk->m_sfSamples.length() - pTailChunk->m_iTail;
int iCount = std::min( iRemain, iChunkRemain );
for (int i=0; i<iChannels; i++)
pTailChunk->m_sfSamples[i].write( vpfSource[i], iCount, pTailChunk->m_iTail );
pTailChunk->m_iTail += iCount;
iWritten += iCount;
iRemain = iTotal - iWritten;
// Neuen Chunk anlegen, falls noch Daten zu schreiben ...
if (iRemain > 0) {
m_lpChunks.push_back( new Chunk( iChannels, m_iGrowBufferSizeSamples) );
}
}
}
private:
// Interner Speicherblock für Samples
class Chunk
{
public:
ITASampleFrame m_sfSamples;
std::vector<float*> m_vpfData; // Zugriffszeiger auf Kanaldaten (für den Writer)
int m_iTail;
inline Chunk( int iChannels, int iCapacity )
: m_sfSamples( iChannels, iCapacity, false )
, m_vpfData(iChannels)
, m_iTail(0)
{
for( int i=0; i<iChannels; i++ )
m_vpfData[i] = m_sfSamples[i].GetData();
}
};
ITAAudiofileWriter* m_pWriter;
std::list<Chunk*> m_lpChunks;
int m_iInitialBufferSizeSamples;
int m_iGrowBufferSizeSamples;
};
ITABufferedAudiofileWriter* ITABufferedAudiofileWriter::create(const std::string& sFilePath,
const ITAAudiofileProperties& props,
double dInitialBufferSizeSeconds,
double dGrowBufferSizeSeconds)
{
return new ITABufferedAudiofileWriterImpl( sFilePath, props, dInitialBufferSizeSeconds, dGrowBufferSizeSeconds );
}