You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

321 lines
9.2KB

  1. /***************************************************/
  2. /*! \class InetWvIn
  3. \brief STK internet streaming input class.
  4. This Wvin subclass reads streamed audio data over a network via a
  5. TCP or UDP socket connection. The data is assumed in big-endian,
  6. or network, byte order. Only a single socket connection is
  7. supported.
  8. InetWvIn supports multi-channel data. It is important to
  9. distinguish the tick() method that computes a single frame (and
  10. returns only the specified sample of a multi-channel frame) from
  11. the overloaded one that takes an StkFrames object for
  12. multi-channel and/or multi-frame data.
  13. This class implements a socket server. When using the TCP
  14. protocol, the server "listens" for a single remote connection
  15. within the InetWvIn::start() function. For the UDP protocol, no
  16. attempt is made to verify packet delivery or order. The default
  17. data type for the incoming stream is signed 16-bit integers,
  18. though any of the defined StkFormats are permissible.
  19. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  20. */
  21. /***************************************************/
  22. #include "InetWvIn.h"
  23. #include <sstream>
  24. namespace stk {
  25. extern "C" THREAD_RETURN THREAD_TYPE inputThread( void * ptr )
  26. {
  27. ThreadInfo *info = (ThreadInfo *)ptr;
  28. while ( !info->finished ) {
  29. ((InetWvIn *) info->object)->receive();
  30. }
  31. return 0;
  32. }
  33. InetWvIn :: InetWvIn( unsigned long bufferFrames, unsigned int nBuffers )
  34. :soket_(0), buffer_(0), bufferFrames_(bufferFrames), bufferBytes_(0), nBuffers_(nBuffers), connected_(false)
  35. {
  36. threadInfo_.finished = false;
  37. threadInfo_.object = (void *) this;
  38. // Start the input thread.
  39. if ( !thread_.start( &inputThread, &threadInfo_ ) ) {
  40. oStream_ << "InetWvIn(): unable to start input thread in constructor!";
  41. handleError( StkError::PROCESS_THREAD );
  42. }
  43. }
  44. InetWvIn :: ~InetWvIn()
  45. {
  46. // Close down the thread.
  47. connected_ = false;
  48. threadInfo_.finished = true;
  49. if ( soket_ ) delete soket_;
  50. if ( buffer_ ) delete [] buffer_;
  51. }
  52. void InetWvIn :: listen( int port, unsigned int nChannels,
  53. Stk::StkFormat format, Socket::ProtocolType protocol )
  54. {
  55. mutex_.lock();
  56. if ( connected_ ) delete soket_;
  57. if ( nChannels < 1 ) {
  58. oStream_ << "InetWvIn()::listen(): the channel argument must be greater than zero.";
  59. handleError( StkError::FUNCTION_ARGUMENT );
  60. }
  61. if ( format == STK_SINT16 ) dataBytes_ = 2;
  62. else if ( format == STK_SINT32 || format == STK_FLOAT32 ) dataBytes_ = 4;
  63. else if ( format == STK_FLOAT64 ) dataBytes_ = 8;
  64. else if ( format == STK_SINT8 ) dataBytes_ = 1;
  65. else {
  66. oStream_ << "InetWvIn(): unknown data type specified!";
  67. handleError( StkError::FUNCTION_ARGUMENT );
  68. }
  69. dataType_ = format;
  70. unsigned long bufferBytes = bufferFrames_ * nBuffers_ * nChannels * dataBytes_;
  71. if ( bufferBytes > bufferBytes_ ) {
  72. if ( buffer_) delete [] buffer_;
  73. buffer_ = (char *) new char[ bufferBytes ];
  74. bufferBytes_ = bufferBytes;
  75. }
  76. data_.resize( bufferFrames_, nChannels );
  77. lastFrame_.resize( 1, nChannels, 0.0 );
  78. bufferCounter_ = 0;
  79. writePoint_ = 0;
  80. readPoint_ = 0;
  81. bytesFilled_ = 0;
  82. if ( protocol == Socket::PROTO_TCP ) {
  83. TcpServer *socket = new TcpServer( port );
  84. oStream_ << "InetWvIn:listen(): waiting for TCP connection on port " << socket->port() << " ... ";
  85. handleError( StkError::STATUS );
  86. fd_ = socket->accept();
  87. if ( fd_ < 0) {
  88. oStream_ << "InetWvIn::listen(): Error accepting TCP connection request!";
  89. handleError( StkError::PROCESS_SOCKET );
  90. }
  91. oStream_ << "InetWvIn::listen(): TCP socket connection made!";
  92. handleError( StkError::STATUS );
  93. soket_ = (Socket *) socket;
  94. }
  95. else {
  96. soket_ = new UdpSocket( port );
  97. fd_ = soket_->id();
  98. }
  99. connected_ = true;
  100. mutex_.unlock();
  101. }
  102. void InetWvIn :: receive( void )
  103. {
  104. if ( !connected_ ) {
  105. Stk::sleep(100);
  106. return;
  107. }
  108. fd_set mask;
  109. FD_ZERO( &mask );
  110. FD_SET( fd_, &mask );
  111. // The select function will block until data is available for reading.
  112. select( fd_+1, &mask, (fd_set *)0, (fd_set *)0, NULL );
  113. if ( FD_ISSET( fd_, &mask ) ) {
  114. mutex_.lock();
  115. unsigned long unfilled = bufferBytes_ - bytesFilled_;
  116. if ( unfilled > 0 ) {
  117. // There's room in our buffer for more data.
  118. unsigned long endPoint = writePoint_ + unfilled;
  119. if ( endPoint > bufferBytes_ ) unfilled -= endPoint - bufferBytes_;
  120. int i = soket_->readBuffer( fd_, (void *)&buffer_[writePoint_], unfilled, 0 );
  121. //int i = Socket::readBuffer( fd_, (void *)&buffer_[writePoint_], unfilled, 0 );
  122. if ( i <= 0 ) {
  123. oStream_ << "InetWvIn::receive(): the remote InetWvIn socket has closed.";
  124. handleError( StkError::STATUS );
  125. connected_ = false;
  126. mutex_.unlock();
  127. return;
  128. }
  129. bytesFilled_ += i;
  130. writePoint_ += i;
  131. if ( writePoint_ == bufferBytes_ )
  132. writePoint_ = 0;
  133. mutex_.unlock();
  134. }
  135. else {
  136. // Sleep 10 milliseconds AFTER unlocking mutex.
  137. mutex_.unlock();
  138. Stk::sleep( 10 );
  139. }
  140. }
  141. }
  142. int InetWvIn :: readData( void )
  143. {
  144. // We have two potential courses of action should this method
  145. // be called and the input buffer isn't sufficiently filled.
  146. // One solution is to fill the data buffer with zeros and return.
  147. // The other solution is to wait until the necessary data exists.
  148. // I chose the latter, as it works for both streamed files
  149. // (non-realtime data transport) and realtime playback (given
  150. // adequate network bandwidth and speed).
  151. // Wait until data is ready.
  152. unsigned long bytes = data_.size() * dataBytes_;
  153. while ( connected_ && bytesFilled_ < bytes )
  154. Stk::sleep( 10 );
  155. if ( !connected_ && bytesFilled_ == 0 ) return 0;
  156. bytes = ( bytesFilled_ < bytes ) ? bytesFilled_ : bytes;
  157. // Copy samples from buffer to data.
  158. StkFloat gain;
  159. long samples = bytes / dataBytes_;
  160. mutex_.lock();
  161. if ( dataType_ == STK_SINT16 ) {
  162. gain = 1.0 / 32767.0;
  163. SINT16 *buf = (SINT16 *) (buffer_+readPoint_);
  164. for (int i=0; i<samples; i++ ) {
  165. #ifdef __LITTLE_ENDIAN__
  166. swap16((unsigned char *) buf);
  167. #endif
  168. data_[i] = (StkFloat) *buf++;
  169. data_[i] *= gain;
  170. }
  171. }
  172. else if ( dataType_ == STK_SINT32 ) {
  173. gain = 1.0 / 2147483647.0;
  174. SINT32 *buf = (SINT32 *) (buffer_+readPoint_);
  175. for (int i=0; i<samples; i++ ) {
  176. #ifdef __LITTLE_ENDIAN__
  177. swap32((unsigned char *) buf);
  178. #endif
  179. data_[i] = (StkFloat) *buf++;
  180. data_[i] *= gain;
  181. }
  182. }
  183. else if ( dataType_ == STK_FLOAT32 ) {
  184. FLOAT32 *buf = (FLOAT32 *) (buffer_+readPoint_);
  185. for (int i=0; i<samples; i++ ) {
  186. #ifdef __LITTLE_ENDIAN__
  187. swap32((unsigned char *) buf);
  188. #endif
  189. data_[i] = (StkFloat) *buf++;
  190. }
  191. }
  192. else if ( dataType_ == STK_FLOAT64 ) {
  193. FLOAT64 *buf = (FLOAT64 *) (buffer_+readPoint_);
  194. for (int i=0; i<samples; i++ ) {
  195. #ifdef __LITTLE_ENDIAN__
  196. swap64((unsigned char *) buf);
  197. #endif
  198. data_[i] = (StkFloat) *buf++;
  199. }
  200. }
  201. else if ( dataType_ == STK_SINT8 ) {
  202. gain = 1.0 / 127.0;
  203. signed char *buf = (signed char *) (buffer_+readPoint_);
  204. for (int i=0; i<samples; i++ ) {
  205. data_[i] = (StkFloat) *buf++;
  206. data_[i] *= gain;
  207. }
  208. }
  209. readPoint_ += bytes;
  210. if ( readPoint_ == bufferBytes_ )
  211. readPoint_ = 0;
  212. bytesFilled_ -= bytes;
  213. mutex_.unlock();
  214. return samples / data_.channels();
  215. }
  216. bool InetWvIn :: isConnected( void )
  217. {
  218. if ( bytesFilled_ > 0 || bufferCounter_ > 0 )
  219. return true;
  220. else
  221. return connected_;
  222. }
  223. StkFloat InetWvIn :: tick( unsigned int channel )
  224. {
  225. // If no connection and we've output all samples in the queue, return 0.0.
  226. if ( !connected_ && bytesFilled_ == 0 && bufferCounter_ == 0 ) {
  227. #if defined(_STK_DEBUG_)
  228. oStream_ << "InetWvIn::tick(): a valid socket connection does not exist!";
  229. handleError( StkError::DEBUG_PRINT );
  230. #endif
  231. return 0.0;
  232. }
  233. #if defined(_STK_DEBUG_)
  234. if ( channel >= data_.channels() ) {
  235. oStream_ << "InetWvIn::tick(): channel argument is incompatible with data stream!";
  236. handleError( StkError::FUNCTION_ARGUMENT );
  237. }
  238. #endif
  239. if ( bufferCounter_ == 0 )
  240. bufferCounter_ = readData();
  241. unsigned int nChannels = lastFrame_.channels();
  242. long index = ( bufferFrames_ - bufferCounter_ ) * nChannels;
  243. for ( unsigned int i=0; i<nChannels; i++ )
  244. lastFrame_[i] = data_[index++];
  245. bufferCounter_--;
  246. if ( bufferCounter_ < 0 )
  247. bufferCounter_ = 0;
  248. return lastFrame_[channel];
  249. }
  250. StkFrames& InetWvIn :: tick( StkFrames& frames, unsigned int channel )
  251. {
  252. #if defined(_STK_DEBUG_)
  253. if ( channel > frames.channels() - data_.channels() ) {
  254. oStream_ << "InetWvIn::tick(): channel and StkFrames arguments are incompatible!";
  255. handleError( StkError::FUNCTION_ARGUMENT );
  256. }
  257. #endif
  258. // If no connection and we've output all samples in the queue, return.
  259. if ( !connected_ && bytesFilled_ == 0 && bufferCounter_ == 0 ) {
  260. #if defined(_STK_DEBUG_)
  261. oStream_ << "InetWvIn::tick(): a valid socket connection does not exist!";
  262. handleError( StkError::DEBUG_PRINT );
  263. #endif
  264. return frames;
  265. }
  266. StkFloat *samples = &frames[channel];
  267. unsigned int j, hop = frames.channels() - data_.channels();
  268. for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
  269. this->tick();
  270. for ( j=0; j<lastFrame_.channels(); j++ )
  271. *samples++ = lastFrame_[j];
  272. }
  273. return frames;
  274. }
  275. } // stk namespace