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