Cleanup, refactoring and changing buffered audio file writer behaviour to...

Cleanup, refactoring and changing buffered audio file writer behaviour to enable lazy file path setting
parent 76518819
......@@ -22,6 +22,7 @@
#include <ITABaseDefinitions.h>
#include <ITAAudiofileWriter.h>
//! Audio file writer that first buffers samples and exports on demand or destruction
/**
* Klasse welche Schreiber von Audiodateien um Pufferung erweitert.
* Dies ist u.A. wichtig in der Echtzeit-Verarbeitung, wobei keine
......@@ -34,15 +35,25 @@
* werden. Wird diese Aufgebraucht, wird der Puffer automatisch um die
* angegebene Wachstumsgröße erweitert.
*/
class ITA_BASE_API ITABufferedAudiofileWriter : public ITAAudiofileWriter
{
public:
//! Factory method. Erzeugt einen gepufferten Schreiber.
static ITABufferedAudiofileWriter* create(const std::string& sFilename,
const ITAAudiofileProperties& props,
double dInitialBufferSizeSeconds=60,
double dGrowBufferSizeSeconds=20);
static ITABufferedAudiofileWriter* create( const ITAAudiofileProperties& props, double dInitialBufferSizeSeconds = 60, double dGrowBufferSizeSeconds = 20 );
//! Returns current file path or empty string
/**
* @return Current file path or empty string
*
*/
virtual std::string GetFilePath() const = 0;
//! Sets the export file path (without any checks)
/**
* @param[in] sFilePath File path (make sure base folder exists)
*
*/
virtual void SetFilePath( const std::string& sFilePath ) = 0;
};
#endif // INCLUDE_WATCHER_ITA_BUFFERED_AUDIO_FILE_WRITER
......@@ -12,71 +12,78 @@
class ITABufferedAudiofileWriterImpl : public ITABufferedAudiofileWriter
{
public:
inline ITABufferedAudiofileWriterImpl( const std::string& sFilePath,
const ITAAudiofileProperties& props,
double dInitialBufferSizeSeconds,
double dGrowBufferSizeSeconds )
inline ITABufferedAudiofileWriterImpl( const ITAAudiofileProperties& props, double dInitialBufferSizeSeconds, double dGrowBufferSizeSeconds )
: m_pWriter( NULL )
, m_oProps( props )
{
// 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_iInitialBufferSizeSamples = ( int ) ceil( dInitialBufferSizeSeconds*props.dSampleRate );
m_iGrowBufferSizeSamples = ( int ) ceil( dGrowBufferSizeSeconds*props.dSampleRate );
m_lpChunks.push_back( new Chunk( (int) props.iChannels, m_iInitialBufferSizeSamples ) );
}
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);
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 void SetFilePath( const std::string& sFilePath )
{
delete m_pWriter;
m_pWriter = ITAAudiofileWriter::create( sFilePath, m_oProps );
m_sFilePath = sFilePath;
};
inline std::string GetFilePath() const
{
return m_sFilePath;
};
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( ( 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) {
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 );
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) );
if( iRemain > 0 ) {
m_lpChunks.push_back( new Chunk( iChannels, m_iGrowBufferSizeSamples ) );
}
}
}
};
private:
// Interner Speicherblock für Samples
......@@ -88,26 +95,31 @@ private:
int m_iTail;
inline Chunk( int iChannels, int iCapacity )
: m_sfSamples( iChannels, iCapacity, false )
, m_vpfData(iChannels)
, m_iTail(0)
: 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();
for( int i = 0; i < iChannels; i++ )
m_vpfData[ i ] = m_sfSamples[ i ].GetData();
}
};
ITAAudiofileWriter* m_pWriter;
std::string m_sFilePath;
std::list<Chunk*> m_lpChunks;
int m_iInitialBufferSizeSamples;
int m_iGrowBufferSizeSamples;
const ITAAudiofileProperties m_oProps;
//! Copy protection
inline ITABufferedAudiofileWriterImpl& operator=( ITABufferedAudiofileWriterImpl& )
{
ITA_EXCEPT_NOT_IMPLEMENTED;
};
};
ITABufferedAudiofileWriter* ITABufferedAudiofileWriter::create(const std::string& sFilePath,
const ITAAudiofileProperties& props,
double dInitialBufferSizeSeconds,
double dGrowBufferSizeSeconds)
ITABufferedAudiofileWriter* ITABufferedAudiofileWriter::create( const ITAAudiofileProperties& props, double dInitialBufferSizeSeconds, double dGrowBufferSizeSeconds )
{
return new ITABufferedAudiofileWriterImpl( sFilePath, props, dInitialBufferSizeSeconds, dGrowBufferSizeSeconds );
return new ITABufferedAudiofileWriterImpl( props, dInitialBufferSizeSeconds, dGrowBufferSizeSeconds );
}
......@@ -33,7 +33,8 @@ bool INIFileKeyExists( const std::string& sINIFilename, const std::string& sSect
return false;
}
void INIFileUseFile( const std::string& sINIFilename ) {
void INIFileUseFile( const std::string& sINIFilename )
{
// Sicherstellen das die INI-Datei existiert
// [fwe 2008-11-07] Bugfix, baby! Das geht beim reinen Schreiben nicht: INIFileRequireINIFile(sINIFilename);
......@@ -478,11 +479,13 @@ bool INIFileWriteStringList( const std::string& sINIFilename,
* | |
* +-----------------------------------------------------------------------------------------+ */
bool INIFileSectionExists( const std::string& sSection ) {
bool INIFileSectionExists( const std::string& sSection )
{
return INIFileSectionExists( sCurrentINIFile, sSection );
}
std::vector<std::string> INIFileGetSections() {
std::vector<std::string> INIFileGetSections()
{
return INIFileGetSections( sCurrentINIFile );
}
......@@ -530,39 +533,48 @@ bool INIFileReadBool( const std::string& sKey, bool bDefaultValue ) {
return INIFileReadBool( sCurrentINIFile, sCurrentSection, sKey, bDefaultValue );
}
std::string INIFileReadString( const std::string& sKey, std::string sDefaultValue ) {
std::string INIFileReadString( const std::string& sKey, std::string sDefaultValue )
{
return INIFileReadString( sCurrentINIFile, sCurrentSection, sKey, sDefaultValue );
}
std::vector<int> INIFileReadIntList( const std::string& sKey, char cSeparator ) {
std::vector<int> INIFileReadIntList( const std::string& sKey, char cSeparator )
{
return INIFileReadIntList( sCurrentINIFile, sCurrentSection, sKey, cSeparator );
}
std::vector<unsigned int> INIFileReadUIntList( const std::string& sKey, char cSeparator ) {
std::vector<unsigned int> INIFileReadUIntList( const std::string& sKey, char cSeparator )
{
return INIFileReadUIntList( sCurrentINIFile, sCurrentSection, sKey, cSeparator );
}
std::vector<float> INIFileReadFloatList( const std::string& sKey, char cSeparator ) {
std::vector<float> INIFileReadFloatList( const std::string& sKey, char cSeparator )
{
return INIFileReadFloatList( sCurrentINIFile, sCurrentSection, sKey, cSeparator );
}
std::vector<double> INIFileReadDoubleList( const std::string& sKey, char cSeparator ) {
std::vector<double> INIFileReadDoubleList( const std::string& sKey, char cSeparator )
{
return INIFileReadDoubleList( sCurrentINIFile, sCurrentSection, sKey, cSeparator );
}
std::vector<std::string> INIFileReadStringList( const std::string& sKey, char cSeparator ) {
std::vector<std::string> INIFileReadStringList( const std::string& sKey, char cSeparator )
{
return INIFileReadStringList( sCurrentINIFile, sCurrentSection, sKey, cSeparator );
}
int INIFileReadIntExplicit( const std::string& sKey ) {
int INIFileReadIntExplicit( const std::string& sKey )
{
return INIFileReadIntExplicit( sCurrentINIFile, sCurrentSection, sKey );
}
unsigned int INIFileReadUIntExplicit( const std::string& sKey ) {
unsigned int INIFileReadUIntExplicit( const std::string& sKey )
{
return INIFileReadUIntExplicit( sCurrentINIFile, sCurrentSection, sKey );
}
long INIFileReadLongExplicit( const std::string& sKey ) {
long INIFileReadLongExplicit( const std::string& sKey )
{
return INIFileReadLongExplicit( sCurrentINIFile, sCurrentSection, sKey );
}
......
......@@ -25,85 +25,92 @@ std::string FixPath( const std::string& sPath )
return std::string( "." ) + PATH_SEPARATOR + sPath;
}
std::vector<std::string> INIFileGetSections(const std::string& sINIFilename) {
std::vector<std::string> INIFileGetSections( const std::string& sINIFilename )
{
// [fwe: Bugfix 2008-09-09] Sicherstellen das die Datei berhaupt existiert
INIFileRequireINIFile(sINIFilename);
INIFileRequireINIFile( sINIFilename );
// fwe: Insgesamt 64k Zeichen fr die Liste der Sektionsnamen
// sollte fr die meisten Anwendungen reichen
const unsigned int SECTION_NAME_BUFFER_SIZE = 65536;
char buf[SECTION_NAME_BUFFER_SIZE];
char buf[ SECTION_NAME_BUFFER_SIZE ];
std::vector<std::string> vsResult;
if (GetPrivateProfileSectionNamesA(buf, SECTION_NAME_BUFFER_SIZE, FixPath(sINIFilename).c_str()) > 0) {
if( GetPrivateProfileSectionNamesA( buf, SECTION_NAME_BUFFER_SIZE, FixPath( sINIFilename ).c_str() ) > 0 )
{
char* p = buf;
unsigned int l;
while ((l = (unsigned int) strlen(p)) > 0) {
vsResult.push_back(p);
p += l+1;
while( ( l = ( unsigned int ) strlen( p ) ) > 0 ) {
vsResult.push_back( p );
p += l + 1;
}
}
return vsResult;
}
std::vector<std::string> INIFileGetKeys(const std::string& sINIFilename, const std::string& sSection) {
std::vector<std::string> INIFileGetKeys( const std::string& sINIFilename, const std::string& sSection )
{
// [fwe: Bugfix 2008-09-09] Sicherstellen das die Datei berhaupt existiert
INIFileRequireINIFile(sINIFilename);
INIFileRequireINIFile( sINIFilename );
// fwe: Insgesamt 64k Zeichen fr die Liste der Sektionsnamen
// sollte fr die meisten Anwendungen reichen
const unsigned int SECTION_BUFFER_SIZE = 65536;
char buf[SECTION_BUFFER_SIZE];
char buf[ SECTION_BUFFER_SIZE ];
std::vector<std::string> vsResult;
if (GetPrivateProfileSectionA(sSection.c_str(), buf, SECTION_BUFFER_SIZE, FixPath(sINIFilename).c_str()) > 0) {
if( GetPrivateProfileSectionA( sSection.c_str(), buf, SECTION_BUFFER_SIZE, FixPath( sINIFilename ).c_str() ) > 0 )
{
char* p = buf;
unsigned int l;
while ((l = (unsigned int) strlen(p)) > 0) {
while( ( l = ( unsigned int ) strlen( p ) ) > 0 )
{
std::string s = p;
// Windows macht einen Fehler und gibt hier auch auskommentierte Schlssel zurck. Deshalb Filtern:
if (s[0] != '#') {
if( s[ 0 ] != '#' ) {
// Gleichheitszeichen suchen
std::string t = s.substr(0, s.find_first_of('='));
if (!t.empty()) vsResult.push_back(t);
std::string t = s.substr( 0, s.find_first_of( '=' ) );
if( !t.empty() ) vsResult.push_back( t );
}
p += l+1;
p += l + 1;
}
}
return vsResult;
}
std::string INIFileReadString(const std::string& sINIFilename, const std::string& sSection, const std::string& sKey, std::string sDefaultValue) {
std::string INIFileReadString( const std::string& sINIFilename, const std::string& sSection, const std::string& sKey, std::string sDefaultValue )
{
// Sicherstellen das die INI-Datei existiert
INIFileRequireINIFile(sINIFilename);
INIFileRequireINIFile( sINIFilename );
// Zeichenpuffer
char buf[MAX_VALUE_STRING_LENGTH];
GetPrivateProfileStringA(sSection.c_str(),
sKey.c_str(),
sDefaultValue.c_str(),
(LPSTR) buf,
(DWORD) MAX_VALUE_STRING_LENGTH,
FixPath(sINIFilename).c_str());
return std::string(buf);
char buf[ MAX_VALUE_STRING_LENGTH ];
GetPrivateProfileStringA( sSection.c_str(),
sKey.c_str(),
sDefaultValue.c_str(),
( LPSTR ) buf,
( DWORD ) MAX_VALUE_STRING_LENGTH,
FixPath( sINIFilename ).c_str() );
return std::string( buf );
}
bool INIFileWriteString(const std::string& sINIFilename, const std::string& sSection, const std::string& sKey, const std::string& sValue) {
bool INIFileWriteString( const std::string& sINIFilename, const std::string& sSection, const std::string& sKey, const std::string& sValue )
{
// [fwe 2011-06-14] Improvement: Put a whitespace after the = in the file. Looks much nicer ;-)
std::string s(" ");
s.append(sValue);
return (WritePrivateProfileStringA(sSection.c_str(),
sKey.c_str(),
s.c_str(),
FixPath(sINIFilename).c_str()) == TRUE);
std::string s( " " );
s.append( sValue );
return ( WritePrivateProfileStringA( sSection.c_str(),
sKey.c_str(),
s.c_str(),
FixPath( sINIFilename ).c_str() ) == TRUE );
}
#endif // _WIN32
......
......@@ -17,6 +17,16 @@ vista_create_default_info_file( ITAStringUtilsTest )
set_property( TARGET ITAStringUtilsTest PROPERTY FOLDER "ITACoreLibs/Tests/ITABase" )
add_executable( ConfigUtilsTest ConfigUtilsTest.cpp )
target_link_libraries( ConfigUtilsTest ${VISTA_USE_PACKAGE_LIBRARIES} )
vista_configure_app( ConfigUtilsTest )
vista_install( ConfigUtilsTest )
vista_create_default_info_file( ConfigUtilsTest )
set_property( TARGET ConfigUtilsTest PROPERTY FOLDER "ITACoreLibs/Tests/ITABase" )
add_executable( ITABaseSampleBufferTest ITABaseSampleBufferTest.cpp )
target_link_libraries( ITABaseSampleBufferTest ${VISTA_USE_PACKAGE_LIBRARIES} )
......
#include <ITAConfigUtils.h>
#include <iostream>
using namespace std;
int main( int nArgsIn, char** pccArgs )
{
if( nArgsIn > 1 )
INIFileUseFile( std::string( pccArgs[ 1 ] ) );
else
INIFileUseFile( "ConfigUtilsTest.ini" );
auto sections = INIFileGetSections();
for( auto section : sections )
{
cout << section << endl;
INIFileUseSection( section );
auto keys = INIFileGetKeys( section );
for( auto key : keys )
cout << " + " << key << "\t'" << INIFileReadString( key ) << "' [STRING] " << endl;
}
return 0;
}
#
# ConfigUtilsTest
#
[ff]
enabled1 = true
enabled2 = 1
enabled3 = false
[a:b]
enabled = true
[a:c]
enabled = false
[d:x]
enabled = true
[dd]
enabled = true
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment