-
Notifications
You must be signed in to change notification settings - Fork 187
/
Copy pathInetWvOut.cpp
231 lines (203 loc) · 6.5 KB
/
InetWvOut.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/***************************************************/
/*! \class InetWvOut
\brief STK internet streaming output class.
This WvOut subclass can stream data over a network via a TCP or
UDP socket connection. The data is converted to big-endian byte
order, if necessary, before being transmitted.
InetWvOut supports multi-channel data. It is important to
distinguish the tick() method that outputs a single sample to all
channels in a sample frame from the overloaded one that takes a
reference to an StkFrames object for multi-channel and/or
multi-frame data.
This class connects to a socket server, the port and IP address of
which must be specified as constructor arguments. The default
data type is signed 16-bit integers but any of the defined
StkFormats are permissible.
by Perry R. Cook and Gary P. Scavone, 1995--2023.
*/
/***************************************************/
#include "InetWvOut.h"
#include "TcpClient.h"
#include "UdpSocket.h"
#include <sstream>
namespace stk {
InetWvOut :: InetWvOut( unsigned long packetFrames )
: buffer_(0), soket_(0), bufferFrames_(packetFrames), bufferBytes_(0)
{
}
InetWvOut :: InetWvOut( int port, Socket::ProtocolType protocol, std::string hostname,
unsigned int nChannels, Stk::StkFormat format, unsigned long packetFrames )
: buffer_(0), soket_(0), bufferFrames_(packetFrames), bufferBytes_(0)
{
connect( port, protocol, hostname, nChannels, format );
}
InetWvOut :: ~InetWvOut()
{
disconnect();
if ( soket_ ) delete soket_;
if ( buffer_ ) delete [] buffer_;
}
void InetWvOut :: connect( int port, Socket::ProtocolType protocol, std::string hostname,
unsigned int nChannels, Stk::StkFormat format )
{
if ( soket_ && soket_->isValid( soket_->id() ) )
disconnect();
if ( nChannels == 0 ) {
oStream_ << "InetWvOut::connect: the channel argument must be greater than zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( format == STK_SINT8 ) dataBytes_ = 1;
else if ( format == STK_SINT16 ) dataBytes_ = 2;
else if ( format == STK_SINT32 || format == STK_FLOAT32 ) dataBytes_ = 4;
else if ( format == STK_FLOAT64 ) dataBytes_ = 8;
else {
oStream_ << "InetWvOut::connect: unknown data type specified.";
handleError( StkError::FUNCTION_ARGUMENT );
}
dataType_ = format;
if ( protocol == Socket::PROTO_TCP ) {
soket_ = new TcpClient( port, hostname );
}
else {
// For UDP sockets, the sending and receiving sockets cannot have
// the same port number. Since the port argument corresponds to
// the destination port, we will associate this socket instance
// with a different port number (arbitrarily determined as port -
// 1).
UdpSocket *socket = new UdpSocket( port - 1 );
socket->setDestination( port, hostname );
soket_ = (Socket *) socket;
}
// Allocate new memory if necessary.
data_.resize( bufferFrames_, nChannels );
unsigned long bufferBytes = dataBytes_ * bufferFrames_ * nChannels;
if ( bufferBytes > bufferBytes_ ) {
if ( buffer_) delete [] buffer_;
buffer_ = (char *) new char[ bufferBytes ];
bufferBytes_ = bufferBytes;
}
frameCounter_ = 0;
bufferIndex_ = 0;
iData_ = 0;
}
void InetWvOut :: disconnect(void)
{
if ( soket_ ) {
writeData( bufferIndex_ );
soket_->close( soket_->id() );
delete soket_;
soket_ = 0;
}
}
void InetWvOut :: writeData( unsigned long frames )
{
unsigned long samples = frames * data_.channels();
if ( dataType_ == STK_SINT8 ) {
signed char *ptr = (signed char *) buffer_;
for ( unsigned long k=0; k<samples; k++ ) {
this->clipTest( data_[k] );
*ptr++ = (signed char) (data_[k] * 127.0);
}
}
else if ( dataType_ == STK_SINT16 ) {
SINT16 *ptr = (SINT16 *) buffer_;
for ( unsigned long k=0; k<samples; k++ ) {
this->clipTest( data_[k] );
*ptr = (SINT16) (data_[k] * 32767.0);
#ifdef __LITTLE_ENDIAN__
swap16 ((unsigned char *)ptr);
#endif
ptr++;
}
}
else if ( dataType_ == STK_SINT32 ) {
SINT32 *ptr = (SINT32 *) buffer_;
for ( unsigned long k=0; k<samples; k++ ) {
this->clipTest( data_[k] );
*ptr = (SINT32) (data_[k] * 2147483647.0);
#ifdef __LITTLE_ENDIAN__
swap32 ((unsigned char *)ptr);
#endif
ptr++;
}
}
else if ( dataType_ == STK_FLOAT32 ) {
FLOAT32 *ptr = (FLOAT32 *) buffer_;
for ( unsigned long k=0; k<samples; k++ ) {
this->clipTest( data_[k] );
*ptr = (FLOAT32) data_[k];
#ifdef __LITTLE_ENDIAN__
swap32 ((unsigned char *)ptr);
#endif
ptr++;
}
}
else if ( dataType_ == STK_FLOAT64 ) {
FLOAT64 *ptr = (FLOAT64 *) buffer_;
for ( unsigned long k=0; k<samples; k++ ) {
this->clipTest( data_[k] );
*ptr = (FLOAT64) data_[k];
#ifdef __LITTLE_ENDIAN__
swap64 ((unsigned char *)ptr);
#endif
ptr++;
}
}
long bytes = dataBytes_ * samples;
if ( soket_->writeBuffer( (const void *)buffer_, bytes, 0 ) < 0 ) {
oStream_ << "InetWvOut: connection to socket server failed!";
handleError( StkError::PROCESS_SOCKET );
}
}
void InetWvOut :: incrementFrame( void )
{
frameCounter_++;
bufferIndex_++;
if ( bufferIndex_ == bufferFrames_ ) {
writeData( bufferFrames_ );
bufferIndex_ = 0;
iData_ = 0;
}
}
void InetWvOut :: tick( const StkFloat sample )
{
if ( !soket_ || !soket_->isValid( soket_->id() ) ) {
#if defined(_STK_DEBUG_)
oStream_ << "InetWvOut::tick(): a valid socket connection does not exist!";
handleError( StkError::DEBUG_PRINT );
#endif
return;
}
unsigned int nChannels = data_.channels();
StkFloat input = sample;
clipTest( input );
for ( unsigned int j=0; j<nChannels; j++ )
data_[iData_++] = input;
this->incrementFrame();
}
void InetWvOut :: tick( const StkFrames& frames )
{
if ( !soket_ || !soket_->isValid( soket_->id() ) ) {
#if defined(_STK_DEBUG_)
oStream_ << "InetWvOut::tick(): a valid socket connection does not exist!";
handleError( StkError::DEBUG_PRINT );
#endif
return;
}
#if defined(_STK_DEBUG_)
if ( data_.channels() != frames.channels() ) {
oStream_ << "InetWvOut::tick(): incompatible channel value in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
unsigned int j, nChannels = data_.channels();
unsigned int iFrames = 0;
for ( unsigned int i=0; i<frames.frames(); i++ ) {
for ( j=0; j<nChannels; j++ ) {
data_[iData_] = frames[iFrames++];
clipTest( data_[iData_++] );
}
this->incrementFrame();
}
}
} // stk namespace