Select Git revision
ITABufferedAudioFileWriter.cpp

Dipl.-Ing. Jonas Stienen authored
Switching from unsigned int to all in. Max WAV file size now 2GB instead of 4GB. Fixing painful implicit conversion of ITADomain and ITAQuantization (was simple enum) to enum classes (can not be converted implicitly, i.e. by false function call).
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 );
}