Commit c283da2e authored by Jonas Stienen's avatar Jonas Stienen

Merging NetAudio to develop

parents d7d9cda2 11ebc640
......@@ -110,23 +110,22 @@ endif( )
if( ITA_DATA_SOURCES_WITH_NET_AUDIO )
list( APPEND ITADataSourcesHeader
"include/ITANetAudioClient.h"
"include/ITANetAudioMessage.h"
"include/ITANetAudioProtocol.h"
"include/ITANetAudioServer.h"
"include/ITANetAudioStream.h"
"include/ITANetAudioStreamingClient.h"
"include/ITANetAudioSampleServer.h"
"include/ITANetAudioStreamingServer.h"
"include/ITANetAudioStreamingClient.h"
)
list( APPEND ITADataSourcesSources
"src/ITANetAudioClient.cpp"
"src/ITANetAudioClient.h"
"src/ITANetAudioMessage.cpp"
"src/ITANetAudioProtocol.cpp"
"src/ITANetAudioMessage.h"
"src/ITANetAudioProtocol.h"
"src/ITANetAudioServer.cpp"
"src/ITANetAudioServer.h"
"src/ITANetAudioStream.cpp"
"src/ITANetAudioStreamingClient.cpp"
"src/ITANetAudioStreamingClient.h"
"src/ITANetAudioStreamingServer.cpp"
"src/ITANetAudioServer.cpp"
)
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 @@
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
using namespace std;
class CITANetAudioStreamingClient;
......@@ -38,7 +35,7 @@ class ITABufferedDataLoggerImplAudio;
//! 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
* from a network audio stream server, CITANetAudioStreamingSearver.
*
......@@ -46,11 +43,13 @@ class ITABufferedDataLoggerImplAudio;
* 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
* overruns, the sample server will be suspended 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.
* Latency can be managed by either providing a small ring buffer and
* 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
*/
......@@ -58,7 +57,21 @@ class ITA_DATA_SOURCES_API CITANetAudioStream : public ITADatasource
{
public:
//! 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();
//! Network streaming status of client
......@@ -68,16 +81,20 @@ public:
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, //!<
BUFFER_UNDERRUN,
BUFFER_OVERRUN,
BUFFER_UNDERRUN, //!< Client internal audio buffer ran out of samples
BUFFER_OVERRUN, //!< Client internal audio ring buffer is full
};
//! 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
* @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
/**
......@@ -85,43 +102,47 @@ public:
*/
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.
* 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()
* @return Minimum latency in seconds
*/
float GetMinimumLatencySeconds() const;
//! Returns the maximum latency possible (entire ring buffer used)
/**
* @return Maximum latency in seconds
*/
float GetMaximumLatencySeconds() const;
//! Returns the minimum latency possible (single block)
/**
* @return Minimum latency in samples
*/
int GetMinimumLatencySamples() const;
//! Returns the maximum latency possible (entire ring buffer used)
/**
* @return Maximum latency in samples
*/
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.
* However, this implementation requires at least one block. Hence latency is
* depending on sampling rate and block length. This method basically
* sets the minimum allowed latency to this value.
*
* @sa GetMinimumLatencySeconds()
* @sa SetAllowedLatencySeconds()
* If debugging is enabled, all debugging files will be named
* with this suffix.
* @param[in] sBaseName Base name string
*
*/
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
/**
......@@ -167,6 +188,7 @@ public:
*/
void IncrementBlockPointer();
protected:
//! This method is called by the networkg client and pushes samples into the ring buffer
/**
......@@ -180,7 +202,7 @@ protected:
*
* @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
/**
......@@ -194,6 +216,9 @@ protected:
*/
int GetRingBufferFreeSamples() const;
//! Returns a string for the streaming status identifier
static std::string GetStreamingStatusString( const int iStreamingStatus );
private:
CITANetAudioStreamingClient* m_pNetAudioStreamingClient; //!< Audio streaming network client
......@@ -204,16 +229,17 @@ private:
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)
ITASampleFrame m_sfRingBuffer; //!< Ring buffer
int m_iTargetSampleLatency; //!< Maximum allowed samples / target sample latency
int m_iStreamingStatus; //!< Current streaming status
double m_dLastStreamingTimeCode;
ITABufferedDataLoggerImplAudio* m_pAudioLogger; //!< Logging for the audio stream
ITABufferedDataLoggerImplStream* m_pStreamLogger; //!< Logging for the audio stream
ITABufferedDataLoggerImplNet* m_pNetLogger; //!< Logging for the network stream
int iAudioStreamingBlockID; //!< Audio streaming block id
int iNetStreamingBlockID; //!< Network streaming block id
ITABufferedDataLoggerImplStream* m_pAudioStreamLogger; //!< Logging for the audio stream
ITABufferedDataLoggerImplNet* m_pNetworkStreamLogger; //!< Logging for the network stream
std::string m_sNetAudioStreamLoggerBaseName;
bool m_bDebuggingEnabled;
int m_iAudioStreamingBlockID; //!< Audio streaming block id
int m_iNetStreamingBlockID; //!< Network streaming block id
friend class CITANetAudioStreamingClient;
};
......
/*
* ----------------------------------------------------------------
*
* ITA core libs
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2017
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*/
#ifndef INCLUDE_WATCHER_ITA_NET_AUDIO_STREAMING_SERVER
#define INCLUDE_WATCHER_ITA_NET_AUDIO_STREAMING_SERVER
#include <ITADataSourcesDefinitions.h>
#include <ITANetAudioProtocol.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <ITANetAudioProtocol.h>
#include <VistaInterProcComm/Concurrency/VistaThreadLoop.h>
#include <ITASampleFrame.h>
class ITADatasource;
class CITANetAudioMessage;
class CITANetAudioProtocol;
class CITANetAudioServer;
class CITANetAudioMessage;
class VistaTCPSocket;
class ITABufferedDataLoggerImplServer;
//! Network audio sample server (for connecting a net audio stream)
/**
* Audio sample transmitter for a networked signal source that can connect via TCP/IP.
*
* \sa CITANetAudioStream
* \note not thread-safe
*/
class ITA_DATA_SOURCES_API CITANetAudioStreamingServer : public VistaThreadLoop
{
public:
enum UpdateStrategy
{
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() {};
bool Start( const std::string& sAddress, int iPort );
bool IsClientConnected() const;
std::string GetNetworkAddress() const;
int GetNetworkPort() const;
bool LoopBody();
void Stop();
void SetInputStream( ITADatasource* pInStream );
int GetNetStreamBlocklength() const;
int GetNetStreamNumberOfChannels() const;
double GetNetStreamSampleRate() const;
void SetAutomaticUpdateRate();
protected:
ITADatasource* GetInputStream() const;
private:
CITANetAudioServer* m_pNetAudioServer;
ITASampleFrame m_sfTempTransmitBuffer;
ITADatasource* m_pInputStream;
VistaConnectionIP* m_pConnection;
CITANetAudioProtocol::StreamingParameters m_oServerParams;
CITANetAudioMessage* m_pMessage;
int iServerBlockId;
ITABufferedDataLoggerImplServer* m_pServerLogger;
int m_iUpdateStrategy;
int m_iClientRingBufferFreeSamples;
int m_iMaxSendBlocks;
friend class CITANetAudioServer;
};
#endif // INCLUDE_WATCHER_ITA_NET_AUDIO_STREAMING_SERVER
/*
* ----------------------------------------------------------------
*
* ITA core libs
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2017
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*/
#ifndef INCLUDE_WATCHER_ITA_NET_AUDIO_STREAMING_SERVER
#define INCLUDE_WATCHER_ITA_NET_AUDIO_STREAMING_SERVER
#include <ITADataSourcesDefinitions.h>
#include <ITASampleFrame.h>
#include <ITAStopWatch.h>
#include <VistaInterProcComm/Concurrency/VistaThreadLoop.h>
#include <string>
#include <vector>
#include <iostream>
<<<<<<<<< Temporary merge branch 1
#include <fstream>
#include <ITANetAudioProtocol.h>
#include <VistaInterProcComm/Concurrency/VistaThreadLoop.h>
#include <ITASampleFrame.h>
class ITADatasource;
class CITANetAudioMessage;
class CITANetAudioProtocol;
class CITANetAudioServer;
class CITANetAudioMessage;
class VistaTCPSocket;
//! Network audio sample server (for connecting a net audio stream)
/**
* Audio sample transmitter for a networked signal source that can connect via TCP/IP.
*
* \sa CITANetAudioStream
* \note not thread-safe
*/
class ITA_DATA_SOURCES_API CITANetAudioStreamingServer : public VistaThreadLoop
{
public:
enum UpdateStrategy
{
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() {};
bool Start( const std::string& sAddress, int iPort );
bool IsClientConnected() const;
std::string GetNetworkAddress() const;
int GetNetworkPort() const;
bool LoopBody();
void Stop();
void SetInputStream( ITADatasource* pInStream );
int GetNetStreamBlocklength() const;
int GetNetStreamNumberOfChannels() const;
double GetNetStreamSampleRate() const;
void SetAutomaticUpdateRate();
protected:
ITADatasource* GetInputStream() const;
private:
CITANetAudioServer* m_pNetAudioServer;
ITASampleFrame m_sfTempTransmitBuffer;
ITADatasource* m_pInputStream;
VistaConnectionIP* m_pConnection;
CITANetAudioProtocol::StreamingParameters m_oServerParams;
CITANetAudioMessage* m_pIncomingMessage;
CITANetAudioMessage* m_pOutgoingMessage;
int m_iUpdateStrategy;
int m_iClientRingBufferFreeSamples;
friend class CITANetAudioServer;
};
#endif // INCLUDE_WATCHER_ITA_NET_AUDIO_STREAMING_SERVER
=========
#include <fstream>
class ITADatasource;
class CITANetAudioMessage;
class CITANetAudioProtocol;
class CITANetAudioServer;
class CITANetAudioMessage;
class CITABufferedDataLoggerImplServer;
class VistaConnectionIP;
//! Network audio streaming server (for connecting a net audio stream) with an ITADataSource connection
/**
* Audio sample transmitter for a networked signal source that can connect via TCP/IP.
*
* @sa CITANetAudioStream
* @note not thread-safe
*/
class ITA_DATA_SOURCES_API CITANetAudioStreamingServer : public VistaThreadLoop
{
public:
CITANetAudioStreamingServer();
~CITANetAudioStreamingServer();
//! Start to listen on a socket (blocking)
bool Start( const std::string& sAddress, const int iPort, const double dTimeIntervalCientSendStatus, const bool bUseUDP = false );
bool IsClientConnected() const;
std::string GetNetworkAddress() const;
int GetNetworkPort() const;
void Stop();
void SetInputStream( ITADatasource* pInStream );
int GetNetStreamBlocklength() const;
int GetNetStreamNumberOfChannels( ) const;
double GetNetStreamSampleRate( ) const;
double GetEstimatedCorrFactor( ) const;
void SetEstimatedCorrFactor( double dcorrFactor );
//! Enabled/disables export of loggers
void SetDebuggingEnabled( bool bEnabled );
//! Logging export flag getter
bool GetIsDebuggingEnabled() const;
int GetSendingBlockLength() const;
void SetSendingBlockLength( const int iSendingBlockLength );
void SetTargetLatencySamples( const int iTargetLatency );
int GetTargetLatencySamples() const;
void SetServerLogBaseName( const std::string& sBaseName );
std::string GetServerLogBaseName() const;
bool LoopBody();
protected:
ITADatasource* GetInputStream() const;
private:
CITANetAudioServer* m_pNetAudioServer;
ITASampleFrame m_sfTempTransmitBuffer;
ITADatasource* m_pInputStream;
VistaConnectionIP* m_pConnection;
CITANetAudioMessage* m_pMessage;
CITABufferedDataLoggerImplServer* m_pServerLogger;
std::string m_sServerLogBaseName;
ITAStopWatch m_swTryReadBlockStats, m_swTryReadAccessStats;
bool m_bDebuggingEnabled;
int m_iServerBlockId;
double m_dLastTimeStamp;
double m_dEstimatedCorrFactor;
int m_iTargetLatencySamples;
int m_iEstimatedClientRingBufferFreeSamples;
int m_iClientRingBufferSize;
int m_iSendingBlockLength;
int m_iMaxSendBlocks;
double m_dStreamTimeStart; //!< Stream time start
long unsigned int m_nStreamSampleCounts; //!< Samples that has been streamed
friend class CITANetAudioServer;
};
#endif // INCLUDE_WATCHER_ITA_NET_AUDIO_STREAMING_SERVER
// $Id: $
/*
* ----------------------------------------------------------------
*
* ITA core libs
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2017
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*/
#ifndef __ITA_STREAM_INFO_H__
#define __ITA_STREAM_INFO_H__
#ifndef INCLUDE_WATCHER_ITA_STREAM_INFO
#define INCLUDE_WATCHER_ITA_STREAM_INFO
#include <ITATypes.h>
// Diese Datenklasse beschreibt den Zustand eines Audiostreams
class ITAStreamInfo {
//! Time code information for audio streams
class ITAStreamInfo
{
public:
// Anzahl der abgespielten Samples seit Beginn des Streamings
uint64_t nSamples;
uint64_t nSamples; //!< Number of samples processed
double dStreamTimeCode; //!< Stream time code (starts with zero)
double dSysTimeCode; //!< System time stamp code (begings with current time stamp of system)
// TODO: Beschreiben
double dTimecode;
inline ITAStreamInfo()
: nSamples( 0 )
, dStreamTimeCode( 0.0f )
, dSysTimeCode( 0.0f )
{};
//! Standard-Konstruktor (setzt alle Werte 0)
ITAStreamInfo() : nSamples(0), dTimecode(0) {}
//! Destruktor
virtual ~ITAStreamInfo() {};
inline virtual ~ITAStreamInfo() {};
};
#endif // __ITA_STREAM_INFO_H__