ITANetAudioStream.cpp 5.25 KB
Newer Older
1
2
#include <ITANetAudioStream.h>

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
3
4
#include <ITANetAudioStreamingClient.h>

5
6
7
8
9
// ITA includes
#include <ITAException.h>

// STL
#include <cmath>
10
#include <iostream>
11
12
13
14
15

CITANetAudioStream::CITANetAudioStream( int iChannels, double dSamplingRate, int iBufferSize, int iRingBufferCapacity )
	: m_sfOutputStreamBuffer( iChannels, iBufferSize, true )
	, m_dSampleRate( dSamplingRate )
	, m_sfRingBuffer( iChannels, iRingBufferCapacity, true )
16
17
	, m_bRingBufferFull( false )
	, m_iStreamingStatus( INVALID )
18
19
	
{
20
21
22
23
	if( iBufferSize > iRingBufferCapacity )
		ITA_EXCEPT1( INVALID_PARAMETER, "Ring buffer capacity can not be smaller than buffer size." );

	m_pNetAudioStreamingClient = new CITANetAudioStreamingClient( this );
Anne's avatar
Anne committed
24
	m_iReadCursor = 0;
25
26
	m_iWriteCursor = 0; // always ahead, i.e. iWriteCursor >= iReadCursor if unwrapped

27
28
	m_iStreamingStatus = STOPPED;
	outputFile.open( "program3data.txt" );
29
30
}

31
32
CITANetAudioStream::~CITANetAudioStream()
{
33
34
	delete m_pNetAudioStreamingClient; 
	outputFile.close( );
35
36
}

37
38
bool CITANetAudioStream::Connect( const std::string& sAddress, int iPort )
{
39
40
41
42
	bool bConnected = m_pNetAudioStreamingClient->Connect( sAddress, iPort );
	if( bConnected )
		m_iStreamingStatus = CONNECTED;
	return bConnected;
43
44
}

45
bool CITANetAudioStream::GetIsConnected() const
46
{
47
	return m_pNetAudioStreamingClient->GetIsConnected();
48
49
}

50
const float* CITANetAudioStream::GetBlockPointer( unsigned int uiChannel, const ITAStreamInfo* )
51
{
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
	ITASampleBuffer& sbOutputStreamBuffer( m_sfOutputStreamBuffer[ uiChannel ] );
	sbOutputStreamBuffer.Zero();
	const float* pfBlockPointer = sbOutputStreamBuffer.GetData();
	
	if( !GetIsConnected() )
		return pfBlockPointer;

	m_iStreamingStatus = STREAMING;
	
	int iCurrentWriteCursor = m_iWriteCursor; // local copy

	if( iCurrentWriteCursor <= m_iReadCursor && GetRingBufferFreeSamples() > 0 ) // Wrap around?
		iCurrentWriteCursor += GetRingBufferSize(); // Write pointer always ahead, so unwrap first

	int iReadableSamples = iCurrentWriteCursor - m_iReadCursor;
Anne's avatar
bugfix    
Anne committed
67
68
69
70
71
72
	if ( iReadableSamples > int( GetBlocklength( ) ) ) // samples can be cyclic-copied safely from ring buffer
	{
		m_sfRingBuffer[ uiChannel ].cyclic_read( sbOutputStreamBuffer.GetData( ), sbOutputStreamBuffer.GetLength( ), m_iReadCursor );
		pfBlockPointer = sbOutputStreamBuffer.GetData( );
	}
	else if( iReadableSamples > 0)
Anne's avatar
Anne committed
73
	{
74
		// @todo: fade with ITAFade
Anne's avatar
bugfix    
Anne committed
75
		//std::cerr << "Should fade right now, but skipping samples." << std::endl;
76
	}
77
	return pfBlockPointer;
78
79
}

80
void CITANetAudioStream::IncrementBlockPointer()
81
{
82
	// Increment read cursor by one audio block and wrap around if exceeding ring buffer
Anne's avatar
bugfix    
Anne committed
83
	if ( ( GetRingBufferSize() - GetRingBufferFreeSamples( )) >= int( GetBlocklength( ) ) )
84
85
86
	{
		m_iReadCursor = ( m_iReadCursor + m_sfOutputStreamBuffer.GetLength() ) % m_sfRingBuffer.GetLength();
		m_iStreamingStatus = STREAMING;
Anne's avatar
bugfix    
Anne committed
87
88
89
90
91
		//outputFile << "incRead ";
	}
	else if ( GetIsRingBufferEmpty( ) )
	{
		//outputFile << "buffer empty ";
92
93
94
95
96
	}
	else
	{
		m_iStreamingStatus = BUFFER_UNDERRUN;
		m_iReadCursor = m_iWriteCursor;
Anne's avatar
bugfix    
Anne committed
97
		//outputFile << "BufferOverrun ";
98
	}
Anne's avatar
bugfix    
Anne committed
99
100
101
102
	m_bRingBufferFull = false;
	//outputFile << "\tRead: " << m_iReadCursor;
	//outputFile << "\tWrite : " << m_iWriteCursor;
	//outputFile << "\tFreeSamples: " << GetRingBufferFreeSamples ()<< endl;
103
	m_pNetAudioStreamingClient->TriggerBlockIncrement();
104
105
}

106
int CITANetAudioStream::Transmit( const ITASampleFrame& sfNewSamples, int iNumSamples )
107
{
108
	// Take local copies (concurrent access)
109
	int iCurrentReadCursor = m_iReadCursor;
110
	int iCurrentWriteCursor = m_iWriteCursor;
111

112
113
	if( iCurrentWriteCursor < iCurrentReadCursor )
		iCurrentWriteCursor += GetRingBufferSize(); // Unwrap, because write cursor always ahead
114

115
116
117
	if( GetRingBufferFreeSamples() < iNumSamples )
	{
		// @todo: only partly write
Anne's avatar
bugfix    
Anne committed
118
		//std::cerr << "BUFFER_OVERRUN! Would partly write samples because ring buffer will be full then." << std::endl;
119
		
120
		m_iWriteCursor = m_iReadCursor;
Anne's avatar
bugfix    
Anne committed
121
122
		m_bRingBufferFull = false;
		//outputFile << " incSomeWrite: ";
123
124
125
126
	}
	else
	{
		// write samples into ring buffer
127
		m_sfRingBuffer.cyclic_write( sfNewSamples, iNumSamples, 0, iCurrentWriteCursor );
Anne's avatar
Anne committed
128

129
		// set write curser
130
		m_iWriteCursor = ( m_iWriteCursor + iNumSamples ) % GetRingBufferSize( );
Anne's avatar
bugfix    
Anne committed
131
132
		m_bRingBufferFull = true;
		//outputFile << " IncWrite: ";
133
	}
Anne's avatar
bugfix    
Anne committed
134
135
136
	//outputFile << "\tRead: " << m_iReadCursor;
	//outputFile << "\tWrite : " << m_iWriteCursor;
	//outputFile << "\tFreeSamples: " << GetRingBufferFreeSamples( ) << endl;
137
138
	
	return GetRingBufferFreeSamples();
139
140
}

141
int CITANetAudioStream::GetRingBufferFreeSamples() const
142
{
143
144
145
146
147
	if( m_bRingBufferFull )
		return 0;

	int iFreeSamples = GetRingBufferSize() - ( ( m_iWriteCursor - m_iReadCursor + GetRingBufferSize() ) % GetRingBufferSize() );
	assert( iFreeSamples > 0 );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
148
	return iFreeSamples;
149
150
}

151
int CITANetAudioStream::GetRingBufferSize() const
152
{
153
	return m_sfRingBuffer.GetLength();
154
155
}

156
157
158
159
160
161
162
163
164
165
bool CITANetAudioStream::GetIsRingBufferFull() const
{
	return m_bRingBufferFull;
}

bool CITANetAudioStream::GetIsRingBufferEmpty() const
{
	return ( !m_bRingBufferFull && m_iReadCursor == m_iWriteCursor );
}

166
unsigned int CITANetAudioStream::GetBlocklength() const
167
{
168
	return  ( unsigned int ) m_sfOutputStreamBuffer.GetLength();
169
170
}

171
unsigned int CITANetAudioStream::GetNumberOfChannels() const
172
{
173
	return ( unsigned int ) m_sfOutputStreamBuffer.channels();
174
175
}

176
double CITANetAudioStream::GetSampleRate() const
177
{
178
	return m_dSampleRate;
179
}