ITABufferDataSource.h 10 KB
Newer Older
Jonas Stienen's avatar
Jonas Stienen committed
1
/*
2
3
4
5
 * ----------------------------------------------------------------
 *
 *		ITA core libs
 *		(c) Copyright Institute of Technical Acoustics (ITA)
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
6
 *		RWTH Aachen University, Germany, 2015-2020
7
8
9
10
11
12
13
14
15
16
17
 *
 * ----------------------------------------------------------------
 *				    ____  __________  _______
 *				   //  / //__   ___/ //  _   |
 *				  //  /    //  /    //  /_|  |
 *				 //  /    //  /    //  ___   |
 *				//__/    //__/    //__/   |__|
 *
 * ----------------------------------------------------------------
 *
 */
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
#include <ITADataSource.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.
 *
40
 * Die Klasse bietet ferner die Möglichkeit einen bestimmten Bereich der Puffer
Jonas Stienen's avatar
Jonas Stienen committed
41
42
43
44
45
46
47
 * 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,
48
 * wenn beim Aufruf des ITABufferDatasource-Konstruktors diese Parameter noch nicht
Jonas Stienen's avatar
Jonas Stienen committed
49
50
51
52
53
54
55
 * 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]
56
 *
Jonas Stienen's avatar
Jonas Stienen committed
57
58
 * \ingroup datasources
 */
59
60
class ITA_DATA_SOURCES_API ITABufferDatasource : public ITADatasource
{
Jonas Stienen's avatar
Jonas Stienen committed
61
62
63
64
65
66
67
68
69
70
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]
	 *
71
	 * \note Bei ungültigen Parametern wird eine Ausnahme vom Typ ITAException ausgelöst
Jonas Stienen's avatar
Jonas Stienen committed
72
	 */
73
	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
74
75
76
77
78
79
80
81
82
83

	//! 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
84
	 * \note Bei ungültigen Parametern wird eine Ausnahme vom Typ CIAException ausgelöst
Jonas Stienen's avatar
Jonas Stienen committed
85
	 */
86
	ITABufferDatasource( const std::vector< float* >& vpfBuffer, unsigned int uiBuffersize, double dSamplerate, unsigned int uiBlocklength, bool bLoopMode = false );
Jonas Stienen's avatar
Jonas Stienen committed
87
88
89
90
91
92
93
94
95
96
97

	//! 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]
	 *
98
	 * \note Bei ungültigen Parametern wird eine Ausnahme vom Typ CITAException ausgelöst
Jonas Stienen's avatar
Jonas Stienen committed
99
	 */
100
101
102
103
104
	ITABufferDatasource( const float* pfBuffer,
		unsigned int uiBuffersize,
		double dSamplerate,
		unsigned int uiBlocklength,
		bool bLoopMode = false );
Jonas Stienen's avatar
Jonas Stienen committed
105
106

	//! Kapazität der Datenquelle zurückgeben
107
	/**
Jonas Stienen's avatar
Jonas Stienen committed
108
	 * Gibt die Anzahl der Samples der Daten der Quelle zurück.
109
	 * Dieser Wert ist das nächstkleinere Blocklängen-Vielfache der
Jonas Stienen's avatar
Jonas Stienen committed
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
	 * 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
131
	void SetCursor( unsigned int uiNewCursor );
Jonas Stienen's avatar
Jonas Stienen committed
132
133
134

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

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

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

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

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

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

Jonas Stienen's avatar
Jonas Stienen committed
157
158
159
160
161
	//! 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
162
	 * Blöcklänge sein und darf frei gewählt werden. Der Wert uiEndOffset ist die Nummer
Jonas Stienen's avatar
Jonas Stienen committed
163
	 * des ersten Samples, welches nicht mehr im Arbeitsbereich enthalten ist.
164
	 * Somit ist definieren beide Werte das HALBOFFENE Interval [uiStartOffset, uiEndOffset).
Jonas Stienen's avatar
Jonas Stienen committed
165
166
167
168
169
	 * 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.
	 */
170
	void SetROI( unsigned int uiStartOffset, unsigned int uiEndOffset );
Jonas Stienen's avatar
Jonas Stienen committed
171
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

	//! 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;
198
	double GetSampleRate() const;
Jonas Stienen's avatar
Jonas Stienen committed
199

200
	const float* GetBlockPointer( unsigned int uiChannel, const ITAStreamInfo* pStreamInfo );
Jonas Stienen's avatar
Jonas Stienen committed
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
	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.
	 */
220
221
222
223
224
	void Init( const std::vector<float*>& vpfBuffer,
		unsigned int uiBuffersize,
		double dSamplerate,
		unsigned int uiBlocklength,
		bool bLoopMode );
Jonas Stienen's avatar
Jonas Stienen committed
225
226
227
228
229
230
231
232
233
234

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
235
	std::atomic< int > m_iCursor;				// Leseposition
Jonas Stienen's avatar
Jonas Stienen committed
236

237
238
	std::atomic< bool> m_bPaused;			// Wiedergabezustand
	std::atomic< bool > m_bPausedInternal;	// Wiedergabezustand (interne Variable)
Jonas Stienen's avatar
Jonas Stienen committed
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
	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