ITABufferDataSource.h 10 KB
Newer Older
Jonas Stienen's avatar
Jonas Stienen committed
1
/*
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
 * ----------------------------------------------------------------
 *
 *		ITA core libs
 *		(c) Copyright Institute of Technical Acoustics (ITA)
 *		RWTH Aachen University, Germany, 2015-2017
 *
 * ----------------------------------------------------------------
 *				    ____  __________  _______
 *				   //  / //__   ___/ //  _   |
 *				  //  /    //  /    //  /_|  |
 *				 //  /    //  /    //  ___   |
 *				//__/    //__/    //__/   |__|
 *
 * ----------------------------------------------------------------
 *
 */
Jonas Stienen's avatar
Jonas Stienen committed
18 19 20 21 22

#ifndef INCLUDE_WATCHER_ITA_BUFFER_DATA_SOURCE
#define INCLUDE_WATCHER_ITA_BUFFER_DATA_SOURCE

#include <ITADataSourcesDefinitions.h>
23

Jonas Stienen's avatar
Jonas Stienen committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
#include <ITADataSource.h>
#include <ITAAtomicPrimitives.h>

#include <vector>

//! Puffer-basierte Datenquelle
/**
 * Die Klasse ITABufferDatasource realisiert Datenquellen, welche
 * Audiodaten aus sich im Speicher befindlichen Puffern freisetzen.
 * Diese Puffer sind ein oder mehrere float-Arrays, welche jeweils die
 * Audiodaten eines Kanals enthalten. Die Verwaltung der Puffer übernimmt
 * die Klasse NICHT; Sie nutzt diese nur zum Freisetzen von Daten.
 *
 * Da die Audiodaten in Blöcken einer festen Blocklänge freigesetzt werden,
 * legt ITABufferDatasource die Kapazität als nächstkleineres Blocklänge-Vielfaches
 * der Buffergröße (uiBufferSize) fest.
 *
41
 * Die Klasse bietet ferner die Möglichkeit einen bestimmten Bereich der Puffer
Jonas Stienen's avatar
Jonas Stienen committed
42 43 44 45 46 47 48
 * für das Freisetzen der Audiodaten zu benutzen, den sogenannten Arbeitsbereich
 * (<i>region of interest, ROI</i>). Zwei Wiedergabemodi werden unterstützt:
 * Einmaliges Freisetzen/Abspielen und Wiederholung.
 *
 * Über den geschützen Konstruktor und die geschützte Init-Methode können von
 * ITABufferDatasource abgeleitete Klasse eine verzögert Initialisierung und damit
 * Festgelegung auf konkrete Puffer und Parameter realisieren. Dies ist notwendig,
49
 * wenn beim Aufruf des ITABufferDatasource-Konstruktors diese Parameter noch nicht
Jonas Stienen's avatar
Jonas Stienen committed
50 51 52 53 54 55 56
 * bekannt sind. Instanzen müssen dann mittels der Init-Methode initialisiert werden.
 *
 * \important <b>Thread-Safety</b>: Ist in dieser Implementierung nicht konsequent durchgezogen.
 *            Es gibt einige potentielle Schwachstellen. Durch den Vorrang von Leistungaspekten
 *            und einem speziellen Einsatzschema der Klasse, beidem Thread-safety ausserhalb
 *            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]
57
 *
Jonas Stienen's avatar
Jonas Stienen committed
58 59
 * \ingroup datasources
 */
60 61
class ITA_DATA_SOURCES_API ITABufferDatasource : public ITADatasource
{
Jonas Stienen's avatar
Jonas Stienen committed
62 63 64 65 66 67 68 69 70 71
public:
	//! Konstruktor (2D-Array)
	/**
	 * \param ppfBuffer Array von float-Zeigern auf die Datenpuffer der einzelnen Kanäle
	 * \param uiChannels Anzahl der Kanäle
	 * \param uiBuffersize Größe der Kanalpuffer (Anzahl der Samples)
	 * \param dSamplerate Abtastrate mit der die Datenquelle arbeiten soll
	 * \param uiBlocklength Blocklänge mit der die Datenquelle arbeiten soll
	 * \param bLoopMode Wiederholungsmodus? [Optional]
	 *
72
	 * \note Bei ungültigen Parametern wird eine Ausnahme vom Typ ITAException ausgelöst
Jonas Stienen's avatar
Jonas Stienen committed
73
	 */
74
	ITABufferDatasource( const float** ppfBuffer, unsigned int uiChannels, unsigned int uiBuffersize, double dSamplerate, unsigned int uiBlocklength, bool bLoopMode = false );
Jonas Stienen's avatar
Jonas Stienen committed
75 76 77 78 79 80 81 82 83 84

	//! Konstruktor (Vektor von Arrays)
	/**
	 * \param vpfBuffer Vektor von float-Zeigern auf die Datenpuffer der einzelnen Kanäle
	 * \param uiBuffersize Größe der Kanalpuffer (Anzahl der Samples)
	 * \param dSamplerate Abtastrate mit der die Datenquelle arbeiten soll
	 * \param uiBlocklength Blocklänge mit der die Datenquelle arbeiten soll
	 * \param bLoopMode Wiederholungsmodus? [Optional]
	 *
	 * \note Die Kanalanzahl wird aus der Anzahl der Elemente im Vektor bestimmt
85
	 * \note Bei ungültigen Parametern wird eine Ausnahme vom Typ CIAException ausgelöst
Jonas Stienen's avatar
Jonas Stienen committed
86
	 */
87
	ITABufferDatasource( const std::vector< float* >& vpfBuffer, unsigned int uiBuffersize, double dSamplerate, unsigned int uiBlocklength, bool bLoopMode = false );
Jonas Stienen's avatar
Jonas Stienen committed
88 89 90 91 92 93 94 95 96 97 98

	//! Spezieller Konstruktor (Einkanal-Betrieb)
	/**
	 * Dies ist ein spezieller Konstruktor für Datenquellen mit nur einem Kanal.
	 *
	 * \param pfBuffer Zeiger auf den Datenpuffer
	 * \param uiBuffersize Größe des Datenpuffers (Anzahl der Samples)
	 * \param dSamplerate Abtastrate mit der die Datenquelle arbeiten soll
	 * \param uiBlocklength Blocklänge mit der die Datenquelle arbeiten soll
	 * \param bLoopMode Wiederholungsmodus? [Optional]
	 *
99
	 * \note Bei ungültigen Parametern wird eine Ausnahme vom Typ CITAException ausgelöst
Jonas Stienen's avatar
Jonas Stienen committed
100
	 */
101 102 103 104 105
	ITABufferDatasource( const float* pfBuffer,
		unsigned int uiBuffersize,
		double dSamplerate,
		unsigned int uiBlocklength,
		bool bLoopMode = false );
Jonas Stienen's avatar
Jonas Stienen committed
106 107

	//! Kapazität der Datenquelle zurückgeben
108
	/**
Jonas Stienen's avatar
Jonas Stienen committed
109
	 * Gibt die Anzahl der Samples der Daten der Quelle zurück.
110
	 * Dieser Wert ist das nächstkleinere Blocklängen-Vielfache der
Jonas Stienen's avatar
Jonas Stienen committed
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
	 * Pufferlänge uiBuffersize und muß somit nicht unbedingt dem
	 * wert uiBuffersize entsprechen. Er ist unabhängig von der
	 * Wahl des Start- und Endcursors und kann als Obergrenze für
	 * den Endcursor verwendet werden.
	 */
	unsigned int GetCapacity();

	//! Aktuelle Wiedergabeposition bezogen auf die gesamten Quellendaten zurückgeben
	/**
	 * Gibt den relativen Cursor zum Beginn der Quellendaten (Offset 0) zurück.
	 *
	 * \note Dieser Wert ist NICHT IMMER ein Vielfaches der Blocklänge.
	 *       Dies hängt davon ab, ob der Startgrenze der ROI ein Vielfaches
	 *       der Blocklänge ist.
	 */
	unsigned int GetAbsoluteCursor();

	//! Relative Wiedergabeposition bezogen auf den Arbeitsbereich zurückgeben
	unsigned int GetCursor();

	//! Wiedergabeposition setzen bezogen auf den Arbeitsbereich
132
	void SetCursor( unsigned int uiNewCursor );
Jonas Stienen's avatar
Jonas Stienen committed
133 134 135

	//! Wiedergabe pausiert?
	bool IsPaused() const;
136

Jonas Stienen's avatar
Jonas Stienen committed
137
	//! Pausierung für Wiedergabe ein-/ausschalten
138
	void SetPaused( bool bPaused );
Jonas Stienen's avatar
Jonas Stienen committed
139 140 141 142 143

	//! Zurückgeben ob die Wiederholung eingeschaltet ist
	bool GetLoopMode();

	//! Wiederholung Ein-/Ausschalten
144
	void SetLoopMode( bool bLoopMode );
Jonas Stienen's avatar
Jonas Stienen committed
145

146 147 148 149 150
	//! Sets the looping mode
	/**
	  * @param[in] bLoopingEnabled True means looping, false will play until EOF
	  */
	void SetIsLooping( bool bLoopingEnabled );
151

152 153 154
	//! Looping mode getter
	/**
	  * @return True means looping, false will play until EOF
155
	  */
156 157
	bool GetIsLooping();

Jonas Stienen's avatar
Jonas Stienen committed
158 159 160 161 162
	//! Arbeitsbereich (region of interest) festlegen
	/**
	 * 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
	 * dar, an dem der Arbeitsbereich beginnt. Dieser Wert muß NICHT unbedingt ein Vielfaches der
163
	 * Blöcklänge sein und darf frei gewählt werden. Der Wert uiEndOffset ist die Nummer
Jonas Stienen's avatar
Jonas Stienen committed
164
	 * des ersten Samples, welches nicht mehr im Arbeitsbereich enthalten ist.
165
	 * Somit ist definieren beide Werte das HALBOFFENE Interval [uiStartOffset, uiEndOffset).
Jonas Stienen's avatar
Jonas Stienen committed
166 167 168 169 170
	 * Die Datenquelle setzt also Audiodaten aus dem Bereich [uiStartOffset, uiEndOffset-1]
	 * frei. Das Ende des Arbeitsbereiches uiEndOffset wird von der Methode so
	 * angepasst, das die Differenz uiEndOffset-uiStartOffset das nächstkleinere Vielfache
	 * der Blocklänge ergibt.
	 */
171
	void SetROI( unsigned int uiStartOffset, unsigned int uiEndOffset );
Jonas Stienen's avatar
Jonas Stienen committed
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198

	//! Startposition des Arbeitsbereiches (region of interest) zurückgeben
	unsigned int GetROIStart();

	//! Endposition des Arbeitsbereiches (region of interest) zurückgeben
	unsigned int GetROIEnd();

	//! Länge der Arbeitsbereiches (region of interest) zurückgeben
	/**
	 * Gibt die Länge des Arbeitsbereiches (region of interest) zurück.
	 * Dies ist die Differenz von End- und Startcursor. Der Wert ist
	 * immer ein Vielfaches der Blocklänge.
	 */
	unsigned int GetROILength();

	//! Zurückspulen
	/**
	 * Spult die Datenquelle an den Beginn der Daten zurück.
	 * Der als nächstes freigesetzten Daten sind wieder die Daten
	 * vom Anfang der Puffer.
	 */
	void Rewind();

	// -= Realisierte Methoden von ITADatasource =-

	unsigned int GetBlocklength() const;
	unsigned int GetNumberOfChannels() const;
199
	double GetSampleRate() const;
Jonas Stienen's avatar
Jonas Stienen committed
200

201
	const float* GetBlockPointer( unsigned int uiChannel, const ITAStreamInfo* pStreamInfo );
Jonas Stienen's avatar
Jonas Stienen committed
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
	void IncrementBlockPointer();

protected:
	//! Geschützer Konstruktor
	/**
	 * Dieser Konstruktor kann von abgeleiteten Klassen benutzt werden um eine
	 * Instanz von ITABufferDatasource zu erzeugen, welche noch nicht auf einen
	 * konkreten Puffer und konkrete Parameter festgelegt ist (z.B. für die
	 * Spezialisierung ITAFileDatasource ist dies notwendig).
	 *
	 * \important Auf jedenfall muss die Instanz später mit der Methode Init
	 *            initialisiert werden.
	 */
	ITABufferDatasource();

	//! Initialisieren
	/**
	 * Zu benutzen im Verbund mit dem geschützen Konstruktor.
	 */
221 222 223 224 225
	void Init( const std::vector<float*>& vpfBuffer,
		unsigned int uiBuffersize,
		double dSamplerate,
		unsigned int uiBlocklength,
		bool bLoopMode );
Jonas Stienen's avatar
Jonas Stienen committed
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255

private:
	unsigned int m_uiBuffersize;		// Größe der einzelnen Kanalpuffer
	std::vector<const float*> m_vpfBuffer;	// Vektor der Kanalpuffer

	double m_dSamplerate;				// Abtastrate [Hz]
	unsigned int m_uiChannels;			// Anzahl Kanäle
	unsigned int m_uiBlocklength;		// Streaming Puffergröße [Samples]

	unsigned int m_uiCapacity;			// Kapazität der Quelle
	ITAAtomicInt m_iCursor;				// Leseposition

	ITAAtomicBool m_bPaused;			// Wiedergabezustand
	ITAAtomicBool m_bPausedInternal;	// Wiedergabezustand (interne Variable)
	bool m_bLoopMode, m_bNewLoopMode;	// Wiederholungsmodusm, neuer Wiederholungsmodus
	bool m_bChangeLoopMode;				// true = Wiederholungsmodus soll geändert werden
	bool m_bRewind;						// Als nächstes Zurückspulen?
	bool m_bChangeROI;					// true = Start-/Endcursor soll geändert werden
	bool m_bInit;						// Instanz initialisiert?
	bool m_bGetBlockPointerTouched;		// Seit letztem IncrementBlockPointer bereits ein GetBlockPointer aufgerufen?
	unsigned int m_uiROIStart, m_uiROIEnd;
	unsigned int m_uiNewROIStart, m_uiNewROIEnd;

	// Zustandsänderungen verarbeiten ggf. Cursor anpassen
	// (Rückgabewert: false falls neuer Cursorstand bereits gesetzt und
	//                keine weitere Bearbeitung des Cursors mehr notwendig)
	bool Update();
};

#endif // INCLUDE_WATCHER_ITA_BUFFER_DATA_SOURCE