Commit ba8d2e8c authored by Marco Berzborn's avatar Marco Berzborn

Merge branch 'develop' into mbe

parents 39b7e4ad 5cf382ae
...@@ -26,4 +26,3 @@ svnaccess ...@@ -26,4 +26,3 @@ svnaccess
*.lib *.lib
*.exp *.exp
*.log *.log
*.txt
## ITADataSources ## ITADataSources
ITADataSources is a C++ library for component-oriented audio streaming providing basic modules to manipulate samples in a block-based audio processing. ITADataSources is a C++ library for component-oriented audio streaming providing basic modules to manipulate samples in a block-based audio processing.
It is marked deprecated because it will be substituted by the module-base [ITAStreaming](https://git.rwth-aachen.de/ita/ITAStreaming) project in the future, but is still heavily used and updated. In future it may be substituted by the new module-base [ITAStreaming](https://git.rwth-aachen.de/ita/ITAStreaming) project, but is still heavily used and therefore also updated.
ITADataSources is a component from [ITACoreLibs](https://git.rwth-aachen.de/ita/ITACoreLibs), a collection of C++ libraries for virtual acoustics. ITADataSources is a component of [ITACoreLibs](https://git.rwth-aachen.de/ita/ITACoreLibs), a collection of C++ libraries for virtual acoustics.
### License ### License
See [LICENSE](LICENSE.md) file. Copyright 2015-2017 Institute of Technical Acoustics, RWTH Aachen University
Licensed under the Apache License, Version 2.0 (the "License");
you may not use files of this project except in compliance with the License.
You may obtain a copy of the License at
<http://www.apache.org/licenses/LICENSE-2.0>
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
### Quick build guide ### Quick build guide
Follow instructions from Wiki pages of [ITABase](https://git.rwth-aachen.de/ita/ITABase/wikis/home) project. It is recommended to clone and follow the build guide of the parent project [ITACoreLibs](https://git.rwth-aachen.de/ita/ITACoreLibs/wikis/home), which includes this project as a submodule.
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#define INCLUDE_WATCHER_ITA_BUFFER_DATA_SOURCE #define INCLUDE_WATCHER_ITA_BUFFER_DATA_SOURCE
#include <ITADataSourcesDefinitions.h> #include <ITADataSourcesDefinitions.h>
#include <ITADataSource.h> #include <ITADataSource.h>
#include <ITAAtomicPrimitives.h> #include <ITAAtomicPrimitives.h>
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
* legt ITABufferDatasource die Kapazität als nächstkleineres Blocklänge-Vielfaches * legt ITABufferDatasource die Kapazität als nächstkleineres Blocklänge-Vielfaches
* der Buffergröße (uiBufferSize) fest. * der Buffergröße (uiBufferSize) fest.
* *
* Die Klasse bietet ferner die Möglichkeit einen bestimmten Bereich der Puffer * Die Klasse bietet ferner die Möglichkeit einen bestimmten Bereich der Puffer
* für das Freisetzen der Audiodaten zu benutzen, den sogenannten Arbeitsbereich * für das Freisetzen der Audiodaten zu benutzen, den sogenannten Arbeitsbereich
* (<i>region of interest, ROI</i>). Zwei Wiedergabemodi werden unterstützt: * (<i>region of interest, ROI</i>). Zwei Wiedergabemodi werden unterstützt:
* Einmaliges Freisetzen/Abspielen und Wiederholung. * Einmaliges Freisetzen/Abspielen und Wiederholung.
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
* Über den geschützen Konstruktor und die geschützte Init-Methode können von * Über den geschützen Konstruktor und die geschützte Init-Methode können von
* ITABufferDatasource abgeleitete Klasse eine verzögert Initialisierung und damit * ITABufferDatasource abgeleitete Klasse eine verzögert Initialisierung und damit
* Festgelegung auf konkrete Puffer und Parameter realisieren. Dies ist notwendig, * Festgelegung auf konkrete Puffer und Parameter realisieren. Dies ist notwendig,
* wenn beim Aufruf des ITABufferDatasource-Konstruktors diese Parameter noch nicht * wenn beim Aufruf des ITABufferDatasource-Konstruktors diese Parameter noch nicht
* bekannt sind. Instanzen müssen dann mittels der Init-Methode initialisiert werden. * bekannt sind. Instanzen müssen dann mittels der Init-Methode initialisiert werden.
* *
* \important <b>Thread-Safety</b>: Ist in dieser Implementierung nicht konsequent durchgezogen. * \important <b>Thread-Safety</b>: Ist in dieser Implementierung nicht konsequent durchgezogen.
...@@ -54,10 +54,11 @@ ...@@ -54,10 +54,11 @@
* und einem speziellen Einsatzschema der Klasse, beidem Thread-safety ausserhalb * und einem speziellen Einsatzschema der Klasse, beidem Thread-safety ausserhalb
* der Klasse realisiert wird, wurde auf eine strikte Thread-sichere Implementierung zunächst * der Klasse realisiert wird, wurde auf eine strikte Thread-sichere Implementierung zunächst
* verzichtet. But remember: <b>You have been warned!</b> :-P [fwe: Dezember 2005] * verzichtet. But remember: <b>You have been warned!</b> :-P [fwe: Dezember 2005]
* *
* \ingroup datasources * \ingroup datasources
*/ */
class ITA_DATA_SOURCES_API ITABufferDatasource : public ITADatasource { class ITA_DATA_SOURCES_API ITABufferDatasource : public ITADatasource
{
public: public:
//! Konstruktor (2D-Array) //! Konstruktor (2D-Array)
/** /**
...@@ -68,14 +69,9 @@ public: ...@@ -68,14 +69,9 @@ public:
* \param uiBlocklength Blocklänge mit der die Datenquelle arbeiten soll * \param uiBlocklength Blocklänge mit der die Datenquelle arbeiten soll
* \param bLoopMode Wiederholungsmodus? [Optional] * \param bLoopMode Wiederholungsmodus? [Optional]
* *
* \note Bei ungültigen Parametern wird eine Ausnahme vom Typ LLCException ausgelöst * \note Bei ungültigen Parametern wird eine Ausnahme vom Typ ITAException ausgelöst
*/ */
ITABufferDatasource(const float** ppfBuffer, ITABufferDatasource( const float** ppfBuffer, unsigned int uiChannels, unsigned int uiBuffersize, double dSamplerate, unsigned int uiBlocklength, bool bLoopMode = false );
unsigned int uiChannels,
unsigned int uiBuffersize,
double dSamplerate,
unsigned int uiBlocklength,
bool bLoopMode=false);
//! Konstruktor (Vektor von Arrays) //! Konstruktor (Vektor von Arrays)
/** /**
...@@ -86,13 +82,9 @@ public: ...@@ -86,13 +82,9 @@ public:
* \param bLoopMode Wiederholungsmodus? [Optional] * \param bLoopMode Wiederholungsmodus? [Optional]
* *
* \note Die Kanalanzahl wird aus der Anzahl der Elemente im Vektor bestimmt * \note Die Kanalanzahl wird aus der Anzahl der Elemente im Vektor bestimmt
* \note Bei ungültigen Parametern wird eine Ausnahme vom Typ LLCException ausgelöst * \note Bei ungültigen Parametern wird eine Ausnahme vom Typ CIAException ausgelöst
*/ */
ITABufferDatasource(const std::vector<float*>& vpfBuffer, ITABufferDatasource( const std::vector< float* >& vpfBuffer, unsigned int uiBuffersize, double dSamplerate, unsigned int uiBlocklength, bool bLoopMode = false );
unsigned int uiBuffersize,
double dSamplerate,
unsigned int uiBlocklength,
bool bLoopMode=false);
//! Spezieller Konstruktor (Einkanal-Betrieb) //! Spezieller Konstruktor (Einkanal-Betrieb)
/** /**
...@@ -104,18 +96,18 @@ public: ...@@ -104,18 +96,18 @@ public:
* \param uiBlocklength Blocklänge mit der die Datenquelle arbeiten soll * \param uiBlocklength Blocklänge mit der die Datenquelle arbeiten soll
* \param bLoopMode Wiederholungsmodus? [Optional] * \param bLoopMode Wiederholungsmodus? [Optional]
* *
* \note Bei ungültigen Parametern wird eine Ausnahme vom Typ LLCException ausgelöst * \note Bei ungültigen Parametern wird eine Ausnahme vom Typ CITAException ausgelöst
*/ */
ITABufferDatasource(const float* pfBuffer, ITABufferDatasource( const float* pfBuffer,
unsigned int uiBuffersize, unsigned int uiBuffersize,
double dSamplerate, double dSamplerate,
unsigned int uiBlocklength, unsigned int uiBlocklength,
bool bLoopMode=false); bool bLoopMode = false );
//! Kapazität der Datenquelle zurückgeben //! Kapazität der Datenquelle zurückgeben
/** /**
* Gibt die Anzahl der Samples der Daten der Quelle zurück. * Gibt die Anzahl der Samples der Daten der Quelle zurück.
* Dieser Wert ist das nächstkleinere Blocklängen-Vielfache der * Dieser Wert ist das nächstkleinere Blocklängen-Vielfache der
* Pufferlänge uiBuffersize und muß somit nicht unbedingt dem * Pufferlänge uiBuffersize und muß somit nicht unbedingt dem
* wert uiBuffersize entsprechen. Er ist unabhängig von der * wert uiBuffersize entsprechen. Er ist unabhängig von der
* Wahl des Start- und Endcursors und kann als Obergrenze für * Wahl des Start- und Endcursors und kann als Obergrenze für
...@@ -137,30 +129,30 @@ public: ...@@ -137,30 +129,30 @@ public:
unsigned int GetCursor(); unsigned int GetCursor();
//! Wiedergabeposition setzen bezogen auf den Arbeitsbereich //! Wiedergabeposition setzen bezogen auf den Arbeitsbereich
void SetCursor(unsigned int uiNewCursor); void SetCursor( unsigned int uiNewCursor );
//! Wiedergabe pausiert? //! Wiedergabe pausiert?
bool IsPaused() const; bool IsPaused() const;
//! Pausierung für Wiedergabe ein-/ausschalten //! Pausierung für Wiedergabe ein-/ausschalten
void SetPaused(bool bPaused); void SetPaused( bool bPaused );
//! Zurückgeben ob die Wiederholung eingeschaltet ist //! Zurückgeben ob die Wiederholung eingeschaltet ist
bool GetLoopMode(); bool GetLoopMode();
//! Wiederholung Ein-/Ausschalten //! Wiederholung Ein-/Ausschalten
void SetLoopMode(bool bLoopMode); void SetLoopMode( bool bLoopMode );
//! Sets the looping mode //! Sets the looping mode
/** /**
* @param[in] bLoopingEnabled True means looping, false will play until EOF * @param[in] bLoopingEnabled True means looping, false will play until EOF
*/ */
void SetIsLooping( bool bLoopingEnabled ); void SetIsLooping( bool bLoopingEnabled );
//! Looping mode getter //! Looping mode getter
/** /**
* @return True means looping, false will play until EOF * @return True means looping, false will play until EOF
*/ */
bool GetIsLooping(); bool GetIsLooping();
//! Arbeitsbereich (region of interest) festlegen //! Arbeitsbereich (region of interest) festlegen
...@@ -168,15 +160,15 @@ public: ...@@ -168,15 +160,15 @@ public:
* Legt den Arbeitsbereich fest, d.h. das Interval in den Quellendaten, aus dem die * Legt den Arbeitsbereich fest, d.h. das Interval in den Quellendaten, aus dem die
* Quelle ihre Daten freisetzt. Dabei stellt uiStartOffset die Nummer des Samples * Quelle ihre Daten freisetzt. Dabei stellt uiStartOffset die Nummer des Samples
* dar, an dem der Arbeitsbereich beginnt. Dieser Wert muß NICHT unbedingt ein Vielfaches der * dar, an dem der Arbeitsbereich beginnt. Dieser Wert muß NICHT unbedingt ein Vielfaches der
* Blöcklänge sein und darf frei gewählt werden. Der Wert uiEndOffset ist die Nummer * Blöcklänge sein und darf frei gewählt werden. Der Wert uiEndOffset ist die Nummer
* des ersten Samples, welches nicht mehr im Arbeitsbereich enthalten ist. * des ersten Samples, welches nicht mehr im Arbeitsbereich enthalten ist.
* Somit ist definieren beide Werte das HALBOFFENE Interval [uiStartOffset, uiEndOffset). * Somit ist definieren beide Werte das HALBOFFENE Interval [uiStartOffset, uiEndOffset).
* Die Datenquelle setzt also Audiodaten aus dem Bereich [uiStartOffset, uiEndOffset-1] * Die Datenquelle setzt also Audiodaten aus dem Bereich [uiStartOffset, uiEndOffset-1]
* frei. Das Ende des Arbeitsbereiches uiEndOffset wird von der Methode so * frei. Das Ende des Arbeitsbereiches uiEndOffset wird von der Methode so
* angepasst, das die Differenz uiEndOffset-uiStartOffset das nächstkleinere Vielfache * angepasst, das die Differenz uiEndOffset-uiStartOffset das nächstkleinere Vielfache
* der Blocklänge ergibt. * der Blocklänge ergibt.
*/ */
void SetROI(unsigned int uiStartOffset, unsigned int uiEndOffset); void SetROI( unsigned int uiStartOffset, unsigned int uiEndOffset );
//! Startposition des Arbeitsbereiches (region of interest) zurückgeben //! Startposition des Arbeitsbereiches (region of interest) zurückgeben
unsigned int GetROIStart(); unsigned int GetROIStart();
...@@ -206,7 +198,7 @@ public: ...@@ -206,7 +198,7 @@ public:
unsigned int GetNumberOfChannels() const; unsigned int GetNumberOfChannels() const;
double GetSampleRate() const; double GetSampleRate() const;
const float* GetBlockPointer(unsigned int uiChannel, const ITAStreamInfo* pStreamInfo); const float* GetBlockPointer( unsigned int uiChannel, const ITAStreamInfo* pStreamInfo );
void IncrementBlockPointer(); void IncrementBlockPointer();
protected: protected:
...@@ -226,11 +218,11 @@ protected: ...@@ -226,11 +218,11 @@ protected:
/** /**
* Zu benutzen im Verbund mit dem geschützen Konstruktor. * Zu benutzen im Verbund mit dem geschützen Konstruktor.
*/ */
void Init(const std::vector<float*>& vpfBuffer, void Init( const std::vector<float*>& vpfBuffer,
unsigned int uiBuffersize, unsigned int uiBuffersize,
double dSamplerate, double dSamplerate,
unsigned int uiBlocklength, unsigned int uiBlocklength,
bool bLoopMode); bool bLoopMode );
private: private:
unsigned int m_uiBuffersize; // Größe der einzelnen Kanalpuffer unsigned int m_uiBuffersize; // Größe der einzelnen Kanalpuffer
......
...@@ -41,20 +41,15 @@ class ITADatasource; ...@@ -41,20 +41,15 @@ class ITADatasource;
* \param uiNumberOfSamples Anzahl der Samples * \param uiNumberOfSamples Anzahl der Samples
* \param dGain Verstärkungsfaktor (optional) * \param dGain Verstärkungsfaktor (optional)
* \param bOnline Echtzeit-Modus verwenden? (d.h. reale Dauern zwischen den * \param bOnline Echtzeit-Modus verwenden? (d.h. reale Dauern zwischen den
* Datenanforderungen verwenden). Falls false, werden die * Datenanforderungen verwenden). Falls false, werden die
* Daten direkt hintereinander angefordert (Maximaler Datendurchsatz) * Daten direkt hintereinander angefordert (Maximaler Datendurchsatz)
* \param bDisplayProgress Fortschritt auf der Konsole ausgeben? (Optional, Standard: Nein) * \param bDisplayProgress Fortschritt auf der Konsole ausgeben? (Optional, Standard: Nein)
* *
* \note Gibt die Datenquelle den Nullzeiger zurück, wird für * \note Gibt die Datenquelle den Nullzeiger zurück, wird für
* den betreffenden Block Stille in den Puffer geschrieben * den betreffenden Block Stille in den Puffer geschrieben
* \note Ausnahmebehandlung mittels der Klasse ITAException * \note Ausnahmebehandlung mittels der Klasse ITAException
*/ */
ITA_DATA_SOURCES_API void WriteFromDatasourceToBuffer(ITADatasource* pSource, ITA_DATA_SOURCES_API void WriteFromDatasourceToBuffer( ITADatasource* pSource, float** ppfDest, unsigned int uiNumberOfSamples, double dGain = 1.0, bool bOnline = true, bool bDisplayProgress = false );
float** ppfDest,
unsigned int uiNumberOfSamples,
double dGain=1.0,
bool bOnline=true,
bool bDisplayProgress=false);
//! Daten einer Datenquelle in eine Datei schreiben //! Daten einer Datenquelle in eine Datei schreiben
/** /**
...@@ -66,20 +61,14 @@ ITA_DATA_SOURCES_API void WriteFromDatasourceToBuffer(ITADatasource* pSource, ...@@ -66,20 +61,14 @@ ITA_DATA_SOURCES_API void WriteFromDatasourceToBuffer(ITADatasource* pSource,
* \param uiNumberOfSamples Anzahl der Samples * \param uiNumberOfSamples Anzahl der Samples
* \param dGain Verstärkungsfaktor (optional) * \param dGain Verstärkungsfaktor (optional)
* \param bOnline Echtzeit-Modus verwenden? (d.h. reale Dauern zwischen den * \param bOnline Echtzeit-Modus verwenden? (d.h. reale Dauern zwischen den
* Datenanforderungen verwenden). Falls false, werden die * Datenanforderungen verwenden). Falls false, werden die
* Daten direkt hintereinander angefordert (Maximaler Datendurchsatz) * Daten direkt hintereinander angefordert (Maximaler Datendurchsatz)
* \param bDisplayProgress Fortschritt auf der Konsole ausgeben? (Optional, Standard: Nein) * \param bDisplayProgress Fortschritt auf der Konsole ausgeben? (Optional, Standard: Nein)
* *
* \note Gibt die Datenquelle den Nullzeiger zurück, wird für * \note Gibt die Datenquelle den Nullzeiger zurück, wird für
* den betreffenden Block Stille in die Datei geschrieben * den betreffenden Block Stille in die Datei geschrieben
* \note Ausnahmebehandlung mittels der Klasse ITAException * \note Ausnahmebehandlung mittels der Klasse ITAException
*/ */
ITA_DATA_SOURCES_API void WriteFromDatasourceToFile(ITADatasource* pSource, ITA_DATA_SOURCES_API void WriteFromDatasourceToFile( ITADatasource* pSource, std::string sFilename, unsigned int uiNumberOfSamples, double dGain = 1.0, bool bOnline = true, bool bDisplayProgress = false );
std::string sFilename,
unsigned int uiNumberOfSamples,
double dGain=1.0,
bool bOnline=true,
bool bDisplayProgress=false);
#endif // INCLUDE_WATCHER_ITA_DATA_SOURCES_UTILS #endif // INCLUDE_WATCHER_ITA_DATA_SOURCES_UTILS
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
// Wichtig: Folgendes Makro definiert Windows-NT als Umgebung und // Wichtig: Folgendes Makro definiert Windows-NT als Umgebung und
// bewirkt somit die Nutzbarkeit der WaitableTimer. // bewirkt somit die Nutzbarkeit der WaitableTimer.
#define _WIN32_WINNT 0x0500 #ifndef _WIN32_WINNT // @todo: remove
#define _WIN32_WINNT 0x0501
#endif
#include <ITADataSource.h> #include <ITADataSource.h>
#include <ITAStreamInfo.h> #include <ITAStreamInfo.h>
...@@ -22,59 +24,62 @@ ...@@ -22,59 +24,62 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
void WriteFromDatasourceToBuffer(ITADatasource* pSource, void WriteFromDatasourceToBuffer( ITADatasource* pSource, float** ppfDest, unsigned int uiNumberOfSamples, double dGain, bool bOnline, bool bDisplayProgress )
float** ppfDest, {
unsigned int uiNumberOfSamples,
double dGain,
bool bOnline,
bool bDisplayProgress) {
// Nullzeiger ausschlieen // Nullzeiger ausschlieen
// TODO: Fehlerbehandlung // TODO: Fehlerbehandlung
if (!pSource) return; if( !pSource )
return;
unsigned int uiChannels = pSource->GetNumberOfChannels(); unsigned int uiChannels = pSource->GetNumberOfChannels();
double dSamplerate = pSource->GetSampleRate(); double dSamplerate = pSource->GetSampleRate();
unsigned int uiBlocklength = pSource->GetBlocklength(); unsigned int uiBlocklength = pSource->GetBlocklength();
ITAStreamInfo siState; ITAStreamInfo siState;
long periodMs = (long)ceil(uiBlocklength / dSamplerate * 1000); long periodMs = ( long ) ceil( uiBlocklength / dSamplerate * 1000 );
#ifdef _WIN32 #ifdef _WIN32
HANDLE hTimer=0; HANDLE hTimer = 0;
if (bOnline) { if( bOnline )
{
// Timer erzeugen // Timer erzeugen
if (FAILED(hTimer = CreateWaitableTimer(NULL, false, NULL))) if( FAILED( hTimer = CreateWaitableTimer( NULL, false, NULL ) ) )
ITA_EXCEPT1(UNKNOWN, "Timer konnte nicht erzeugt werden"); ITA_EXCEPT1( UNKNOWN, "Timer konnte nicht erzeugt werden" );
LARGE_INTEGER liDueTime; LARGE_INTEGER liDueTime;
liDueTime.QuadPart = 0; liDueTime.QuadPart = 0;
SetWaitableTimer(hTimer, &liDueTime, periodMs, NULL, NULL, true); SetWaitableTimer( hTimer, &liDueTime, periodMs, NULL, NULL, true );
} }
#endif #endif
try { try {
unsigned int n=0; unsigned int n = 0;
float fProgress = 0.0f; float fProgress = 0.0f;
while (n < uiNumberOfSamples) while( n < uiNumberOfSamples )
{ {
#ifdef _WIN32 #ifdef _WIN32
// Warten // Warten
if (bOnline) WaitForSingleObject(hTimer, INFINITE); if( bOnline )
WaitForSingleObject( hTimer, INFINITE );
#else #else
if (bOnline) usleep(periodMs * 1000); if( bOnline )
usleep( periodMs * 1000 );
#endif #endif
// Daten von der Quelle holen // Daten von der Quelle holen
for (unsigned int i=0; i<uiChannels; i++) { for( unsigned int i = 0; i < uiChannels; i++ )
const float* pfData = pSource->GetBlockPointer(i, &siState); {
const float* pfData = pSource->GetBlockPointer( i, &siState );
unsigned int k = (uiNumberOfSamples - n); unsigned int k = ( uiNumberOfSamples - n );
if (k > uiBlocklength) k = uiBlocklength; if( k > uiBlocklength )
k = uiBlocklength;
if( !pfData ) if( !pfData )
{ // Stille einfgen {
// Stille einfgen
for( unsigned int j = 0; j < uiBlocklength; j++ ) for( unsigned int j = 0; j < uiBlocklength; j++ )
ppfDest[ i ][ n + j ] = 0; ppfDest[ i ][ n + j ] = 0;
} }
...@@ -92,52 +97,52 @@ void WriteFromDatasourceToBuffer(ITADatasource* pSource, ...@@ -92,52 +97,52 @@ void WriteFromDatasourceToBuffer(ITADatasource* pSource,
n += uiBlocklength; n += uiBlocklength;
siState.nSamples += uiBlocklength; siState.nSamples += uiBlocklength;
siState.dStreamTimeCode = (double) (siState.nSamples) / dSamplerate; siState.dStreamTimeCode = ( double ) ( siState.nSamples ) / dSamplerate;
siState.dSysTimeCode = ITAClock::getDefaultClock()->getTime(); siState.dSysTimeCode = ITAClock::getDefaultClock()->getTime();
if (bDisplayProgress) if( bDisplayProgress )
{ {
float p = 100 * (float) n / uiNumberOfSamples; float p = 100 * ( float ) n / uiNumberOfSamples;
if(p > fProgress + 5.0f) if( p > fProgress + 5.0f )
{ {
fProgress = p; fProgress = p;
printf("WriteFromDatasourceToBuffer: %0.2f%% geschrieben", p); printf( "WriteFromDatasourceToBuffer: %0.2f%% geschrieben", p );
} }
} }
} }
} catch (...) { }
catch( ... )
{
#ifdef _WIN32 #ifdef _WIN32
if (bOnline) CloseHandle(hTimer); if( bOnline )
CloseHandle( hTimer );
#endif #endif
throw; throw;
} }
if (bDisplayProgress) if( bDisplayProgress )
printf("WriteFromDatasourceToBuffer: 100,00%% geschrieben"); printf( "WriteFromDatasourceToBuffer: 100,00%% geschrieben" );
#ifdef _WIN32 #ifdef _WIN32
if (bOnline) if( bOnline )
CloseHandle(hTimer); CloseHandle( hTimer );
#endif #endif
} }
void WriteFromDatasourceToFile(ITADatasource* pSource, void WriteFromDatasourceToFile( ITADatasource* pSource, std::string sFilename, unsigned int uiNumberOfSamples, double dGain, bool bOnline, bool bDisplayProgress )
std::string sFilename, {
unsigned int uiNumberOfSamples,
double dGain,
bool bOnline,
bool bDisplayProgress) {
// Nullzeiger ausschlieen // Nullzeiger ausschlieen
// TODO: Fehlerbehandlung // TODO: Fehlerbehandlung
if (!pSource) return; if( !pSource )
return;
unsigned int uiChannels = pSource->GetNumberOfChannels(); unsigned int uiChannels = pSource->GetNumberOfChannels();
unsigned int uiBlocklength = pSource->GetBlocklength(); unsigned int uiBlocklength = pSource->GetBlocklength();
double dSamplerate = pSource->GetSampleRate(); double dSamplerate = pSource->GetSampleRate();
std::vector<float*> vpfData; std::vector<float*> vpfData;
for (unsigned int i=0; i<uiChannels; i++) for( unsigned int i = 0; i < uiChannels; i++ )
vpfData.push_back(new float[uiBlocklength]); vpfData.push_back( new float[ uiBlocklength ] );
ITAAudiofileProperties props; ITAAudiofileProperties props;
props.iChannels = uiChannels; props.iChannels = uiChannels;
...@@ -145,91 +150,103 @@ void WriteFromDatasourceToFile(ITADatasource* pSource, ...@@ -145,91 +150,103 @@ void WriteFromDatasourceToFile(ITADatasource* pSource,
props.eQuantization = ITAQuantization::ITA_FLOAT; props.eQuantization = ITAQuantization::ITA_FLOAT;
props.eDomain = ITADomain::ITA_TIME_DOMAIN; props.eDomain = ITADomain::ITA_TIME_DOMAIN;
props.iLength = uiNumberOfSamples; props.iLength = uiNumberOfSamples;
ITAAudiofileWriter* writer = ITAAudiofileWriter::create(sFilename, props); ITAAudiofileWriter* writer = ITAAudiofileWriter::create( sFilename, props );
ITAStreamInfo siState; ITAStreamInfo siState;
long periodMs = (long)ceil(uiBlocklength / dSamplerate * 1000); long periodMs = ( long ) ceil( uiBlocklength / dSamplerate * 1000 );
#ifdef _WIN32 #ifdef _WIN32
HANDLE hTimer=0; HANDLE hTimer = 0;
if (bOnline) { if( bOnline )
{
// Timer erzeugen // Timer erzeugen
if (FAILED(hTimer = CreateWaitableTimer(NULL, false, NULL))) { if( FAILED( hTimer = CreateWaitableTimer( NULL, false, NULL ) ) )
{
delete writer; delete writer;
ITA_EXCEPT1(UNKNOWN, "Timer konnte nicht erzeugt werden"); ITA_EXCEPT1( UNKNOWN, "Timer konnte nicht erzeugt werden" );
} }
LARGE_INTEGER liDueTime; LARGE_INTEGER liDueTime;
liDueTime.QuadPart=0; liDueTime.QuadPart = 0;
SetWaitableTimer(hTimer, &liDueTime, periodMs, NULL, NULL, true); SetWaitableTimer( hTimer, &liDueTime, periodMs, NULL, NULL, true );
} }
#endif #endif
try { try {
unsigned int n=0; unsigned int n = 0;
float fProgress = 0.0; float fProgress = 0.0;
while (n < uiNumberOfSamples) { while( n < uiNumberOfSamples )
{
#ifdef _WIN32 #ifdef _WIN32
// Warten // Warten
if (bOnline) WaitForSingleObject(hTimer, INFINITE); if( bOnline )
WaitForSingleObject( hTimer, INFINITE );
#else #else
if (bOnline) usleep(periodMs * 1000); if( bOnline )
usleep( periodMs * 1000 );
#endif #endif
// Daten von der Quelle holen // Daten von der Quelle holen
for (unsigned int i=0; i<uiChannels; i++) { for( unsigned int i = 0; i < uiChannels; i++ )
const float* pfSource = pSource->GetBlockPointer(i, &siState); {
float* pfDest = vpfData[i]; const float* pfSource = pSource->GetBlockPointer( i, &siState );
if (!pfSource) float* pfDest = vpfData[ i ];
if( !pfSource )
{
// Stille einfgen // Stille einfgen
for (unsigned int j=0; j<uiBlocklength; j++) pfDest[j] = 0; for( unsigned int j = 0; j < uiBlocklength; j++ )
else { pfDest[ j ] = 0;
if (dGain == 1) }
memcpy(pfDest, pfSource, uiBlocklength*sizeof(float)); else
else {
for (unsigned int j=0; j<uiBlocklength; j++) if( dGain == 1 )
pfDest[j] = pfSource[j] * (float) dGain; memcpy( pfDest, pfSource, uiBlocklength*sizeof( float ) );
else
for( unsigned int j = 0; j < uiBlocklength; j++ )
pfDest[ j ] = pfSource[ j ] * ( float ) dGain;
} }
} }
pSource->IncrementBlockPointer(); pSource->IncrementBlockPointer();
siState.nSamples += uiBlocklength; siState.nSamples += uiBlocklength;
siState.dStreamTimeCode = (double) (siState.nSamples) / dSamplerate; siState.dStreamTimeCode = ( double ) ( siState.nSamples ) / dSamplerate;
siState.dSysTimeCode = ITAClock::getDefaultClock()->getTime(); siState.dSysTimeCode = ITAClock::getDefaultClock()->getTime();
// Daten schreiben // Daten schreiben
writer->write((std::min)(uiBlocklength, (uiNumberOfSamples - n)), vpfData); writer->write( ( std::min )( uiBlocklength, ( uiNumberOfSamples - n ) ), vpfData );
n += uiBlocklength; n += uiBlocklength;
if (bDisplayProgress) if( bDisplayProgress )
{ {
float p = 100 * (float) n / uiNumberOfSamples; float p = 100 * ( float ) n / uiNumberOfSamples;
if(p > fProgress + 5.0f) if( p > fProgress + 5.0f )
{ {
fProgress = p; fProgress = p;