ITANetAudioStream.h 7.09 KB
Newer Older
1 2 3 4 5
/*
 * ----------------------------------------------------------------
 *
 *		ITA core libs
 *		(c) Copyright Institute of Technical Acoustics (ITA)
6
 *		RWTH Aachen University, Germany, 2015-2017
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 *
 * ----------------------------------------------------------------
 *				    ____  __________  _______
 *				   //  / //__   ___/ //  _   |
 *				  //  /    //  /    //  /_|  |
 *				 //  /    //  /    //  ___   |
 *				//__/    //__/    //__/   |__|
 *
 * ----------------------------------------------------------------
 *
 */

#ifndef INCLUDE_WATCHER_ITA_NET_AUDIO_STREAM
#define INCLUDE_WATCHER_ITA_NET_AUDIO_STREAM

#include <ITADataSourcesDefinitions.h>

#include <ITADataSource.h>
#include <ITASampleFrame.h>

#include <string>
#include <vector>
29 30 31 32
#include <iostream>
#include <fstream>
using namespace std;

33

34
class CITANetAudioStreamingClient;
35 36
class ITABufferedDataLoggerImplStream;
class ITABufferedDataLoggerImplNet;
37
class ITABufferedDataLoggerImplAudio;
38 39 40

//! Network audio stream
/**
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
  * Audio streaming for a signal source that is connected via TCP/IP.
  * The network audio stream behaves like a client and receives samples
  * from a network audio stream server, CITANetAudioStreamingSearver.
  * 
  * The stream will always work within a streaming context and will never
  * block the streaming processing, because it is decoupled from the 
  * network connection and forwards samples from an internal ring buffer.
  * If the buffer runs out of samples, zeros will be return. If the buffer
  * overruns, the sample server will be suspendeb by blocking the network
  * data flow.
  *
  * Latency can be managed by either providing a small ring buffer or
  * oversizing the ring buffer and requesting a target latency.
  *
  * \note not thread-safe
  */
57
class ITA_DATA_SOURCES_API CITANetAudioStream : public ITADatasource
58 59
{
public:
60
	//! Constructor of a network audio stream
61
	CITANetAudioStream( int iChannels, double dSamplingRate, int iBufferSize, int iRingBufferCapacity = 2048 );
62 63
	virtual ~CITANetAudioStream();

64
	//! Network streaming status of client
65 66
	enum StreamingStatus
	{
67 68 69 70
		INVALID = -1, //!< Invalid status, for exception detection
		STOPPED, //!< Client not connected to a server and streaming stopped, i.e. not receiving samples by choice
		CONNECTED, //!< Client is connected to a sample server (and potentially receives samples)
		STREAMING, //!< 
71
		BUFFER_UNDERRUN,
72
		BUFFER_OVERRUN,
73 74
	};

75 76 77 78 79 80 81
	//! Connect a streaming server
	/**
	  * @sAddress[in] Server address IP, i.e. 127.0.0.1
	  * @iPort[in] Server socket port, defaults to 12480
	  */
	bool Connect( const std::string& sAddress, int iPort = 12480 );

82 83
	void Disconnect();

84 85 86 87
	//! Returns the connection status
	/**
	  * @return True, if connected
	  */
88
	bool GetIsConnected() const;
89

90 91 92 93 94 95 96 97 98
	//! Sets the minimal latency possible
	/**
	  * Real-time network audio is considered to process at lowest latency possible.
	  * However, this implementation requires at least one block. Hence latency is
	  * depending on sampling rate and block length.
	  *
	  * @sa GetMinimumLatencySamples()
	  * @sa GetMinimumLatencySamples()
	  */
99
	float GetMinimumLatencySeconds() const;
100

101 102 103 104
	float GetMaximumLatencySeconds() const;
	int GetMinimumLatencySamples() const;
	int GetMaximumLatencySamples() const;

Jonas Stienen's avatar
Jonas Stienen committed
105 106 107 108 109
	//! Returns the NetAudio streaming logger base name
	std::string GetNetAudioStreamLoggerBaseName() const;

	//! Sets the NetAudio streaming logger base name
	void SetNetAudioStreamingLoggerBaseName( const std::string& sBaseName );
110

111
	//! Returns (static) size of ring buffer
112 113 114
	/**
	  * @return Number of maximum samples that can be hold by internal ring buffer
	  */
115
	int GetRingBufferSize() const;
116 117

	//! Returns true if ring buffer is full
118 119 120
	/**
	  * @return True, if ring buffer full (down to the last sample, not smaller that block size)
	  */
121 122 123
	bool GetIsRingBufferFull() const;

	//! Returns true if ring buffer is empty
124 125 126
	/**
	  * @return True, if ring buffer empty (down to the last sample, not smaller that block size)
	  */
127
	bool GetIsRingBufferEmpty() const;
128
	
129
	//! Returns block size
130
	unsigned int GetBlocklength() const;
131 132

	//! Returns number of channels
133
	unsigned int GetNumberOfChannels() const;
134 135

	//! Returns sampling rate
136
	double GetSampleRate() const;
137 138 139 140 141 142

	//! Audio streaming block read for a given channel
	/** 
	  * This method is called by the streaming context for each channel, also providing stream infos.
	  * It copies samples out of the ring buffer, but does not touch the read/write cursors.
	  */
143
	const float* GetBlockPointer( unsigned int uiChannel, const ITAStreamInfo* );
144 145 146 147 148 149 150 151 152
	
	//! Audio streaming block increment
	/**
	  * This method updates the read curser and forwards it by one block. This operations
	  * frees samples out of the ring buffer. It also triggersan event
	  * to indicate that the ring buffer readable sample number has been decreased.
	  * Depending on the network streaming settings, the trigger will be forwarded
	  * to the server to inform about the number of free samples, that can be re-filled.
	  */
153 154
	void IncrementBlockPointer();

Jonas Stienen's avatar
Jonas Stienen committed
155

156
protected:
157
	//! This method is called by the networkg client and pushes samples into the ring buffer
158
	/**
159 160 161 162
	  * If samples fit ring buffer, the rite curser will be increased by iNumSamples, hence
	  * the number of free (writable) samples decreases.
	  *
	  * @param[in] sfNewSamples Sample frame with new samples to be appended to the ring buffer
163 164
	  * \param iNumSamples samples to be read from the sample frame (must be smaller or equal length)
	  *
165 166 167
	  * @return Number of free samples in ring buffer
	  *
	  * @note This method is not called out of the audio streaming context but out of the network context.
168
	  */
169 170
	int Transmit( const ITASampleFrame& sfNewSamples, int iNumSamples );

171 172 173 174 175 176
	//! Returns samples that can be read from ring buffer
	/**
	* @return Readable samples between read and write cursor.
	*/
	int GetRingBufferAvailableSamples() const;

177
	//! Returns free samples between write and read cursor
178 179 180
	/**
	* @return Free samples between write and read cursor.
	*/
181
	int GetRingBufferFreeSamples() const;
182

183
private:
184
	CITANetAudioStreamingClient* m_pNetAudioStreamingClient; //!< Audio streaming network client
185

186 187
	double m_dSampleRate; //!< Sampling rate
	ITASampleFrame m_sfOutputStreamBuffer; //!< Output samples temp buffer (audio context)
188 189

	int m_iReadCursor; //!< Cursor where samples will be consumed from ring buffer on next block
190 191
	int m_iWriteCursor; //!< Cursor where samples will be fed into ring buffer from net audio producer (always ahead)
	bool m_bRingBufferFull; //!< Indicator if ring buffer is full (and read cursor equals write cursor)
192
	ITASampleFrame m_sfRingBuffer; //!< Ring buffer
193

194
	int m_iStreamingStatus; //!< Current streaming status
195
	double m_dLastStreamingTimeCode;
196

Jonas Stienen's avatar
Jonas Stienen committed
197 198 199 200
	ITABufferedDataLoggerImplStream* m_pAudioStreamLogger; //!< Logging for the audio stream
	ITABufferedDataLoggerImplNet* m_pNetworkStreamLogger; //!< Logging for the network stream
	std::string m_sNetAudioStreamLoggerBaseName;

201 202 203 204
	int iAudioStreamingBlockID; //!< Audio streaming block id
	int iNetStreamingBlockID; //!< Network streaming block id
	
	friend class CITANetAudioStreamingClient;
205
	static std::string GetStreamingStatusString( int iStreamingStatus );
206 207 208
};

#endif // INCLUDE_WATCHER_ITA_NET_AUDIO_STREAM