ITABufferDataSource.h 9.95 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
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
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
/*
* ----------------------------------------------------------------
*
*		ITA core libs
*		(c) Copyright Institute of Technical Acoustics (ITA)
*		RWTH Aachen University, Germany, 2015-2016
*
* ----------------------------------------------------------------
*				    ____  __________  _______
*				   //  / //__   ___/ //  _   |
*				  //  /    //  /    //  /_|  |
*				 //  /    //  /    //  ___   |
*				//__/    //__/    //__/   |__|
*
* ----------------------------------------------------------------
*
*/
// $Id: ITABufferDatasource.h 2900 2012-09-17 08:42:42Z stienen $

#ifndef INCLUDE_WATCHER_ITA_BUFFER_DATA_SOURCE
#define INCLUDE_WATCHER_ITA_BUFFER_DATA_SOURCE

#include <ITADataSourcesDefinitions.h>
          
#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.
 *
 * Die Klasse bietet ferner die Möglichkeit einen bestimmten Bereich der Puffer 
 * 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,
 * wenn beim Aufruf des ITABufferDatasource-Konstruktors diese Parameter noch nicht 
 * 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]
 * 
 * \ingroup datasources
 */
class ITA_DATA_SOURCES_API ITABufferDatasource : public ITADatasource {
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]
	 *
	 * \note Bei ungültigen Parametern wird eine Ausnahme vom Typ LLCException ausgelöst
	 */
	ITABufferDatasource(const float** ppfBuffer,
		                unsigned int uiChannels,
					    unsigned int uiBuffersize,
						double dSamplerate,
		                unsigned int uiBlocklength,
						bool bLoopMode=false);	

	//! 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
	 * \note Bei ungültigen Parametern wird eine Ausnahme vom Typ LLCException ausgelöst
	 */
	ITABufferDatasource(const std::vector<float*>& vpfBuffer,
					    unsigned int uiBuffersize,
						double dSamplerate,
		                unsigned int uiBlocklength,
						bool bLoopMode=false);	

	//! 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]
	 *
	 * \note Bei ungültigen Parametern wird eine Ausnahme vom Typ LLCException ausgelöst
	 */
	ITABufferDatasource(const float* pfBuffer,
					    unsigned int uiBuffersize,
						double dSamplerate,
		                unsigned int uiBlocklength,
						bool bLoopMode=false);	

	//! Kapazität der Datenquelle zurückgeben
	/** 
	 * Gibt die Anzahl der Samples der Daten der Quelle zurück.
	 * Dieser Wert ist das nächstkleinere Blocklängen-Vielfache der 
	 * 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
	void SetCursor(unsigned int uiNewCursor);

	//! Wiedergabe pausiert?
	bool IsPaused() const;
	
	//! Pausierung für Wiedergabe ein-/ausschalten
	void SetPaused(bool bPaused);

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

	//! Wiederholung Ein-/Ausschalten
	void SetLoopMode(bool bLoopMode);

	//! 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
	 * 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.
	 * Somit ist definieren beide Werte das HALBOFFENE Interval [uiStartOffset, uiEndOffset). 
	 * 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.
	 */
	void SetROI(unsigned int uiStartOffset, unsigned int uiEndOffset);

	//! 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;
	double GetSamplerate() const;

    const float* GetBlockPointer(unsigned int uiChannel, const ITAStreamInfo* pStreamInfo);	
	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.
	 */
	void Init(const std::vector<float*>& vpfBuffer,
		      unsigned int uiBuffersize,
			  double dSamplerate,
			  unsigned int uiBlocklength,
			  bool bLoopMode);

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