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.

214 lines
6.4KB

  1. /***************************************************/
  2. /*! \class RtWvOut
  3. \brief STK realtime audio (blocking) output class.
  4. This class provides a simplified interface to RtAudio for realtime
  5. audio output. It is a subclass of WvOut. This class makes use of
  6. RtAudio's callback functionality by creating a large ring-buffer
  7. into which data is written. This class should not be used when
  8. low-latency is desired.
  9. RtWvOut supports multi-channel data in interleaved format. It is
  10. important to distinguish the tick() method that outputs a single
  11. sample to all channels in a sample frame from the overloaded one
  12. that takes a reference to an StkFrames object for multi-channel
  13. and/or multi-frame data.
  14. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  15. */
  16. /***************************************************/
  17. #include "RtWvOut.h"
  18. #include <cstring>
  19. namespace stk {
  20. // Streaming status states.
  21. enum { RUNNING, EMPTYING, FINISHED };
  22. // This function is automatically called by RtAudio to get audio data for output.
  23. int write( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
  24. double streamTime, RtAudioStreamStatus status, void *dataPointer )
  25. {
  26. return ( (RtWvOut *) dataPointer )->readBuffer( outputBuffer, nBufferFrames );
  27. }
  28. // This function does not block. If the user does not write output
  29. // data to the buffer fast enough, previous data will be re-output
  30. // (data underrun).
  31. int RtWvOut :: readBuffer( void *buffer, unsigned int frameCount )
  32. {
  33. unsigned int nSamples, nChannels = data_.channels();
  34. unsigned int nFrames = frameCount;
  35. StkFloat *input = (StkFloat *) &data_[ readIndex_ * nChannels ];
  36. StkFloat *output = (StkFloat *) buffer;
  37. long counter;
  38. while ( nFrames > 0 ) {
  39. // I'm assuming that both the RtAudio and StkFrames buffers
  40. // contain interleaved data.
  41. counter = nFrames;
  42. // Pre-increment read pointer and check bounds.
  43. readIndex_ += nFrames;
  44. if ( readIndex_ >= data_.frames() ) {
  45. counter -= readIndex_ - data_.frames();
  46. readIndex_ = 0;
  47. }
  48. // Copy data from the StkFrames container.
  49. if ( status_ == EMPTYING && framesFilled_ <= counter ) {
  50. nSamples = framesFilled_ * nChannels;
  51. unsigned int i;
  52. for ( i=0; i<nSamples; i++ ) *output++ = *input++;
  53. nSamples = (counter - framesFilled_) * nChannels;
  54. for ( i=0; i<nSamples; i++ ) *output++ = 0.0;
  55. status_ = FINISHED;
  56. return 1;
  57. }
  58. else {
  59. nSamples = counter * nChannels;
  60. for ( unsigned int i=0; i<nSamples; i++ )
  61. *output++ = *input++;
  62. }
  63. nFrames -= counter;
  64. }
  65. mutex_.lock();
  66. framesFilled_ -= frameCount;
  67. mutex_.unlock();
  68. if ( framesFilled_ < 0 ) {
  69. framesFilled_ = 0;
  70. // writeIndex_ = readIndex_;
  71. oStream_ << "RtWvOut: audio buffer underrun!";
  72. handleError( StkError::WARNING );
  73. }
  74. return 0;
  75. }
  76. RtWvOut :: RtWvOut( unsigned int nChannels, StkFloat sampleRate, int device, int bufferFrames, int nBuffers )
  77. : stopped_( true ), readIndex_( 0 ), writeIndex_( 0 ), framesFilled_( 0 ), status_(0)
  78. {
  79. // We'll let RtAudio deal with channel and sample rate limitations.
  80. RtAudio::StreamParameters parameters;
  81. if ( device == 0 )
  82. parameters.deviceId = dac_.getDefaultOutputDevice();
  83. else
  84. parameters.deviceId = device - 1;
  85. parameters.nChannels = nChannels;
  86. unsigned int size = bufferFrames;
  87. RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
  88. // Open a stream and set the callback function.
  89. try {
  90. dac_.openStream( &parameters, NULL, format, (unsigned int)Stk::sampleRate(), &size, &write, (void *)this );
  91. }
  92. catch ( RtAudioError &error ) {
  93. handleError( error.what(), StkError::AUDIO_SYSTEM );
  94. }
  95. data_.resize( size * nBuffers, nChannels );
  96. // Start writing half-way into buffer.
  97. writeIndex_ = (unsigned int ) (data_.frames() / 2.0);
  98. framesFilled_ = writeIndex_;
  99. }
  100. RtWvOut :: ~RtWvOut( void )
  101. {
  102. // Change status flag to signal callback to clear the buffer and close.
  103. status_ = EMPTYING;
  104. while ( status_ != FINISHED || dac_.isStreamRunning() == true ) Stk::sleep( 100 );
  105. dac_.closeStream();
  106. }
  107. void RtWvOut :: start( void )
  108. {
  109. if ( stopped_ ) {
  110. dac_.startStream();
  111. stopped_ = false;
  112. }
  113. }
  114. void RtWvOut :: stop( void )
  115. {
  116. if ( !stopped_ ) {
  117. dac_.stopStream();
  118. stopped_ = true;
  119. }
  120. }
  121. void RtWvOut :: tick( const StkFloat sample )
  122. {
  123. if ( stopped_ ) this->start();
  124. // Block until we have room for at least one frame of output data.
  125. while ( framesFilled_ == (long) data_.frames() ) Stk::sleep( 1 );
  126. unsigned int nChannels = data_.channels();
  127. StkFloat input = sample;
  128. clipTest( input );
  129. unsigned long index = writeIndex_ * nChannels;
  130. for ( unsigned int j=0; j<nChannels; j++ )
  131. data_[index++] = input;
  132. mutex_.lock();
  133. framesFilled_++;
  134. mutex_.unlock();
  135. frameCounter_++;
  136. writeIndex_++;
  137. if ( writeIndex_ == data_.frames() )
  138. writeIndex_ = 0;
  139. }
  140. void RtWvOut :: tick( const StkFrames& frames )
  141. {
  142. #if defined(_STK_DEBUG_)
  143. if ( data_.channels() != frames.channels() ) {
  144. oStream_ << "RtWvOut::tick(): incompatible channel value in StkFrames argument!";
  145. handleError( StkError::FUNCTION_ARGUMENT );
  146. }
  147. #endif
  148. if ( stopped_ ) this->start();
  149. // See how much space we have and fill as much as we can ... if we
  150. // still have samples left in the frames object, then wait and
  151. // repeat.
  152. unsigned int framesEmpty, nFrames, bytes, framesWritten = 0;
  153. unsigned int nChannels = data_.channels();
  154. while ( framesWritten < frames.frames() ) {
  155. // Block until we have some room for output data.
  156. while ( framesFilled_ == (long) data_.frames() ) Stk::sleep( 1 );
  157. framesEmpty = data_.frames() - framesFilled_;
  158. // Copy data in one chunk up to the end of the data buffer.
  159. nFrames = framesEmpty;
  160. if ( writeIndex_ + nFrames > data_.frames() )
  161. nFrames = data_.frames() - writeIndex_;
  162. if ( nFrames > frames.frames() - framesWritten )
  163. nFrames = frames.frames() - framesWritten;
  164. bytes = nFrames * nChannels * sizeof( StkFloat );
  165. StkFloat *samples = &data_[writeIndex_ * nChannels];
  166. StkFrames *ins = (StkFrames *) &frames;
  167. memcpy( samples, &(*ins)[framesWritten * nChannels], bytes );
  168. for ( unsigned int i=0; i<nFrames * nChannels; i++ ) clipTest( *samples++ );
  169. writeIndex_ += nFrames;
  170. if ( writeIndex_ == data_.frames() ) writeIndex_ = 0;
  171. framesWritten += nFrames;
  172. mutex_.lock();
  173. framesFilled_ += nFrames;
  174. mutex_.unlock();
  175. frameCounter_ += nFrames;
  176. }
  177. }
  178. } // stk namespace