1 /***************************************************/ 2 /*! \class FileWvOut 3 \brief STK audio file output class. 4 5 This class inherits from WvOut. It provides a "tick-level" 6 interface to the FileWrite class. 7 8 FileWvOut writes samples to an audio file and supports 9 multi-channel data. It is important to distinguish the tick() 10 method that outputs a single sample to all channels in a sample 11 frame from the overloaded one that takes a reference to an 12 StkFrames object for multi-channel and/or multi-frame data. 13 14 See the FileWrite class for a description of the supported audio 15 file formats. 16 17 Currently, FileWvOut is non-interpolating and the output rate is 18 always Stk::sampleRate(). 19 20 by Perry R. Cook and Gary P. Scavone, 1995--2021. 21 */ 22 /***************************************************/ 23 24 #include "FileWvOut.h" 25 26 namespace stk { 27 28 FileWvOut :: FileWvOut( unsigned int bufferFrames ) 29 :bufferFrames_( bufferFrames ) 30 { 31 } 32 33 FileWvOut::FileWvOut( std::string fileName, unsigned int nChannels, FileWrite::FILE_TYPE type, Stk::StkFormat format, unsigned int bufferFrames ) 34 :bufferFrames_( bufferFrames ) 35 { 36 this->openFile( fileName, nChannels, type, format ); 37 } 38 39 FileWvOut :: ~FileWvOut() 40 { 41 this->closeFile(); 42 } 43 44 void FileWvOut :: closeFile( void ) 45 { 46 if ( file_.isOpen() ) { 47 48 // Output any remaining samples in the buffer before closing. 49 if ( bufferIndex_ > 0 ) { 50 data_.resize( bufferIndex_, data_.channels() ); 51 file_.write( data_ ); 52 } 53 54 file_.close(); 55 frameCounter_ = 0; 56 } 57 } 58 59 void FileWvOut :: openFile( std::string fileName, 60 unsigned int nChannels, 61 FileWrite::FILE_TYPE type, 62 Stk::StkFormat format ) 63 { 64 closeFile(); 65 66 if ( nChannels < 1 ) { 67 oStream_ << "FileWvOut::openFile: the channels argument must be greater than zero!"; 68 handleError( StkError::FUNCTION_ARGUMENT ); 69 } 70 71 // An StkError can be thrown by the FileWrite class here. 72 file_.open( fileName, nChannels, type, format ); 73 74 // Allocate new memory if necessary. 75 data_.resize( bufferFrames_, nChannels ); 76 77 bufferIndex_ = 0; 78 iData_ = 0; 79 } 80 81 void FileWvOut :: incrementFrame( void ) 82 { 83 frameCounter_++; 84 bufferIndex_++; 85 86 if ( bufferIndex_ == bufferFrames_ ) { 87 file_.write( data_ ); 88 bufferIndex_ = 0; 89 iData_ = 0; 90 } 91 } 92 93 void FileWvOut :: tick( const StkFloat sample ) 94 { 95 #if defined(_STK_DEBUG_) 96 if ( !file_.isOpen() ) { 97 oStream_ << "FileWvOut::tick(): no file open!"; 98 handleError( StkError::WARNING ); 99 return; 100 } 101 #endif 102 103 unsigned int nChannels = data_.channels(); 104 StkFloat input = sample; 105 clipTest( input ); 106 for ( unsigned int j=0; j<nChannels; j++ ) 107 data_[iData_++] = input; 108 109 this->incrementFrame(); 110 } 111 112 void FileWvOut :: tick( const StkFrames& frames ) 113 { 114 #if defined(_STK_DEBUG_) 115 if ( !file_.isOpen() ) { 116 oStream_ << "FileWvOut::tick(): no file open!"; 117 handleError( StkError::WARNING ); 118 return; 119 } 120 121 if ( data_.channels() != frames.channels() ) { 122 oStream_ << "FileWvOut::tick(): incompatible channel value in StkFrames argument!"; 123 handleError( StkError::FUNCTION_ARGUMENT ); 124 } 125 #endif 126 127 unsigned int iFrames = 0; 128 unsigned int j, nChannels = data_.channels(); 129 for ( unsigned int i=0; i<frames.frames(); i++ ) { 130 131 for ( j=0; j<nChannels; j++ ) { 132 data_[iData_] = frames[iFrames++]; 133 clipTest( data_[iData_++] ); 134 } 135 136 this->incrementFrame(); 137 } 138 } 139 140 } // stk namespace 141