diff --git a/CMakeLists.txt b/CMakeLists.txt index c88c3ea29b499c03aa1da8aaa8503d8c88a8a2af..0c9b9828ed3f322021fde52a217de07d53d13270 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,6 +111,7 @@ endif( ) if( ITA_DATA_SOURCES_WITH_NET_AUDIO ) list( APPEND ITADataSourcesHeader "include/ITANetAudioStream.h" + "include/ITANetAudioSampleServer.h" "include/ITANetAudioStreamingServer.h" ) list( APPEND ITADataSourcesSources diff --git a/include/ITANetAudioSampleServer.h b/include/ITANetAudioSampleServer.h new file mode 100644 index 0000000000000000000000000000000000000000..e9ca564e123d0ccb73e26519621d7b6ab2038b26 --- /dev/null +++ b/include/ITANetAudioSampleServer.h @@ -0,0 +1,139 @@ +/* + * ---------------------------------------------------------------- + * + * 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 +#include +#include + + +//! 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 ITA_DATA_SOURCES_API 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(); + }; + + //! 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 ITA_DATA_SOURCES_API 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 diff --git a/include/ITANetAudioStreamingServer.h b/include/ITANetAudioStreamingServer.h index 5f14aeecc976ac0b25fed15e6f3f7ef9e4821630..cf734e6e144a79b3c9afc84b4c0fcdd12114f792 100644 --- a/include/ITANetAudioStreamingServer.h +++ b/include/ITANetAudioStreamingServer.h @@ -44,7 +44,7 @@ class VistaConnectionIP; /** * Audio sample transmitter for a networked signal source that can connect via TCP/IP. * - * @sa CITANetAudioStream, CITANetAudioSampleServer + * @sa CITANetAudioStream * @note not thread-safe */ class ITA_DATA_SOURCES_API CITANetAudioStreamingServer : public VistaThreadLoop @@ -115,6 +115,9 @@ private: 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; }; diff --git a/include/ITAStreamInfo.h b/include/ITAStreamInfo.h index f8f53459d9ac2e00140a80aacb0a58cc67b08363..4bc75b1e985231abb98fcaa39f60ad3e997425d3 100644 --- a/include/ITAStreamInfo.h +++ b/include/ITAStreamInfo.h @@ -1,24 +1,39 @@ -// $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 -// 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 dTimecode; //!< Time code - // TODO: Beschreiben - double dTimecode; + inline ITAStreamInfo() + : nSamples( 0 ) + , dTimecode( 0 ) + {}; - //! Standard-Konstruktor (setzt alle Werte 0) - ITAStreamInfo() : nSamples(0), dTimecode(0) {} - - //! Destruktor virtual ~ITAStreamInfo() {}; }; -#endif // __ITA_STREAM_INFO_H__ +#endif // INCLUDE_WATCHER_ITA_STREAM_INFO diff --git a/src/ITADataSourceRealization.cpp b/src/ITADataSourceRealization.cpp index 5a08ab5bb2be916ac682900f2ec6675ac35d918b..fc7c027db1d21a6e529b956f295d1919d7e7191d 100644 --- a/src/ITADataSourceRealization.cpp +++ b/src/ITADataSourceRealization.cpp @@ -1,33 +1,17 @@ - #include "ITADataSourceRealization.h" - -#include #include +#include -/* -ITADatasourceRealization::ITADatasourceRealization(unsigned int uiChannels, - unsigned int uiBlocklength, - unsigned int uiCapacity) -{ - Init(uiChannels, uiBlocklength, uiCapacity); -} -*/ - -ITADatasourceRealization::ITADatasourceRealization(unsigned int uiChannels, - double dSamplerate, - unsigned int uiBlocklength, - unsigned int uiCapacity) +ITADatasourceRealization::ITADatasourceRealization( unsigned int uiChannels, double dSamplerate, unsigned int uiBlocklength, unsigned int uiCapacity ) { assert( dSamplerate > 0 ); m_dSampleRate = dSamplerate; m_oStreamProps.dSamplerate = dSamplerate; - Init(uiChannels, uiBlocklength, uiCapacity); -} + Init( uiChannels, uiBlocklength, uiCapacity ); +} -void ITADatasourceRealization::Init(unsigned int uiChannels, - unsigned int uiBlocklength, - unsigned int uiCapacity) +void ITADatasourceRealization::Init( unsigned int uiChannels, unsigned int uiBlocklength, unsigned int uiCapacity ) { assert( uiChannels > 0 ); assert( uiBlocklength > 0 ); @@ -49,7 +33,7 @@ void ITADatasourceRealization::Init(unsigned int uiChannels, m_oStreamProps.uiChannels = m_uiChannels; m_oStreamProps.uiBlocklength = m_uiBlocklength; - m_uiBufferSize = uiBlocklength * (uiCapacity+1); + m_uiBufferSize = uiBlocklength * ( uiCapacity + 1 ); m_pEventHandler = NULL; @@ -57,31 +41,33 @@ void ITADatasourceRealization::Init(unsigned int uiChannels, Organisation des Puffers: Damit die Blöcke der einzelnen Kanäle im Speicher ortlich näher liegen ist das Array wiefolgt indiziert: - [1. Block Kanal 1], ..., [1. Block Kanal k], [2. Block Kanal 1], ... + [1. Block Kanal 1], ..., [1. Block Kanal k], [2. Block Kanal 1], ... - */ + */ // Puffer erzeugen und mit Nullen initialiseren // TODO: Fehlerbehandlung beim Speicherallozieren /* Bugfix zu Bug #001: - + Hier wurde der Puffer einfach um 1024 Felder verlängert. Damit Funktioniert Wuschels ASIO4ALL jetzt. Ungeklärt aber warum der Fehler auftrat? - 2005-2-14 - */ + 2005-2-14 + */ - m_pfBuffer = fm_falloc(m_uiBufferSize * m_uiChannels + /* >>> */ 1024 /* <<< */, false); + m_pfBuffer = fm_falloc( m_uiBufferSize * m_uiChannels + /* >>> */ 1024 /* <<< */, false ); - Reset(); + Reset(); } -ITADatasourceRealization::~ITADatasourceRealization() { - fm_free(m_pfBuffer); +ITADatasourceRealization::~ITADatasourceRealization() +{ + fm_free( m_pfBuffer ); } -void ITADatasourceRealization::Reset() { +void ITADatasourceRealization::Reset() +{ m_uiReadCursor = 0; m_uiWriteCursor = 0; @@ -93,22 +79,26 @@ void ITADatasourceRealization::Reset() { m_iGBPEntrances = 0; m_bGBPFirst = true; - fm_zero(m_pfBuffer, m_uiBufferSize * m_uiChannels + /* >>> */ 1024 /* <<< */); + fm_zero( m_pfBuffer, m_uiBufferSize * m_uiChannels + /* >>> */ 1024 /* <<< */ ); } -bool ITADatasourceRealization::HasStreamErrors() const { - return (m_iBufferUnderflows > 0) || (m_iBufferOverflows > 0) || (m_iGBPReentrances > 0); +bool ITADatasourceRealization::HasStreamErrors() const +{ + return ( m_iBufferUnderflows > 0 ) || ( m_iBufferOverflows > 0 ) || ( m_iGBPReentrances > 0 ); } -ITADatasourceRealizationEventHandler* ITADatasourceRealization::GetStreamEventHandler() const { +ITADatasourceRealizationEventHandler* ITADatasourceRealization::GetStreamEventHandler() const +{ return m_pEventHandler; } -void ITADatasourceRealization::SetStreamEventHandler(ITADatasourceRealizationEventHandler* pHandler) { +void ITADatasourceRealization::SetStreamEventHandler( ITADatasourceRealizationEventHandler* pHandler ) +{ m_pEventHandler = pHandler; } -const float* ITADatasourceRealization::GetBlockPointer(unsigned int uiChannel, const ITAStreamInfo* pStreamInfo) { +const float* ITADatasourceRealization::GetBlockPointer( unsigned int uiChannel, const ITAStreamInfo* pStreamInfo ) +{ assert( uiChannel < m_uiChannels ); /* @@ -117,7 +107,8 @@ const float* ITADatasourceRealization::GetBlockPointer(unsigned int uiChannel, c * * WICHTIG: Dies sollte nicht passieren. Fehler beim anwendenden Programmierer! */ - if (++m_iGBPEntrances > 1) { + if( ++m_iGBPEntrances > 1 ) + { --m_iGBPEntrances; ++m_iGBPReentrances; return NULL; @@ -125,12 +116,16 @@ const float* ITADatasourceRealization::GetBlockPointer(unsigned int uiChannel, c // Hook/Handler aufrufen PreGetBlockPointer(); - if (m_pEventHandler) m_pEventHandler->HandlePreGetBlockPointer(this, uiChannel); + if( m_pEventHandler ) + m_pEventHandler->HandlePreGetBlockPointer( this, uiChannel ); - if (m_bGBPFirst) { + if( m_bGBPFirst ) + { // Erster Eintritt in GBP seit letztem IBP => Daten produzieren - ProcessStream(pStreamInfo); - if (m_pEventHandler) m_pEventHandler->HandleProcessStream(this, pStreamInfo); + ProcessStream( pStreamInfo ); + + if( m_pEventHandler ) + m_pEventHandler->HandleProcessStream( this, pStreamInfo ); m_bGBPFirst = false; } @@ -145,45 +140,51 @@ const float* ITADatasourceRealization::GetBlockPointer(unsigned int uiChannel, c */ unsigned int uiLocalReadCursor = m_uiReadCursor; - if (uiLocalReadCursor == m_uiWriteCursor) { + if( uiLocalReadCursor == m_uiWriteCursor ) + { ++m_iBufferUnderflows; --m_iGBPEntrances; return NULL; } --m_iGBPEntrances; - return m_pfBuffer + (uiChannel * m_uiBufferSize) + uiLocalReadCursor; + return m_pfBuffer + ( uiChannel * m_uiBufferSize ) + uiLocalReadCursor; } -void ITADatasourceRealization::IncrementBlockPointer() { - +void ITADatasourceRealization::IncrementBlockPointer() +{ unsigned int uiLocalReadCursor = m_uiReadCursor; - if (uiLocalReadCursor == m_uiWriteCursor) + if( uiLocalReadCursor == m_uiWriteCursor ) // Keine Daten im Ausgabepuffer? Kein Inkrement möglich! (Fehlerfall) ++m_iBufferUnderflows; else // Lesezeiger inkrementieren - m_uiReadCursor = (uiLocalReadCursor + m_uiBlocklength) % m_uiBufferSize; + m_uiReadCursor = ( uiLocalReadCursor + m_uiBlocklength ) % m_uiBufferSize; m_bGBPFirst = true; PostIncrementBlockPointer(); - if (m_pEventHandler) m_pEventHandler->HandlePostIncrementBlockPointer(this); + + if( m_pEventHandler ) + m_pEventHandler->HandlePostIncrementBlockPointer( this ); } -float* ITADatasourceRealization::GetWritePointer(unsigned int uiChannel) { +float* ITADatasourceRealization::GetWritePointer( unsigned int uiChannel ) +{ assert( uiChannel < m_uiChannels ); - return m_pfBuffer + (uiChannel * m_uiBufferSize) + m_uiWriteCursor; + return m_pfBuffer + ( uiChannel * m_uiBufferSize ) + m_uiWriteCursor; } -void ITADatasourceRealization::IncrementWritePointer() { +void ITADatasourceRealization::IncrementWritePointer() +{ // Lokaler Schreibcursor unsigned int uiLocalWriteCursor = m_uiWriteCursor; - unsigned int uiNewWriteCursor = (uiLocalWriteCursor + m_uiBlocklength) % m_uiBufferSize; + unsigned int uiNewWriteCursor = ( uiLocalWriteCursor + m_uiBlocklength ) % m_uiBufferSize; // Pufferüberlauf - if (uiNewWriteCursor == m_uiReadCursor) { + if( uiNewWriteCursor == m_uiReadCursor ) + { ++m_iBufferOverflows; return; } @@ -192,6 +193,6 @@ void ITADatasourceRealization::IncrementWritePointer() { m_uiWriteCursor = uiNewWriteCursor; } -void ITADatasourceRealizationEventHandler::HandlePreGetBlockPointer(ITADatasourceRealization* pSender, unsigned int uiChannel) {} -void ITADatasourceRealizationEventHandler::HandlePostIncrementBlockPointer(ITADatasourceRealization* pSender) {} -void ITADatasourceRealizationEventHandler::HandleProcessStream(ITADatasourceRealization* pSender, const ITAStreamInfo* pStreamInfo) {} +void ITADatasourceRealizationEventHandler::HandlePreGetBlockPointer( ITADatasourceRealization*, unsigned int ) {} +void ITADatasourceRealizationEventHandler::HandlePostIncrementBlockPointer( ITADatasourceRealization* ) {} +void ITADatasourceRealizationEventHandler::HandleProcessStream( ITADatasourceRealization*, const ITAStreamInfo* ) {} diff --git a/src/ITANetAudioStreamingServer.cpp b/src/ITANetAudioStreamingServer.cpp index d9da164a3eb891e4d1e13872e548c7948d15285a..a323c2cfe1855a7e3c49ac71db203ff0dfdae2eb 100644 --- a/src/ITANetAudioStreamingServer.cpp +++ b/src/ITANetAudioStreamingServer.cpp @@ -71,6 +71,8 @@ CITANetAudioStreamingServer::CITANetAudioStreamingServer() , m_iEstimatedClientRingBufferFreeSamples( 0 ) , m_iClientRingBufferSize( 0 ) , m_dEstimatedCorrFactor( 1 ) + , m_dStreamTimeStart( 0.0f ) + , m_nStreamSampleCounts( 0 ) { // Careful with this: //SetPriority( VistaPriority::VISTA_MID_PRIORITY ); @@ -160,6 +162,9 @@ bool CITANetAudioStreamingServer::LoopBody() { const double dNow = ITAClock::getDefaultClock()->getTime(); + if( m_dStreamTimeStart == 0.0f ) + m_dStreamTimeStart = dNow; + CITAServerLog oLog; oLog.dWorldTimeStamp = dNow; oLog.uiBlockId = ++m_iServerBlockId; @@ -182,10 +187,11 @@ bool CITANetAudioStreamingServer::LoopBody() for( int i = 0; i < int( m_pInputStream->GetNumberOfChannels() ); i++ ) { ITAStreamInfo oStreamInfo; - oStreamInfo.nSamples = m_iSendingBlockLength; + oStreamInfo.nSamples = ( m_nStreamSampleCounts += m_iSendingBlockLength ); + oStreamInfo.dTimecode = dNow - m_dStreamTimeStart; const float* pfData = m_pInputStream->GetBlockPointer( i, &oStreamInfo ); - if( pfData != 0 ) + if( pfData != nullptr ) m_sfTempTransmitBuffer[ i ].write( pfData, m_iSendingBlockLength, 0 ); } diff --git a/tests/NetAudio/ITANetAudioTest.cpp b/tests/NetAudio/ITANetAudioTest.cpp index 6c9b4b8bcf039492b0a72b158dfe709454bce585..658ee05cfd15744877b734cf5e0125addcf9be0a 100644 --- a/tests/NetAudio/ITANetAudioTest.cpp +++ b/tests/NetAudio/ITANetAudioTest.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -8,6 +9,7 @@ #include #include #include +#include #include #include @@ -24,7 +26,7 @@ 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 = 512; -const static int g_iChannels = 160; +const static int g_iChannels = 2; const static int g_iTargetLatencySamples = g_iBlockLength * 2; const static int g_iRingerBufferCapacity = g_iBlockLength * 10; const static double g_dDuration = 10.0f; @@ -34,53 +36,103 @@ const static string g_sAudioInterface = "ASIO4ALL v2"; //const static string g_sAudioInterface = "ASIO Hammerfall DSP"; const static bool g_bUseUDP = false; -class CServer : public VistaThread +class CSampleGenerator : public CITASampleProcessor { public: - inline CServer( const string& sInputFilePath ) + inline CSampleGenerator() + : CITASampleProcessor( g_dSampleRate, g_iChannels, g_iBlockLength ) + {}; + + inline void Process( const ITAStreamInfo* pStreamInfo ) { - pStreamingServer = new CITANetAudioStreamingServer; - pStreamingServer->SetDebuggingEnabled( true ); - pStreamingServer->SetTargetLatencySamples( g_iTargetLatencySamples ); - pStreamingServer->SetServerLogBaseName( "ITANetAudioTest_Server" ); - - pInputFile = new ITAFileDatasource( sInputFilePath, g_iBlockLength ); - pInputFile->SetIsLooping( true ); - assert( pInputFile->GetNumberOfChannels() == 1 ); - pMuliplier = new ITAStreamMultiplier1N( pInputFile, g_iChannels ); - pInputStreamProbe = new ITAStreamProbe( pMuliplier, "ITANetAudioTest.serverstream.wav" ); - pStreamingServer->SetInputStream( pInputStreamProbe ); + for( size_t c = 0; c < m_vvfSampleBuffer.size(); c++ ) + { + for( size_t n = 0; n < m_vvfSampleBuffer[ c ].size(); n++ ) + { + float fSample = ( c == 0 ? 1.0f : -1.0f ) * ( 1.0f - 2.0f * n / float( GetBlocklength() ) ); + m_vvfSampleBuffer[ c ][ n ] = fSample; + } + } + }; +}; + +class CSampleServerExample : public VistaThread +{ +public: + inline CSampleServerExample() + { + m_pSampleGenerator = new CSampleGenerator(); + m_pSampleServer = new CITANetAudioSampleServer( m_pSampleGenerator ); + m_pSampleServer->SetDebuggingEnabled( true ); + m_pSampleServer->SetTargetLatencySamples( g_iTargetLatencySamples ); + m_pSampleServer->SetServerLogBaseName( "ITANetAudioTest_Server" ); + + Run(); + }; + + inline ~CSampleServerExample() + { + delete m_pSampleServer; + delete m_pSampleGenerator; + }; + + void ThreadBody() + { + vstr::out() << "[ NetAudioTestServer ] Starting net audio sample server and waiting for client connections on '" << g_sServerName << "' on port " << g_iServerPort << endl; + m_pSampleServer->Start( g_sServerName, g_iServerPort, g_dSyncTimout, g_bUseUDP ); + }; + + CITANetAudioSampleServer* m_pSampleServer; + CSampleGenerator* m_pSampleGenerator; +}; + +class CStreamServerExample : public VistaThread +{ +public: + inline CStreamServerExample( const string& sInputFilePath ) + { + m_pStreamingServer = new CITANetAudioStreamingServer; + m_pStreamingServer->SetDebuggingEnabled( true ); + m_pStreamingServer->SetTargetLatencySamples( g_iTargetLatencySamples ); + m_pStreamingServer->SetServerLogBaseName( "ITANetAudioTest_Server" ); + + m_pInputFile = new ITAFileDatasource( sInputFilePath, g_iBlockLength ); + m_pInputFile->SetIsLooping( true ); + assert( m_pInputFile->GetNumberOfChannels() == 1 ); + m_pMultiplier = new ITAStreamMultiplier1N( m_pInputFile, g_iChannels ); + m_pInputStreamProbe = new ITAStreamProbe( m_pMultiplier, "ITANetAudioTest.serverstream.wav" ); + m_pStreamingServer->SetInputStream( m_pInputStreamProbe ); Run(); }; - inline ~CServer( ) + inline ~CStreamServerExample() { - delete pInputFile; - delete pMuliplier; - delete pStreamingServer; - delete pInputStreamProbe; + delete m_pInputFile; + delete m_pMultiplier; + delete m_pStreamingServer; + delete m_pInputStreamProbe; }; void ThreadBody( ) { vstr::out() << "[ NetAudioTestServer ] Starting net audio server and waiting for client connections on '" << g_sServerName << "' on port " << g_iServerPort << endl; - pStreamingServer->Start( g_sServerName, g_iServerPort, g_dSyncTimout, g_bUseUDP ); + m_pStreamingServer->Start( g_sServerName, g_iServerPort, g_dSyncTimout, g_bUseUDP ); }; private: - ITAFileDatasource* pInputFile; - ITAStreamMultiplier1N* pMuliplier; - CITANetAudioStreamingServer* pStreamingServer; - ITAStreamProbe* pInputStreamProbe; - + ITAFileDatasource* m_pInputFile; + ITAStreamMultiplier1N* m_pMultiplier; + CITANetAudioStreamingServer* m_pStreamingServer; + ITAStreamProbe* m_pInputStreamProbe; }; void run_test() { // Sample server (forked away into a thread) - CServer* pServer = new CServer( g_sInputFilePath ); + //CStreamServerExample* pServer = new CStreamServerExample( g_sInputFilePath ); + CSampleServerExample* pServer = new CSampleServerExample(); // Client dumping received stream and mixing down to two channels CITANetAudioStream oNetAudioStream( g_iChannels, g_dSampleRate, g_iBlockLength, g_iRingerBufferCapacity );