1
/******************************************/
3
StrmWvOut Audio Output Class,
4
by Gary P. Scavone, 2000
6
This object inherits from WvOut and is used
7
to send 16-bit data (signed integer) via
8
a socket connection (streamed audio).
9
Streamed data must be in big-endian format,
10
which conforms to network byte ordering.
12
This class connects to a socket server, the
13
port and IP address of which must be specified
14
as constructor arguments. No data buffering
15
is currently implemented. The class simply
16
fires off a buffer of data over the socket
17
connection as soon as it is filled.
19
/******************************************/
21
#include "StrmWvOut.h"
23
#if defined(__STK_REALTIME_)
25
#ifdef __LITTLE_ENDIAN__
29
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
30
#include <sys/socket.h>
31
#include <arpa/inet.h>
35
#elif defined(__OS_Win_)
40
StrmWvOut :: StrmWvOut(int port, const char *hostname, int chans)
43
struct sockaddr_in server_address;
46
sprintf(msg, "StrmWvOut: number of channels (%d) must be one or greater.\n", chans);
47
throw StkError(msg, StkError::FUNCTION_SYNTAX);
52
#if defined(__OS_Win_) // Windoze-only stuff
54
WORD wVersionRequested = MAKEWORD(1,1);
56
WSAStartup(wVersionRequested, &wsaData);
57
if (wsaData.wVersion != wVersionRequested) {
58
sprintf(msg, "StrmWvOut: Wrong Windoze socket library version!\n");
59
throw StkError(msg, StkError::PROCESS_SOCKET);
63
// Create the client-side socket
64
local_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
65
if (local_socket < 0) {
66
sprintf(msg, "StrmWvOut: Couldn't create socket!\n");
67
throw StkError(msg, StkError::PROCESS_SOCKET);
70
struct hostent *hostp;
72
if ((hostp = gethostbyname(hostname)) == 0) {
73
sprintf(msg, "StrmWvOut: unknown host (%s)!\n", hostname);
74
throw StkError(msg, StkError::PROCESS_SOCKET_IPADDR);
77
// Fill in the address structure
78
server_address.sin_family = AF_INET;
79
memcpy((void *)&server_address.sin_addr, hostp->h_addr, hostp->h_length);
80
server_address.sin_port = htons(port);
82
// Connect to the server
83
if (connect(local_socket, (struct sockaddr *)&server_address,
84
sizeof(server_address) ) < 0) {
85
#if defined(__OS_Win_)
86
closesocket(local_socket);
91
sprintf(msg, "StrmWvOut: Couldn't connect to socket server!\n");
92
throw StkError(msg, StkError::PROCESS_SOCKET);
95
data_length = RT_BUFFER_SIZE*channels; // samples
96
// Add a few extra samples for good measure
97
data = (INT16 *) new INT16[data_length+10];
100
StrmWvOut :: ~StrmWvOut()
102
while (counter<data_length) {
105
send(local_socket, (const char *)data, data_length*2, 0);
107
#if defined(__OS_Win_)
108
closesocket(local_socket);
115
void StrmWvOut :: tick(MY_FLOAT sample)
117
static INT16 isample;
119
isample = (INT16) (sample * 32000.0);
120
#ifdef __LITTLE_ENDIAN__
121
swap16 ((unsigned char *)&isample);
123
for (int i=0;i<channels;i++)
124
data[counter++] = isample;
126
if (counter >= data_length) {
127
if (send(local_socket, (const char *)data, data_length*2, 0) < 0) {
129
#if defined(__OS_Win_)
130
closesocket(local_socket);
135
sprintf(msg, "StrmWvOut: connection to socket server failed!\n");
136
throw StkError(msg, StkError::PROCESS_SOCKET);
142
void StrmWvOut :: mtick(MY_MULTI samples)
144
for (int i=0;i<channels;i++) {
145
data[counter] = (INT16) (*samples++ * 32000.0);
146
#ifdef __LITTLE_ENDIAN__
147
swap16((unsigned char *)&data[counter]);
152
if (counter >= data_length) {
153
if (send(local_socket, (const char *)data, data_length*2, 0) < 0) {
155
#if defined(__OS_Win_)
156
closesocket(local_socket);
161
sprintf(msg, "StrmWvOut: connection to socket server failed!\n");
162
throw StkError(msg, StkError::PROCESS_SOCKET);