Refactoring #1

parent 8bc757bd
......@@ -65,4 +65,5 @@ private:
std::string m_sServerAddress;
};
#endif // INCLUDE_WATCHER_ITA_NET_AUDIO_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
/**
* @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( int iChannels, double dSamplingRate, int iBufferSize, int iRingBufferCapacity = 2048 );
virtual ~CITANetAudioStream();
//! Network streaming status of client
......@@ -68,17 +81,19 @@ 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 );
//! Disconnct safely from server
void Disconnect();
//! Returns the connection status
......@@ -87,27 +102,48 @@ public:
*/
bool GetIsConnected() const;
//! Sets the minimal latency possible
//! Returns the minimal latency possible (single block)
/**
* 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;
//! Returns the NetAudio streaming logger base name
std::string GetNetAudioStreamLoggerBaseName() const;
//! Sets the NetAudio streaming logger base name
/**
* If debugging is enabled, all debugging files will be named
* with this suffix.
* @param[in] sBaseName Base name string
*
*/
void SetNetAudioStreamingLoggerBaseName( const std::string& sBaseName );
//! Enabled/disables export of loggers
void SetLoggingExportEnabled( bool bEnabled );
//! Logging export flag getter
bool GetLoggingExportEnabled() const;
//! Returns (static) size of ring buffer
/**
* @return Number of maximum samples that can be hold by internal ring buffer
......@@ -200,6 +236,7 @@ private:
ITABufferedDataLoggerImplStream* m_pAudioStreamLogger; //!< Logging for the audio stream
ITABufferedDataLoggerImplNet* m_pNetworkStreamLogger; //!< Logging for the network stream
std::string m_sNetAudioStreamLoggerBaseName;
bool m_bExportLogs;
int m_iAudioStreamingBlockID; //!< Audio streaming block id
int m_iNetStreamingBlockID; //!< Network streaming block id
......
......@@ -42,29 +42,22 @@ class VistaTCPSocket;
class ITABufferedDataLoggerImplServer;
//! Network audio sample server (for connecting a net audio stream)
//! 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
*/
* Audio sample transmitter for a networked signal source that can connect via TCP/IP.
*
* @sa CITANetAudioStream, CITANetAudioSampleServer
* @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();
~CITANetAudioStreamingServer();
//! Start to listen on a socket (blocking)
bool Start(const std::string& sAddress, const int iPort, const double dTimeIntervalCientSendStatus);
bool Start( const std::string& sAddress, const int iPort, const double dTimeIntervalCientSendStatus );
bool IsClientConnected() const;
std::string GetNetworkAddress() const;
int GetNetworkPort() const;
......@@ -76,12 +69,17 @@ public:
int GetNetStreamBlocklength() const;
int GetNetStreamNumberOfChannels() const;
double GetNetStreamSampleRate() const;
//! Enabled/disables export of loggers
void SetLoggingExportEnabled( bool bEnabled );
//! Logging export flag getter
bool GetLoggingExportEnabled() const;
int GetSendingBlockLength() const;
void SetSendingBlockLength( const int iSendingBlockLength );
void SetAutomaticUpdateRate();
void SetTargetLatencySamples( const int iTargetLatency );
int GetTargetLatencySamples() const;
......@@ -102,17 +100,18 @@ private:
CITANetAudioProtocol::StreamingParameters m_oServerParams;
CITANetAudioMessage* m_pMessage;
int iServerBlockId;
ITABufferedDataLoggerImplServer* m_pServerLogger;
std::string m_sServerLogBaseName;
ITAStopWatch m_swTryReadBlockStats, m_swTryReadAccessStats;
bool m_bExportLogs;
int m_iServerBlockId;
double m_dLastTimeStamp;
int m_iUpdateStrategy;
int m_iEstimatedClientRingBufferFreeSamples;
int m_iTargetLatencySamples;
int m_iMaxSendBlocks;
int m_iEstimatedClientRingBufferFreeSamples;
int m_iSendingBlockLength;
double m_dLastTimeStamp;
int m_iMaxSendBlocks;
friend class CITANetAudioServer;
};
......
#include <ITANetAudioStream.h>
#include <ITANetAudioStreamingClient.h>
// ITA includes
......@@ -7,13 +6,13 @@
#include <ITADataLog.h>
#include <ITAStreamInfo.h>
#include <ITAClock.h>
#include <iomanip>
// Vista includes
#include <VistaBase/VistaStreamUtils.h>
// STL includes
#include <cmath>
#include <iomanip>
#include <iostream>
......@@ -97,6 +96,7 @@ CITANetAudioStream::CITANetAudioStream(int iChannels, double dSamplingRate, int
, m_iWriteCursor( 0 ) // always ahead, i.e. iWriteCursor >= iReadCursor if unwrapped
, m_iAudioStreamingBlockID( 0 )
, m_iNetStreamingBlockID( 0 )
, m_bExportLogs( false )
{
if( iBufferSize > iRingBufferCapacity )
ITA_EXCEPT1( INVALID_PARAMETER, "Ring buffer capacity can not be smaller than Target Sample Latency." );
......@@ -114,6 +114,12 @@ CITANetAudioStream::CITANetAudioStream(int iChannels, double dSamplingRate, int
CITANetAudioStream::~CITANetAudioStream()
{
if( m_bExportLogs == false )
{
m_pAudioStreamLogger->setOutputFile( "" ); // Disables file storing
m_pNetworkStreamLogger->setOutputFile( "" ); // Disables file storing
}
delete m_pAudioStreamLogger;
delete m_pNetworkStreamLogger;
delete m_pNetAudioStreamingClient;
......@@ -246,8 +252,6 @@ void CITANetAudioStream::IncrementBlockPointer()
oLog.uiBlockId = ++m_iAudioStreamingBlockID;
oLog.iFreeSamples = GetRingBufferFreeSamples( );
m_pAudioStreamLogger->log( oLog );
//m_pNetAudioStreamingClient->TriggerBlockIncrement();
}
int CITANetAudioStream::Transmit( const ITASampleFrame& sfNewSamples, int iNumSamples )
......@@ -382,3 +386,13 @@ void CITANetAudioStream::SetNetAudioStreamingLoggerBaseName( const std::string&
m_pNetworkStreamLogger->setOutputFile( GetNetAudioStreamLoggerBaseName() + "_NetworkStream.log" );
m_pNetAudioStreamingClient->SetClientLoggerBaseName( sBaseName );
}
void CITANetAudioStream::SetLoggingExportEnabled( bool bEnabled )
{
m_bExportLogs = bEnabled;
}
bool CITANetAudioStream::GetLoggingExportEnabled() const
{
return m_bExportLogs;
}
......@@ -58,23 +58,26 @@ class ITABufferedDataLoggerImplServer : public ITABufferedDataLogger < ITAServer
CITANetAudioStreamingServer::CITANetAudioStreamingServer()
: m_pInputStream( NULL )
, m_iUpdateStrategy( AUTO )
, m_pConnection( NULL )
, m_pNetAudioServer( new CITANetAudioServer() )
, m_dLastTimeStamp( 0 )
, m_iTargetLatencySamples( -1 )
, m_sServerLogBaseName( "ITANetAudioStreamingServer" )
, m_bExportLogs( false )
, m_iMaxSendBlocks( 40 )
, m_iServerBlockId( 0 )
, m_iEstimatedClientRingBufferFreeSamples( 0 )
{
iServerBlockId = 0;
m_iMaxSendBlocks = 40;
m_iEstimatedClientRingBufferFreeSamples = 0;
// Careful with this:
//SetPriority( VistaPriority::VISTA_MID_PRIORITY );
}
CITANetAudioStreamingServer::~CITANetAudioStreamingServer()
{
delete m_pNetAudioServer;
if( m_bExportLogs == false )
m_pServerLogger->setOutputFile( "" ); // disables export
delete m_pServerLogger;
vstr::out() << "[ ITANetAudioStreamingServer ] Processing statistics: " << m_swTryReadBlockStats.ToString() << std::endl;
......@@ -103,7 +106,9 @@ bool CITANetAudioStreamingServer::Start(const std::string& sAddress, int iPort,
m_oServerParams.iRingBufferSize = oClientParams.iRingBufferSize;
m_oServerParams.iBlockSize = oClientParams.iBlockSize;
m_iEstimatedClientRingBufferFreeSamples = m_oServerParams.iRingBufferSize;
m_iSendingBlockLength = m_oServerParams.iBlockSize;
m_sfTempTransmitBuffer.init( m_pInputStream->GetNumberOfChannels(), m_oServerParams.iRingBufferSize, true );
......@@ -144,7 +149,7 @@ bool CITANetAudioStreamingServer::LoopBody()
ITAServerLog oLog;
oLog.dWorldTimeStamp = dNow;
oLog.uiBlockId = ++iServerBlockId;
oLog.uiBlockId = ++m_iServerBlockId;
oLog.iTransmittedSamples = 0;
// Sending Samples
......@@ -281,9 +286,14 @@ int CITANetAudioStreamingServer::GetNetStreamNumberOfChannels() const
return m_sfTempTransmitBuffer.channels();
}
void CITANetAudioStreamingServer::SetAutomaticUpdateRate()
void CITANetAudioStreamingServer::SetLoggingExportEnabled( bool bEnabled )
{
m_bExportLogs = bEnabled;
}
bool CITANetAudioStreamingServer::GetLoggingExportEnabled() const
{
m_iUpdateStrategy = AUTO;
return m_bExportLogs;
}
void CITANetAudioStreamingServer::SetTargetLatencySamples( const int iTargetLatency )
......
......@@ -62,6 +62,7 @@ int main( int argc, char* argv[] )
ss << "_RB" << g_iRingBufferSize;
ss << "_SB" << g_iSendingBlockLength;
oNetAudioStream.SetNetAudioStreamingLoggerBaseName( ss.str() );
oNetAudioStream.SetLoggingExportEnabled( true );
ITAStreamPatchbay oPatchbay( g_dSampleRate, g_iBlockLength );
oPatchbay.AddInput( &oNetAudioStream );
......
......@@ -71,6 +71,7 @@ int main( int argc, char** argv )
ss << "_RB" << g_iRingBufferSize;
ss << "_SB" << g_iSendingBlockLength;
oStreamingServer.SetServerLogBaseName( ss.str() );
oStreamingServer.SetLoggingExportEnabled( true );
oStreamingServer.SetInputStream( &oMuliplier );
oStreamingServer.SetTargetLatencySamples( g_iTargetLatencySamples );
......
......@@ -24,15 +24,15 @@ const static string g_sServerName = "localhost";
const static string g_sInputFilePath = "gershwin-mono.wav";
const static int g_iServerPort = 12480;
const static double g_dSampleRate = 44100;
const static int g_iBlockLength = 32;
const static int g_iBlockLength = 512;
const static int g_iChannels = 2;
const static int g_iTargetLatencySamples = g_iBlockLength * 1;
const static int g_iRingerBufferCapacity = g_iBlockLength * 5;
const static double g_dDuration = 10.0f;
const static double g_dSyncTimout = 0.001f;
const static bool g_bUseASIO = true;
//const static string g_sAudioInterface = "ASIO4ALL v2";
const static string g_sAudioInterface = "ASIO Hammerfall DSP";
const static string g_sAudioInterface = "ASIO4ALL v2";
//const static string g_sAudioInterface = "ASIO Hammerfall DSP";
class CServer : public VistaThread
{
......@@ -40,6 +40,7 @@ public:
inline CServer( const string& sInputFilePath )
{
pStreamingServer = new CITANetAudioStreamingServer;
pStreamingServer->SetLoggingExportEnabled( true );
pStreamingServer->SetTargetLatencySamples( g_iTargetLatencySamples );
pStreamingServer->SetServerLogBaseName( "ITANetAudioTest_Server" );
......@@ -84,6 +85,7 @@ void run_test()
// Client dumping received stream and mixing down to two channels
CITANetAudioStream oNetAudioStream( g_iChannels, g_dSampleRate, g_iBlockLength, g_iRingerBufferCapacity );
oNetAudioStream.SetNetAudioStreamingLoggerBaseName( "ITANetAudioTest_Client" );
oNetAudioStream.SetLoggingExportEnabled( true );
ITAStreamPatchbay oPatchbay( g_dSampleRate, g_iBlockLength );
oPatchbay.AddInput( &oNetAudioStream );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment