annotate stk/src/Stk.cpp @ 1:2ca5d7440b5c tip

added README
author Fiore Martin <f.martin@qmul.ac.uk>
date Fri, 26 Feb 2016 16:11:20 +0000
parents 3004dd663202
children
rev   line source
f@0 1 /***************************************************/
f@0 2 /*! \class Stk
f@0 3 \brief STK base class
f@0 4
f@0 5 Nearly all STK classes inherit from this class.
f@0 6 The global sample rate can be queried and
f@0 7 modified via Stk. In addition, this class
f@0 8 provides error handling and byte-swapping
f@0 9 functions.
f@0 10
f@0 11 The Synthesis ToolKit in C++ (STK) is a set of open source audio
f@0 12 signal processing and algorithmic synthesis classes written in the
f@0 13 C++ programming language. STK was designed to facilitate rapid
f@0 14 development of music synthesis and audio processing software, with
f@0 15 an emphasis on cross-platform functionality, realtime control,
f@0 16 ease of use, and educational example code. STK currently runs
f@0 17 with realtime support (audio and MIDI) on Linux, Macintosh OS X,
f@0 18 and Windows computer platforms. Generic, non-realtime support has
f@0 19 been tested under NeXTStep, Sun, and other platforms and should
f@0 20 work with any standard C++ compiler.
f@0 21
f@0 22 STK WWW site: http://ccrma.stanford.edu/software/stk/
f@0 23
f@0 24 The Synthesis ToolKit in C++ (STK)
f@0 25 Copyright (c) 1995--2014 Perry R. Cook and Gary P. Scavone
f@0 26
f@0 27 Permission is hereby granted, free of charge, to any person
f@0 28 obtaining a copy of this software and associated documentation files
f@0 29 (the "Software"), to deal in the Software without restriction,
f@0 30 including without limitation the rights to use, copy, modify, merge,
f@0 31 publish, distribute, sublicense, and/or sell copies of the Software,
f@0 32 and to permit persons to whom the Software is furnished to do so,
f@0 33 subject to the following conditions:
f@0 34
f@0 35 The above copyright notice and this permission notice shall be
f@0 36 included in all copies or substantial portions of the Software.
f@0 37
f@0 38 Any person wishing to distribute modifications to the Software is
f@0 39 asked to send the modifications to the original developer so that
f@0 40 they can be incorporated into the canonical version. This is,
f@0 41 however, not a binding provision of this license.
f@0 42
f@0 43 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
f@0 44 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
f@0 45 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
f@0 46 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
f@0 47 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
f@0 48 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
f@0 49 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
f@0 50 */
f@0 51 /***************************************************/
f@0 52
f@0 53 #include "../include/Stk.h"
f@0 54 #include <stdlib.h>
f@0 55
f@0 56 namespace stk {
f@0 57
f@0 58 StkFloat Stk :: srate_ = (StkFloat) SRATE;
f@0 59 std::string Stk :: rawwavepath_ = RAWWAVE_PATH;
f@0 60 const Stk::StkFormat Stk :: STK_SINT8 = 0x1;
f@0 61 const Stk::StkFormat Stk :: STK_SINT16 = 0x2;
f@0 62 const Stk::StkFormat Stk :: STK_SINT24 = 0x4;
f@0 63 const Stk::StkFormat Stk :: STK_SINT32 = 0x8;
f@0 64 const Stk::StkFormat Stk :: STK_FLOAT32 = 0x10;
f@0 65 const Stk::StkFormat Stk :: STK_FLOAT64 = 0x20;
f@0 66 bool Stk :: showWarnings_ = true;
f@0 67 bool Stk :: printErrors_ = true;
f@0 68 std::vector<Stk *> Stk :: alertList_;
f@0 69 std::ostringstream Stk :: oStream_;
f@0 70
f@0 71 Stk :: Stk( void )
f@0 72 : ignoreSampleRateChange_(false)
f@0 73 {
f@0 74 }
f@0 75
f@0 76 Stk :: ~Stk( void )
f@0 77 {
f@0 78 }
f@0 79
f@0 80 void Stk :: setSampleRate( StkFloat rate )
f@0 81 {
f@0 82 if ( rate > 0.0 && rate != srate_ ) {
f@0 83 StkFloat oldRate = srate_;
f@0 84 srate_ = rate;
f@0 85
f@0 86 for ( unsigned int i=0; i<alertList_.size(); i++ )
f@0 87 alertList_[i]->sampleRateChanged( srate_, oldRate );
f@0 88 }
f@0 89 }
f@0 90
f@0 91 void Stk :: sampleRateChanged( StkFloat /*newRate*/, StkFloat /*oldRate*/ )
f@0 92 {
f@0 93 // This function should be reimplemented in classes that need to
f@0 94 // make internal variable adjustments in response to a global sample
f@0 95 // rate change.
f@0 96 }
f@0 97
f@0 98 void Stk :: addSampleRateAlert( Stk *ptr )
f@0 99 {
f@0 100 for ( unsigned int i=0; i<alertList_.size(); i++ )
f@0 101 if ( alertList_[i] == ptr ) return;
f@0 102
f@0 103 alertList_.push_back( ptr );
f@0 104 }
f@0 105
f@0 106 void Stk :: removeSampleRateAlert( Stk *ptr )
f@0 107 {
f@0 108 for ( unsigned int i=0; i<alertList_.size(); i++ ) {
f@0 109 if ( alertList_[i] == ptr ) {
f@0 110 alertList_.erase( alertList_.begin() + i );
f@0 111 return;
f@0 112 }
f@0 113 }
f@0 114 }
f@0 115
f@0 116 void Stk :: setRawwavePath( std::string path )
f@0 117 {
f@0 118 if ( !path.empty() )
f@0 119 rawwavepath_ = path;
f@0 120
f@0 121 // Make sure the path includes a "/"
f@0 122 if ( rawwavepath_[rawwavepath_.length()-1] != '/' )
f@0 123 rawwavepath_ += "/";
f@0 124 }
f@0 125
f@0 126 void Stk :: swap16(unsigned char *ptr)
f@0 127 {
f@0 128 unsigned char val;
f@0 129
f@0 130 // Swap 1st and 2nd bytes
f@0 131 val = *(ptr);
f@0 132 *(ptr) = *(ptr+1);
f@0 133 *(ptr+1) = val;
f@0 134 }
f@0 135
f@0 136 void Stk :: swap32(unsigned char *ptr)
f@0 137 {
f@0 138 unsigned char val;
f@0 139
f@0 140 // Swap 1st and 4th bytes
f@0 141 val = *(ptr);
f@0 142 *(ptr) = *(ptr+3);
f@0 143 *(ptr+3) = val;
f@0 144
f@0 145 //Swap 2nd and 3rd bytes
f@0 146 ptr += 1;
f@0 147 val = *(ptr);
f@0 148 *(ptr) = *(ptr+1);
f@0 149 *(ptr+1) = val;
f@0 150 }
f@0 151
f@0 152 void Stk :: swap64(unsigned char *ptr)
f@0 153 {
f@0 154 unsigned char val;
f@0 155
f@0 156 // Swap 1st and 8th bytes
f@0 157 val = *(ptr);
f@0 158 *(ptr) = *(ptr+7);
f@0 159 *(ptr+7) = val;
f@0 160
f@0 161 // Swap 2nd and 7th bytes
f@0 162 ptr += 1;
f@0 163 val = *(ptr);
f@0 164 *(ptr) = *(ptr+5);
f@0 165 *(ptr+5) = val;
f@0 166
f@0 167 // Swap 3rd and 6th bytes
f@0 168 ptr += 1;
f@0 169 val = *(ptr);
f@0 170 *(ptr) = *(ptr+3);
f@0 171 *(ptr+3) = val;
f@0 172
f@0 173 // Swap 4th and 5th bytes
f@0 174 ptr += 1;
f@0 175 val = *(ptr);
f@0 176 *(ptr) = *(ptr+1);
f@0 177 *(ptr+1) = val;
f@0 178 }
f@0 179
f@0 180 #if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
f@0 181 #include <unistd.h>
f@0 182 #elif defined(__OS_WINDOWS__)
f@0 183 #include <windows.h>
f@0 184 #endif
f@0 185
f@0 186 void Stk :: sleep(unsigned long milliseconds)
f@0 187 {
f@0 188 #if defined(__OS_WINDOWS__)
f@0 189 Sleep((DWORD) milliseconds);
f@0 190 #elif (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
f@0 191 usleep( (unsigned long) (milliseconds * 1000.0) );
f@0 192 #endif
f@0 193 }
f@0 194
f@0 195 void Stk :: handleError( StkError::Type type ) const
f@0 196 {
f@0 197 handleError( oStream_.str(), type );
f@0 198 oStream_.str( std::string() ); // reset the ostringstream buffer
f@0 199 }
f@0 200
f@0 201 void Stk :: handleError( const char *message, StkError::Type type )
f@0 202 {
f@0 203 std::string msg( message );
f@0 204 handleError( msg, type );
f@0 205 }
f@0 206
f@0 207 void Stk :: handleError( std::string message, StkError::Type type )
f@0 208 {
f@0 209 if ( type == StkError::WARNING || type == StkError::STATUS ) {
f@0 210 if ( !showWarnings_ ) return;
f@0 211 std::cerr << '\n' << message << '\n' << std::endl;
f@0 212 }
f@0 213 else if (type == StkError::DEBUG_PRINT) {
f@0 214 #if defined(_STK_DEBUG_)
f@0 215 std::cerr << '\n' << message << '\n' << std::endl;
f@0 216 #endif
f@0 217 }
f@0 218 else {
f@0 219 if ( printErrors_ ) {
f@0 220 // Print error message before throwing.
f@0 221 std::cerr << '\n' << message << '\n' << std::endl;
f@0 222 }
f@0 223 throw StkError(message, type);
f@0 224 }
f@0 225 }
f@0 226
f@0 227 //
f@0 228 // StkFrames definitions
f@0 229 //
f@0 230
f@0 231 StkFrames :: StkFrames( unsigned int nFrames, unsigned int nChannels )
f@0 232 : data_( 0 ), nFrames_( nFrames ), nChannels_( nChannels )
f@0 233 {
f@0 234 size_ = nFrames_ * nChannels_;
f@0 235 bufferSize_ = size_;
f@0 236
f@0 237 if ( size_ > 0 ) {
f@0 238 data_ = (StkFloat *) calloc( size_, sizeof( StkFloat ) );
f@0 239 #if defined(_STK_DEBUG_)
f@0 240 if ( data_ == NULL ) {
f@0 241 std::string error = "StkFrames: memory allocation error in constructor!";
f@0 242 Stk::handleError( error, StkError::MEMORY_ALLOCATION );
f@0 243 }
f@0 244 #endif
f@0 245 }
f@0 246
f@0 247 dataRate_ = Stk::sampleRate();
f@0 248 }
f@0 249
f@0 250 StkFrames :: StkFrames( const StkFloat& value, unsigned int nFrames, unsigned int nChannels )
f@0 251 : data_( 0 ), nFrames_( nFrames ), nChannels_( nChannels )
f@0 252 {
f@0 253 size_ = nFrames_ * nChannels_;
f@0 254 bufferSize_ = size_;
f@0 255 if ( size_ > 0 ) {
f@0 256 data_ = (StkFloat *) malloc( size_ * sizeof( StkFloat ) );
f@0 257 #if defined(_STK_DEBUG_)
f@0 258 if ( data_ == NULL ) {
f@0 259 std::string error = "StkFrames: memory allocation error in constructor!";
f@0 260 Stk::handleError( error, StkError::MEMORY_ALLOCATION );
f@0 261 }
f@0 262 #endif
f@0 263 for ( long i=0; i<(long)size_; i++ ) data_[i] = value;
f@0 264 }
f@0 265
f@0 266 dataRate_ = Stk::sampleRate();
f@0 267 }
f@0 268
f@0 269 StkFrames :: ~StkFrames()
f@0 270 {
f@0 271 if ( data_ ) free( data_ );
f@0 272 }
f@0 273
f@0 274 StkFrames :: StkFrames( const StkFrames& f )
f@0 275 : data_(0), size_(0), bufferSize_(0)
f@0 276 {
f@0 277 resize( f.frames(), f.channels() );
f@0 278 dataRate_ = Stk::sampleRate();
f@0 279 for ( unsigned int i=0; i<size_; i++ ) data_[i] = f[i];
f@0 280 }
f@0 281
f@0 282 StkFrames& StkFrames :: operator= ( const StkFrames& f )
f@0 283 {
f@0 284 data_ = 0;
f@0 285 size_ = 0;
f@0 286 bufferSize_ = 0;
f@0 287 resize( f.frames(), f.channels() );
f@0 288 dataRate_ = Stk::sampleRate();
f@0 289 for ( unsigned int i=0; i<size_; i++ ) data_[i] = f[i];
f@0 290 return *this;
f@0 291 }
f@0 292
f@0 293 void StkFrames :: resize( size_t nFrames, unsigned int nChannels )
f@0 294 {
f@0 295 nFrames_ = nFrames;
f@0 296 nChannels_ = nChannels;
f@0 297
f@0 298 size_ = nFrames_ * nChannels_;
f@0 299 if ( size_ > bufferSize_ ) {
f@0 300 if ( data_ ) free( data_ );
f@0 301 data_ = (StkFloat *) malloc( size_ * sizeof( StkFloat ) );
f@0 302 #if defined(_STK_DEBUG_)
f@0 303 if ( data_ == NULL ) {
f@0 304 std::string error = "StkFrames::resize: memory allocation error!";
f@0 305 Stk::handleError( error, StkError::MEMORY_ALLOCATION );
f@0 306 }
f@0 307 #endif
f@0 308 bufferSize_ = size_;
f@0 309 }
f@0 310 }
f@0 311
f@0 312 void StkFrames :: resize( size_t nFrames, unsigned int nChannels, StkFloat value )
f@0 313 {
f@0 314 this->resize( nFrames, nChannels );
f@0 315
f@0 316 for ( size_t i=0; i<size_; i++ ) data_[i] = value;
f@0 317 }
f@0 318
f@0 319 StkFloat StkFrames :: interpolate( StkFloat frame, unsigned int channel ) const
f@0 320 {
f@0 321 #if defined(_STK_DEBUG_)
f@0 322 if ( frame < 0.0 || frame > (StkFloat) ( nFrames_ - 1 ) || channel >= nChannels_ ) {
f@0 323 std::ostringstream error;
f@0 324 error << "StkFrames::interpolate: invalid frame (" << frame << ") or channel (" << channel << ") value!";
f@0 325 Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
f@0 326 }
f@0 327 #endif
f@0 328
f@0 329 size_t iIndex = ( size_t ) frame; // integer part of index
f@0 330 StkFloat output, alpha = frame - (StkFloat) iIndex; // fractional part of index
f@0 331
f@0 332 iIndex = iIndex * nChannels_ + channel;
f@0 333 output = data_[ iIndex ];
f@0 334 if ( alpha > 0.0 )
f@0 335 output += ( alpha * ( data_[ iIndex + nChannels_ ] - output ) );
f@0 336
f@0 337 return output;
f@0 338 }
f@0 339
f@0 340 } // stk namespace