Commit c283da2e authored by Jonas Stienen's avatar Jonas Stienen
Browse files

Merging NetAudio to develop

parents d7d9cda2 11ebc640
...@@ -110,23 +110,22 @@ endif( ) ...@@ -110,23 +110,22 @@ endif( )
if( ITA_DATA_SOURCES_WITH_NET_AUDIO ) if( ITA_DATA_SOURCES_WITH_NET_AUDIO )
list( APPEND ITADataSourcesHeader list( APPEND ITADataSourcesHeader
"include/ITANetAudioClient.h"
"include/ITANetAudioMessage.h"
"include/ITANetAudioProtocol.h"
"include/ITANetAudioServer.h"
"include/ITANetAudioStream.h" "include/ITANetAudioStream.h"
"include/ITANetAudioStreamingClient.h" "include/ITANetAudioSampleServer.h"
"include/ITANetAudioStreamingServer.h" "include/ITANetAudioStreamingServer.h"
"include/ITANetAudioStreamingClient.h"
) )
list( APPEND ITADataSourcesSources list( APPEND ITADataSourcesSources
"src/ITANetAudioClient.cpp" "src/ITANetAudioClient.cpp"
"src/ITANetAudioClient.h"
"src/ITANetAudioMessage.cpp" "src/ITANetAudioMessage.cpp"
"src/ITANetAudioProtocol.cpp" "src/ITANetAudioMessage.h"
"src/ITANetAudioProtocol.h"
"src/ITANetAudioServer.cpp"
"src/ITANetAudioServer.h"
"src/ITANetAudioStream.cpp" "src/ITANetAudioStream.cpp"
"src/ITANetAudioStreamingClient.cpp" "src/ITANetAudioStreamingClient.cpp"
"src/ITANetAudioStreamingClient.h"
"src/ITANetAudioStreamingServer.cpp" "src/ITANetAudioStreamingServer.cpp"
"src/ITANetAudioServer.cpp"
) )
endif( ) endif( )
......
/*
* ----------------------------------------------------------------
*
* ITA core libs
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2017
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*/
#ifndef INCLUDE_WATCHER_ITA_NET_AUDIO_SAMPLE_SERVER
#define INCLUDE_WATCHER_ITA_NET_AUDIO_SAMPLE_SERVER
#include <ITADataSourcesDefinitions.h>
#include <ITANetAudioStreamingServer.h>
#include <ITADataSourceRealization.h>
//! Sample-generation class with abstract method for providing samples
/*
* This ready-to-use class helps to provide samples for a NetAudio streaming server with
* a single method for processing that has to be implemented ...
* ... just derive and implement Process() method. Have a look at Zero() method
* for exemplary usage of sample buffer.
*/
class CITASampleProcessor : public ITADatasourceRealization
{
public:
//! Create a sample processor with streaming parameters
/*
* @param[in] iNumChannels Channels provided
* @param[in] dSampleRate Audio processing sampling rate
* @param[in] iBlockLength Audio processing block length / buffer size
*/
inline CITASampleProcessor( const int iNumChannels, const double dSampleRate, const int iBlockLength )
: ITADatasourceRealization( ( unsigned int ) ( iNumChannels ), dSampleRate, ( unsigned int ) ( iBlockLength ) )
{
m_vvfSampleBuffer.resize( iNumChannels );
for( size_t c = 0; c < iNumChannels; c++ )
m_vvfSampleBuffer[ c ].resize( iBlockLength );
Zero();
};
inline ~CITASampleProcessor()
{
};
//! Sets all channels and samples to zero
inline void Zero()
{
/*
* Use this as an example how to work with the buffer structure.
*/
// Iterate over channels
for( size_t c = 0; c < m_vvfSampleBuffer.size(); c++ )
{
std::vector< float >& vfSingleChannelSampleBuffer( m_vvfSampleBuffer[ c ] ); // One channel
// Iterate over samples of channel
for( size_t n = 0; n < vfSingleChannelSampleBuffer.size(); n++ )
{
float& fSample( vfSingleChannelSampleBuffer[ n ] ); // One sample
fSample = 0.0f; // -> Manipulation
}
}
};
//! Process samples (overwrite this virtual method)
/**
* Method that is called in audio streaming context and requests
* to produce or copy audio samples into the internal buffer m_vvfSampleBuffer
*
* @param[in] pStreamInfo Information over streaming status, i.e. sample count and time stamp
*
*/
virtual void Process( const ITAStreamInfo* pStreamInfo ) =0;
protected:
std::vector< std::vector< float > > m_vvfSampleBuffer; //!< Multi-channel sample buffer to be filled
private:
//! Delegate internal buffer to audio stream (ITADatasource)
inline void ProcessStream( const ITAStreamInfo* pInfo )
{
Process( pInfo );
for( size_t c = 0; c < m_vvfSampleBuffer.size(); c++ )
{
float* pfData = GetWritePointer( ( unsigned int ) ( c ) );
for( size_t n = 0; n < m_vvfSampleBuffer[ c ].size(); n++ )
pfData[ n ] = m_vvfSampleBuffer[ c ][ n ];
}
IncrementWritePointer();
};
};
//! Network audio sample server (for providing samples via derived generator class)
/**
* Audio sample transmitter for a networked sample callback function that can connect via TCP/IP.
*
* @sa CITANetAudioStream CITANetAudioStreamingServer CITASampleProcessor
* @note not thread-safe
*/
class CITANetAudioSampleServer : public CITANetAudioStreamingServer
{
public:
inline CITANetAudioSampleServer( CITASampleProcessor* pProcessor )
: m_pSampleProcessor( pProcessor )
{
SetInputStream( m_pSampleProcessor );
};
inline ~CITANetAudioSampleServer()
{};
private:
//! Prohibit public access to streaming context and delegate
inline void SetInputStream( ITADatasource* pDataSource )
{
CITANetAudioStreamingServer::SetInputStream( pDataSource );
};
//! Prohibit public access to streaming context and delegate
inline ITADatasource* GetInputStream() const
{
return CITANetAudioStreamingServer::GetInputStream();
};
CITASampleProcessor* m_pSampleProcessor; //!< Callback / sample processor
};
#endif // INCLUDE_WATCHER_ITA_NET_AUDIO_SAMPLE_SERVER
...@@ -26,9 +26,6 @@ ...@@ -26,9 +26,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <iostream>
#include <fstream>
using namespace std;
class CITANetAudioStreamingClient; class CITANetAudioStreamingClient;
...@@ -38,7 +35,7 @@ class ITABufferedDataLoggerImplAudio; ...@@ -38,7 +35,7 @@ class ITABufferedDataLoggerImplAudio;
//! Network audio stream //! Network audio stream
/** /**
* Audio streaming for a signal source that is connected via TCP/IP. * Audio streaming for a signal source that is connected via TCP/IP or UDP.
* The network audio stream behaves like a client and receives samples * The network audio stream behaves like a client and receives samples
* from a network audio stream server, CITANetAudioStreamingSearver. * from a network audio stream server, CITANetAudioStreamingSearver.
* *
...@@ -46,11 +43,13 @@ class ITABufferedDataLoggerImplAudio; ...@@ -46,11 +43,13 @@ class ITABufferedDataLoggerImplAudio;
* block the streaming processing, because it is decoupled from the * block the streaming processing, because it is decoupled from the
* network connection and forwards samples from an internal ring buffer. * network connection and forwards samples from an internal ring buffer.
* If the buffer runs out of samples, zeros will be return. If the 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 * overruns, the sample server will be suspended by blocking the network
* data flow. * data flow.
* *
* Latency can be managed by either providing a small ring buffer or * Latency can be managed by either providing a small ring buffer and
* oversizing the ring buffer and requesting a target latency. * constantly filling it uo, or by oversizing the internal ring buffer
* only pushing samples to meet a target latency. This has to be
* implemented by the server.
* *
* \note not thread-safe * \note not thread-safe
*/ */
...@@ -58,7 +57,21 @@ class ITA_DATA_SOURCES_API CITANetAudioStream : public ITADatasource ...@@ -58,7 +57,21 @@ class ITA_DATA_SOURCES_API CITANetAudioStream : public ITADatasource
{ {
public: public:
//! Constructor of a network audio stream //! Constructor of a network audio stream
CITANetAudioStream( int iChannels, double dSamplingRate, int iBufferSize, int iRingBufferCapacity = 2048 ); /**
* @param[in] iChannels Number of channels
* @param[in] dSamplingRate Sampling rate
* @param[in] iBufferSize Size of audio streaming buffer
* @param[in] iRingBufferCapacity Internal ring buffer
*
* The ring buffer capacity should be roughly 6-10 buffer sizes long for short audio streaming buffers,
* and can go down to one block in case of higher audio buffer sizes.
*
* The streaming parameters have to match with the server settings (yes also buffer size, that of the audio streaming context)
*
* @note Accept for more memory usage, oversizing the buffer does not require more CPU.
*/
CITANetAudioStream( const int iChannels, const double dSamplingRate, const int iBufferSize, const int iRingBufferCapacity = 2048 );
virtual ~CITANetAudioStream(); virtual ~CITANetAudioStream();
//! Network streaming status of client //! Network streaming status of client
...@@ -68,16 +81,20 @@ public: ...@@ -68,16 +81,20 @@ public:
STOPPED, //!< Client not connected to a server and streaming stopped, i.e. not receiving samples by choice 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) CONNECTED, //!< Client is connected to a sample server (and potentially receives samples)
STREAMING, //!< STREAMING, //!<
BUFFER_UNDERRUN, BUFFER_UNDERRUN, //!< Client internal audio buffer ran out of samples
BUFFER_OVERRUN, BUFFER_OVERRUN, //!< Client internal audio ring buffer is full
}; };
//! Connect a streaming server //! Connect a streaming server
/** /**
* @sAddress[in] Server address IP, i.e. 127.0.0.1 * @sAddress[in] Server address IP (127.0.0.1, localhost, etc.)
* @iPort[in] Server socket port, defaults to 12480 * @iPort[in] Server socket port, defaults to 12480
* @return True, if connection could be established and streaming parameters match
*/ */
bool Connect( const std::string& sAddress, int iPort = 12480 ); bool Connect( const std::string& sAddress, const int iPort = 12480, const bool bUseUDP = false );
//! Disconnct safely from server
void Disconnect();
//! Returns the connection status //! Returns the connection status
/** /**
...@@ -85,43 +102,47 @@ public: ...@@ -85,43 +102,47 @@ public:
*/ */
bool GetIsConnected() const; bool GetIsConnected() const;
//! Set allowed latency (s) //! Returns the minimal latency possible (single block)
/** /**
* Sets the latency that will be used for reading and writing from ring buffer. * @return Minimum latency in seconds
* New samples will be requested and send if the latency / ring buffer samples
* is lower than the target latency.
*/
void SetAllowedLatencySeconds( float fLatencySeconds );
void SetAllowedLatencySamples( int iLatencySamples );
float GetAllowedLatencySeconds() const;
int GetAllowedLatencySamples() const;
//! 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()
*/ */
float GetMinimumLatencySeconds() const; float GetMinimumLatencySeconds() const;
//! Returns the maximum latency possible (entire ring buffer used)
/**
* @return Maximum latency in seconds
*/
float GetMaximumLatencySeconds() const; float GetMaximumLatencySeconds() const;
//! Returns the minimum latency possible (single block)
/**
* @return Minimum latency in samples
*/
int GetMinimumLatencySamples() const; int GetMinimumLatencySamples() const;
//! Returns the maximum latency possible (entire ring buffer used)
/**
* @return Maximum latency in samples
*/
int GetMaximumLatencySamples() const; int GetMaximumLatencySamples() const;
//! Sets the latency for real-time processing //! Returns the NetAudio streaming logger base name
std::string GetNetAudioStreamLoggerBaseName() const;
//! Sets the NetAudio streaming logger base name
/** /**
* Real-time network audio is considered to process at lowest latency possible. * If debugging is enabled, all debugging files will be named
* However, this implementation requires at least one block. Hence latency is * with this suffix.
* depending on sampling rate and block length. This method basically * @param[in] sBaseName Base name string
* sets the minimum allowed latency to this value. *
*
* @sa GetMinimumLatencySeconds()
* @sa SetAllowedLatencySeconds()
*/ */
void SetLatencyForRealtime(); void SetNetAudioStreamingLoggerBaseName( const std::string& sBaseName );
//! Enabled/disables export of loggers
void SetDebuggingEnabled( bool bEnabled );
//! Logging export flag getter
bool GetIsDebuggingEnabled() const;
//! Returns (static) size of ring buffer //! Returns (static) size of ring buffer
/** /**
...@@ -167,6 +188,7 @@ public: ...@@ -167,6 +188,7 @@ public:
*/ */
void IncrementBlockPointer(); void IncrementBlockPointer();
protected: protected:
//! This method is called by the networkg client and pushes samples into the ring buffer //! This method is called by the networkg client and pushes samples into the ring buffer
/** /**
...@@ -180,7 +202,7 @@ protected: ...@@ -180,7 +202,7 @@ protected:
* *
* @note This method is not called out of the audio streaming context but out of the network context. * @note This method is not called out of the audio streaming context but out of the network context.
*/ */
int Transmit( const ITASampleFrame& sfNewSamples, int iNumSamples ); int Transmit( const ITASampleFrame& sfNewSamples, const int iNumSamples );
//! Returns samples that can be read from ring buffer //! Returns samples that can be read from ring buffer
/** /**
...@@ -194,6 +216,9 @@ protected: ...@@ -194,6 +216,9 @@ protected:
*/ */
int GetRingBufferFreeSamples() const; int GetRingBufferFreeSamples() const;
//! Returns a string for the streaming status identifier
static std::string GetStreamingStatusString( const int iStreamingStatus );
private: private:
CITANetAudioStreamingClient* m_pNetAudioStreamingClient; //!< Audio streaming network client CITANetAudioStreamingClient* m_pNetAudioStreamingClient; //!< Audio streaming network client
...@@ -204,16 +229,17 @@ private: ...@@ -204,16 +229,17 @@ private:
int m_iWriteCursor; //!< Cursor where samples will be fed into ring buffer from net audio producer (always ahead) 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) bool m_bRingBufferFull; //!< Indicator if ring buffer is full (and read cursor equals write cursor)
ITASampleFrame m_sfRingBuffer; //!< Ring buffer ITASampleFrame m_sfRingBuffer; //!< Ring buffer
int m_iTargetSampleLatency; //!< Maximum allowed samples / target sample latency
int m_iStreamingStatus; //!< Current streaming status int m_iStreamingStatus; //!< Current streaming status
double m_dLastStreamingTimeCode; double m_dLastStreamingTimeCode;
ITABufferedDataLoggerImplAudio* m_pAudioLogger; //!< Logging for the audio stream ITABufferedDataLoggerImplStream* m_pAudioStreamLogger; //!< Logging for the audio stream
ITABufferedDataLoggerImplStream* m_pStreamLogger; //!< Logging for the audio stream ITABufferedDataLoggerImplNet* m_pNetworkStreamLogger; //!< Logging for the network stream
ITABufferedDataLoggerImplNet* m_pNetLogger; //!< Logging for the network stream std::string m_sNetAudioStreamLoggerBaseName;
int iAudioStreamingBlockID; //!< Audio streaming block id bool m_bDebuggingEnabled;
int iNetStreamingBlockID; //!< Network streaming block id
int m_iAudioStreamingBlockID; //!< Audio streaming block id
int m_iNetStreamingBlockID; //!< Network streaming block id
friend class CITANetAudioStreamingClient; friend class CITANetAudioStreamingClient;
}; };
......
/* /*
* ---------------------------------------------------------------- * ----------------------------------------------------------------
* *
* ITA core libs * ITA core libs
* (c) Copyright Institute of Technical Acoustics (ITA) * (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2017 * RWTH Aachen University, Germany, 2015-2017
* *
* ---------------------------------------------------------------- * ----------------------------------------------------------------
* ____ __________ _______ * ____ __________ _______
* // / //__ ___/ // _ | * // / //__ ___/ // _ |
* // / // / // /_| | * // / // / // /_| |
* // / // / // ___ | * // / // / // ___ |
* //__/ //__/ //__/ |__| * //__/ //__/ //__/ |__|
* *
* ---------------------------------------------------------------- * ----------------------------------------------------------------
* *
*/ */
#ifndef INCLUDE_WATCHER_ITA_NET_AUDIO_STREAMING_SERVER #ifndef INCLUDE_WATCHER_ITA_NET_AUDIO_STREAMING_SERVER
#define INCLUDE_WATCHER_ITA_NET_AUDIO_STREAMING_SERVER #define INCLUDE_WATCHER_ITA_NET_AUDIO_STREAMING_SERVER
#include <ITADataSourcesDefinitions.h> #include <ITADataSourcesDefinitions.h>
#include <ITANetAudioProtocol.h> #include <ITASampleFrame.h>
#include <ITAStopWatch.h>
#include <string>
#include <vector> #include <VistaInterProcComm/Concurrency/VistaThreadLoop.h>
#include <iostream>
#include <fstream> #include <string>
#include <vector>
#include <ITANetAudioProtocol.h> #include <iostream>
<<<<<<<<< Temporary merge branch 1
#include <VistaInterProcComm/Concurrency/VistaThreadLoop.h> #include <fstream>
#include <ITASampleFrame.h>
#include <ITANetAudioProtocol.h>
class ITADatasource;
class CITANetAudioMessage; #include <VistaInterProcComm/Concurrency/VistaThreadLoop.h>
class CITANetAudioProtocol; #include <ITASampleFrame.h>
class CITANetAudioServer;
class CITANetAudioMessage; class ITADatasource;
class VistaTCPSocket; class CITANetAudioMessage;
class ITABufferedDataLoggerImplServer; class CITANetAudioProtocol;
class CITANetAudioServer;
class CITANetAudioMessage;
//! Network audio sample server (for connecting a net audio stream) class VistaTCPSocket;
/**
* Audio sample transmitter for a networked signal source that can connect via TCP/IP. //! Network audio sample server (for connecting a net audio stream)
* /**
* \sa CITANetAudioStream * Audio sample transmitter for a networked signal source that can connect via TCP/IP.
* \note not thread-safe *
*/ * \sa CITANetAudioStream
class ITA_DATA_SOURCES_API CITANetAudioStreamingServer : public VistaThreadLoop * \note not thread-safe
{ */
public: class ITA_DATA_SOURCES_API CITANetAudioStreamingServer : public VistaThreadLoop
{
enum UpdateStrategy public:
{
AUTO = 1, //!< Automatic update rate based on sample rate and block length of client (default) enum UpdateStrategy
ADAPTIVE, //!< Adaptive update rate, adjusts for drifting clocks {
CONSTANT, //!< Set a user-defined update rate (may cause forced pausing of sample feeding or dropouts on client side) AUTO = 1, //!< Automatic update rate based on sample rate and block length of client (default)
}; ADAPTIVE, //!< Adaptive update rate, adjusts for drifting clocks
CONSTANT, //!< Set a user-defined update rate (may cause forced pausing of sample feeding or dropouts on client side)
CITANetAudioStreamingServer(); };
virtual ~CITANetAudioStreamingServer() {};
CITANetAudioStreamingServer();
bool Start( const std::string& sAddress, int iPort ); virtual ~CITANetAudioStreamingServer() {};
bool IsClientConnected() const;
std::string GetNetworkAddress() const; bool Start( const std::string& sAddress, int iPort );
int GetNetworkPort() const; bool IsClientConnected() const;
bool LoopBody(); std::string GetNetworkAddress() const;
void Stop(); int GetNetworkPort() const;
bool LoopBody();
void SetInputStream( ITADatasource* pInStream ); void Stop();
int GetNetStreamBlocklength() const; void SetInputStream( ITADatasource* pInStream );
int GetNetStreamNumberOfChannels() const;
double GetNetStreamSampleRate() const; int GetNetStreamBlocklength() const;
int GetNetStreamNumberOfChannels() const;
void SetAutomaticUpdateRate(); double GetNetStreamSampleRate() const;
protected: void SetAutomaticUpdateRate();
ITADatasource* GetInputStream() const;
protected:
private: ITADatasource* GetInputStream() const;
CITANetAudioServer* m_pNetAudioServer;
ITASampleFrame m_sfTempTransmitBuffer; private:
ITADatasource* m_pInputStream; CITANetAudioServer* m_pNetAudioServer;
VistaConnectionIP* m_pConnection; ITASampleFrame m_sfTempTransmitBuffer;
ITADatasource* m_pInputStream;
CITANetAudioProtocol::StreamingParameters m_oServerParams; VistaConnectionIP* m_pConnection;
CITANetAudioMessage* m_pMessage;
CITANetAudioProtocol::StreamingParameters m_oServerParams;
int iServerBlockId; CITANetAudioMessage* m_pIncomingMessage;
ITABufferedDataLoggerImplServer* m_pServerLogger; CITANetAudioMessage* m_pOutgoingMessage;
int m_iUpdateStrategy; int m_iUpdateStrategy;
int m_iClientRingBufferFreeSamples; int m_iClientRingBufferFreeSamples;
int m_iMaxSendBlocks;
friend class CITANetAudioServer;
friend class CITANetAudioServer;