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