Aufgrund einer Wartung wird GitLab am 19.10. zwischen 8:00 und 9:00 Uhr kurzzeitig nicht zur Verfügung stehen. / Due to maintenance, GitLab will be temporarily unavailable on 19.10. between 8:00 and 9:00 am.

Commit d84daa74 authored by Dipl.-Ing. Jonas Stienen's avatar Dipl.-Ing. Jonas Stienen
Browse files

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,44 +12,51 @@
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);
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);
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;
......@@ -57,26 +64,26 @@ public:
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
......@@ -89,25 +96,30 @@ private:
inline Chunk( int iChannels, int iCapacity )
: m_sfSamples( iChannels, iCapacity, false )
, m_vpfData(iChannels)
, m_iTail(0)
, 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('='));
std::string t = s.substr( 0, s.find_first_of( '=' ) );
if (!t.empty()) vsResult.push_back(t);
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];
char buf[ MAX_VALUE_STRING_LENGTH ];
GetPrivateProfileStringA(sSection.c_str(),
GetPrivateProfileStringA( sSection.c_str(),
sKey.c_str(),
sDefaultValue.c_str(),
(LPSTR) buf,
(DWORD) MAX_VALUE_STRING_LENGTH,
FixPath(sINIFilename).c_str());
( LPSTR ) buf,
( DWORD ) MAX_VALUE_STRING_LENGTH,
FixPath( sINIFilename ).c_str() );
return std::string(buf);
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(),
std::string s( " " );
s.append( sValue );
return ( WritePrivateProfileStringA( sSection.c_str(),
sKey.c_str(),
s.c_str(),
FixPath(sINIFilename).c_str()) == TRUE);
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