1 #ifndef STK_STK_H
2 #define STK_STK_H
3
4 #include <string>
5 #include <cstring>
6 #include <iostream>
7 #include <sstream>
8 #include <vector>
9 #include <stdexcept>
10 //#include <cstdlib>
11
12 /*! \namespace stk
13 \brief The STK namespace.
14
15 Most Stk classes are defined within the STK namespace. Exceptions
16 to this include the classes RtAudio and RtMidi.
17 */
18 namespace stk {
19
20 /***************************************************/
21 /*! \class Stk
22 \brief STK base class
23
24 Nearly all STK classes inherit from this class.
25 The global sample rate and rawwave path variables
26 can be queried and modified via Stk. In addition,
27 this class provides error handling and
28 byte-swapping functions.
29
30 The Synthesis ToolKit in C++ (STK) is a set of open source audio
31 signal processing and algorithmic synthesis classes written in the
32 C++ programming language. STK was designed to facilitate rapid
33 development of music synthesis and audio processing software, with
34 an emphasis on cross-platform functionality, realtime control,
35 ease of use, and educational example code. STK currently runs
36 with realtime support (audio and MIDI) on Linux, Macintosh OS X,
37 and Windows computer platforms. Generic, non-realtime support has
38 been tested under NeXTStep, Sun, and other platforms and should
39 work with any standard C++ compiler.
40
41 STK WWW site: http://ccrma.stanford.edu/software/stk/
42
43 The Synthesis ToolKit in C++ (STK)
44 Copyright (c) 1995--2021 Perry R. Cook and Gary P. Scavone
45
46 Permission is hereby granted, free of charge, to any person
47 obtaining a copy of this software and associated documentation files
48 (the "Software"), to deal in the Software without restriction,
49 including without limitation the rights to use, copy, modify, merge,
50 publish, distribute, sublicense, and/or sell copies of the Software,
51 and to permit persons to whom the Software is furnished to do so,
52 subject to the following conditions:
53
54 The above copyright notice and this permission notice shall be
55 included in all copies or substantial portions of the Software.
56
57 Any person wishing to distribute modifications to the Software is
58 asked to send the modifications to the original developer so that
59 they can be incorporated into the canonical version. This is,
60 however, not a binding provision of this license.
61
62 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
63 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
64 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
65 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
66 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
67 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
68 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
69 */
70 /***************************************************/
71
72 //#define _STK_DEBUG_
73
74 // Most data in STK is passed and calculated with the
75 // following user-definable floating-point type. You
76 // can change this to "float" if you prefer or perhaps
77 // a "long double" in the future.
78 typedef double StkFloat;
79
80 //! STK error handling class.
81 /*!
82 This is a fairly abstract exception handling class. There could
83 be sub-classes to take care of more specific error conditions ... or
84 not.
85 */
86 class StkError : public std::exception
87 {
88 public:
89 enum Type {
90 STATUS,
91 WARNING,
92 DEBUG_PRINT,
93 MEMORY_ALLOCATION,
94 MEMORY_ACCESS,
95 FUNCTION_ARGUMENT,
96 FILE_NOT_FOUND,
97 FILE_UNKNOWN_FORMAT,
98 FILE_ERROR,
99 PROCESS_THREAD,
100 PROCESS_SOCKET,
101 PROCESS_SOCKET_IPADDR,
102 AUDIO_SYSTEM,
103 MIDI_SYSTEM,
104 UNSPECIFIED
105 };
106
107 protected:
108 std::string message_;
109 Type type_;
110
111 public:
112 //! The constructor.
113 StkError(const std::string& message, Type type = StkError::UNSPECIFIED)
exception()114 : std::exception(), message_(message), type_(type) {}
115
116 //! The destructor.
~StkError(void)117 virtual ~StkError(void) throw() {};
118
119 //! Prints thrown error message to stderr.
printMessage(void)120 virtual void printMessage(void) { std::cerr << '\n' << message_ << "\n\n"; }
121
122 //! Returns the thrown error message type.
getType(void)123 virtual const Type& getType(void) { return type_; }
124
125 //! Returns the thrown error message string.
getMessage(void)126 virtual const std::string& getMessage(void) { return message_; }
127
128 //! Returns the thrown error message as a C string.
getMessageCString(void)129 virtual const char *getMessageCString(void) { return message_.c_str(); }
130
what(void)131 virtual const char *what(void) const throw() { return message_.c_str(); }
132 };
133
134
135 class Stk
136 {
137 public:
138
139 typedef unsigned long StkFormat;
140 static const StkFormat STK_SINT8; /*!< -128 to +127 */
141 static const StkFormat STK_SINT16; /*!< -32768 to +32767 */
142 static const StkFormat STK_SINT24; /*!< Lower 3 bytes of 32-bit signed integer. */
143 static const StkFormat STK_SINT32; /*!< -2147483648 to +2147483647. */
144 static const StkFormat STK_FLOAT32; /*!< Normalized between plus/minus 1.0. */
145 static const StkFormat STK_FLOAT64; /*!< Normalized between plus/minus 1.0. */
146
147 //! Static method that returns the current STK sample rate.
sampleRate(void)148 static StkFloat sampleRate( void ) { return srate_; }
149
150 //! Static method that sets the STK sample rate.
151 /*!
152 The sample rate set using this method is queried by all STK
153 classes that depend on its value. It is initialized to the
154 default SRATE set in Stk.h. Many STK classes use the sample rate
155 during instantiation. Therefore, if you wish to use a rate that
156 is different from the default rate, it is imperative that it be
157 set \e BEFORE STK objects are instantiated. A few classes that
158 make use of the global STK sample rate are automatically notified
159 when the rate changes so that internal class data can be
160 appropriately updated. However, this has not been fully
161 implemented. Specifically, classes that appropriately update
162 their own data when either a setFrequency() or noteOn() function
163 is called do not currently receive the automatic notification of
164 rate change. If the user wants a specific class instance to
165 ignore such notifications, perhaps in a multi-rate context, the
166 function Stk::ignoreSampleRateChange() should be called.
167 */
168 static void setSampleRate( StkFloat rate );
169
170 //! A function to enable/disable the automatic updating of class data when the STK sample rate changes.
171 /*!
172 This function allows the user to enable or disable class data
173 updates in response to global sample rate changes on a class by
174 class basis.
175 */
176 void ignoreSampleRateChange( bool ignore = true ) { ignoreSampleRateChange_ = ignore; };
177
178 //! Static method that frees memory from alertList_.
clear_alertList()179 static void clear_alertList(){std::vector<Stk *>().swap(alertList_);};
180
181 //! Static method that returns the current rawwave path.
rawwavePath(void)182 static std::string rawwavePath(void) { return rawwavepath_; }
183
184 //! Static method that sets the STK rawwave path.
185 static void setRawwavePath( std::string path );
186
187 //! Static method that byte-swaps a 16-bit data type.
188 static void swap16( unsigned char *ptr );
189
190 //! Static method that byte-swaps a 32-bit data type.
191 static void swap32( unsigned char *ptr );
192
193 //! Static method that byte-swaps a 64-bit data type.
194 static void swap64( unsigned char *ptr );
195
196 //! Static cross-platform method to sleep for a number of milliseconds.
197 static void sleep( unsigned long milliseconds );
198
199 //! Static method to check whether a value is within a specified range.
inRange(StkFloat value,StkFloat min,StkFloat max)200 static bool inRange( StkFloat value, StkFloat min, StkFloat max ) {
201 if ( value < min ) return false;
202 else if ( value > max ) return false;
203 else return true;
204 }
205
206 //! Static function for error reporting and handling using c-strings.
207 static void handleError( const char *message, StkError::Type type );
208
209 //! Static function for error reporting and handling using c++ strings.
210 static void handleError( std::string message, StkError::Type type );
211
212 //! Toggle display of WARNING and STATUS messages.
showWarnings(bool status)213 static void showWarnings( bool status ) { showWarnings_ = status; }
214
215 //! Toggle display of error messages before throwing exceptions.
printErrors(bool status)216 static void printErrors( bool status ) { printErrors_ = status; }
217
218 private:
219 static StkFloat srate_;
220 static std::string rawwavepath_;
221 static bool showWarnings_;
222 static bool printErrors_;
223 static std::vector<Stk *> alertList_;
224
225 protected:
226
227 static std::ostringstream oStream_;
228 bool ignoreSampleRateChange_;
229
230 //! Default constructor.
231 Stk( void );
232
233 //! Class destructor.
234 virtual ~Stk( void );
235
236 //! This function should be implemented in subclasses that depend on the sample rate.
237 virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
238
239 //! Add class pointer to list for sample rate change notification.
240 void addSampleRateAlert( Stk *ptr );
241
242 //! Remove class pointer from list for sample rate change notification.
243 void removeSampleRateAlert( Stk *ptr );
244
245 //! Internal function for error reporting that assumes message in \c oStream_ variable.
246 void handleError( StkError::Type type ) const;
247 };
248
249
250 /***************************************************/
251 /*! \class StkFrames
252 \brief An STK class to handle vectorized audio data.
253
254 This class can hold single- or multi-channel audio data. The data
255 type is always StkFloat and the channel format is always
256 interleaved. In an effort to maintain efficiency, no
257 out-of-bounds checks are performed in this class unless
258 _STK_DEBUG_ is defined.
259
260 Internally, the data is stored in a one-dimensional C array. An
261 indexing operator is available to set and retrieve data values.
262 Alternately, one can use pointers to access the data, using the
263 index operator to get an address for a particular location in the
264 data:
265
266 StkFloat* ptr = &myStkFrames[0];
267
268 Note that this class can also be used as a table with interpolating
269 lookup.
270
271 Possible future improvements in this class could include functions
272 to convert to and return other data types.
273
274 by Perry R. Cook and Gary P. Scavone, 1995--2021.
275 */
276 /***************************************************/
277
278 class StkFrames
279 {
280 public:
281
282 //! The default constructor initializes the frame data structure to size zero.
283 StkFrames( unsigned int nFrames = 0, unsigned int nChannels = 0 );
284
285 //! Overloaded constructor that initializes the frame data to the specified size with \c value.
286 StkFrames( const StkFloat& value, unsigned int nFrames, unsigned int nChannels );
287
288 //! The destructor.
289 virtual ~StkFrames();
290
291 // A copy constructor.
292 StkFrames( const StkFrames& f );
293
294 // Assignment operator that returns a reference to self.
295 virtual StkFrames& operator= ( const StkFrames& f );
296
297 //! Subscript operator that returns a reference to element \c n of self.
298 /*!
299 The result can be used as an lvalue. This reference is valid
300 until the resize function is called or the array is destroyed. The
301 index \c n must be between 0 and size less one. No range checking
302 is performed unless _STK_DEBUG_ is defined.
303 */
304 StkFloat& operator[] ( size_t n );
305
306 //! Subscript operator that returns the value at element \c n of self.
307 /*!
308 The index \c n must be between 0 and size less one. No range
309 checking is performed unless _STK_DEBUG_ is defined.
310 */
311 StkFloat operator[] ( size_t n ) const;
312
313 //! Sum operator
314 /*!
315 The dimensions of the argument are expected to be the same as
316 self. No range checking is performed unless _STK_DEBUG_ is
317 defined.
318 */
319 StkFrames operator+(const StkFrames &frames) const;
320
321 //! Assignment by sum operator into self.
322 /*!
323 The dimensions of the argument are expected to be the same as
324 self. No range checking is performed unless _STK_DEBUG_ is
325 defined.
326 */
327 StkFrames& operator+= ( StkFrames& f );
328
329 //! Assignment by product operator into self.
330 /*!
331 The dimensions of the argument are expected to be the same as
332 self. No range checking is performed unless _STK_DEBUG_ is
333 defined.
334 */
335 StkFrames& operator*= ( StkFrames& f );
336
337 //! Scaling operator (StkFrame * StkFloat).
338 StkFrames operator* ( StkFloat v ) const;
339
340 //! Scaling operator (StkFloat * StkFrame)
341 friend StkFrames operator*(StkFloat v, const StkFrames& f);
342
343 //! Scaling operator (inline).
344 StkFrames& operator*= ( StkFloat v );
345
346 //! Channel / frame subscript operator that returns a reference.
347 /*!
348 The result can be used as an lvalue. This reference is valid
349 until the resize function is called or the array is destroyed. The
350 \c frame index must be between 0 and frames() - 1. The \c channel
351 index must be between 0 and channels() - 1. No range checking is
352 performed unless _STK_DEBUG_ is defined.
353 */
354 StkFloat& operator() ( size_t frame, unsigned int channel );
355
356 //! Channel / frame subscript operator that returns a value.
357 /*!
358 The \c frame index must be between 0 and frames() - 1. The \c
359 channel index must be between 0 and channels() - 1. No range checking
360 is performed unless _STK_DEBUG_ is defined.
361 */
362 StkFloat operator() ( size_t frame, unsigned int channel ) const;
363
364 //! Return an interpolated value at the fractional frame index and channel.
365 /*!
366 This function performs linear interpolation. The \c frame
367 index must be between 0.0 and frames() - 1. The \c channel index
368 must be between 0 and channels() - 1. No range checking is
369 performed unless _STK_DEBUG_ is defined.
370 */
371 StkFloat interpolate( StkFloat frame, unsigned int channel = 0 ) const;
372
373 //! Returns the total number of audio samples represented by the object.
size()374 size_t size() const { return size_; };
375
376 //! Returns \e true if the object size is zero and \e false otherwise.
377 bool empty() const;
378
379 //! Resize self to represent the specified number of channels and frames.
380 /*!
381 Changes the size of self based on the number of frames and
382 channels. No element assignment is performed. No memory
383 deallocation occurs if the new size is smaller than the previous
384 size. Further, no new memory is allocated when the new size is
385 smaller or equal to a previously allocated size.
386 */
387 virtual void resize( size_t nFrames, unsigned int nChannels = 1 );
388
389 //! Resize self to represent the specified number of channels and frames and perform element initialization.
390 /*!
391 Changes the size of self based on the number of frames and
392 channels, and assigns \c value to every element. No memory
393 deallocation occurs if the new size is smaller than the previous
394 size. Further, no new memory is allocated when the new size is
395 smaller or equal to a previously allocated size.
396 */
397 virtual void resize( size_t nFrames, unsigned int nChannels, StkFloat value );
398
399 //! Retrieves a single channel
400 /*!
401 Copies the specified \c channel into \c destinationFrames's \c destinationChannel. \c destinationChannel must be between 0 and destination.channels() - 1 and
402 \c channel must be between 0 and channels() - 1. destination.frames() must be >= frames().
403 No range checking is performed unless _STK_DEBUG_ is defined.
404 */
405 StkFrames& getChannel(unsigned int channel,StkFrames& destinationFrames, unsigned int destinationChannel) const;
406
407 //! Sets a single channel
408 /*!
409 Copies the \c sourceChannel of \c sourceFrames into the \c channel of self.
410 SourceFrames.frames() must be equal to frames().
411 No range checking is performed unless _STK_DEBUG_ is defined.
412 */
413 void setChannel(unsigned int channel,const StkFrames &sourceFrames,unsigned int sourceChannel);
414
415 //! Return the number of channels represented by the data.
channels(void)416 unsigned int channels( void ) const { return nChannels_; };
417
418 //! Return the number of sample frames represented by the data.
frames(void)419 unsigned int frames( void ) const { return (unsigned int)nFrames_; };
420
421 //! Set the sample rate associated with the StkFrames data.
422 /*!
423 By default, this value is set equal to the current STK sample
424 rate at the time of instantiation.
425 */
setDataRate(StkFloat rate)426 void setDataRate( StkFloat rate ) { dataRate_ = rate; };
427
428 //! Return the sample rate associated with the StkFrames data.
429 /*!
430 By default, this value is set equal to the current STK sample
431 rate at the time of instantiation.
432 */
dataRate(void)433 StkFloat dataRate( void ) const { return dataRate_; };
434
435 protected:
436
437 StkFloat *data_;
438 StkFloat dataRate_;
439 size_t nFrames_;
440 unsigned int nChannels_;
441 size_t size_;
442 size_t bufferSize_;
443
444 };
445
empty()446 inline bool StkFrames :: empty() const
447 {
448 if ( size_ > 0 ) return false;
449 else return true;
450 }
451
452 inline StkFloat& StkFrames :: operator[] ( size_t n )
453 {
454 #if defined(_STK_DEBUG_)
455 if ( n >= size_ ) {
456 std::ostringstream error;
457 error << "StkFrames::operator[]: invalid index (" << n << ") value!";
458 Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
459 }
460 #endif
461
462 return data_[n];
463 }
464
465 inline StkFloat StkFrames :: operator[] ( size_t n ) const
466 {
467 #if defined(_STK_DEBUG_)
468 if ( n >= size_ ) {
469 std::ostringstream error;
470 error << "StkFrames::operator[]: invalid index (" << n << ") value!";
471 Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
472 }
473 #endif
474
475 return data_[n];
476 }
477
operator()478 inline StkFloat& StkFrames :: operator() ( size_t frame, unsigned int channel )
479 {
480 #if defined(_STK_DEBUG_)
481 if ( frame >= nFrames_ || channel >= nChannels_ ) {
482 std::ostringstream error;
483 error << "StkFrames::operator(): invalid frame (" << frame << ") or channel (" << channel << ") value!";
484 Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
485 }
486 #endif
487
488 return data_[ frame * nChannels_ + channel ];
489 }
490
operator()491 inline StkFloat StkFrames :: operator() ( size_t frame, unsigned int channel ) const
492 {
493 #if defined(_STK_DEBUG_)
494 if ( frame >= nFrames_ || channel >= nChannels_ ) {
495 std::ostringstream error;
496 error << "StkFrames::operator(): invalid frame (" << frame << ") or channel (" << channel << ") value!";
497 Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
498 }
499 #endif
500
501 return data_[ frame * nChannels_ + channel ];
502 }
503
504 inline StkFrames StkFrames::operator+(const StkFrames &f) const
505 {
506 #if defined(_STK_DEBUG_)
507 if ( f.frames() != nFrames_ || f.channels() != nChannels_ ) {
508 std::ostringstream error;
509 error << "StkFrames::operator+: frames argument must be of equal dimensions!";
510 Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
511 }
512 #endif
513 StkFrames sum((unsigned int)nFrames_,nChannels_);
514 StkFloat *sumPtr = &sum[0];
515 const StkFloat *fptr = f.data_;
516 const StkFloat *dPtr = data_;
517 for (unsigned int i = 0; i < size_; i++) {
518 *sumPtr++ = *fptr++ + *dPtr++;
519 }
520 return sum;
521 }
522
523 inline StkFrames& StkFrames :: operator+= ( StkFrames& f )
524 {
525 #if defined(_STK_DEBUG_)
526 if ( f.frames() != nFrames_ || f.channels() != nChannels_ ) {
527 std::ostringstream error;
528 error << "StkFrames::operator+=: frames argument must be of equal dimensions!";
529 Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
530 }
531 #endif
532
533 StkFloat *fptr = &f[0];
534 StkFloat *dptr = data_;
535 for ( unsigned int i=0; i<size_; i++ )
536 *dptr++ += *fptr++;
537 return *this;
538 }
539
540 inline StkFrames& StkFrames :: operator*= ( StkFrames& f )
541 {
542 #if defined(_STK_DEBUG_)
543 if ( f.frames() != nFrames_ || f.channels() != nChannels_ ) {
544 std::ostringstream error;
545 error << "StkFrames::operator*=: frames argument must be of equal dimensions!";
546 Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
547 }
548 #endif
549
550 StkFloat *fptr = &f[0];
551 StkFloat *dptr = data_;
552 for ( unsigned int i=0; i<size_; i++ )
553 *dptr++ *= *fptr++;
554 return *this;
555 }
556
557 inline StkFrames StkFrames::operator*(StkFloat v) const
558 {
559 StkFrames res((unsigned int)nFrames_, nChannels_);
560 StkFloat *resPtr = &res[0];
561 const StkFloat *dPtr = data_;
562 for (unsigned int i = 0; i < size_; i++) {
563 *resPtr++ = v * *dPtr++;
564 }
565 return res;
566 }
567
568 inline StkFrames operator*(StkFloat v, const StkFrames& f)
569 {
570 StkFrames res((unsigned int)f.nFrames_, f.nChannels_);
571 StkFloat *resPtr = &res[0];
572 StkFloat *dPtr = f.data_;
573 for (unsigned int i = 0; i < f.size_; i++) {
574 *resPtr++ = v * *dPtr++;
575 }
576 return res;
577 }
578
579 inline StkFrames& StkFrames :: operator*= ( StkFloat v )
580 {
581 StkFloat *dptr = data_;
582 for ( unsigned int i=0; i<size_; i++ )
583 *dptr++ *= v;
584 return *this;
585 }
586
587
588 // Here are a few other useful typedefs.
589 typedef unsigned short UINT16;
590 typedef unsigned int UINT32;
591 typedef signed short SINT16;
592 typedef signed int SINT32;
593 typedef float FLOAT32;
594 typedef double FLOAT64;
595
596 // The default sampling rate.
597 const StkFloat SRATE = 44100.0;
598
599 // The default real-time audio input and output buffer size. If
600 // clicks are occuring in the input and/or output sound stream, a
601 // larger buffer size may help. Larger buffer sizes, however, produce
602 // more latency.
603 const unsigned int RT_BUFFER_SIZE = 512;
604
605 // The default rawwave path value is set with the preprocessor
606 // definition RAWWAVE_PATH. This can be specified as an argument to
607 // the configure script, in an integrated development environment, or
608 // below. The global STK rawwave path variable can be dynamically set
609 // with the Stk::setRawwavePath() function. This value is
610 // concatenated to the beginning of all references to rawwave files in
611 // the various STK core classes (e.g. Clarinet.cpp). If you wish to
612 // move the rawwaves directory to a different location in your file
613 // system, you will need to set this path definition appropriately.
614 #if !defined(RAWWAVE_PATH)
615 #define RAWWAVE_PATH "../../rawwaves/"
616 #endif
617
618 const StkFloat PI = 3.14159265358979;
619 const StkFloat TWO_PI = 2 * PI;
620 const StkFloat ONE_OVER_128 = 0.0078125;
621
622 #if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_MM__)
623 #define __OS_WINDOWS__
624 #define __STK_REALTIME__
625 #elif defined(__LINUX_OSS__) || defined(__LINUX_ALSA__) || defined(__UNIX_JACK__)
626 #define __OS_LINUX__
627 #define __STK_REALTIME__
628 #elif defined(__IRIX_AL__)
629 #define __OS_IRIX__
630 #elif defined(__MACOSX_CORE__) || defined(__UNIX_JACK__)
631 #define __OS_MACOSX__
632 #define __STK_REALTIME__
633 #endif
634
635 } // stk namespace
636
637 #endif
638