Commit 6c4f4aa7 authored by Jonas Stienen's avatar Jonas Stienen

Merge branch 'ba_2016_heimes' of https://git.rwth-aachen.de/ita/ITADataSources into ba_2016_heimes

# Conflicts:
#	include/ITANetAudioStreamingClient.h
#	src/ITANetAudioStreamingClient.cpp
parents 0d9073a6 1bfecbc7
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project( ITADataSources )
......
......@@ -6,13 +6,13 @@ include( VistaCommon )
vista_use_package( ITADataSources REQUIRED FIND_DEPENDENCIES )
if( TA_DATA_SOURCES_WITH_INTEGRATED_ASIO )
if( ITA_DATA_SOURCES_WITH_INTEGRATED_ASIO )
add_definitions( "-DITA_WHAD_WITH_ASIO" )
endif( TA_DATA_SOURCES_WITH_INTEGRATED_ASIO )
endif( )
if( TA_DATA_SOURCES_WITH_INTEGRATED_PORTAUDIO )
if( ITA_DATA_SOURCES_WITH_INTEGRATED_PORTAUDIO )
add_definitions( "-DITA_WHAD_WITH_PORTAUDIO" )
endif( TA_DATA_SOURCES_WITH_INTEGRATED_PORTAUDIO )
endif( )
add_executable( ita_whad main.cpp )
target_link_libraries( ita_whad ${VISTA_USE_PACKAGE_LIBRARIES} )
......
......@@ -31,26 +31,55 @@ int main( int, char** )
#ifdef ITA_WHAD_WITH_ASIO
string sFileName = "ita_whad_asio.txt";
FILE* file = fopen( sFileName.c_str(), "w" );
string sASIOFileName = "ita_whad_asio.txt";
FILE* PASIOFile = fopen( sASIOFileName.c_str(), "w" );
ITAsioInitializeLibrary();
long lDrivers = ITAsioGetNumDrivers();
if( lDrivers == 0 )
long lASIODrivers = ITAsioGetNumDrivers();
if( lASIODrivers == 0 )
cerr << "Warning: no ASIO drivers found." << endl;
for( long i = 0; i < lDrivers; i++ )
cout << " ### ASIO ### " << endl;
for( long i = 0; i < lASIODrivers; i++ )
{
cout << "[" << i+1 << "] \"" << ITAsioGetDriverName(i) << "\"" << endl;
cout << "[" << i + 1 << "] \"" << ITAsioGetDriverName( i ) << "\"" << endl;
}
cout << endl;
ITAsioFinalizeLibrary();
fclose( file );
fclose( PASIOFile );
#endif // ITA_WHAD_WITH_ASIO
#ifdef ITA_WHAD_WITH_PORTAUDIO
string sPAFileName = "ita_whad_portaudio.txt";
FILE* pPAFile = fopen( sPAFileName.c_str(), "w" );
ITAPortaudioInterface oITAPA( 44.1e3, 1024 );
oITAPA.Initialize();
int iPANumDevices = oITAPA.GetNumDevices();
int iPADefaultIn = oITAPA.GetDefaultInputDevice();
int iPADefaultOut = oITAPA.GetDefaultOutputDevice();
cout << " ### Portaudio ### " << endl;
for( int i = 0; i < iPANumDevices; i++ )
{
string sExtra = "";
if( i == iPADefaultIn || i == iPADefaultOut )
sExtra = " *";
cout << "[" << i + 1 << "] \"" << oITAPA.GetDeviceName( i ) << "\"" << sExtra << endl;
}
cout << endl;
oITAPA.Finalize();
fclose( pPAFile );
#endif // ITA_WHAD_WITH:PORTAUDIO
return 0;
}
......@@ -151,6 +151,18 @@ public:
//! Wiederholung Ein-/Ausschalten
void SetLoopMode(bool bLoopMode);
//! Sets the looping mode
/**
* @param[in] bLoopingEnabled True means looping, false will play until EOF
*/
void SetIsLooping( bool bLoopingEnabled );
//! Looping mode getter
/**
* @return True means looping, false will play until EOF
*/
bool GetIsLooping();
//! Arbeitsbereich (region of interest) festlegen
/**
* Legt den Arbeitsbereich fest, d.h. das Interval in den Quellendaten, aus dem die
......
......@@ -16,7 +16,7 @@
#ifndef _ITADATASOURCEDELEGATOR_H_
#define _ITADATASOURCEDELEGATOR_H_
#include <ITADatasource.h>
#include <ITADataSource.h>
/**
* Diese Klasse implementiert die Schnittstelle der ITADatasource, stellt die
......@@ -74,4 +74,4 @@ private:
ITADatasource* m_pDatasourceDelegatorTarget;
};
#endif // _ITADATASOURCEDELEGATOR_H_
\ No newline at end of file
#endif // _ITADATASOURCEDELEGATOR_H_
......@@ -49,7 +49,8 @@
*
* \ingroup datasources
*/
class ITA_DATA_SOURCES_API ITAFileDatasource : public ITABufferDatasource {
class ITA_DATA_SOURCES_API ITAFileDatasource : public ITABufferDatasource
{
public:
//! Konstruktor
/**
......
......@@ -55,9 +55,8 @@ public:
void ClearConnection();
void WriteMessage();
void ReadMessage();
void WriteAnswer();
void ReadAnswer();
// Returns false if no incomming data
bool ReadMessage( int timeout );
void ResetMessage();
......@@ -66,9 +65,7 @@ public:
bool GetOutgoingMessageHasData() const;
void SetMessageType( int nType );
void SetAnswerType( int nType );
int GetMessageType() const;
int GetAnswerType() const;
void WriteInt( const int );
......@@ -100,12 +97,16 @@ public:
private:
int m_nMessageType;
int m_nMessageId;
int m_nAnswerType;
unsigned long m_iBytesReceivedTotal;
VistaByteBufferSerializer m_oOutgoing; //!< Serialization buffer for messages
VistaByteBufferDeSerializer m_oIncoming; //!< Deserialization buffer for messages
std::vector< VistaType::byte > m_vecIncomingBuffer; // Net IO buffer
VistaConnectionIP* m_pConnection;
//DEBUG
int i;
};
#endif // INCLUDE_WATCHER_ITA_NET_AUDIO_MESSAGE
......@@ -47,21 +47,14 @@ class CITANetAudioStream;
class ITA_DATA_SOURCES_API CITANetAudioProtocol
{
public:
static const int NET_AUDIO_VERSION = 1;
static const int NP_INVALID = -1;
static const int NP_GET_VERSION_INFO = 1;
static const int NP_CLIENT_OPEN = 100;
static const int NP_CLIENT_CLOSE = 101;
static const int NP_CLIENT_WAITING_FOR_SAMPLES = 111;
static const int NP_CLIENT_SENDING_RINGBUFFER_FREE_SAMPLES = 111;
static const int NP_SERVER_CLOSE = 200;
static const int NP_SERVER_OPEN = 201;
static const int NP_SERVER_GET_RINGBUFFER_SIZE = 210;
static const int NP_SERVER_GET_RINGBUFFER_FREE = 211;
static const int NP_SERVER_WAITING_FOR_TRIGGER = 221;
static const int NP_SERVER_SEND_SAMPLES = 222;
static const int NP_SERVER_OPEN = 200;
static const int NP_SERVER_CLOSE = 201;
static const int NP_SERVER_GET_RINGBUFFER_FREE_SAMPLES = 211;
static const int NP_SERVER_SENDING_SAMPLES = 222;
inline CITANetAudioProtocol() {};
inline ~CITANetAudioProtocol() {};
......@@ -71,17 +64,25 @@ public:
int iChannels;
double dSampleRate;
int iBlockSize;
int iRingBufferSize;
int iTargetSampleLatency;
inline StreamingParameters()
{
iChannels = 0;
dSampleRate = 0.0f;
iBlockSize = 0;
iRingBufferSize = 0;
iTargetSampleLatency = 0;
};
inline bool operator==( const StreamingParameters& rhs )
{
if( ( iChannels == rhs.iChannels ) && ( dSampleRate == rhs.dSampleRate ) && ( iBlockSize == rhs.iBlockSize ) )
if ( ( iChannels == rhs.iChannels )
&& ( dSampleRate == rhs.dSampleRate )
&& (iBlockSize == rhs.iBlockSize)
&& (iRingBufferSize == rhs.iRingBufferSize)
&& (iTargetSampleLatency == rhs.iTargetSampleLatency))
return true;
else
return false;
......
......@@ -34,6 +34,7 @@ using namespace std;
class CITANetAudioStreamingClient;
class ITABufferedDataLoggerImplStream;
class ITABufferedDataLoggerImplNet;
class ITABufferedDataLoggerImplAudio;
//! Network audio stream
/**
......@@ -96,12 +97,34 @@ public:
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 GetMaximumLatencySeconds() const;
int GetMinimumLatencySamples() const;
int GetMaximumLatencySamples() const;
//! Sets the latency for real-time processing
/**
* 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()
*/
void SetLatencyForRealtime();
//! Returns (static) size of ring buffer
/**
* @return Number of maximum samples that can be hold by internal ring buffer
......@@ -183,11 +206,12 @@ 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_iTargetSampleLatencyServer; //!< 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
......
......@@ -36,6 +36,7 @@ class CITANetAudioClient;
class CITANetAudioMessage;
class CITANetAudioProtocol;
class CITANetAudioStream;
class ITABufferedDataLoggerImplClient;
//! Network audio streaming client
/**
......
/*
* ----------------------------------------------------------------
*
* 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>
/*
* ----------------------------------------------------------------
*
* 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;
//! 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 m_iUpdateStrategy;
int m_iClientRingBufferFreeSamples;
friend class CITANetAudioServer;
};
#endif // INCLUDE_WATCHER_ITA_NET_AUDIO_STREAMING_SERVER
#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
......@@ -40,7 +40,7 @@ class ITA_DATA_SOURCES_API ITAPortaudioInterface
{
public:
//! ITAPortaudio error code table
typedef enum ITA_PA_ERRORCODE
enum ITA_PA_ERRORCODE
{
//! Portaudio/ITAPortaudio no error
ITA_PA_NO_ERROR=0,
......@@ -161,7 +161,7 @@ public:
};
//! Portaudio available host APIs
typedef enum ITA_PA_HOST_APIS
enum ITA_PA_HOST_APIS
{
ITA_PA_DIRECT_SOUND = 1, //!< Windows DirectSound
ITA_PA_MME = 2, //!< Windows MME
......
......@@ -176,6 +176,16 @@ void ITABufferDatasource::SetCursor(unsigned int uiNewCursor) {
m_iCursor = (int) uiNewCursor;
}
void ITABufferDatasource::SetIsLooping( bool bEnabled )
{
SetLoopMode( bEnabled );
}
bool ITABufferDatasource::GetIsLooping()
{
return GetLoopMode();
}
bool ITABufferDatasource::GetLoopMode() {
/* TODO: Diese Implementierung ist NICHT THREAD-SAFE.
m_bLoopMode kann durch IncrementReadPointer modifiziert werden,
......@@ -190,6 +200,7 @@ void ITABufferDatasource::SetLoopMode(bool bLoopMode) {
m_bChangeLoopMode = true;
}
bool ITABufferDatasource::IsPaused() const {
return m_bPaused;
}
......
This diff is collapsed.
......@@ -17,6 +17,37 @@
#include <iostream>
//! Audio streaming log item
struct ITAAudioLog : public ITALogDataBase
{
inline static std::ostream& outputDesc( std::ostream& os )
{
os << "\t" << "Channel";
os << "\t" << "Samplerate";
os << "\t" << "BufferSize";
os << "\t" << "RingBufferSize";
os << "\t" << "TargetSampleLatency";
os << std::endl;
return os;
};
inline std::ostream& outputData( std::ostream& os ) const
{
os << "\t" << iChannel;
os << "\t" << dSampleRate;
os << "\t" << iBufferSize;
os << "\t" << iRingBufferSize;
os << "\t" << iTargetSampleLatency;
os << std::endl;
return os;
};
int iChannel;
double dSampleRate;
int iBufferSize;
int iRingBufferSize;
int iTargetSampleLatency;
};
//! Audio streaming log item
struct ITAStreamLog : public ITALogDataBase
{
inline static std::ostream& outputDesc( std::ostream& os )
......@@ -81,6 +112,7 @@ struct ITANetLog : public ITALogDataBase
int iNumSamplesTransmitted;
};
class ITABufferedDataLoggerImplAudio : public ITABufferedDataLogger < ITAAudioLog > {};
class ITABufferedDataLoggerImplStream : public ITABufferedDataLogger < ITAStreamLog > {};
class ITABufferedDataLoggerImplNet : public ITABufferedDataLogger < ITANetLog > {};
......@@ -92,7 +124,7 @@ CITANetAudioStream::CITANetAudioStream( int iChannels, double dSamplingRate, int
, m_bRingBufferFull( false )
, m_iStreamingStatus( INVALID )
, m_dLastStreamingTimeCode( 0.0f )
, m_iTargetSampleLatency( 10*iBufferSize )
, m_iTargetSampleLatencyServer( iRingBufferCapacity )
{
m_bRingBufferFull = false;
if( iBufferSize > iRingBufferCapacity )
......@@ -105,19 +137,35 @@ CITANetAudioStream::CITANetAudioStream( int iChannels, double dSamplingRate, int
m_iStreamingStatus = STOPPED;
// Logging
std::string paras = std::string("NetAudioLogBaseData") + std::string("_BS") + std::to_string(iBufferSize) + std::string("_Ch") + std::to_string(iChannels) + std::string(".txt");
m_pAudioLogger = new ITABufferedDataLoggerImplAudio( );
m_pAudioLogger->setOutputFile(paras);
paras = std::string("NetAudioLogStream") + std::string("_BS") + std::to_string(iBufferSize) + std::string("_Ch") + std::to_string(iChannels) + std::string(".txt");
m_pStreamLogger = new ITABufferedDataLoggerImplStream();
m_pStreamLogger->setOutputFile( "NetAudioLogStream.txt" );
m_pStreamLogger->setOutputFile(paras);
iAudioStreamingBlockID = 0;
paras = std::string("NetAudioLogNet") + std::string("_BS") + std::to_string(iBufferSize) + std::string("_Ch") + std::to_string(iChannels) + std::string(".txt");
m_pNetLogger = new ITABufferedDataLoggerImplNet();
m_pNetLogger->setOutputFile( "NetAudioLogNet.txt" );
m_pNetLogger->setOutputFile(paras);
iNetStreamingBlockID = 0;
// Logging Base Data
ITAAudioLog oLog;
oLog.iChannel = GetNumberOfChannels();
oLog.dSampleRate = m_dSampleRate;
oLog.iBufferSize = GetBlocklength();
oLog.iRingBufferSize = GetRingBufferSize();
oLog.iTargetSampleLatency = m_iTargetSampleLatencyServer;
m_pAudioLogger->log( oLog );
}
CITANetAudioStream::~CITANetAudioStream()
{
delete m_pNetLogger;
delete m_pStreamLogger;
delete m_pAudioLogger;
delete m_pNetAudioStreamingClient;