f@0: /***************************************************/ f@0: /*! \class Stk f@0: \brief STK base class f@0: f@0: Nearly all STK classes inherit from this class. f@0: The global sample rate can be queried and f@0: modified via Stk. In addition, this class f@0: provides error handling and byte-swapping f@0: functions. f@0: f@0: The Synthesis ToolKit in C++ (STK) is a set of open source audio f@0: signal processing and algorithmic synthesis classes written in the f@0: C++ programming language. STK was designed to facilitate rapid f@0: development of music synthesis and audio processing software, with f@0: an emphasis on cross-platform functionality, realtime control, f@0: ease of use, and educational example code. STK currently runs f@0: with realtime support (audio and MIDI) on Linux, Macintosh OS X, f@0: and Windows computer platforms. Generic, non-realtime support has f@0: been tested under NeXTStep, Sun, and other platforms and should f@0: work with any standard C++ compiler. f@0: f@0: STK WWW site: http://ccrma.stanford.edu/software/stk/ f@0: f@0: The Synthesis ToolKit in C++ (STK) f@0: Copyright (c) 1995--2014 Perry R. Cook and Gary P. Scavone f@0: f@0: Permission is hereby granted, free of charge, to any person f@0: obtaining a copy of this software and associated documentation files f@0: (the "Software"), to deal in the Software without restriction, f@0: including without limitation the rights to use, copy, modify, merge, f@0: publish, distribute, sublicense, and/or sell copies of the Software, f@0: and to permit persons to whom the Software is furnished to do so, f@0: subject to the following conditions: f@0: f@0: The above copyright notice and this permission notice shall be f@0: included in all copies or substantial portions of the Software. f@0: f@0: Any person wishing to distribute modifications to the Software is f@0: asked to send the modifications to the original developer so that f@0: they can be incorporated into the canonical version. This is, f@0: however, not a binding provision of this license. f@0: f@0: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, f@0: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF f@0: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. f@0: IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR f@0: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF f@0: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION f@0: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. f@0: */ f@0: /***************************************************/ f@0: f@0: #include "../include/Stk.h" f@0: #include f@0: f@0: namespace stk { f@0: f@0: StkFloat Stk :: srate_ = (StkFloat) SRATE; f@0: std::string Stk :: rawwavepath_ = RAWWAVE_PATH; f@0: const Stk::StkFormat Stk :: STK_SINT8 = 0x1; f@0: const Stk::StkFormat Stk :: STK_SINT16 = 0x2; f@0: const Stk::StkFormat Stk :: STK_SINT24 = 0x4; f@0: const Stk::StkFormat Stk :: STK_SINT32 = 0x8; f@0: const Stk::StkFormat Stk :: STK_FLOAT32 = 0x10; f@0: const Stk::StkFormat Stk :: STK_FLOAT64 = 0x20; f@0: bool Stk :: showWarnings_ = true; f@0: bool Stk :: printErrors_ = true; f@0: std::vector Stk :: alertList_; f@0: std::ostringstream Stk :: oStream_; f@0: f@0: Stk :: Stk( void ) f@0: : ignoreSampleRateChange_(false) f@0: { f@0: } f@0: f@0: Stk :: ~Stk( void ) f@0: { f@0: } f@0: f@0: void Stk :: setSampleRate( StkFloat rate ) f@0: { f@0: if ( rate > 0.0 && rate != srate_ ) { f@0: StkFloat oldRate = srate_; f@0: srate_ = rate; f@0: f@0: for ( unsigned int i=0; isampleRateChanged( srate_, oldRate ); f@0: } f@0: } f@0: f@0: void Stk :: sampleRateChanged( StkFloat /*newRate*/, StkFloat /*oldRate*/ ) f@0: { f@0: // This function should be reimplemented in classes that need to f@0: // make internal variable adjustments in response to a global sample f@0: // rate change. f@0: } f@0: f@0: void Stk :: addSampleRateAlert( Stk *ptr ) f@0: { f@0: for ( unsigned int i=0; i f@0: #elif defined(__OS_WINDOWS__) f@0: #include f@0: #endif f@0: f@0: void Stk :: sleep(unsigned long milliseconds) f@0: { f@0: #if defined(__OS_WINDOWS__) f@0: Sleep((DWORD) milliseconds); f@0: #elif (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) f@0: usleep( (unsigned long) (milliseconds * 1000.0) ); f@0: #endif f@0: } f@0: f@0: void Stk :: handleError( StkError::Type type ) const f@0: { f@0: handleError( oStream_.str(), type ); f@0: oStream_.str( std::string() ); // reset the ostringstream buffer f@0: } f@0: f@0: void Stk :: handleError( const char *message, StkError::Type type ) f@0: { f@0: std::string msg( message ); f@0: handleError( msg, type ); f@0: } f@0: f@0: void Stk :: handleError( std::string message, StkError::Type type ) f@0: { f@0: if ( type == StkError::WARNING || type == StkError::STATUS ) { f@0: if ( !showWarnings_ ) return; f@0: std::cerr << '\n' << message << '\n' << std::endl; f@0: } f@0: else if (type == StkError::DEBUG_PRINT) { f@0: #if defined(_STK_DEBUG_) f@0: std::cerr << '\n' << message << '\n' << std::endl; f@0: #endif f@0: } f@0: else { f@0: if ( printErrors_ ) { f@0: // Print error message before throwing. f@0: std::cerr << '\n' << message << '\n' << std::endl; f@0: } f@0: throw StkError(message, type); f@0: } f@0: } f@0: f@0: // f@0: // StkFrames definitions f@0: // f@0: f@0: StkFrames :: StkFrames( unsigned int nFrames, unsigned int nChannels ) f@0: : data_( 0 ), nFrames_( nFrames ), nChannels_( nChannels ) f@0: { f@0: size_ = nFrames_ * nChannels_; f@0: bufferSize_ = size_; f@0: f@0: if ( size_ > 0 ) { f@0: data_ = (StkFloat *) calloc( size_, sizeof( StkFloat ) ); f@0: #if defined(_STK_DEBUG_) f@0: if ( data_ == NULL ) { f@0: std::string error = "StkFrames: memory allocation error in constructor!"; f@0: Stk::handleError( error, StkError::MEMORY_ALLOCATION ); f@0: } f@0: #endif f@0: } f@0: f@0: dataRate_ = Stk::sampleRate(); f@0: } f@0: f@0: StkFrames :: StkFrames( const StkFloat& value, unsigned int nFrames, unsigned int nChannels ) f@0: : data_( 0 ), nFrames_( nFrames ), nChannels_( nChannels ) f@0: { f@0: size_ = nFrames_ * nChannels_; f@0: bufferSize_ = size_; f@0: if ( size_ > 0 ) { f@0: data_ = (StkFloat *) malloc( size_ * sizeof( StkFloat ) ); f@0: #if defined(_STK_DEBUG_) f@0: if ( data_ == NULL ) { f@0: std::string error = "StkFrames: memory allocation error in constructor!"; f@0: Stk::handleError( error, StkError::MEMORY_ALLOCATION ); f@0: } f@0: #endif f@0: for ( long i=0; i<(long)size_; i++ ) data_[i] = value; f@0: } f@0: f@0: dataRate_ = Stk::sampleRate(); f@0: } f@0: f@0: StkFrames :: ~StkFrames() f@0: { f@0: if ( data_ ) free( data_ ); f@0: } f@0: f@0: StkFrames :: StkFrames( const StkFrames& f ) f@0: : data_(0), size_(0), bufferSize_(0) f@0: { f@0: resize( f.frames(), f.channels() ); f@0: dataRate_ = Stk::sampleRate(); f@0: for ( unsigned int i=0; i bufferSize_ ) { f@0: if ( data_ ) free( data_ ); f@0: data_ = (StkFloat *) malloc( size_ * sizeof( StkFloat ) ); f@0: #if defined(_STK_DEBUG_) f@0: if ( data_ == NULL ) { f@0: std::string error = "StkFrames::resize: memory allocation error!"; f@0: Stk::handleError( error, StkError::MEMORY_ALLOCATION ); f@0: } f@0: #endif f@0: bufferSize_ = size_; f@0: } f@0: } f@0: f@0: void StkFrames :: resize( size_t nFrames, unsigned int nChannels, StkFloat value ) f@0: { f@0: this->resize( nFrames, nChannels ); f@0: f@0: for ( size_t i=0; i (StkFloat) ( nFrames_ - 1 ) || channel >= nChannels_ ) { f@0: std::ostringstream error; f@0: error << "StkFrames::interpolate: invalid frame (" << frame << ") or channel (" << channel << ") value!"; f@0: Stk::handleError( error.str(), StkError::MEMORY_ACCESS ); f@0: } f@0: #endif f@0: f@0: size_t iIndex = ( size_t ) frame; // integer part of index f@0: StkFloat output, alpha = frame - (StkFloat) iIndex; // fractional part of index f@0: f@0: iIndex = iIndex * nChannels_ + channel; f@0: output = data_[ iIndex ]; f@0: if ( alpha > 0.0 ) f@0: output += ( alpha * ( data_[ iIndex + nChannels_ ] - output ) ); f@0: f@0: return output; f@0: } f@0: f@0: } // stk namespace