mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-06-18 11:40:33 +02:00
545 lines
19 KiB
C++
545 lines
19 KiB
C++
#ifndef STK_STK_H
|
|
#define STK_STK_H
|
|
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <vector>
|
|
//#include <cstdlib>
|
|
|
|
/*! \namespace stk
|
|
\brief The STK namespace.
|
|
|
|
Most Stk classes are defined within the STK namespace. Exceptions
|
|
to this include the classes RtAudio, RtMidi, and RtError.
|
|
*/
|
|
namespace stk {
|
|
|
|
/***************************************************/
|
|
/*! \class Stk
|
|
\brief STK base class
|
|
|
|
Nearly all STK classes inherit from this class.
|
|
The global sample rate and rawwave path variables
|
|
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-2012 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.
|
|
*/
|
|
/***************************************************/
|
|
|
|
//#define _STK_DEBUG_
|
|
|
|
// Most data in STK is passed and calculated with the
|
|
// following user-definable floating-point type. You
|
|
// can change this to "float" if you prefer or perhaps
|
|
// a "long double" in the future.
|
|
typedef double StkFloat;
|
|
|
|
//! STK error handling class.
|
|
/*!
|
|
This is a fairly abstract exception handling class. There could
|
|
be sub-classes to take care of more specific error conditions ... or
|
|
not.
|
|
*/
|
|
class StkError
|
|
{
|
|
public:
|
|
enum Type {
|
|
STATUS,
|
|
WARNING,
|
|
DEBUG_PRINT,
|
|
MEMORY_ALLOCATION,
|
|
MEMORY_ACCESS,
|
|
FUNCTION_ARGUMENT,
|
|
FILE_NOT_FOUND,
|
|
FILE_UNKNOWN_FORMAT,
|
|
FILE_ERROR,
|
|
PROCESS_THREAD,
|
|
PROCESS_SOCKET,
|
|
PROCESS_SOCKET_IPADDR,
|
|
AUDIO_SYSTEM,
|
|
MIDI_SYSTEM,
|
|
UNSPECIFIED
|
|
};
|
|
|
|
protected:
|
|
std::string message_;
|
|
Type type_;
|
|
|
|
public:
|
|
//! The constructor.
|
|
StkError(const std::string& message, Type type = StkError::UNSPECIFIED)
|
|
: message_(message), type_(type) {}
|
|
|
|
//! The destructor.
|
|
virtual ~StkError(void) {};
|
|
|
|
//! Prints thrown error message to stderr.
|
|
virtual void printMessage(void) { std::cerr << '\n' << message_ << "\n\n"; }
|
|
|
|
//! Returns the thrown error message type.
|
|
virtual const Type& getType(void) { return type_; }
|
|
|
|
//! Returns the thrown error message string.
|
|
virtual const std::string& getMessage(void) { return message_; }
|
|
|
|
//! Returns the thrown error message as a C string.
|
|
virtual const char *getMessageCString(void) { return message_.c_str(); }
|
|
};
|
|
|
|
|
|
class Stk
|
|
{
|
|
public:
|
|
|
|
typedef unsigned long StkFormat;
|
|
static const StkFormat STK_SINT8; /*!< -128 to +127 */
|
|
static const StkFormat STK_SINT16; /*!< -32768 to +32767 */
|
|
static const StkFormat STK_SINT24; /*!< Lower 3 bytes of 32-bit signed integer. */
|
|
static const StkFormat STK_SINT32; /*!< -2147483648 to +2147483647. */
|
|
static const StkFormat STK_FLOAT32; /*!< Normalized between plus/minus 1.0. */
|
|
static const StkFormat STK_FLOAT64; /*!< Normalized between plus/minus 1.0. */
|
|
|
|
//! Static method that returns the current STK sample rate.
|
|
static StkFloat sampleRate( void ) { return srate_; }
|
|
|
|
//! Static method that sets the STK sample rate.
|
|
/*!
|
|
The sample rate set using this method is queried by all STK
|
|
classes that depend on its value. It is initialized to the
|
|
default SRATE set in Stk.h. Many STK classes use the sample rate
|
|
during instantiation. Therefore, if you wish to use a rate that
|
|
is different from the default rate, it is imperative that it be
|
|
set \e BEFORE STK objects are instantiated. A few classes that
|
|
make use of the global STK sample rate are automatically notified
|
|
when the rate changes so that internal class data can be
|
|
appropriately updated. However, this has not been fully
|
|
implemented. Specifically, classes that appropriately update
|
|
their own data when either a setFrequency() or noteOn() function
|
|
is called do not currently receive the automatic notification of
|
|
rate change. If the user wants a specific class instance to
|
|
ignore such notifications, perhaps in a multi-rate context, the
|
|
function Stk::ignoreSampleRateChange() should be called.
|
|
*/
|
|
static void setSampleRate( StkFloat rate );
|
|
|
|
//! A function to enable/disable the automatic updating of class data when the STK sample rate changes.
|
|
/*!
|
|
This function allows the user to enable or disable class data
|
|
updates in response to global sample rate changes on a class by
|
|
class basis.
|
|
*/
|
|
void ignoreSampleRateChange( bool ignore = true ) { ignoreSampleRateChange_ = ignore; };
|
|
|
|
//! Static method that returns the current rawwave path.
|
|
static std::string rawwavePath(void) { return rawwavepath_; }
|
|
|
|
//! Static method that sets the STK rawwave path.
|
|
static void setRawwavePath( std::string path );
|
|
|
|
//! Static method that byte-swaps a 16-bit data type.
|
|
static void swap16( unsigned char *ptr );
|
|
|
|
//! Static method that byte-swaps a 32-bit data type.
|
|
static void swap32( unsigned char *ptr );
|
|
|
|
//! Static method that byte-swaps a 64-bit data type.
|
|
static void swap64( unsigned char *ptr );
|
|
|
|
//! Static cross-platform method to sleep for a number of milliseconds.
|
|
static void sleep( unsigned long milliseconds );
|
|
|
|
//! Static method to check whether a value is within a specified range.
|
|
static bool inRange( StkFloat value, StkFloat min, StkFloat max ) {
|
|
if ( value < min ) return false;
|
|
else if ( value > max ) return false;
|
|
else return true;
|
|
}
|
|
|
|
//! Static function for error reporting and handling using c-strings.
|
|
static void handleError( const char *message, StkError::Type type );
|
|
|
|
//! Static function for error reporting and handling using c++ strings.
|
|
static void handleError( std::string message, StkError::Type type );
|
|
|
|
//! Toggle display of WARNING and STATUS messages.
|
|
static void showWarnings( bool status ) { showWarnings_ = status; }
|
|
|
|
//! Toggle display of error messages before throwing exceptions.
|
|
static void printErrors( bool status ) { printErrors_ = status; }
|
|
|
|
private:
|
|
static StkFloat srate_;
|
|
static std::string rawwavepath_;
|
|
static bool showWarnings_;
|
|
static bool printErrors_;
|
|
static std::vector<Stk *> alertList_;
|
|
|
|
protected:
|
|
|
|
static std::ostringstream oStream_;
|
|
bool ignoreSampleRateChange_;
|
|
|
|
//! Default constructor.
|
|
Stk( void );
|
|
|
|
//! Class destructor.
|
|
virtual ~Stk( void );
|
|
|
|
//! This function should be implemented in subclasses that depend on the sample rate.
|
|
virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
|
|
|
|
//! Add class pointer to list for sample rate change notification.
|
|
void addSampleRateAlert( Stk *ptr );
|
|
|
|
//! Remove class pointer from list for sample rate change notification.
|
|
void removeSampleRateAlert( Stk *ptr );
|
|
|
|
//! Internal function for error reporting that assumes message in \c oStream_ variable.
|
|
void handleError( StkError::Type type );
|
|
};
|
|
|
|
|
|
/***************************************************/
|
|
/*! \class StkFrames
|
|
\brief An STK class to handle vectorized audio data.
|
|
|
|
This class can hold single- or multi-channel audio data. The data
|
|
type is always StkFloat and the channel format is always
|
|
interleaved. In an effort to maintain efficiency, no
|
|
out-of-bounds checks are performed in this class unless
|
|
_STK_DEBUG_ is defined.
|
|
|
|
Internally, the data is stored in a one-dimensional C array. An
|
|
indexing operator is available to set and retrieve data values.
|
|
Alternately, one can use pointers to access the data, using the
|
|
index operator to get an address for a particular location in the
|
|
data:
|
|
|
|
StkFloat* ptr = &myStkFrames[0];
|
|
|
|
Note that this class can also be used as a table with interpolating
|
|
lookup.
|
|
|
|
Possible future improvements in this class could include functions
|
|
to convert to and return other data types.
|
|
|
|
by Perry R. Cook and Gary P. Scavone, 1995-2012.
|
|
*/
|
|
/***************************************************/
|
|
|
|
class StkFrames
|
|
{
|
|
public:
|
|
|
|
//! The default constructor initializes the frame data structure to size zero.
|
|
StkFrames( unsigned int nFrames = 0, unsigned int nChannels = 0 );
|
|
|
|
//! Overloaded constructor that initializes the frame data to the specified size with \c value.
|
|
StkFrames( const StkFloat& value, unsigned int nFrames, unsigned int nChannels );
|
|
|
|
//! The destructor.
|
|
~StkFrames();
|
|
|
|
// A copy constructor.
|
|
StkFrames( const StkFrames& f );
|
|
|
|
// Assignment operator that returns a reference to self.
|
|
StkFrames& operator= ( const StkFrames& f );
|
|
|
|
//! Subscript operator that returns a reference to element \c n of self.
|
|
/*!
|
|
The result can be used as an lvalue. This reference is valid
|
|
until the resize function is called or the array is destroyed. The
|
|
index \c n must be between 0 and size less one. No range checking
|
|
is performed unless _STK_DEBUG_ is defined.
|
|
*/
|
|
StkFloat& operator[] ( size_t n );
|
|
|
|
//! Subscript operator that returns the value at element \c n of self.
|
|
/*!
|
|
The index \c n must be between 0 and size less one. No range
|
|
checking is performed unless _STK_DEBUG_ is defined.
|
|
*/
|
|
StkFloat operator[] ( size_t n ) const;
|
|
|
|
//! Assignment by sum operator into self.
|
|
/*!
|
|
The dimensions of the argument are expected to be the same as
|
|
self. No range checking is performed unless _STK_DEBUG_ is
|
|
defined.
|
|
*/
|
|
void operator+= ( StkFrames& f );
|
|
|
|
//! Assignment by product operator into self.
|
|
/*!
|
|
The dimensions of the argument are expected to be the same as
|
|
self. No range checking is performed unless _STK_DEBUG_ is
|
|
defined.
|
|
*/
|
|
void operator*= ( StkFrames& f );
|
|
|
|
//! Channel / frame subscript operator that returns a reference.
|
|
/*!
|
|
The result can be used as an lvalue. This reference is valid
|
|
until the resize function is called or the array is destroyed. The
|
|
\c frame index must be between 0 and frames() - 1. The \c channel
|
|
index must be between 0 and channels() - 1. No range checking is
|
|
performed unless _STK_DEBUG_ is defined.
|
|
*/
|
|
StkFloat& operator() ( size_t frame, unsigned int channel );
|
|
|
|
//! Channel / frame subscript operator that returns a value.
|
|
/*!
|
|
The \c frame index must be between 0 and frames() - 1. The \c
|
|
channel index must be between 0 and channels() - 1. No range checking
|
|
is performed unless _STK_DEBUG_ is defined.
|
|
*/
|
|
StkFloat operator() ( size_t frame, unsigned int channel ) const;
|
|
|
|
//! Return an interpolated value at the fractional frame index and channel.
|
|
/*!
|
|
This function performs linear interpolation. The \c frame
|
|
index must be between 0.0 and frames() - 1. The \c channel index
|
|
must be between 0 and channels() - 1. No range checking is
|
|
performed unless _STK_DEBUG_ is defined.
|
|
*/
|
|
StkFloat interpolate( StkFloat frame, unsigned int channel = 0 ) const;
|
|
|
|
//! Returns the total number of audio samples represented by the object.
|
|
size_t size() const { return size_; };
|
|
|
|
//! Returns \e true if the object size is zero and \e false otherwise.
|
|
bool empty() const;
|
|
|
|
//! Resize self to represent the specified number of channels and frames.
|
|
/*!
|
|
Changes the size of self based on the number of frames and
|
|
channels. No element assignment is performed. No memory
|
|
deallocation occurs if the new size is smaller than the previous
|
|
size. Further, no new memory is allocated when the new size is
|
|
smaller or equal to a previously allocated size.
|
|
*/
|
|
void resize( size_t nFrames, unsigned int nChannels = 1 );
|
|
|
|
//! Resize self to represent the specified number of channels and frames and perform element initialization.
|
|
/*!
|
|
Changes the size of self based on the number of frames and
|
|
channels, and assigns \c value to every element. No memory
|
|
deallocation occurs if the new size is smaller than the previous
|
|
size. Further, no new memory is allocated when the new size is
|
|
smaller or equal to a previously allocated size.
|
|
*/
|
|
void resize( size_t nFrames, unsigned int nChannels, StkFloat value );
|
|
|
|
//! Return the number of channels represented by the data.
|
|
unsigned int channels( void ) const { return nChannels_; };
|
|
|
|
//! Return the number of sample frames represented by the data.
|
|
unsigned int frames( void ) const { return nFrames_; };
|
|
|
|
//! Set the sample rate associated with the StkFrames data.
|
|
/*!
|
|
By default, this value is set equal to the current STK sample
|
|
rate at the time of instantiation.
|
|
*/
|
|
void setDataRate( StkFloat rate ) { dataRate_ = rate; };
|
|
|
|
//! Return the sample rate associated with the StkFrames data.
|
|
/*!
|
|
By default, this value is set equal to the current STK sample
|
|
rate at the time of instantiation.
|
|
*/
|
|
StkFloat dataRate( void ) const { return dataRate_; };
|
|
|
|
private:
|
|
|
|
StkFloat *data_;
|
|
StkFloat dataRate_;
|
|
size_t nFrames_;
|
|
unsigned int nChannels_;
|
|
size_t size_;
|
|
size_t bufferSize_;
|
|
|
|
};
|
|
|
|
inline bool StkFrames :: empty() const
|
|
{
|
|
if ( size_ > 0 ) return false;
|
|
else return true;
|
|
}
|
|
|
|
inline StkFloat& StkFrames :: operator[] ( size_t n )
|
|
{
|
|
#if defined(_STK_DEBUG_)
|
|
if ( n >= size_ ) {
|
|
std::ostringstream error;
|
|
error << "StkFrames::operator[]: invalid index (" << n << ") value!";
|
|
Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
|
|
}
|
|
#endif
|
|
|
|
return data_[n];
|
|
}
|
|
|
|
inline StkFloat StkFrames :: operator[] ( size_t n ) const
|
|
{
|
|
#if defined(_STK_DEBUG_)
|
|
if ( n >= size_ ) {
|
|
std::ostringstream error;
|
|
error << "StkFrames::operator[]: invalid index (" << n << ") value!";
|
|
Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
|
|
}
|
|
#endif
|
|
|
|
return data_[n];
|
|
}
|
|
|
|
inline StkFloat& StkFrames :: operator() ( size_t frame, unsigned int channel )
|
|
{
|
|
#if defined(_STK_DEBUG_)
|
|
if ( frame >= nFrames_ || channel >= nChannels_ ) {
|
|
std::ostringstream error;
|
|
error << "StkFrames::operator(): invalid frame (" << frame << ") or channel (" << channel << ") value!";
|
|
Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
|
|
}
|
|
#endif
|
|
|
|
return data_[ frame * nChannels_ + channel ];
|
|
}
|
|
|
|
inline StkFloat StkFrames :: operator() ( size_t frame, unsigned int channel ) const
|
|
{
|
|
#if defined(_STK_DEBUG_)
|
|
if ( frame >= nFrames_ || channel >= nChannels_ ) {
|
|
std::ostringstream error;
|
|
error << "StkFrames::operator(): invalid frame (" << frame << ") or channel (" << channel << ") value!";
|
|
Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
|
|
}
|
|
#endif
|
|
|
|
return data_[ frame * nChannels_ + channel ];
|
|
}
|
|
|
|
inline void StkFrames :: operator+= ( StkFrames& f )
|
|
{
|
|
#if defined(_STK_DEBUG_)
|
|
if ( f.frames() != nFrames_ || f.channels() != nChannels_ ) {
|
|
std::ostringstream error;
|
|
error << "StkFrames::operator+=: frames argument must be of equal dimensions!";
|
|
Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
|
|
}
|
|
#endif
|
|
|
|
StkFloat *fptr = &f[0];
|
|
StkFloat *dptr = data_;
|
|
for ( unsigned int i=0; i<size_; i++ )
|
|
*dptr++ += *fptr++;
|
|
}
|
|
|
|
inline void StkFrames :: operator*= ( StkFrames& f )
|
|
{
|
|
#if defined(_STK_DEBUG_)
|
|
if ( f.frames() != nFrames_ || f.channels() != nChannels_ ) {
|
|
std::ostringstream error;
|
|
error << "StkFrames::operator*=: frames argument must be of equal dimensions!";
|
|
Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
|
|
}
|
|
#endif
|
|
|
|
StkFloat *fptr = &f[0];
|
|
StkFloat *dptr = data_;
|
|
for ( unsigned int i=0; i<size_; i++ )
|
|
*dptr++ *= *fptr++;
|
|
}
|
|
|
|
// Here are a few other useful typedefs.
|
|
typedef unsigned short UINT16;
|
|
typedef unsigned int UINT32;
|
|
typedef signed short SINT16;
|
|
typedef signed int SINT32;
|
|
typedef float FLOAT32;
|
|
typedef double FLOAT64;
|
|
|
|
// The default sampling rate.
|
|
const StkFloat SRATE = 44100.0;
|
|
|
|
// The default real-time audio input and output buffer size. If
|
|
// clicks are occuring in the input and/or output sound stream, a
|
|
// larger buffer size may help. Larger buffer sizes, however, produce
|
|
// more latency.
|
|
const unsigned int RT_BUFFER_SIZE = 512;
|
|
|
|
// The default rawwave path value is set with the preprocessor
|
|
// definition RAWWAVE_PATH. This can be specified as an argument to
|
|
// the configure script, in an integrated development environment, or
|
|
// below. The global STK rawwave path variable can be dynamically set
|
|
// with the Stk::setRawwavePath() function. This value is
|
|
// concatenated to the beginning of all references to rawwave files in
|
|
// the various STK core classes (ex. Clarinet.cpp). If you wish to
|
|
// move the rawwaves directory to a different location in your file
|
|
// system, you will need to set this path definition appropriately.
|
|
#if !defined(RAWWAVE_PATH)
|
|
#define RAWWAVE_PATH "../../rawwaves/"
|
|
#endif
|
|
|
|
const StkFloat PI = 3.14159265358979;
|
|
const StkFloat TWO_PI = 2 * PI;
|
|
const StkFloat ONE_OVER_128 = 0.0078125;
|
|
|
|
#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_MM__)
|
|
#define __OS_WINDOWS__
|
|
#define __STK_REALTIME__
|
|
#elif defined(__LINUX_OSS__) || defined(__LINUX_ALSA__) || defined(__UNIX_JACK__)
|
|
#define __OS_LINUX__
|
|
#define __STK_REALTIME__
|
|
#elif defined(__IRIX_AL__)
|
|
#define __OS_IRIX__
|
|
#elif defined(__MACOSX_CORE__) || defined(__UNIX_JACK__)
|
|
#define __OS_MACOSX__
|
|
#define __STK_REALTIME__
|
|
#endif
|
|
|
|
} // stk namespace
|
|
|
|
#endif
|