├── .gitignore ├── README.md ├── juce_module_info ├── stk.cpp ├── stk.h ├── stk.mm └── stk ├── .DS_Store ├── ADSR.cpp ├── ADSR.h ├── Asymp.cpp ├── Asymp.h ├── BandedWG.cpp ├── BandedWG.h ├── BeeThree.cpp ├── BeeThree.h ├── BiQuad.cpp ├── BiQuad.h ├── Blit.cpp ├── Blit.h ├── BlitSaw.cpp ├── BlitSaw.h ├── BlitSquare.cpp ├── BlitSquare.h ├── BlowBotl.cpp ├── BlowBotl.h ├── BlowHole.cpp ├── BlowHole.h ├── BowTable.h ├── Bowed.cpp ├── Bowed.h ├── Brass.cpp ├── Brass.h ├── Chorus.cpp ├── Chorus.h ├── Clarinet.cpp ├── Clarinet.h ├── Cubic.h ├── Delay.cpp ├── Delay.h ├── DelayA.cpp ├── DelayA.h ├── DelayL.cpp ├── DelayL.h ├── Drummer.cpp ├── Drummer.h ├── Echo.cpp ├── Echo.h ├── Effect.h ├── Envelope.cpp ├── Envelope.h ├── FM.cpp ├── FM.h ├── FMVoices.cpp ├── FMVoices.h ├── FileLoop.cpp ├── FileLoop.h ├── FileRead.cpp ├── FileRead.h ├── FileWrite.cpp ├── FileWrite.h ├── FileWvIn.cpp ├── FileWvIn.h ├── FileWvOut.cpp ├── FileWvOut.h ├── Filter.h ├── Fir.cpp ├── Fir.h ├── Flute.cpp ├── Flute.h ├── FormSwep.cpp ├── FormSwep.h ├── Function.h ├── Generator.h ├── Granulate.cpp ├── Granulate.h ├── HevyMetl.cpp ├── HevyMetl.h ├── Iir.cpp ├── Iir.h ├── InetWvIn.cpp ├── InetWvIn.h ├── InetWvOut.cpp ├── InetWvOut.h ├── Instrmnt.h ├── JCRev.cpp ├── JCRev.h ├── JetTable.h ├── LentPitShift.cpp ├── LentPitShift.h ├── Mandolin.cpp ├── Mandolin.h ├── Mesh2D.cpp ├── Mesh2D.h ├── Messager.cpp ├── Messager.h ├── MidiFileIn.cpp ├── MidiFileIn.h ├── Modal.cpp ├── Modal.h ├── ModalBar.cpp ├── ModalBar.h ├── Modulate.cpp ├── Modulate.h ├── Moog.cpp ├── Moog.h ├── Mutex.cpp ├── Mutex.h ├── NRev.cpp ├── NRev.h ├── Noise.cpp ├── Noise.h ├── OnePole.cpp ├── OnePole.h ├── OneZero.cpp ├── OneZero.h ├── PRCRev.cpp ├── PRCRev.h ├── PercFlut.cpp ├── PercFlut.h ├── Phonemes.cpp ├── Phonemes.h ├── PitShift.cpp ├── PitShift.h ├── Plucked.cpp ├── Plucked.h ├── PoleZero.cpp ├── PoleZero.h ├── ReedTable.h ├── Resonate.cpp ├── Resonate.h ├── Rhodey.cpp ├── Rhodey.h ├── RtAudio.cpp ├── RtAudio.h ├── RtError.h ├── RtMidi.cpp ├── RtMidi.h ├── RtWvIn.cpp ├── RtWvIn.h ├── RtWvOut.cpp ├── RtWvOut.h ├── SKINI.msg ├── SKINI.tbl ├── Sampler.cpp ├── Sampler.h ├── Saxofony.cpp ├── Saxofony.h ├── Shakers.cpp ├── Shakers.h ├── Simple.cpp ├── Simple.h ├── SineWave.cpp ├── SineWave.h ├── SingWave.cpp ├── SingWave.h ├── Sitar.cpp ├── Sitar.h ├── Skini.cpp ├── Skini.h ├── Socket.cpp ├── Socket.h ├── Sphere.cpp ├── Sphere.h ├── StifKarp.cpp ├── StifKarp.h ├── Stk.cpp ├── Stk.h ├── TapDelay.cpp ├── TapDelay.h ├── TcpClient.cpp ├── TcpClient.h ├── TcpServer.cpp ├── TcpServer.h ├── Thread.cpp ├── Thread.h ├── TubeBell.cpp ├── TubeBell.h ├── Twang.cpp ├── Twang.h ├── TwoPole.cpp ├── TwoPole.h ├── TwoZero.cpp ├── TwoZero.h ├── UdpSocket.cpp ├── UdpSocket.h ├── Vector3D.h ├── VoicForm.cpp ├── VoicForm.h ├── Voicer.cpp ├── Voicer.h ├── Whistle.cpp ├── Whistle.h ├── Wurley.cpp ├── Wurley.h ├── WvIn.h └── WvOut.h /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_STORE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | stk_module 2 | ========== 3 | 4 | JUCE module wrapper for the STK library. 5 | 6 | This wrapper has all the real-time classes (audio-in, threading, sockets etc.) removed to reduce external dependancies and because JUCE provides all of this functionality. 7 | 8 | This module is designed as a quick way to add effects and generators to a JUCE based audio project. To use simply add the module to the JUCE modules folder, create a new project in the Introjucer and add the module. All the classes are in the stk namespace. 9 | 10 | There are a few amendments to the STK codebase in order to remove some compiler warnings. -------------------------------------------------------------------------------- /juce_module_info: -------------------------------------------------------------------------------- 1 | { 2 | "id": "stk", 3 | "name": "STK Library", 4 | "version": "4.4.3", 5 | "description": "STK Library for audio sysnthesis and effects", 6 | "website": "https://ccrma.stanford.edu/software/stk", 7 | "license": "GPL/Commercial", 8 | 9 | "dependencies": [ { "id": "juce_core", "version": "matching" } ], 10 | 11 | "include": "stk.h", 12 | 13 | "compile": [ { "file": "stk.cpp", "target": "! xcode" }, 14 | { "file": "stk.mm", "target": "xcode" } ], 15 | 16 | "browse": [ "stk/*" ] 17 | } 18 | -------------------------------------------------------------------------------- /stk.mm: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | The Synthesis ToolKit in C++ (STK) is a set of open source audio 5 | signal processing and algorithmic synthesis classes written in the 6 | C++ programming language. STK was designed to facilitate rapid 7 | development of music synthesis and audio processing software, with 8 | an emphasis on cross-platform functionality, realtime control, 9 | ease of use, and educational example code. STK currently runs 10 | with realtime support (audio and MIDI) on Linux, Macintosh OS X, 11 | and Windows computer platforms. Generic, non-realtime support has 12 | been tested under NeXTStep, Sun, and other platforms and should 13 | work with any standard C++ compiler. 14 | 15 | STK WWW site: http://ccrma.stanford.edu/software/stk/ 16 | 17 | The Synthesis ToolKit in C++ (STK) 18 | Copyright (c) 1995-2011 Perry R. Cook and Gary P. Scavone 19 | 20 | Permission is hereby granted, free of charge, to any person 21 | obtaining a copy of this software and associated documentation files 22 | (the "Software"), to deal in the Software without restriction, 23 | including without limitation the rights to use, copy, modify, merge, 24 | publish, distribute, sublicense, and/or sell copies of the Software, 25 | and to permit persons to whom the Software is furnished to do so, 26 | subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be 29 | included in all copies or substantial portions of the Software. 30 | 31 | Any person wishing to distribute modifications to the Software is 32 | asked to send the modifications to the original developer so that 33 | they can be incorporated into the canonical version. This is, 34 | however, not a binding provision of this license. 35 | 36 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 37 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 38 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 39 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 40 | ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 41 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 42 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 43 | 44 | ============================================================================== 45 | */ 46 | 47 | #include "stk.cpp" 48 | -------------------------------------------------------------------------------- /stk/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drowaudio/stk_module/c7298c47a78ca30cb0ea75aea534618d6a5b5f3c/stk/.DS_Store -------------------------------------------------------------------------------- /stk/Asymp.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Asymp 3 | \brief STK asymptotic curve envelope class 4 | 5 | This class implements a simple envelope generator 6 | which asymptotically approaches a target value. 7 | The algorithm used is of the form: 8 | 9 | y[n] = a y[n-1] + (1-a) target, 10 | 11 | where a = exp(-T/tau), T is the sample period, and 12 | tau is a time constant. The user can set the time 13 | constant (default value = 0.3) and target value. 14 | Theoretically, this recursion never reaches its 15 | target, though the calculations in this class are 16 | stopped when the current value gets within a small 17 | threshold value of the target (at which time the 18 | current value is set to the target). It responds 19 | to \e keyOn and \e keyOff messages by ramping to 20 | 1.0 on keyOn and to 0.0 on keyOff. 21 | 22 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 23 | */ 24 | /***************************************************/ 25 | 26 | #include "Asymp.h" 27 | #include 28 | 29 | namespace stk { 30 | 31 | Asymp :: Asymp( void ) 32 | { 33 | value_ = 0.0; 34 | target_ = 0.0; 35 | state_ = 0; 36 | factor_ = exp( -1.0 / ( 0.3 * Stk::sampleRate() ) ); 37 | constant_ = 0.0; 38 | Stk::addSampleRateAlert( this ); 39 | } 40 | 41 | Asymp :: ~Asymp( void ) 42 | { 43 | } 44 | 45 | void Asymp :: sampleRateChanged( StkFloat newRate, StkFloat oldRate ) 46 | { 47 | if ( !ignoreSampleRateChange_ ) { 48 | StkFloat tau = -1.0 / ( std::log( factor_ ) * oldRate ); 49 | factor_ = std::exp( -1.0 / ( tau * newRate ) ); 50 | } 51 | } 52 | 53 | void Asymp :: keyOn( void ) 54 | { 55 | this->setTarget( 1.0 ); 56 | } 57 | 58 | void Asymp :: keyOff( void ) 59 | { 60 | this->setTarget( 0.0 ); 61 | } 62 | 63 | void Asymp :: setTau( StkFloat tau ) 64 | { 65 | if ( tau <= 0.0 ) { 66 | oStream_ << "Asymp::setTau: negative or zero tau not allowed!"; 67 | handleError( StkError::WARNING ); return; 68 | } 69 | 70 | factor_ = std::exp( -1.0 / ( tau * Stk::sampleRate() ) ); 71 | constant_ = ( 1.0 - factor_ ) * target_; 72 | } 73 | 74 | void Asymp :: setTime( StkFloat time ) 75 | { 76 | if ( time <= 0.0 ) { 77 | oStream_ << "Asymp::setTime: negative or zero times not allowed!"; 78 | handleError( StkError::WARNING ); return; 79 | } 80 | 81 | StkFloat tau = -time / std::log( TARGET_THRESHOLD ); 82 | factor_ = std::exp( -1.0 / ( tau * Stk::sampleRate() ) ); 83 | constant_ = ( 1.0 - factor_ ) * target_; 84 | } 85 | 86 | void Asymp :: setT60( StkFloat t60 ) 87 | { 88 | if ( t60 <= 0.0 ) { 89 | oStream_ << "Asymp::setT60: negative or zero t60 not allowed!"; 90 | handleError( StkError::WARNING ); return; 91 | } 92 | 93 | setTau( t60 / 6.91 ); 94 | } 95 | 96 | void Asymp :: setTarget( StkFloat target ) 97 | { 98 | target_ = target; 99 | if ( value_ != target_ ) state_ = 1; 100 | constant_ = ( 1.0 - factor_ ) * target_; 101 | } 102 | 103 | void Asymp :: setValue( StkFloat value ) 104 | { 105 | state_ = 0; 106 | target_ = value; 107 | value_ = value; 108 | } 109 | 110 | } // stk namespace 111 | 112 | -------------------------------------------------------------------------------- /stk/BeeThree.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class BeeThree 3 | \brief STK Hammond-oid organ FM synthesis instrument. 4 | 5 | This class implements a simple 4 operator 6 | topology, also referred to as algorithm 8 of 7 | the TX81Z. 8 | 9 | \code 10 | Algorithm 8 is : 11 | 1 --. 12 | 2 -\| 13 | +-> Out 14 | 3 -/| 15 | 4 -- 16 | \endcode 17 | 18 | Control Change Numbers: 19 | - Operator 4 (feedback) Gain = 2 20 | - Operator 3 Gain = 4 21 | - LFO Speed = 11 22 | - LFO Depth = 1 23 | - ADSR 2 & 4 Target = 128 24 | 25 | The basic Chowning/Stanford FM patent expired 26 | in 1995, but there exist follow-on patents, 27 | mostly assigned to Yamaha. If you are of the 28 | type who should worry about this (making 29 | money) worry away. 30 | 31 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 32 | */ 33 | /***************************************************/ 34 | 35 | #include "BeeThree.h" 36 | 37 | namespace stk { 38 | 39 | BeeThree :: BeeThree( void ) 40 | : FM() 41 | { 42 | // Concatenate the STK rawwave path to the rawwave files 43 | for ( unsigned int i=0; i<3; i++ ) 44 | waves_[i] = new FileLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true ); 45 | waves_[3] = new FileLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true ); 46 | 47 | this->setRatio( 0, 0.999 ); 48 | this->setRatio( 1, 1.997 ); 49 | this->setRatio( 2, 3.006 ); 50 | this->setRatio( 3, 6.009 ); 51 | 52 | gains_[0] = fmGains_[95]; 53 | gains_[1] = fmGains_[95]; 54 | gains_[2] = fmGains_[99]; 55 | gains_[3] = fmGains_[95]; 56 | 57 | adsr_[0]->setAllTimes( 0.005, 0.003, 1.0, 0.01 ); 58 | adsr_[1]->setAllTimes( 0.005, 0.003, 1.0, 0.01 ); 59 | adsr_[2]->setAllTimes( 0.005, 0.003, 1.0, 0.01 ); 60 | adsr_[3]->setAllTimes( 0.005, 0.001, 0.4, 0.03 ); 61 | 62 | twozero_.setGain( 0.1 ); 63 | } 64 | 65 | BeeThree :: ~BeeThree( void ) 66 | { 67 | } 68 | 69 | void BeeThree :: noteOn( StkFloat frequency, StkFloat amplitude ) 70 | { 71 | gains_[0] = amplitude * fmGains_[95]; 72 | gains_[1] = amplitude * fmGains_[95]; 73 | gains_[2] = amplitude * fmGains_[99]; 74 | gains_[3] = amplitude * fmGains_[95]; 75 | this->setFrequency( frequency ); 76 | this->keyOn(); 77 | } 78 | 79 | } // stk namespace 80 | -------------------------------------------------------------------------------- /stk/BiQuad.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class BiQuad 3 | \brief STK biquad (two-pole, two-zero) filter class. 4 | 5 | This class implements a two-pole, two-zero digital filter. 6 | Methods are provided for creating a resonance or notch in the 7 | frequency response while maintaining a constant filter gain. 8 | 9 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 10 | */ 11 | /***************************************************/ 12 | 13 | #include "BiQuad.h" 14 | #include 15 | 16 | namespace stk { 17 | 18 | BiQuad :: BiQuad() : Filter() 19 | { 20 | b_.resize( 3, 0.0 ); 21 | a_.resize( 3, 0.0 ); 22 | b_[0] = 1.0; 23 | a_[0] = 1.0; 24 | inputs_.resize( 3, 1, 0.0 ); 25 | outputs_.resize( 3, 1, 0.0 ); 26 | 27 | Stk::addSampleRateAlert( this ); 28 | } 29 | 30 | BiQuad :: ~BiQuad() 31 | { 32 | Stk::removeSampleRateAlert( this ); 33 | } 34 | 35 | void BiQuad :: setCoefficients( StkFloat b0, StkFloat b1, StkFloat b2, StkFloat a1, StkFloat a2, bool clearState ) 36 | { 37 | b_[0] = b0; 38 | b_[1] = b1; 39 | b_[2] = b2; 40 | a_[1] = a1; 41 | a_[2] = a2; 42 | 43 | if ( clearState ) this->clear(); 44 | } 45 | 46 | void BiQuad :: sampleRateChanged( StkFloat newRate, StkFloat oldRate ) 47 | { 48 | if ( !ignoreSampleRateChange_ ) { 49 | oStream_ << "BiQuad::sampleRateChanged: you may need to recompute filter coefficients!"; 50 | handleError( StkError::WARNING ); 51 | } 52 | } 53 | 54 | void BiQuad :: setResonance( StkFloat frequency, StkFloat radius, bool normalize ) 55 | { 56 | #if defined(_STK_DEBUG_) 57 | if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) { 58 | oStream_ << "BiQuad::setResonance: frequency argument (" << frequency << ") is out of range!"; 59 | handleError( StkError::WARNING ); return; 60 | } 61 | if ( radius < 0.0 || radius >= 1.0 ) { 62 | oStream_ << "BiQuad::setResonance: radius argument (" << radius << ") is out of range!"; 63 | handleError( StkError::WARNING ); return; 64 | } 65 | #endif 66 | 67 | a_[2] = radius * radius; 68 | a_[1] = -2.0 * radius * cos( TWO_PI * frequency / Stk::sampleRate() ); 69 | 70 | if ( normalize ) { 71 | // Use zeros at +- 1 and normalize the filter peak gain. 72 | b_[0] = 0.5 - 0.5 * a_[2]; 73 | b_[1] = 0.0; 74 | b_[2] = -b_[0]; 75 | } 76 | } 77 | 78 | void BiQuad :: setNotch( StkFloat frequency, StkFloat radius ) 79 | { 80 | #if defined(_STK_DEBUG_) 81 | if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) { 82 | oStream_ << "BiQuad::setNotch: frequency argument (" << frequency << ") is out of range!"; 83 | handleError( StkError::WARNING ); return; 84 | } 85 | if ( radius < 0.0 ) { 86 | oStream_ << "BiQuad::setNotch: radius argument (" << radius << ") is negative!"; 87 | handleError( StkError::WARNING ); return; 88 | } 89 | #endif 90 | 91 | // This method does not attempt to normalize the filter gain. 92 | b_[2] = radius * radius; 93 | b_[1] = (StkFloat) -2.0 * radius * cos( TWO_PI * (double) frequency / Stk::sampleRate() ); 94 | } 95 | 96 | void BiQuad :: setEqualGainZeroes( void ) 97 | { 98 | b_[0] = 1.0; 99 | b_[1] = 0.0; 100 | b_[2] = -1.0; 101 | } 102 | 103 | } // stk namespace 104 | -------------------------------------------------------------------------------- /stk/Blit.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Blit 3 | \brief STK band-limited impulse train class. 4 | 5 | This class generates a band-limited impulse train using a 6 | closed-form algorithm reported by Stilson and Smith in "Alias-Free 7 | Digital Synthesis of Classic Analog Waveforms", 1996. The user 8 | can specify both the fundamental frequency of the impulse train 9 | and the number of harmonics contained in the resulting signal. 10 | 11 | The signal is normalized so that the peak value is +/-1.0. 12 | 13 | If nHarmonics is 0, then the signal will contain all harmonics up 14 | to half the sample rate. Note, however, that this setting may 15 | produce aliasing in the signal when the frequency is changing (no 16 | automatic modification of the number of harmonics is performed by 17 | the setFrequency() function). 18 | 19 | Original code by Robin Davies, 2005. 20 | Revisions by Gary Scavone for STK, 2005. 21 | */ 22 | /***************************************************/ 23 | 24 | #include "Blit.h" 25 | 26 | namespace stk { 27 | 28 | Blit:: Blit( StkFloat frequency ) 29 | { 30 | if ( frequency <= 0.0 ) { 31 | oStream_ << "Blit::Blit: argument (" << frequency << ") must be positive!"; 32 | handleError( StkError::FUNCTION_ARGUMENT ); 33 | } 34 | 35 | nHarmonics_ = 0; 36 | this->setFrequency( frequency ); 37 | this->reset(); 38 | } 39 | 40 | Blit :: ~Blit() 41 | { 42 | } 43 | 44 | void Blit :: reset() 45 | { 46 | phase_ = 0.0; 47 | lastFrame_[0] = 0.0; 48 | } 49 | 50 | void Blit :: setFrequency( StkFloat frequency ) 51 | { 52 | if ( frequency <= 0.0 ) { 53 | oStream_ << "Blit::setFrequency: argument (" << frequency << ") must be positive!"; 54 | handleError( StkError::WARNING ); return; 55 | } 56 | 57 | p_ = Stk::sampleRate() / frequency; 58 | rate_ = PI / p_; 59 | this->updateHarmonics(); 60 | } 61 | 62 | void Blit :: setHarmonics( unsigned int nHarmonics ) 63 | { 64 | nHarmonics_ = nHarmonics; 65 | this->updateHarmonics(); 66 | } 67 | 68 | void Blit :: updateHarmonics( void ) 69 | { 70 | if ( nHarmonics_ <= 0 ) { 71 | unsigned int maxHarmonics = (unsigned int) floor( 0.5 * p_ ); 72 | m_ = 2 * maxHarmonics + 1; 73 | } 74 | else 75 | m_ = 2 * nHarmonics_ + 1; 76 | } 77 | 78 | } // stk namespace 79 | -------------------------------------------------------------------------------- /stk/BlitSaw.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class BlitSaw 3 | \brief STK band-limited sawtooth wave class. 4 | 5 | This class generates a band-limited sawtooth waveform using a 6 | closed-form algorithm reported by Stilson and Smith in "Alias-Free 7 | Digital Synthesis of Classic Analog Waveforms", 1996. The user 8 | can specify both the fundamental frequency of the sawtooth and the 9 | number of harmonics contained in the resulting signal. 10 | 11 | If nHarmonics is 0, then the signal will contain all harmonics up 12 | to half the sample rate. Note, however, that this setting may 13 | produce aliasing in the signal when the frequency is changing (no 14 | automatic modification of the number of harmonics is performed by 15 | the setFrequency() function). 16 | 17 | Based on initial code of Robin Davies, 2005. 18 | Modified algorithm code by Gary Scavone, 2005. 19 | */ 20 | /***************************************************/ 21 | 22 | #include "BlitSaw.h" 23 | 24 | namespace stk { 25 | 26 | BlitSaw:: BlitSaw( StkFloat frequency ) 27 | { 28 | if ( frequency <= 0.0 ) { 29 | oStream_ << "BlitSaw::BlitSaw: argument (" << frequency << ") must be positive!"; 30 | handleError( StkError::FUNCTION_ARGUMENT ); 31 | } 32 | 33 | nHarmonics_ = 0; 34 | this->reset(); 35 | this->setFrequency( frequency ); 36 | } 37 | 38 | BlitSaw :: ~BlitSaw() 39 | { 40 | } 41 | 42 | void BlitSaw :: reset() 43 | { 44 | phase_ = 0.0f; 45 | state_ = 0.0; 46 | lastFrame_[0] = 0.0; 47 | } 48 | 49 | void BlitSaw :: setFrequency( StkFloat frequency ) 50 | { 51 | if ( frequency <= 0.0 ) { 52 | oStream_ << "BlitSaw::setFrequency: argument (" << frequency << ") must be positive!"; 53 | handleError( StkError::WARNING ); return; 54 | } 55 | 56 | p_ = Stk::sampleRate() / frequency; 57 | C2_ = 1 / p_; 58 | rate_ = PI * C2_; 59 | this->updateHarmonics(); 60 | } 61 | 62 | void BlitSaw :: setHarmonics( unsigned int nHarmonics ) 63 | { 64 | nHarmonics_ = nHarmonics; 65 | this->updateHarmonics(); 66 | 67 | // I found that the initial DC offset could be minimized with an 68 | // initial state setting as given below. This initialization should 69 | // only happen before starting the oscillator for the first time 70 | // (but after setting the frequency and number of harmonics). I 71 | // struggled a bit to decide where best to put this and finally 72 | // settled on here. In general, the user shouldn't be messing with 73 | // the number of harmonics once the oscillator is running because 74 | // this is automatically taken care of in the setFrequency() 75 | // function. (GPS - 1 October 2005) 76 | state_ = -0.5 * a_; 77 | } 78 | 79 | void BlitSaw :: updateHarmonics( void ) 80 | { 81 | if ( nHarmonics_ <= 0 ) { 82 | unsigned int maxHarmonics = (unsigned int) floor( 0.5 * p_ ); 83 | m_ = 2 * maxHarmonics + 1; 84 | } 85 | else 86 | m_ = 2 * nHarmonics_ + 1; 87 | 88 | a_ = m_ / p_; 89 | } 90 | 91 | } // stk namespace 92 | -------------------------------------------------------------------------------- /stk/BlitSquare.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class BlitSquare 3 | \brief STK band-limited square wave class. 4 | 5 | This class generates a band-limited square wave signal. It is 6 | derived in part from the approach reported by Stilson and Smith in 7 | "Alias-Free Digital Synthesis of Classic Analog Waveforms", 1996. 8 | The algorithm implemented in this class uses a SincM function with 9 | an even M value to achieve a bipolar bandlimited impulse train. 10 | This signal is then integrated to achieve a square waveform. The 11 | integration process has an associated DC offset so a DC blocking 12 | filter is applied at the output. 13 | 14 | The user can specify both the fundamental frequency of the 15 | waveform and the number of harmonics contained in the resulting 16 | signal. 17 | 18 | If nHarmonics is 0, then the signal will contain all harmonics up 19 | to half the sample rate. Note, however, that this setting may 20 | produce aliasing in the signal when the frequency is changing (no 21 | automatic modification of the number of harmonics is performed by 22 | the setFrequency() function). Also note that the harmonics of a 23 | square wave fall at odd integer multiples of the fundamental, so 24 | aliasing will happen with a lower fundamental than with the other 25 | Blit waveforms. This class is not guaranteed to be well behaved 26 | in the presence of significant aliasing. 27 | 28 | Based on initial code of Robin Davies, 2005 29 | Modified algorithm code by Gary Scavone, 2005 - 2010. 30 | */ 31 | /***************************************************/ 32 | 33 | #include "BlitSquare.h" 34 | 35 | namespace stk { 36 | 37 | BlitSquare:: BlitSquare( StkFloat frequency ) 38 | { 39 | if ( frequency <= 0.0 ) { 40 | oStream_ << "BlitSquare::BlitSquare: argument (" << frequency << ") must be positive!"; 41 | handleError( StkError::FUNCTION_ARGUMENT ); 42 | } 43 | 44 | nHarmonics_ = 0; 45 | this->setFrequency( frequency ); 46 | this->reset(); 47 | } 48 | 49 | BlitSquare :: ~BlitSquare() 50 | { 51 | } 52 | 53 | void BlitSquare :: reset() 54 | { 55 | phase_ = 0.0; 56 | lastFrame_[0] = 0.0; 57 | dcbState_ = 0.0; 58 | lastBlitOutput_ = 0; 59 | } 60 | 61 | void BlitSquare :: setFrequency( StkFloat frequency ) 62 | { 63 | if ( frequency <= 0.0 ) { 64 | oStream_ << "BlitSquare::setFrequency: argument (" << frequency << ") must be positive!"; 65 | handleError( StkError::WARNING ); return; 66 | } 67 | 68 | // By using an even value of the parameter M, we get a bipolar blit 69 | // waveform at half the blit frequency. Thus, we need to scale the 70 | // frequency value here by 0.5. (GPS, 2006). 71 | p_ = 0.5 * Stk::sampleRate() / frequency; 72 | rate_ = PI / p_; 73 | this->updateHarmonics(); 74 | } 75 | 76 | void BlitSquare :: setHarmonics( unsigned int nHarmonics ) 77 | { 78 | nHarmonics_ = nHarmonics; 79 | this->updateHarmonics(); 80 | } 81 | 82 | void BlitSquare :: updateHarmonics( void ) 83 | { 84 | // Make sure we end up with an even value of the parameter M here. 85 | if ( nHarmonics_ <= 0 ) { 86 | unsigned int maxHarmonics = (unsigned int) floor( 0.5 * p_ ); 87 | m_ = 2 * (maxHarmonics + 1); 88 | } 89 | else 90 | m_ = 2 * (nHarmonics_ + 1); 91 | 92 | a_ = m_ / p_; 93 | } 94 | 95 | } // stk namespace 96 | -------------------------------------------------------------------------------- /stk/BlowBotl.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class BlowBotl 3 | \brief STK blown bottle instrument class. 4 | 5 | This class implements a helmholtz resonator 6 | (biquad filter) with a polynomial jet 7 | excitation (a la Cook). 8 | 9 | Control Change Numbers: 10 | - Noise Gain = 4 11 | - Vibrato Frequency = 11 12 | - Vibrato Gain = 1 13 | - Volume = 128 14 | 15 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 16 | */ 17 | /***************************************************/ 18 | 19 | #include "BlowBotl.h" 20 | #include "SKINI.msg" 21 | 22 | namespace stk { 23 | 24 | #define __BOTTLE_RADIUS_ 0.999 25 | 26 | BlowBotl :: BlowBotl( void ) 27 | { 28 | dcBlock_.setBlockZero(); 29 | 30 | vibrato_.setFrequency( 5.925 ); 31 | vibratoGain_ = 0.0; 32 | 33 | resonator_.setResonance( 500.0, __BOTTLE_RADIUS_, true ); 34 | adsr_.setAllTimes( 0.005, 0.01, 0.8, 0.010 ); 35 | 36 | noiseGain_ = 20.0; 37 | maxPressure_ = 0.0; 38 | } 39 | 40 | BlowBotl :: ~BlowBotl( void ) 41 | { 42 | } 43 | 44 | void BlowBotl :: clear( void ) 45 | { 46 | resonator_.clear(); 47 | } 48 | 49 | void BlowBotl :: setFrequency( StkFloat frequency ) 50 | { 51 | #if defined(_STK_DEBUG_) 52 | if ( frequency <= 0.0 ) { 53 | oStream_ << "BlowBotl::setFrequency: argument is less than or equal to zero!"; 54 | handleError( StkError::WARNING ); return; 55 | } 56 | #endif 57 | 58 | resonator_.setResonance( frequency, __BOTTLE_RADIUS_, true ); 59 | } 60 | 61 | void BlowBotl :: startBlowing( StkFloat amplitude, StkFloat rate ) 62 | { 63 | if ( amplitude <= 0.0 || rate <= 0.0 ) { 64 | oStream_ << "BlowBotl::startBowing: one or more arguments is less than or equal to zero!"; 65 | handleError( StkError::WARNING ); return; 66 | } 67 | 68 | adsr_.setAttackRate( rate ); 69 | maxPressure_ = amplitude; 70 | adsr_.keyOn(); 71 | } 72 | 73 | void BlowBotl :: stopBlowing( StkFloat rate ) 74 | { 75 | if ( rate <= 0.0 ) { 76 | oStream_ << "BlowBotl::stopBowing: argument is less than or equal to zero!"; 77 | handleError( StkError::WARNING ); return; 78 | } 79 | 80 | adsr_.setReleaseRate( rate ); 81 | adsr_.keyOff(); 82 | } 83 | 84 | void BlowBotl :: noteOn( StkFloat frequency, StkFloat amplitude ) 85 | { 86 | this->setFrequency( frequency ); 87 | startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02); 88 | outputGain_ = amplitude + 0.001; 89 | } 90 | 91 | void BlowBotl :: noteOff( StkFloat amplitude ) 92 | { 93 | this->stopBlowing( amplitude * 0.02 ); 94 | } 95 | 96 | void BlowBotl :: controlChange( int number, StkFloat value ) 97 | { 98 | #if defined(_STK_DEBUG_) 99 | if ( value < 0 || ( number != 101 && value > 128.0 ) ) { 100 | oStream_ << "BlowBotl::controlChange: value (" << value << ") is out of range!"; 101 | handleError( StkError::WARNING ); return; 102 | } 103 | #endif 104 | 105 | StkFloat normalizedValue = value * ONE_OVER_128; 106 | if (number == __SK_NoiseLevel_) // 4 107 | noiseGain_ = normalizedValue * 30.0; 108 | else if (number == __SK_ModFrequency_) // 11 109 | vibrato_.setFrequency( normalizedValue * 12.0 ); 110 | else if (number == __SK_ModWheel_) // 1 111 | vibratoGain_ = normalizedValue * 0.4; 112 | else if (number == __SK_AfterTouch_Cont_) // 128 113 | adsr_.setTarget( normalizedValue ); 114 | #if defined(_STK_DEBUG_) 115 | else { 116 | oStream_ << "BlowBotl::controlChange: undefined control number (" << number << ")!"; 117 | handleError( StkError::WARNING ); 118 | } 119 | #endif 120 | } 121 | 122 | } // stk namespace 123 | -------------------------------------------------------------------------------- /stk/Chorus.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Chorus 3 | \brief STK chorus effect class. 4 | 5 | This class implements a chorus effect. It takes a monophonic 6 | input signal and produces a stereo output signal. 7 | 8 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 9 | */ 10 | /***************************************************/ 11 | 12 | #include "Chorus.h" 13 | 14 | namespace stk { 15 | 16 | Chorus :: Chorus( StkFloat baseDelay ) 17 | { 18 | lastFrame_.resize( 1, 2, 0.0 ); // resize lastFrame_ for stereo output 19 | delayLine_[0].setMaximumDelay( (unsigned long) (baseDelay * 1.414) + 2); 20 | delayLine_[0].setDelay( baseDelay ); 21 | delayLine_[1].setMaximumDelay( (unsigned long) (baseDelay * 1.414) + 2); 22 | delayLine_[1].setDelay( baseDelay ); 23 | baseLength_ = baseDelay; 24 | 25 | mods_[0].setFrequency( 0.2 ); 26 | mods_[1].setFrequency( 0.222222 ); 27 | modDepth_ = 0.05; 28 | effectMix_ = 0.5; 29 | this->clear(); 30 | } 31 | 32 | void Chorus :: clear( void ) 33 | { 34 | delayLine_[0].clear(); 35 | delayLine_[1].clear(); 36 | lastFrame_[0] = 0.0; 37 | lastFrame_[1] = 0.0; 38 | } 39 | 40 | void Chorus :: setModDepth( StkFloat depth ) 41 | { 42 | if ( depth < 0.0 || depth > 1.0 ) { 43 | oStream_ << "Chorus::setModDepth(): depth argument must be between 0.0 - 1.0!"; 44 | handleError( StkError::WARNING ); return; 45 | } 46 | 47 | modDepth_ = depth; 48 | }; 49 | 50 | void Chorus :: setModFrequency( StkFloat frequency ) 51 | { 52 | mods_[0].setFrequency( frequency ); 53 | mods_[1].setFrequency( frequency * 1.1111 ); 54 | } 55 | 56 | } // stk namespace 57 | -------------------------------------------------------------------------------- /stk/Delay.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Delay 3 | \brief STK non-interpolating delay line class. 4 | 5 | This class implements a non-interpolating digital delay-line. If 6 | the delay and maximum length are not specified during 7 | instantiation, a fixed maximum length of 4095 and a delay of zero 8 | is set. 9 | 10 | A non-interpolating delay line is typically used in fixed 11 | delay-length applications, such as for reverberation. 12 | 13 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 14 | */ 15 | /***************************************************/ 16 | 17 | #include "Delay.h" 18 | 19 | namespace stk { 20 | 21 | Delay :: Delay( unsigned long delay, unsigned long maxDelay ) 22 | { 23 | // Writing before reading allows delays from 0 to length-1. 24 | // If we want to allow a delay of maxDelay, we need a 25 | // delay-line of length = maxDelay+1. 26 | if ( delay > maxDelay ) { 27 | oStream_ << "Delay::Delay: maxDelay must be > than delay argument!\n"; 28 | handleError( StkError::FUNCTION_ARGUMENT ); 29 | } 30 | 31 | if ( ( maxDelay + 1 ) > inputs_.size() ) 32 | inputs_.resize( maxDelay + 1, 1, 0.0 ); 33 | 34 | inPoint_ = 0; 35 | this->setDelay( delay ); 36 | } 37 | 38 | Delay :: ~Delay() 39 | { 40 | } 41 | 42 | void Delay :: setMaximumDelay( unsigned long delay ) 43 | { 44 | if ( delay < inputs_.size() ) return; 45 | inputs_.resize( delay + 1 ); 46 | } 47 | 48 | void Delay :: setDelay( unsigned long delay ) 49 | { 50 | if ( delay > inputs_.size() - 1 ) { // The value is too big. 51 | oStream_ << "Delay::setDelay: argument (" << delay << ") greater than maximum!\n"; 52 | handleError( StkError::WARNING ); return; 53 | } 54 | 55 | if ( delay < 0 ) { 56 | oStream_ << "Delay::setDelay: argument (" << delay << ") less than zero!\n"; 57 | handleError( StkError::WARNING ); return; 58 | } 59 | 60 | // read chases write 61 | if ( inPoint_ >= delay ) outPoint_ = inPoint_ - delay; 62 | else outPoint_ = inputs_.size() + inPoint_ - delay; 63 | delay_ = delay; 64 | } 65 | 66 | StkFloat Delay :: energy( void ) const 67 | { 68 | unsigned long i; 69 | register StkFloat e = 0; 70 | if ( inPoint_ >= outPoint_ ) { 71 | for ( i=outPoint_; i= 0.5!"; 29 | handleError( StkError::FUNCTION_ARGUMENT ); 30 | } 31 | 32 | if ( delay > (StkFloat) maxDelay ) { 33 | oStream_ << "DelayA::DelayA: maxDelay must be > than delay argument!"; 34 | handleError( StkError::FUNCTION_ARGUMENT ); 35 | } 36 | 37 | // Writing before reading allows delays from 0 to length-1. 38 | if ( maxDelay + 1 > inputs_.size() ) 39 | inputs_.resize( maxDelay + 1, 1, 0.0 ); 40 | 41 | inPoint_ = 0; 42 | this->setDelay( delay ); 43 | apInput_ = 0.0; 44 | doNextOut_ = true; 45 | } 46 | 47 | DelayA :: ~DelayA() 48 | { 49 | } 50 | 51 | void DelayA :: clear() 52 | { 53 | for ( unsigned int i=0; i length ) { // The value is too big. 69 | oStream_ << "DelayA::setDelay: argument (" << delay << ") greater than maximum!"; 70 | handleError( StkError::WARNING ); return; 71 | } 72 | 73 | if ( delay < 0.5 ) { 74 | oStream_ << "DelayA::setDelay: argument (" << delay << ") less than 0.5 not possible!"; 75 | handleError( StkError::WARNING ); 76 | } 77 | 78 | StkFloat outPointer = inPoint_ - delay + 1.0; // outPoint chases inpoint 79 | delay_ = delay; 80 | 81 | while ( outPointer < 0 ) 82 | outPointer += length; // modulo maximum length 83 | 84 | outPoint_ = (long) outPointer; // integer part 85 | if ( outPoint_ == length ) outPoint_ = 0; 86 | alpha_ = 1.0 + outPoint_ - outPointer; // fractional part 87 | 88 | if ( alpha_ < 0.5 ) { 89 | // The optimal range for alpha is about 0.5 - 1.5 in order to 90 | // achieve the flattest phase delay response. 91 | outPoint_ += 1; 92 | if ( outPoint_ >= length ) outPoint_ -= length; 93 | alpha_ += (StkFloat) 1.0; 94 | } 95 | 96 | coeff_ = (1.0 - alpha_) / (1.0 + alpha_); // coefficient for allpass 97 | } 98 | 99 | StkFloat DelayA :: tapOut( unsigned long tapDelay ) 100 | { 101 | long tap = inPoint_ - tapDelay - 1; 102 | while ( tap < 0 ) // Check for wraparound. 103 | tap += inputs_.size(); 104 | 105 | return inputs_[tap]; 106 | } 107 | 108 | void DelayA :: tapIn( StkFloat value, unsigned long tapDelay ) 109 | { 110 | long tap = inPoint_ - tapDelay - 1; 111 | while ( tap < 0 ) // Check for wraparound. 112 | tap += inputs_.size(); 113 | 114 | inputs_[tap] = value; 115 | } 116 | 117 | } // stk namespace 118 | -------------------------------------------------------------------------------- /stk/DelayL.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class DelayL 3 | \brief STK linear interpolating delay line class. 4 | 5 | This class implements a fractional-length digital delay-line using 6 | first-order linear interpolation. If the delay and maximum length 7 | are not specified during instantiation, a fixed maximum length of 8 | 4095 and a delay of zero is set. 9 | 10 | Linear interpolation is an efficient technique for achieving 11 | fractional delay lengths, though it does introduce high-frequency 12 | signal attenuation to varying degrees depending on the fractional 13 | delay setting. The use of higher order Lagrange interpolators can 14 | typically improve (minimize) this attenuation characteristic. 15 | 16 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 17 | */ 18 | /***************************************************/ 19 | 20 | #include "DelayL.h" 21 | 22 | namespace stk { 23 | 24 | DelayL :: DelayL( StkFloat delay, unsigned long maxDelay ) 25 | { 26 | if ( delay < 0.0 ) { 27 | oStream_ << "DelayL::DelayL: delay must be >= 0.0!"; 28 | handleError( StkError::FUNCTION_ARGUMENT ); 29 | } 30 | 31 | if ( delay > (StkFloat) maxDelay ) { 32 | oStream_ << "DelayL::DelayL: maxDelay must be > than delay argument!"; 33 | handleError( StkError::FUNCTION_ARGUMENT ); 34 | } 35 | 36 | // Writing before reading allows delays from 0 to length-1. 37 | if ( maxDelay + 1 > inputs_.size() ) 38 | inputs_.resize( maxDelay + 1, 1, 0.0 ); 39 | 40 | inPoint_ = 0; 41 | this->setDelay( delay ); 42 | doNextOut_ = true; 43 | } 44 | 45 | DelayL :: ~DelayL() 46 | { 47 | } 48 | 49 | void DelayL :: setMaximumDelay( unsigned long delay ) 50 | { 51 | if ( delay < inputs_.size() ) return; 52 | inputs_.resize( delay + 1 ); 53 | } 54 | 55 | void DelayL :: setDelay( StkFloat delay ) 56 | { 57 | if ( delay + 1 > inputs_.size() ) { // The value is too big. 58 | oStream_ << "DelayL::setDelay: argument (" << delay << ") greater than maximum!"; 59 | handleError( StkError::WARNING ); return; 60 | } 61 | 62 | if (delay < 0 ) { 63 | oStream_ << "DelayL::setDelay: argument (" << delay << ") less than zero!"; 64 | handleError( StkError::WARNING ); return; 65 | } 66 | 67 | StkFloat outPointer = inPoint_ - delay; // read chases write 68 | delay_ = delay; 69 | 70 | while ( outPointer < 0 ) 71 | outPointer += inputs_.size(); // modulo maximum length 72 | 73 | outPoint_ = (long) outPointer; // integer part 74 | if ( outPoint_ == inputs_.size() ) outPoint_ = 0; 75 | alpha_ = outPointer - outPoint_; // fractional part 76 | omAlpha_ = (StkFloat) 1.0 - alpha_; 77 | } 78 | 79 | StkFloat DelayL :: tapOut( unsigned long tapDelay ) 80 | { 81 | long tap = inPoint_ - tapDelay - 1; 82 | while ( tap < 0 ) // Check for wraparound. 83 | tap += inputs_.size(); 84 | 85 | return inputs_[tap]; 86 | } 87 | 88 | void DelayL :: tapIn( StkFloat value, unsigned long tapDelay ) 89 | { 90 | long tap = inPoint_ - tapDelay - 1; 91 | while ( tap < 0 ) // Check for wraparound. 92 | tap += inputs_.size(); 93 | 94 | inputs_[tap] = value; 95 | } 96 | 97 | } // stk namespace 98 | -------------------------------------------------------------------------------- /stk/Echo.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Echo 3 | \brief STK echo effect class. 4 | 5 | This class implements an echo effect. 6 | 7 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 8 | */ 9 | /***************************************************/ 10 | 11 | #include "Echo.h" 12 | #include 13 | 14 | namespace stk { 15 | 16 | Echo :: Echo( unsigned long maximumDelay ) : Effect() 17 | { 18 | this->setMaximumDelay( maximumDelay ); 19 | delayLine_.setDelay( length_ >> 1 ); 20 | effectMix_ = 0.5; 21 | this->clear(); 22 | } 23 | 24 | void Echo :: clear( void ) 25 | { 26 | delayLine_.clear(); 27 | lastFrame_[0] = 0.0; 28 | } 29 | 30 | void Echo :: setMaximumDelay( unsigned long delay ) 31 | { 32 | if ( delay == 0 ) { 33 | oStream_ << "Echo::setMaximumDelay: parameter cannot be zero!"; 34 | handleError( StkError::WARNING ); return; 35 | } 36 | 37 | delayLine_.setMaximumDelay( delay ); 38 | } 39 | 40 | void Echo :: setDelay( unsigned long delay ) 41 | { 42 | if ( delay > length_ ) { 43 | oStream_ << "Echo::setDelay: parameter is greater than maximum delay length!"; 44 | handleError( StkError::WARNING ); return; 45 | } 46 | 47 | delayLine_.setDelay( delay ); 48 | } 49 | 50 | } // stk namespace 51 | -------------------------------------------------------------------------------- /stk/Effect.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_EFFECT_H 2 | #define STK_EFFECT_H 3 | 4 | #include "Stk.h" 5 | #include 6 | 7 | namespace stk { 8 | 9 | /***************************************************/ 10 | /*! \class Effect 11 | \brief STK abstract effects parent class. 12 | 13 | This class provides common functionality for STK effects 14 | subclasses. It is general enough to support both monophonic and 15 | polyphonic input/output classes. 16 | 17 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 18 | */ 19 | /***************************************************/ 20 | 21 | class Effect : public Stk 22 | { 23 | public: 24 | //! Class constructor. 25 | Effect( void ) { lastFrame_.resize( 1, 1, 0.0 ); }; 26 | 27 | //! Return the number of output channels for the class. 28 | unsigned int channelsOut( void ) const { return lastFrame_.channels(); }; 29 | 30 | //! Return an StkFrames reference to the last output sample frame. 31 | const StkFrames& lastFrame( void ) const { return lastFrame_; }; 32 | 33 | //! Reset and clear all internal state. 34 | virtual void clear() = 0; 35 | 36 | //! Set the mixture of input and "effected" levels in the output (0.0 = input only, 1.0 = effect only). 37 | void setEffectMix( StkFloat mix ); 38 | 39 | protected: 40 | 41 | // Returns true if argument value is prime. 42 | bool isPrime( unsigned int number ); 43 | 44 | StkFrames lastFrame_; 45 | StkFloat effectMix_; 46 | 47 | }; 48 | 49 | inline void Effect :: setEffectMix( StkFloat mix ) 50 | { 51 | if ( mix < 0.0 ) { 52 | oStream_ << "Effect::setEffectMix: mix parameter is less than zero ... setting to zero!"; 53 | handleError( StkError::WARNING ); 54 | effectMix_ = 0.0; 55 | } 56 | else if ( mix > 1.0 ) { 57 | oStream_ << "Effect::setEffectMix: mix parameter is greater than 1.0 ... setting to one!"; 58 | handleError( StkError::WARNING ); 59 | effectMix_ = 1.0; 60 | } 61 | else 62 | effectMix_ = mix; 63 | } 64 | 65 | inline bool Effect :: isPrime( unsigned int number ) 66 | { 67 | if ( number == 2 ) return true; 68 | if ( number & 1 ) { 69 | for ( int i=3; i<(int)sqrt((double)number)+1; i+=2 ) 70 | if ( (number % i) == 0 ) return false; 71 | return true; // prime 72 | } 73 | else return false; // even 74 | } 75 | 76 | } // stk namespace 77 | 78 | #endif 79 | 80 | -------------------------------------------------------------------------------- /stk/Envelope.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Envelope 3 | \brief STK linear line envelope class. 4 | 5 | This class implements a simple linear line envelope generator 6 | which is capable of ramping to an arbitrary target value by a 7 | specified \e rate. It also responds to simple \e keyOn and \e 8 | keyOff messages, ramping to 1.0 on keyOn and to 0.0 on keyOff. 9 | 10 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 11 | */ 12 | /***************************************************/ 13 | 14 | #include "Envelope.h" 15 | 16 | namespace stk { 17 | 18 | Envelope :: Envelope( void ) : Generator() 19 | { 20 | target_ = 0.0; 21 | value_ = 0.0; 22 | rate_ = 0.001; 23 | state_ = 0; 24 | Stk::addSampleRateAlert( this ); 25 | } 26 | 27 | Envelope :: ~Envelope( void ) 28 | { 29 | Stk::removeSampleRateAlert( this ); 30 | } 31 | 32 | Envelope& Envelope :: operator= ( const Envelope& e ) 33 | { 34 | if ( this != &e ) { 35 | target_ = e.target_; 36 | value_ = e.value_; 37 | rate_ = e.rate_; 38 | state_ = e.state_; 39 | } 40 | 41 | return *this; 42 | } 43 | 44 | void Envelope :: sampleRateChanged( StkFloat newRate, StkFloat oldRate ) 45 | { 46 | if ( !ignoreSampleRateChange_ ) 47 | rate_ = oldRate * rate_ / newRate; 48 | } 49 | 50 | void Envelope :: setRate( StkFloat rate ) 51 | { 52 | if ( rate < 0.0 ) { 53 | oStream_ << "Envelope::setRate: argument must be >= 0.0!"; 54 | handleError( StkError::WARNING ); return; 55 | } 56 | 57 | rate_ = rate; 58 | } 59 | 60 | void Envelope :: setTime( StkFloat time ) 61 | { 62 | if ( time <= 0.0 ) { 63 | oStream_ << "Envelope::setTime: argument must be > 0.0!"; 64 | handleError( StkError::WARNING ); return; 65 | } 66 | 67 | rate_ = 1.0 / ( time * Stk::sampleRate() ); 68 | } 69 | 70 | void Envelope :: setTarget( StkFloat target ) 71 | { 72 | target_ = target; 73 | if ( value_ != target_ ) state_ = 1; 74 | } 75 | 76 | void Envelope :: setValue( StkFloat value ) 77 | { 78 | state_ = 0; 79 | target_ = value; 80 | value_ = value; 81 | lastFrame_[0] = value_; 82 | } 83 | 84 | } // stk namespace 85 | -------------------------------------------------------------------------------- /stk/Envelope.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_ENVELOPE_H 2 | #define STK_ENVELOPE_H 3 | 4 | #include "Generator.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class Envelope 10 | \brief STK linear line envelope class. 11 | 12 | This class implements a simple linear line envelope generator 13 | which is capable of ramping to an arbitrary target value by a 14 | specified \e rate. It also responds to simple \e keyOn and \e 15 | keyOff messages, ramping to 1.0 on keyOn and to 0.0 on keyOff. 16 | 17 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 18 | */ 19 | /***************************************************/ 20 | 21 | class Envelope : public Generator 22 | { 23 | public: 24 | 25 | //! Default constructor. 26 | Envelope( void ); 27 | 28 | //! Class destructor. 29 | ~Envelope( void ); 30 | 31 | //! Assignment operator. 32 | Envelope& operator= ( const Envelope& e ); 33 | 34 | //! Set target = 1. 35 | void keyOn( void ) { this->setTarget( 1.0 ); }; 36 | 37 | //! Set target = 0. 38 | void keyOff( void ) { this->setTarget( 0.0 ); }; 39 | 40 | //! Set the \e rate. 41 | /*! 42 | The \e rate must be positive (though a value of 0.0 is allowed). 43 | */ 44 | void setRate( StkFloat rate ); 45 | 46 | //! Set the \e rate based on a positive time duration (seconds). 47 | /*! 48 | The \e rate is calculated such that the envelope will ramp from 49 | a value of 0.0 to 1.0 in the specified time duration. 50 | */ 51 | void setTime( StkFloat time ); 52 | 53 | //! Set the target value. 54 | void setTarget( StkFloat target ); 55 | 56 | //! Set current and target values to \e value. 57 | void setValue( StkFloat value ); 58 | 59 | //! Return the current envelope \e state (0 = at target, 1 otherwise). 60 | int getState( void ) const { return state_; }; 61 | 62 | //! Return the last computed output value. 63 | StkFloat lastOut( void ) const { return lastFrame_[0]; }; 64 | 65 | //! Compute and return one output sample. 66 | StkFloat tick( void ); 67 | 68 | //! Fill a channel of the StkFrames object with computed outputs. 69 | /*! 70 | The \c channel argument must be less than the number of 71 | channels in the StkFrames argument (the first channel is specified 72 | by 0). However, range checking is only performed if _STK_DEBUG_ 73 | is defined during compilation, in which case an out-of-range value 74 | will trigger an StkError exception. 75 | */ 76 | StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); 77 | 78 | protected: 79 | 80 | void sampleRateChanged( StkFloat newRate, StkFloat oldRate ); 81 | 82 | StkFloat value_; 83 | StkFloat target_; 84 | StkFloat rate_; 85 | int state_; 86 | }; 87 | 88 | inline StkFloat Envelope :: tick( void ) 89 | { 90 | if ( state_ ) { 91 | if ( target_ > value_ ) { 92 | value_ += rate_; 93 | if ( value_ >= target_ ) { 94 | value_ = target_; 95 | state_ = 0; 96 | } 97 | } 98 | else { 99 | value_ -= rate_; 100 | if ( value_ <= target_ ) { 101 | value_ = target_; 102 | state_ = 0; 103 | } 104 | } 105 | lastFrame_[0] = value_; 106 | } 107 | 108 | return value_; 109 | } 110 | 111 | inline StkFrames& Envelope :: tick( StkFrames& frames, unsigned int channel ) 112 | { 113 | #if defined(_STK_DEBUG_) 114 | if ( channel >= frames.channels() ) { 115 | oStream_ << "Envelope::tick(): channel and StkFrames arguments are incompatible!"; 116 | handleError( StkError::FUNCTION_ARGUMENT ); 117 | } 118 | #endif 119 | 120 | StkFloat *samples = &frames[channel]; 121 | unsigned int hop = frames.channels(); 122 | for ( unsigned int i=0; i adsr_; 104 | std::vector waves_; 105 | SineWave vibrato_; 106 | TwoZero twozero_; 107 | unsigned int nOperators_; 108 | StkFloat baseFrequency_; 109 | std::vector ratios_; 110 | std::vector gains_; 111 | StkFloat modDepth_; 112 | StkFloat control1_; 113 | StkFloat control2_; 114 | StkFloat fmGains_[100]; 115 | StkFloat fmSusLevels_[16]; 116 | StkFloat fmAttTimes_[32]; 117 | 118 | }; 119 | 120 | } // stk namespace 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /stk/FileWrite.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_FILEWRITE_H 2 | #define STK_FILEWRITE_H 3 | 4 | #include "Stk.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class FileWrite 10 | \brief STK audio file output class. 11 | 12 | This class provides output support for various 13 | audio file formats. 14 | 15 | FileWrite writes samples to an audio file. It supports 16 | multi-channel data. 17 | 18 | FileWrite currently supports uncompressed WAV, AIFF, AIFC, SND 19 | (AU), MAT-file (Matlab), and STK RAW file formats. Signed integer 20 | (8-, 16-, 24-, and 32-bit) and floating- point (32- and 64-bit) 21 | data types are supported. STK RAW files use 16-bit integers by 22 | definition. MAT-files will always be written as 64-bit floats. 23 | If a data type specification does not match the specified file 24 | type, the data type will automatically be modified. Compressed 25 | data types are not supported. 26 | 27 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 28 | */ 29 | /***************************************************/ 30 | 31 | class FileWrite : public Stk 32 | { 33 | public: 34 | 35 | typedef unsigned long FILE_TYPE; 36 | 37 | static const FILE_TYPE FILE_RAW; /*!< STK RAW file type. */ 38 | static const FILE_TYPE FILE_WAV; /*!< WAV file type. */ 39 | static const FILE_TYPE FILE_SND; /*!< SND (AU) file type. */ 40 | static const FILE_TYPE FILE_AIF; /*!< AIFF file type. */ 41 | static const FILE_TYPE FILE_MAT; /*!< Matlab MAT-file type. */ 42 | 43 | //! Default constructor. 44 | FileWrite( void ); 45 | 46 | //! Overloaded constructor used to specify a file name, type, and data format with this object. 47 | /*! 48 | An StkError is thrown for invalid argument values or if an error occurs when initializing the output file. 49 | */ 50 | FileWrite( std::string fileName, unsigned int nChannels = 1, FILE_TYPE type = FILE_WAV, Stk::StkFormat format = STK_SINT16 ); 51 | 52 | //! Class destructor. 53 | virtual ~FileWrite(); 54 | 55 | //! Create a file of the specified type and name and output samples to it in the given data format. 56 | /*! 57 | An StkError is thrown for invalid argument values or if an error occurs when initializing the output file. 58 | */ 59 | void open( std::string fileName, unsigned int nChannels = 1, 60 | FileWrite::FILE_TYPE type = FILE_WAV, Stk::StkFormat format = STK_SINT16 ); 61 | 62 | //! If a file is open, write out samples in the queue and then close it. 63 | void close( void ); 64 | 65 | //! Returns \e true if a file is currently open. 66 | bool isOpen( void ); 67 | 68 | //! Write sample frames from the StkFrames object to the file. 69 | /*! 70 | An StkError will be thrown if the number of channels in the 71 | StkFrames argument does not agree with the number of channels 72 | specified when opening the file. 73 | */ 74 | void write( StkFrames& buffer ); 75 | 76 | protected: 77 | 78 | // Write STK RAW file header. 79 | bool setRawFile( std::string fileName ); 80 | 81 | // Write WAV file header. 82 | bool setWavFile( std::string fileName ); 83 | 84 | // Close WAV file, updating the header. 85 | void closeWavFile( void ); 86 | 87 | // Write SND (AU) file header. 88 | bool setSndFile( std::string fileName ); 89 | 90 | // Close SND file, updating the header. 91 | void closeSndFile( void ); 92 | 93 | // Write AIFF file header. 94 | bool setAifFile( std::string fileName ); 95 | 96 | // Close AIFF file, updating the header. 97 | void closeAifFile( void ); 98 | 99 | // Write MAT-file header. 100 | bool setMatFile( std::string fileName ); 101 | 102 | // Close MAT-file, updating the header. 103 | void closeMatFile( void ); 104 | 105 | FILE *fd_; 106 | FILE_TYPE fileType_; 107 | StkFormat dataType_; 108 | unsigned int channels_; 109 | unsigned long frameCounter_; 110 | bool byteswap_; 111 | 112 | }; 113 | 114 | } // stk namespace 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /stk/FileWvOut.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_FILEWVOUT_H 2 | #define STK_FILEWVOUT_H 3 | 4 | #include "WvOut.h" 5 | #include "FileWrite.h" 6 | 7 | namespace stk { 8 | 9 | /***************************************************/ 10 | /*! \class FileWvOut 11 | \brief STK audio file output class. 12 | 13 | This class inherits from WvOut. It provides a "tick-level" 14 | interface to the FileWrite class. 15 | 16 | FileWvOut writes samples to an audio file and supports 17 | multi-channel data. It is important to distinguish the tick() 18 | method that outputs a single sample to all channels in a sample 19 | frame from the overloaded one that takes a reference to an 20 | StkFrames object for multi-channel and/or multi-frame data. 21 | 22 | See the FileWrite class for a description of the supported audio 23 | file formats. 24 | 25 | Currently, FileWvOut is non-interpolating and the output rate is 26 | always Stk::sampleRate(). 27 | 28 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 29 | */ 30 | /***************************************************/ 31 | 32 | class FileWvOut : public WvOut 33 | { 34 | public: 35 | 36 | //! Default constructor with optional output buffer size argument. 37 | /*! 38 | The output buffer size defines the number of frames that are 39 | accumulated between writes to disk. 40 | */ 41 | FileWvOut( unsigned int bufferFrames = 1024 ); 42 | 43 | //! Overloaded constructor used to specify a file name, type, and data format with this object. 44 | /*! 45 | An StkError is thrown for invalid argument values or if an error occurs when initializing the output file. 46 | */ 47 | FileWvOut( std::string fileName, 48 | unsigned int nChannels = 1, 49 | FileWrite::FILE_TYPE type = FileWrite::FILE_WAV, 50 | Stk::StkFormat format = STK_SINT16, 51 | unsigned int bufferFrames = 1024 ); 52 | 53 | //! Class destructor. 54 | virtual ~FileWvOut(); 55 | 56 | //! Open a new file with the specified parameters. 57 | /*! 58 | If a file was previously open, it will be closed. An StkError 59 | will be thrown if any of the specified arguments are invalid or a 60 | file error occurs during opening. 61 | */ 62 | void openFile( std::string fileName, 63 | unsigned int nChannels, 64 | FileWrite::FILE_TYPE type, 65 | Stk::StkFormat format ); 66 | 67 | //! Close a file if one is open. 68 | /*! 69 | Any data remaining in the internal buffer will be written to 70 | the file before closing. 71 | */ 72 | void closeFile( void ); 73 | 74 | //! Output a single sample to all channels in a sample frame. 75 | /*! 76 | An StkError is thrown if an output error occurs. 77 | */ 78 | void tick( const StkFloat sample ); 79 | 80 | //! Output the StkFrames data. 81 | /*! 82 | An StkError will be thrown if an output error occurs. An 83 | StkError will also be thrown if _STK_DEBUG_ is defined during 84 | compilation and there is an incompatability between the number of 85 | channels in the FileWvOut object and that in the StkFrames object. 86 | */ 87 | void tick( const StkFrames& frames ); 88 | 89 | protected: 90 | 91 | void incrementFrame( void ); 92 | 93 | FileWrite file_; 94 | unsigned int bufferFrames_; 95 | unsigned int bufferIndex_; 96 | unsigned int iData_; 97 | 98 | }; 99 | 100 | } // stk namespace 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /stk/Fir.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Fir 3 | \brief STK general finite impulse response filter class. 4 | 5 | This class provides a generic digital filter structure that can be 6 | used to implement FIR filters. For filters with feedback terms, 7 | the Iir class should be used. 8 | 9 | In particular, this class implements the standard difference 10 | equation: 11 | 12 | y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb] 13 | 14 | The \e gain parameter is applied at the filter input and does not 15 | affect the coefficient values. The default gain value is 1.0. 16 | This structure results in one extra multiply per computed sample, 17 | but allows easy control of the overall filter gain. 18 | 19 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 20 | */ 21 | /***************************************************/ 22 | 23 | #include "Fir.h" 24 | #include 25 | 26 | namespace stk { 27 | 28 | Fir :: Fir() 29 | { 30 | // The default constructor should setup for pass-through. 31 | b_.push_back( 1.0 ); 32 | 33 | inputs_.resize( 1, 1, 0.0 ); 34 | } 35 | 36 | Fir :: Fir( std::vector &coefficients ) 37 | { 38 | // Check the arguments. 39 | if ( coefficients.size() == 0 ) { 40 | oStream_ << "Fir: coefficient vector must have size > 0!"; 41 | handleError( StkError::FUNCTION_ARGUMENT ); 42 | } 43 | 44 | gain_ = 1.0; 45 | b_ = coefficients; 46 | 47 | inputs_.resize( b_.size(), 1, 0.0 ); 48 | this->clear(); 49 | } 50 | 51 | Fir :: ~Fir() 52 | { 53 | } 54 | 55 | void Fir :: setCoefficients( std::vector &coefficients, bool clearState ) 56 | { 57 | // Check the argument. 58 | if ( coefficients.size() == 0 ) { 59 | oStream_ << "Fir::setCoefficients: coefficient vector must have size > 0!"; 60 | handleError( StkError::FUNCTION_ARGUMENT ); 61 | } 62 | 63 | if ( b_.size() != coefficients.size() ) { 64 | b_ = coefficients; 65 | inputs_.resize( b_.size(), 1, 0.0 ); 66 | } 67 | else { 68 | for ( unsigned int i=0; iclear(); 72 | } 73 | 74 | } // stk namespace 75 | -------------------------------------------------------------------------------- /stk/Function.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_FUNCTION_H 2 | #define STK_FUNCTION_H 3 | 4 | #include "Stk.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class Function 10 | \brief STK abstract function parent class. 11 | 12 | This class provides common functionality for STK classes that 13 | implement tables or other types of input to output function 14 | mappings. 15 | 16 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 17 | */ 18 | /***************************************************/ 19 | 20 | class Function : public Stk 21 | { 22 | public: 23 | //! Class constructor. 24 | Function( void ) { lastFrame_.resize( 1, 1, 0.0 ); }; 25 | 26 | //! Return the last computed output sample. 27 | StkFloat lastOut( void ) const { return lastFrame_[0]; }; 28 | 29 | //! Take one sample input and compute one sample of output. 30 | virtual StkFloat tick( StkFloat input ) = 0; 31 | 32 | protected: 33 | 34 | StkFrames lastFrame_; 35 | 36 | }; 37 | 38 | } // stk namespace 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /stk/Generator.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_GENERATOR_H 2 | #define STK_GENERATOR_H 3 | 4 | #include "Stk.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class Generator 10 | \brief STK abstract unit generator parent class. 11 | 12 | This class provides limited common functionality for STK unit 13 | generator sample-source subclasses. It is general enough to 14 | support both monophonic and polyphonic output classes. 15 | 16 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 17 | */ 18 | /***************************************************/ 19 | 20 | class Generator : public Stk 21 | { 22 | public: 23 | 24 | //! Class constructor. 25 | Generator( void ) { lastFrame_.resize( 1, 1, 0.0 ); }; 26 | 27 | //! Return the number of output channels for the class. 28 | unsigned int channelsOut( void ) const { return lastFrame_.channels(); }; 29 | 30 | //! Return an StkFrames reference to the last output sample frame. 31 | const StkFrames& lastFrame( void ) const { return lastFrame_; }; 32 | 33 | //! Fill the StkFrames object with computed sample frames, starting at the specified channel. 34 | /*! 35 | The \c channel argument plus the number of output channels must 36 | be less than the number of channels in the StkFrames argument (the 37 | first channel is specified by 0). However, range checking is only 38 | performed if _STK_DEBUG_ is defined during compilation, in which 39 | case an out-of-range value will trigger an StkError exception. 40 | */ 41 | virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ) = 0; 42 | 43 | protected: 44 | 45 | StkFrames lastFrame_; 46 | }; 47 | 48 | } // stk namespace 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /stk/HevyMetl.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class HevyMetl 3 | \brief STK heavy metal FM synthesis instrument. 4 | 5 | This class implements 3 cascade operators with 6 | feedback modulation, also referred to as 7 | algorithm 3 of the TX81Z. 8 | 9 | Algorithm 3 is : 4--\ 10 | 3-->2-- + -->1-->Out 11 | 12 | Control Change Numbers: 13 | - Total Modulator Index = 2 14 | - Modulator Crossfade = 4 15 | - LFO Speed = 11 16 | - LFO Depth = 1 17 | - ADSR 2 & 4 Target = 128 18 | 19 | The basic Chowning/Stanford FM patent expired 20 | in 1995, but there exist follow-on patents, 21 | mostly assigned to Yamaha. If you are of the 22 | type who should worry about this (making 23 | money) worry away. 24 | 25 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 26 | */ 27 | /***************************************************/ 28 | 29 | #include "HevyMetl.h" 30 | 31 | namespace stk { 32 | 33 | HevyMetl :: HevyMetl( void ) 34 | : FM() 35 | { 36 | // Concatenate the STK rawwave path to the rawwave files 37 | for ( unsigned int i=0; i<3; i++ ) 38 | waves_[i] = new FileLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true ); 39 | waves_[3] = new FileLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true ); 40 | 41 | this->setRatio(0, 1.0 * 1.000); 42 | this->setRatio(1, 4.0 * 0.999); 43 | this->setRatio(2, 3.0 * 1.001); 44 | this->setRatio(3, 0.5 * 1.002); 45 | 46 | gains_[0] = fmGains_[92]; 47 | gains_[1] = fmGains_[76]; 48 | gains_[2] = fmGains_[91]; 49 | gains_[3] = fmGains_[68]; 50 | 51 | adsr_[0]->setAllTimes( 0.001, 0.001, 1.0, 0.01); 52 | adsr_[1]->setAllTimes( 0.001, 0.010, 1.0, 0.50); 53 | adsr_[2]->setAllTimes( 0.010, 0.005, 1.0, 0.20); 54 | adsr_[3]->setAllTimes( 0.030, 0.010, 0.2, 0.20); 55 | 56 | twozero_.setGain( 2.0 ); 57 | vibrato_.setFrequency( 5.5 ); 58 | modDepth_ = 0.0; 59 | } 60 | 61 | HevyMetl :: ~HevyMetl( void ) 62 | { 63 | } 64 | 65 | void HevyMetl :: noteOn( StkFloat frequency, StkFloat amplitude ) 66 | { 67 | gains_[0] = amplitude * fmGains_[92]; 68 | gains_[1] = amplitude * fmGains_[76]; 69 | gains_[2] = amplitude * fmGains_[91]; 70 | gains_[3] = amplitude * fmGains_[68]; 71 | this->setFrequency( frequency ); 72 | this->keyOn(); 73 | } 74 | 75 | } // stk namespace 76 | -------------------------------------------------------------------------------- /stk/Iir.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Iir 3 | \brief STK general infinite impulse response filter class. 4 | 5 | This class provides a generic digital filter structure that can be 6 | used to implement IIR filters. For filters containing only 7 | feedforward terms, the Fir class is slightly more efficient. 8 | 9 | In particular, this class implements the standard difference 10 | equation: 11 | 12 | a[0]*y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb] - 13 | a[1]*y[n-1] - ... - a[na]*y[n-na] 14 | 15 | If a[0] is not equal to 1, the filter coeffcients are normalized 16 | by a[0]. 17 | 18 | The \e gain parameter is applied at the filter input and does not 19 | affect the coefficient values. The default gain value is 1.0. 20 | This structure results in one extra multiply per computed sample, 21 | but allows easy control of the overall filter gain. 22 | 23 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 24 | */ 25 | /***************************************************/ 26 | 27 | #include "Iir.h" 28 | 29 | namespace stk { 30 | 31 | Iir :: Iir() 32 | { 33 | // The default constructor should setup for pass-through. 34 | b_.push_back( 1.0 ); 35 | a_.push_back( 1.0 ); 36 | 37 | inputs_.resize( 1, 1, 0.0 ); 38 | outputs_.resize( 1, 1, 0.0 ); 39 | } 40 | 41 | Iir :: Iir( std::vector &bCoefficients, std::vector &aCoefficients ) 42 | { 43 | // Check the arguments. 44 | if ( bCoefficients.size() == 0 || aCoefficients.size() == 0 ) { 45 | oStream_ << "Iir: a and b coefficient vectors must both have size > 0!"; 46 | handleError( StkError::FUNCTION_ARGUMENT ); 47 | } 48 | 49 | if ( aCoefficients[0] == 0.0 ) { 50 | oStream_ << "Iir: a[0] coefficient cannot == 0!"; 51 | handleError( StkError::FUNCTION_ARGUMENT ); 52 | } 53 | 54 | gain_ = 1.0; 55 | b_ = bCoefficients; 56 | a_ = aCoefficients; 57 | 58 | inputs_.resize( b_.size(), 1, 0.0 ); 59 | outputs_.resize( a_.size(), 1, 0.0 ); 60 | this->clear(); 61 | } 62 | 63 | Iir :: ~Iir() 64 | { 65 | } 66 | 67 | void Iir :: setCoefficients( std::vector &bCoefficients, std::vector &aCoefficients, bool clearState ) 68 | { 69 | this->setNumerator( bCoefficients, false ); 70 | this->setDenominator( aCoefficients, false ); 71 | 72 | if ( clearState ) this->clear(); 73 | } 74 | 75 | void Iir :: setNumerator( std::vector &bCoefficients, bool clearState ) 76 | { 77 | // Check the argument. 78 | if ( bCoefficients.size() == 0 ) { 79 | oStream_ << "Iir::setNumerator: coefficient vector must have size > 0!"; 80 | handleError( StkError::FUNCTION_ARGUMENT ); 81 | } 82 | 83 | if ( b_.size() != bCoefficients.size() ) { 84 | b_ = bCoefficients; 85 | inputs_.resize( b_.size(), 1, 0.0 ); 86 | } 87 | else { 88 | for ( unsigned int i=0; iclear(); 92 | } 93 | 94 | void Iir :: setDenominator( std::vector &aCoefficients, bool clearState ) 95 | { 96 | // Check the argument. 97 | if ( aCoefficients.size() == 0 ) { 98 | oStream_ << "Iir::setDenominator: coefficient vector must have size > 0!"; 99 | handleError( StkError::FUNCTION_ARGUMENT ); 100 | } 101 | 102 | if ( aCoefficients[0] == 0.0 ) { 103 | oStream_ << "Iir::setDenominator: a[0] coefficient cannot == 0!"; 104 | handleError( StkError::FUNCTION_ARGUMENT ); 105 | } 106 | 107 | if ( a_.size() != aCoefficients.size() ) { 108 | a_ = aCoefficients; 109 | outputs_.resize( a_.size(), 1, 0.0 ); 110 | } 111 | else { 112 | for ( unsigned int i=0; iclear(); 116 | 117 | // Scale coefficients by a[0] if necessary 118 | if ( a_[0] != 1.0 ) { 119 | unsigned int i; 120 | for ( i=0; i= lastFrame_.channels() ) { 86 | oStream_ << "Instrmnt::lastOut(): channel argument is invalid!"; 87 | handleError( StkError::FUNCTION_ARGUMENT ); 88 | } 89 | #endif 90 | 91 | return lastFrame_[channel]; 92 | } 93 | 94 | inline void Instrmnt :: controlChange( int number, StkFloat value ) 95 | { 96 | oStream_ << "Instrmnt::controlChange: virtual function call!"; 97 | handleError( StkError::WARNING ); 98 | } 99 | 100 | } // stk namespace 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /stk/LentPitShift.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class LentPitShift 3 | \brief Pitch shifter effect class based on the Lent algorithm. 4 | 5 | This class implements a pitch shifter using pitch 6 | tracking and sample windowing and shifting. 7 | 8 | by Francois Germain, 2009. 9 | */ 10 | /***************************************************/ 11 | 12 | #include "LentPitShift.h" 13 | 14 | namespace stk { 15 | 16 | LentPitShift::LentPitShift( StkFloat periodRatio, int tMax ) 17 | : inputFrames(0.,tMax,1), outputFrames(0.,tMax,1), ptrFrames(0), inputPtr(0), outputPtr(0.), tMax_(tMax), periodRatio_(periodRatio), zeroFrame(0., tMax, 1) 18 | { 19 | window = new StkFloat[2*tMax_]; // Allocation of the array for the hamming window 20 | threshold_ = 0.1; // Default threshold for pitch tracking 21 | 22 | dt = new StkFloat[tMax+1]; // Allocation of the euclidian distance coefficient array. The first one is never used. 23 | cumDt = new StkFloat[tMax+1]; // Allocation of the cumulative sum array 24 | cumDt[0] = 0.; // Initialization of the first coefficient of the cumulative sum 25 | dpt = new StkFloat[tMax+1]; // Allocation of the pitch tracking function coefficient array 26 | dpt[0] = 1.; // Initialization of the first coefficient of dpt which is always the same 27 | 28 | // Initialisation of the input and output delay lines 29 | inputLine_.setMaximumDelay( 3 * tMax_ ); 30 | // The delay is choosed such as the coefficients are not read before being finalised. 31 | outputLine_.setMaximumDelay( 3 * tMax_ ); 32 | outputLine_.setDelay( 3 * tMax_ ); 33 | 34 | //Initialization of the delay line of pitch tracking coefficients 35 | //coeffLine_ = new Delay[512]; 36 | //for(int i=0;i= noiseRate_ ) { 82 | noise_.tick(); 83 | noiseCounter_ = 0; 84 | } 85 | lastFrame_[0] += filter_.tick( noise_.lastOut() ); 86 | return lastFrame_[0]; 87 | } 88 | 89 | inline StkFrames& Modulate :: tick( StkFrames& frames, unsigned int channel ) 90 | { 91 | #if defined(_STK_DEBUG_) 92 | if ( channel >= frames.channels() ) { 93 | oStream_ << "Modulate::tick(): channel and StkFrames arguments are incompatible!"; 94 | handleError( StkError::FUNCTION_ARGUMENT ); 95 | } 96 | #endif 97 | 98 | StkFloat *samples = &frames[channel]; 99 | unsigned int hop = frames.channels(); 100 | for ( unsigned int i=0; isetFrequency( 6.122 ); 33 | 34 | filters_[0].setTargets( 0.0, 0.7 ); 35 | filters_[1].setTargets( 0.0, 0.7 ); 36 | 37 | adsr_.setAllTimes( 0.001, 1.5, 0.6, 0.250 ); 38 | filterQ_ = 0.85; 39 | filterRate_ = 0.0001; 40 | modDepth_ = 0.0; 41 | } 42 | 43 | Moog :: ~Moog( void ) 44 | { 45 | } 46 | 47 | void Moog :: setFrequency( StkFloat frequency ) 48 | { 49 | #if defined(_STK_DEBUG_) 50 | if ( frequency <= 0.0 ) { 51 | oStream_ << "Moog::setFrequency: parameter is less than or equal to zero!"; 52 | handleError( StkError::WARNING ); return; 53 | } 54 | #endif 55 | 56 | baseFrequency_ = frequency; 57 | StkFloat rate = attacks_[0]->getSize() * 0.01 * baseFrequency_ / Stk::sampleRate(); 58 | attacks_[0]->setRate( rate ); 59 | loops_[0]->setFrequency( baseFrequency_ ); 60 | } 61 | 62 | void Moog :: noteOn( StkFloat frequency, StkFloat amplitude ) 63 | { 64 | StkFloat temp; 65 | 66 | this->setFrequency( frequency ); 67 | this->keyOn(); 68 | attackGain_ = amplitude * 0.5; 69 | loopGain_ = amplitude; 70 | 71 | temp = filterQ_ + 0.05; 72 | filters_[0].setStates( 2000.0, temp ); 73 | filters_[1].setStates( 2000.0, temp ); 74 | 75 | temp = filterQ_ + 0.099; 76 | filters_[0].setTargets( frequency, temp ); 77 | filters_[1].setTargets( frequency, temp ); 78 | 79 | filters_[0].setSweepRate( filterRate_ * 22050.0 / Stk::sampleRate() ); 80 | filters_[1].setSweepRate( filterRate_ * 22050.0 / Stk::sampleRate() ); 81 | } 82 | 83 | void Moog :: controlChange( int number, StkFloat value ) 84 | { 85 | #if defined(_STK_DEBUG_) 86 | if ( Stk::inRange( value, 0.0, 128.0 ) == false ) { 87 | oStream_ << "Moog::controlChange: value (" << value << ") is out of range!"; 88 | handleError( StkError::WARNING ); return; 89 | } 90 | #endif 91 | 92 | StkFloat normalizedValue = value * ONE_OVER_128; 93 | if (number == __SK_FilterQ_) // 2 94 | filterQ_ = 0.80 + ( 0.1 * normalizedValue ); 95 | else if (number == __SK_FilterSweepRate_) // 4 96 | filterRate_ = normalizedValue * 0.0002; 97 | else if (number == __SK_ModFrequency_) // 11 98 | this->setModulationSpeed( normalizedValue * 12.0 ); 99 | else if (number == __SK_ModWheel_) // 1 100 | this->setModulationDepth( normalizedValue ); 101 | else if (number == __SK_AfterTouch_Cont_) // 128 102 | adsr_.setTarget( normalizedValue ); 103 | #if defined(_STK_DEBUG_) 104 | else { 105 | oStream_ << "Moog::controlChange: undefined control number (" << number << ")!"; 106 | handleError( StkError::WARNING ); 107 | } 108 | #endif 109 | } 110 | 111 | } // stk namespace 112 | -------------------------------------------------------------------------------- /stk/Moog.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_MOOG_H 2 | #define STK_MOOG_H 3 | 4 | #include "Sampler.h" 5 | #include "FormSwep.h" 6 | 7 | namespace stk { 8 | 9 | /***************************************************/ 10 | /*! \class Moog 11 | \brief STK moog-like swept filter sampling synthesis class. 12 | 13 | This instrument uses one attack wave, one 14 | looped wave, and an ADSR envelope (inherited 15 | from the Sampler class) and adds two sweepable 16 | formant (FormSwep) filters. 17 | 18 | Control Change Numbers: 19 | - Filter Q = 2 20 | - Filter Sweep Rate = 4 21 | - Vibrato Frequency = 11 22 | - Vibrato Gain = 1 23 | - Gain = 128 24 | 25 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 26 | */ 27 | /***************************************************/ 28 | 29 | class Moog : public Sampler 30 | { 31 | public: 32 | //! Class constructor. 33 | /*! 34 | An StkError will be thrown if the rawwave path is incorrectly set. 35 | */ 36 | Moog( void ); 37 | 38 | //! Class destructor. 39 | ~Moog( void ); 40 | 41 | //! Set instrument parameters for a particular frequency. 42 | void setFrequency( StkFloat frequency ); 43 | 44 | //! Start a note with the given frequency and amplitude. 45 | void noteOn( StkFloat frequency, StkFloat amplitude ); 46 | 47 | //! Set the modulation (vibrato) speed in Hz. 48 | void setModulationSpeed( StkFloat mSpeed ) { loops_[1]->setFrequency( mSpeed ); }; 49 | 50 | //! Set the modulation (vibrato) depth. 51 | void setModulationDepth( StkFloat mDepth ) { modDepth_ = mDepth * 0.5; }; 52 | 53 | //! Perform the control change specified by \e number and \e value (0.0 - 128.0). 54 | void controlChange( int number, StkFloat value ); 55 | 56 | //! Compute and return one output sample. 57 | StkFloat tick( unsigned int channel = 0 ); 58 | 59 | //! Fill a channel of the StkFrames object with computed outputs. 60 | /*! 61 | The \c channel argument must be less than the number of 62 | channels in the StkFrames argument (the first channel is specified 63 | by 0). However, range checking is only performed if _STK_DEBUG_ 64 | is defined during compilation, in which case an out-of-range value 65 | will trigger an StkError exception. 66 | */ 67 | StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); 68 | 69 | protected: 70 | 71 | FormSwep filters_[2]; 72 | StkFloat modDepth_; 73 | StkFloat filterQ_; 74 | StkFloat filterRate_; 75 | 76 | }; 77 | 78 | inline StkFloat Moog :: tick( unsigned int ) 79 | { 80 | StkFloat temp; 81 | 82 | if ( modDepth_ != 0.0 ) { 83 | temp = loops_[1]->tick() * modDepth_; 84 | loops_[0]->setFrequency( baseFrequency_ * (1.0 + temp) ); 85 | } 86 | 87 | temp = attackGain_ * attacks_[0]->tick(); 88 | temp += loopGain_ * loops_[0]->tick(); 89 | temp = filter_.tick( temp ); 90 | temp *= adsr_.tick(); 91 | temp = filters_[0].tick( temp ); 92 | lastFrame_[0] = filters_[1].tick( temp ); 93 | return lastFrame_[0] * 6.0; 94 | } 95 | 96 | inline StkFrames& Moog :: tick( StkFrames& frames, unsigned int channel ) 97 | { 98 | unsigned int nChannels = lastFrame_.channels(); 99 | #if defined(_STK_DEBUG_) 100 | if ( channel > frames.channels() - nChannels ) { 101 | oStream_ << "Moog::tick(): channel and StkFrames arguments are incompatible!"; 102 | handleError( StkError::FUNCTION_ARGUMENT ); 103 | } 104 | #endif 105 | 106 | StkFloat *samples = &frames[channel]; 107 | unsigned int j, hop = frames.channels() - nChannels; 108 | if ( nChannels == 1 ) { 109 | for ( unsigned int i=0; i 9 | typedef pthread_mutex_t MUTEX; 10 | typedef pthread_cond_t CONDITION; 11 | 12 | #elif defined(__OS_WINDOWS__) 13 | 14 | #include 15 | #include 16 | typedef CRITICAL_SECTION MUTEX; 17 | typedef HANDLE CONDITION; 18 | 19 | #endif 20 | 21 | namespace stk { 22 | 23 | /***************************************************/ 24 | /*! \class Mutex 25 | \brief STK mutex class. 26 | 27 | This class provides a uniform interface for 28 | cross-platform mutex use. On Linux and IRIX 29 | systems, the pthread library is used. Under 30 | Windows, critical sections are used. 31 | 32 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 33 | */ 34 | /***************************************************/ 35 | 36 | class Mutex : public Stk 37 | { 38 | public: 39 | //! Default constructor. 40 | Mutex(); 41 | 42 | //! Class destructor. 43 | ~Mutex(); 44 | 45 | //! Lock the mutex. 46 | void lock(void); 47 | 48 | //! Unlock the mutex. 49 | void unlock(void); 50 | 51 | //! Wait indefinitely on the mutex condition variable. 52 | /*! 53 | The mutex must be locked before calling this function, and then 54 | subsequently unlocked after this function returns. 55 | */ 56 | void wait(void); 57 | 58 | //! Signal the condition variable. 59 | /*! 60 | The mutex must be locked before calling this function, and then 61 | subsequently unlocked after this function returns. 62 | */ 63 | void signal(void); 64 | 65 | protected: 66 | 67 | MUTEX mutex_; 68 | CONDITION condition_; 69 | 70 | }; 71 | 72 | } // stk namespace 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /stk/Noise.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Noise 3 | \brief STK noise generator. 4 | 5 | Generic random number generation using the 6 | C rand() function. The quality of the rand() 7 | function varies from one OS to another. 8 | 9 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 10 | */ 11 | /***************************************************/ 12 | 13 | #include "Noise.h" 14 | #include 15 | 16 | namespace stk { 17 | 18 | Noise :: Noise( unsigned int seed ) 19 | { 20 | // Seed the random number generator 21 | this->setSeed( seed ); 22 | } 23 | 24 | void Noise :: setSeed( unsigned int seed ) 25 | { 26 | if ( seed == 0 ) 27 | srand( (unsigned int) time( NULL ) ); 28 | else 29 | srand( seed ); 30 | } 31 | 32 | } // stk namespace 33 | 34 | 35 | -------------------------------------------------------------------------------- /stk/Noise.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_NOISE_H 2 | #define STK_NOISE_H 3 | 4 | #include "Generator.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class Noise 10 | \brief STK noise generator. 11 | 12 | Generic random number generation using the 13 | C rand() function. The quality of the rand() 14 | function varies from one OS to another. 15 | 16 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 17 | */ 18 | /***************************************************/ 19 | 20 | class Noise : public Generator 21 | { 22 | public: 23 | 24 | //! Default constructor that can also take a specific seed value. 25 | /*! 26 | If the seed value is zero (the default value), the random number generator is 27 | seeded with the system time. 28 | */ 29 | Noise( unsigned int seed = 0 ); 30 | 31 | //! Seed the random number generator with a specific seed value. 32 | /*! 33 | If no seed is provided or the seed value is zero, the random 34 | number generator is seeded with the current system time. 35 | */ 36 | void setSeed( unsigned int seed = 0 ); 37 | 38 | //! Return the last computed output value. 39 | StkFloat lastOut( void ) const { return lastFrame_[0]; }; 40 | 41 | //! Compute and return one output sample. 42 | StkFloat tick( void ); 43 | 44 | //! Fill a channel of the StkFrames object with computed outputs. 45 | /*! 46 | The \c channel argument must be less than the number of 47 | channels in the StkFrames argument (the first channel is specified 48 | by 0). However, range checking is only performed if _STK_DEBUG_ 49 | is defined during compilation, in which case an out-of-range value 50 | will trigger an StkError exception. 51 | */ 52 | StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); 53 | 54 | protected: 55 | 56 | }; 57 | 58 | inline StkFloat Noise :: tick( void ) 59 | { 60 | return lastFrame_[0] = (StkFloat) ( 2.0 * rand() / (RAND_MAX + 1.0) - 1.0 ); 61 | } 62 | 63 | inline StkFrames& Noise :: tick( StkFrames& frames, unsigned int channel ) 64 | { 65 | #if defined(_STK_DEBUG_) 66 | if ( channel >= frames.channels() ) { 67 | oStream_ << "Noise::tick(): channel and StkFrames arguments are incompatible!"; 68 | handleError( StkError::FUNCTION_ARGUMENT ); 69 | } 70 | #endif 71 | 72 | StkFloat *samples = &frames[channel]; 73 | unsigned int hop = frames.channels(); 74 | for ( unsigned int i=0; isetPole( thePole ); 26 | } 27 | 28 | OnePole :: ~OnePole() 29 | { 30 | } 31 | 32 | void OnePole :: setPole( StkFloat thePole ) 33 | { 34 | if ( std::abs( thePole ) >= 1.0 ) { 35 | oStream_ << "OnePole::setPole: argument (" << thePole << ") should be less than 1.0!"; 36 | handleError( StkError::WARNING ); return; 37 | } 38 | 39 | // Normalize coefficients for peak unity gain. 40 | if ( thePole > 0.0 ) 41 | b_[0] = (StkFloat) (1.0 - thePole); 42 | else 43 | b_[0] = (StkFloat) (1.0 + thePole); 44 | 45 | a_[1] = -thePole; 46 | } 47 | 48 | void OnePole :: setCoefficients( StkFloat b0, StkFloat a1, bool clearState ) 49 | { 50 | if ( std::abs( a1 ) >= 1.0 ) { 51 | oStream_ << "OnePole::setCoefficients: a1 argument (" << a1 << ") should be less than 1.0!"; 52 | handleError( StkError::WARNING ); return; 53 | } 54 | 55 | b_[0] = b0; 56 | a_[1] = a1; 57 | 58 | if ( clearState ) this->clear(); 59 | } 60 | 61 | } // stk namespace 62 | -------------------------------------------------------------------------------- /stk/OneZero.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class OneZero 3 | \brief STK one-zero filter class. 4 | 5 | This class implements a one-zero digital filter. A method is 6 | provided for setting the zero position along the real axis of the 7 | z-plane while maintaining a constant filter gain. 8 | 9 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 10 | */ 11 | /***************************************************/ 12 | 13 | #include "OneZero.h" 14 | #include 15 | 16 | namespace stk { 17 | 18 | OneZero :: OneZero( StkFloat theZero ) 19 | { 20 | b_.resize( 2 ); 21 | inputs_.resize( 2, 1, 0.0 ); 22 | 23 | this->setZero( theZero ); 24 | } 25 | 26 | OneZero :: ~OneZero( void ) 27 | { 28 | } 29 | 30 | void OneZero :: setZero( StkFloat theZero ) 31 | { 32 | // Normalize coefficients for unity gain. 33 | if ( theZero > 0.0 ) 34 | b_[0] = 1.0 / ((StkFloat) 1.0 + theZero); 35 | else 36 | b_[0] = 1.0 / ((StkFloat) 1.0 - theZero); 37 | 38 | b_[1] = -theZero * b_[0]; 39 | } 40 | 41 | void OneZero :: setCoefficients( StkFloat b0, StkFloat b1, bool clearState ) 42 | { 43 | b_[0] = b0; 44 | b_[1] = b1; 45 | 46 | if ( clearState ) this->clear(); 47 | } 48 | 49 | } // stk namespace 50 | -------------------------------------------------------------------------------- /stk/PRCRev.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class PRCRev 3 | \brief Perry's simple reverberator class. 4 | 5 | This class is based on some of the famous 6 | Stanford/CCRMA reverbs (NRev, KipRev), which 7 | were based on the Chowning/Moorer/Schroeder 8 | reverberators using networks of simple allpass 9 | and comb delay filters. This class implements 10 | two series allpass units and two parallel comb 11 | filters. 12 | 13 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 14 | */ 15 | /***************************************************/ 16 | 17 | #include "PRCRev.h" 18 | #include 19 | 20 | namespace stk { 21 | 22 | PRCRev :: PRCRev( StkFloat T60 ) 23 | { 24 | if ( T60 <= 0.0 ) { 25 | oStream_ << "PRCRev::PRCRev: argument (" << T60 << ") must be positive!"; 26 | handleError( StkError::FUNCTION_ARGUMENT ); 27 | } 28 | 29 | lastFrame_.resize( 1, 2, 0.0 ); // resize lastFrame_ for stereo output 30 | 31 | // Delay lengths for 44100 Hz sample rate. 32 | int lengths[4]= {341, 613, 1557, 2137}; 33 | double scaler = Stk::sampleRate() / 44100.0; 34 | 35 | // Scale the delay lengths if necessary. 36 | int delay, i; 37 | if ( scaler != 1.0 ) { 38 | for (i=0; i<4; i++) { 39 | delay = (int) floor(scaler * lengths[i]); 40 | if ( (delay & 1) == 0) delay++; 41 | while ( !this->isPrime(delay) ) delay += 2; 42 | lengths[i] = delay; 43 | } 44 | } 45 | 46 | for ( i=0; i<2; i++ ) { 47 | allpassDelays_[i].setMaximumDelay( lengths[i] ); 48 | allpassDelays_[i].setDelay( lengths[i] ); 49 | 50 | combDelays_[i].setMaximumDelay( lengths[i+2] ); 51 | combDelays_[i].setDelay( lengths[i+2] ); 52 | } 53 | 54 | this->setT60( T60 ); 55 | allpassCoefficient_ = 0.7; 56 | effectMix_ = 0.5; 57 | this->clear(); 58 | } 59 | 60 | void PRCRev :: clear( void ) 61 | { 62 | allpassDelays_[0].clear(); 63 | allpassDelays_[1].clear(); 64 | combDelays_[0].clear(); 65 | combDelays_[1].clear(); 66 | lastFrame_[0] = 0.0; 67 | lastFrame_[1] = 0.0; 68 | } 69 | 70 | void PRCRev :: setT60( StkFloat T60 ) 71 | { 72 | if ( T60 <= 0.0 ) { 73 | oStream_ << "PRCRev::setT60: argument (" << T60 << ") must be positive!"; 74 | handleError( StkError::WARNING ); return; 75 | } 76 | 77 | combCoefficient_[0] = pow(10.0, (-3.0 * combDelays_[0].getDelay() / (T60 * Stk::sampleRate()))); 78 | combCoefficient_[1] = pow(10.0, (-3.0 * combDelays_[1].getDelay() / (T60 * Stk::sampleRate()))); 79 | } 80 | 81 | StkFrames& PRCRev :: tick( StkFrames& frames, unsigned int channel ) 82 | { 83 | #if defined(_STK_DEBUG_) 84 | if ( channel >= frames.channels() - 1 ) { 85 | oStream_ << "PRCRev::tick(): channel and StkFrames arguments are incompatible!"; 86 | handleError( StkError::FUNCTION_ARGUMENT ); 87 | } 88 | #endif 89 | 90 | StkFloat *samples = &frames[channel]; 91 | unsigned int hop = frames.channels(); 92 | for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() - 1 ) { 104 | oStream_ << "PRCRev::tick(): channel and StkFrames arguments are incompatible!"; 105 | handleError( StkError::FUNCTION_ARGUMENT ); 106 | } 107 | #endif 108 | 109 | StkFloat *iSamples = &iFrames[iChannel]; 110 | StkFloat *oSamples = &oFrames[oChannel]; 111 | unsigned int iHop = iFrames.channels(), oHop = oFrames.channels(); 112 | for ( unsigned int i=0; i3--\ 9 | 2-- + -->1-->Out 10 | \endcode 11 | 12 | Control Change Numbers: 13 | - Total Modulator Index = 2 14 | - Modulator Crossfade = 4 15 | - LFO Speed = 11 16 | - LFO Depth = 1 17 | - ADSR 2 & 4 Target = 128 18 | 19 | The basic Chowning/Stanford FM patent expired 20 | in 1995, but there exist follow-on patents, 21 | mostly assigned to Yamaha. If you are of the 22 | type who should worry about this (making 23 | money) worry away. 24 | 25 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 26 | */ 27 | /***************************************************/ 28 | 29 | #include "PercFlut.h" 30 | 31 | namespace stk { 32 | 33 | PercFlut :: PercFlut( void ) 34 | : FM() 35 | { 36 | // Concatenate the STK rawwave path to the rawwave files 37 | for ( unsigned int i=0; i<3; i++ ) 38 | waves_[i] = new FileLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true ); 39 | waves_[3] = new FileLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true ); 40 | 41 | this->setRatio(0, 1.50 * 1.000); 42 | this->setRatio(1, 3.00 * 0.995); 43 | this->setRatio(2, 2.99 * 1.005); 44 | this->setRatio(3, 6.00 * 0.997); 45 | gains_[0] = fmGains_[99]; 46 | gains_[1] = fmGains_[71]; 47 | gains_[2] = fmGains_[93]; 48 | gains_[3] = fmGains_[85]; 49 | 50 | adsr_[0]->setAllTimes( 0.05, 0.05, fmSusLevels_[14], 0.05); 51 | adsr_[1]->setAllTimes( 0.02, 0.50, fmSusLevels_[13], 0.5); 52 | adsr_[2]->setAllTimes( 0.02, 0.30, fmSusLevels_[11], 0.05); 53 | adsr_[3]->setAllTimes( 0.02, 0.05, fmSusLevels_[13], 0.01); 54 | 55 | twozero_.setGain( 0.0 ); 56 | modDepth_ = 0.005; 57 | } 58 | 59 | PercFlut :: ~PercFlut( void ) 60 | { 61 | } 62 | 63 | void PercFlut :: setFrequency( StkFloat frequency ) 64 | { 65 | #if defined(_STK_DEBUG_) 66 | if ( frequency <= 0.0 ) { 67 | oStream_ << "PercFlut::setFrequency: argument is less than or equal to zero!"; 68 | handleError( StkError::WARNING ); return; 69 | } 70 | #endif 71 | 72 | baseFrequency_ = frequency; 73 | } 74 | 75 | void PercFlut :: noteOn( StkFloat frequency, StkFloat amplitude ) 76 | { 77 | gains_[0] = amplitude * fmGains_[99] * 0.5; 78 | gains_[1] = amplitude * fmGains_[71] * 0.5; 79 | gains_[2] = amplitude * fmGains_[93] * 0.5; 80 | gains_[3] = amplitude * fmGains_[85] * 0.5; 81 | this->setFrequency( frequency ); 82 | this->keyOn(); 83 | } 84 | 85 | } // stk namespace 86 | -------------------------------------------------------------------------------- /stk/Phonemes.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_PHONEMES_H 2 | #define STK_PHONEMES_H 3 | 4 | #include "Stk.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class Phonemes 10 | \brief STK phonemes table. 11 | 12 | This class does nothing other than declare a 13 | set of 32 static phoneme formant parameters 14 | and provide access to those values. 15 | 16 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 17 | */ 18 | /***************************************************/ 19 | 20 | class Phonemes : public Stk 21 | { 22 | public: 23 | 24 | Phonemes( void ); 25 | 26 | ~Phonemes( void ); 27 | 28 | //! Returns the phoneme name for the given index (0-31). 29 | static const char *name( unsigned int index ); 30 | 31 | //! Returns the voiced component gain for the given phoneme index (0-31). 32 | static StkFloat voiceGain( unsigned int index ); 33 | 34 | //! Returns the unvoiced component gain for the given phoneme index (0-31). 35 | static StkFloat noiseGain( unsigned int index ); 36 | 37 | //! Returns the formant frequency for the given phoneme index (0-31) and partial (0-3). 38 | static StkFloat formantFrequency( unsigned int index, unsigned int partial ); 39 | 40 | //! Returns the formant radius for the given phoneme index (0-31) and partial (0-3). 41 | static StkFloat formantRadius( unsigned int index, unsigned int partial ); 42 | 43 | //! Returns the formant gain for the given phoneme index (0-31) and partial (0-3). 44 | static StkFloat formantGain( unsigned int index, unsigned int partial ); 45 | 46 | private: 47 | 48 | static const char phonemeNames[][4]; 49 | static const StkFloat phonemeGains[][2]; 50 | static const StkFloat phonemeParameters[][4][3]; 51 | }; 52 | 53 | } // stk namespace 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /stk/PitShift.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class PitShift 3 | \brief STK simple pitch shifter effect class. 4 | 5 | This class implements a simple pitch shifter 6 | using delay lines. 7 | 8 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 9 | */ 10 | /***************************************************/ 11 | 12 | #include "PitShift.h" 13 | #include 14 | 15 | namespace stk { 16 | 17 | PitShift :: PitShift( void ) 18 | { 19 | delayLength_ = maxDelay - 24; 20 | halfLength_ = delayLength_ / 2; 21 | delay_[0] = 12; 22 | delay_[1] = maxDelay / 2; 23 | 24 | delayLine_[0].setMaximumDelay( maxDelay ); 25 | delayLine_[0].setDelay( delay_[0] ); 26 | delayLine_[1].setMaximumDelay( maxDelay ); 27 | delayLine_[1].setDelay( delay_[1] ); 28 | effectMix_ = 0.5; 29 | rate_ = 1.0; 30 | } 31 | 32 | void PitShift :: clear() 33 | { 34 | delayLine_[0].clear(); 35 | delayLine_[1].clear(); 36 | lastFrame_[0] = 0.0; 37 | } 38 | 39 | void PitShift :: setShift( StkFloat shift ) 40 | { 41 | if ( shift < 1.0 ) { 42 | rate_ = 1.0 - shift; 43 | } 44 | else if ( shift > 1.0 ) { 45 | rate_ = 1.0 - shift; 46 | } 47 | else { 48 | rate_ = 0.0; 49 | delay_[0] = halfLength_ + 12; 50 | } 51 | } 52 | 53 | StkFrames& PitShift :: tick( StkFrames& frames, unsigned int channel ) 54 | { 55 | #if defined(_STK_DEBUG_) 56 | if ( channel >= frames.channels() ) { 57 | oStream_ << "PitShift::tick(): channel and StkFrames arguments are incompatible!"; 58 | handleError( StkError::FUNCTION_ARGUMENT ); 59 | } 60 | #endif 61 | 62 | StkFloat *samples = &frames[channel]; 63 | unsigned int hop = frames.channels(); 64 | for ( unsigned int i=0; i= iFrames.channels() || oChannel >= oFrames.channels() ) { 74 | oStream_ << "PitShift::tick(): channel and StkFrames arguments are incompatible!"; 75 | handleError( StkError::FUNCTION_ARGUMENT ); 76 | } 77 | #endif 78 | 79 | StkFloat *iSamples = &iFrames[iChannel]; 80 | StkFloat *oSamples = &oFrames[oChannel]; 81 | unsigned int iHop = iFrames.channels(), oHop = oFrames.channels(); 82 | for ( unsigned int i=0; i maxDelay-12 ) delay_[0] -= delayLength_; 79 | while ( delay_[0] < 12 ) delay_[0] += delayLength_; 80 | 81 | delay_[1] = delay_[0] + halfLength_; 82 | while ( delay_[1] > maxDelay-12 ) delay_[1] -= delayLength_; 83 | while ( delay_[1] < 12 ) delay_[1] += delayLength_; 84 | 85 | // Set the new delay line lengths. 86 | delayLine_[0].setDelay( delay_[0] ); 87 | delayLine_[1].setDelay( delay_[1] ); 88 | 89 | // Calculate a triangular envelope. 90 | env_[1] = fabs( ( delay_[0] - halfLength_ + 12 ) * ( 1.0 / (halfLength_ + 12 ) ) ); 91 | env_[0] = 1.0 - env_[1]; 92 | 93 | // Delay input and apply envelope. 94 | lastFrame_[0] = env_[0] * delayLine_[0].tick( input ); 95 | lastFrame_[0] += env_[1] * delayLine_[1].tick( input ); 96 | 97 | // Compute effect mix and output. 98 | lastFrame_[0] *= effectMix_; 99 | lastFrame_[0] += ( 1.0 - effectMix_ ) * input; 100 | 101 | return lastFrame_[0]; 102 | } 103 | 104 | } // stk namespace 105 | 106 | #endif 107 | 108 | -------------------------------------------------------------------------------- /stk/Plucked.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Plucked 3 | \brief STK basic plucked string class. 4 | 5 | This class implements a simple plucked string 6 | physical model based on the Karplus-Strong 7 | algorithm. 8 | 9 | For a more advanced plucked string implementation, 10 | see the stk::Twang class. 11 | 12 | This is a digital waveguide model, making its 13 | use possibly subject to patents held by 14 | Stanford University, Yamaha, and others. 15 | There exist at least two patents, assigned to 16 | Stanford, bearing the names of Karplus and/or 17 | Strong. 18 | 19 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 20 | */ 21 | /***************************************************/ 22 | 23 | #include "Plucked.h" 24 | 25 | namespace stk { 26 | 27 | Plucked :: Plucked( StkFloat lowestFrequency ) 28 | { 29 | if ( lowestFrequency <= 0.0 ) { 30 | oStream_ << "Plucked::Plucked: argument is less than or equal to zero!"; 31 | handleError( StkError::FUNCTION_ARGUMENT ); 32 | } 33 | 34 | unsigned long delays = (unsigned long) ( Stk::sampleRate() / lowestFrequency ); 35 | delayLine_.setMaximumDelay( delays + 1 ); 36 | 37 | this->setFrequency( 220.0 ); 38 | } 39 | 40 | Plucked :: ~Plucked( void ) 41 | { 42 | } 43 | 44 | void Plucked :: clear( void ) 45 | { 46 | delayLine_.clear(); 47 | loopFilter_.clear(); 48 | pickFilter_.clear(); 49 | } 50 | 51 | void Plucked :: setFrequency( StkFloat frequency ) 52 | { 53 | #if defined(_STK_DEBUG_) 54 | if ( frequency <= 0.0 ) { 55 | oStream_ << "Plucked::setFrequency: argument is less than or equal to zero!"; 56 | handleError( StkError::WARNING ); return; 57 | } 58 | #endif 59 | 60 | // Delay = length - filter delay. 61 | StkFloat delay = ( Stk::sampleRate() / frequency ) - loopFilter_.phaseDelay( frequency ); 62 | delayLine_.setDelay( delay ); 63 | 64 | loopGain_ = 0.995 + (frequency * 0.000005); 65 | if ( loopGain_ >= 1.0 ) loopGain_ = 0.99999; 66 | } 67 | 68 | void Plucked :: pluck( StkFloat amplitude ) 69 | { 70 | if ( amplitude < 0.0 || amplitude > 1.0 ) { 71 | oStream_ << "Plucked::pluck: amplitude is out of range!"; 72 | handleError( StkError::WARNING ); return; 73 | } 74 | 75 | pickFilter_.setPole( 0.999 - (amplitude * 0.15) ); 76 | pickFilter_.setGain( amplitude * 0.5 ); 77 | for ( unsigned long i=0; isetFrequency( frequency ); 85 | this->pluck( amplitude ); 86 | } 87 | 88 | void Plucked :: noteOff( StkFloat amplitude ) 89 | { 90 | if ( amplitude < 0.0 || amplitude > 1.0 ) { 91 | oStream_ << "Plucked::noteOff: amplitude is out of range!"; 92 | handleError( StkError::WARNING ); return; 93 | } 94 | 95 | loopGain_ = 1.0 - amplitude; 96 | } 97 | 98 | } // stk namespace 99 | -------------------------------------------------------------------------------- /stk/Plucked.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_PLUCKED_H 2 | #define STK_PLUCKED_H 3 | 4 | #include "Instrmnt.h" 5 | #include "DelayA.h" 6 | #include "OneZero.h" 7 | #include "OnePole.h" 8 | #include "Noise.h" 9 | 10 | namespace stk { 11 | 12 | /***************************************************/ 13 | /*! \class Plucked 14 | \brief STK basic plucked string class. 15 | 16 | This class implements a simple plucked string 17 | physical model based on the Karplus-Strong 18 | algorithm. 19 | 20 | For a more advanced plucked string implementation, 21 | see the stk::Twang class. 22 | 23 | This is a digital waveguide model, making its 24 | use possibly subject to patents held by 25 | Stanford University, Yamaha, and others. 26 | There exist at least two patents, assigned to 27 | Stanford, bearing the names of Karplus and/or 28 | Strong. 29 | 30 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 31 | */ 32 | /***************************************************/ 33 | 34 | class Plucked : public Instrmnt 35 | { 36 | public: 37 | //! Class constructor, taking the lowest desired playing frequency. 38 | Plucked( StkFloat lowestFrequency = 10.0 ); 39 | 40 | //! Class destructor. 41 | ~Plucked( void ); 42 | 43 | //! Reset and clear all internal state. 44 | void clear( void ); 45 | 46 | //! Set instrument parameters for a particular frequency. 47 | void setFrequency( StkFloat frequency ); 48 | 49 | //! Pluck the string with the given amplitude using the current frequency. 50 | void pluck( StkFloat amplitude ); 51 | 52 | //! Start a note with the given frequency and amplitude. 53 | void noteOn( StkFloat frequency, StkFloat amplitude ); 54 | 55 | //! Stop a note with the given amplitude (speed of decay). 56 | void noteOff( StkFloat amplitude ); 57 | 58 | //! Compute and return one output sample. 59 | StkFloat tick( unsigned int channel = 0 ); 60 | 61 | //! Fill a channel of the StkFrames object with computed outputs. 62 | /*! 63 | The \c channel argument must be less than the number of 64 | channels in the StkFrames argument (the first channel is specified 65 | by 0). However, range checking is only performed if _STK_DEBUG_ 66 | is defined during compilation, in which case an out-of-range value 67 | will trigger an StkError exception. 68 | */ 69 | StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); 70 | 71 | protected: 72 | 73 | DelayA delayLine_; 74 | OneZero loopFilter_; 75 | OnePole pickFilter_; 76 | Noise noise_; 77 | 78 | StkFloat loopGain_; 79 | }; 80 | 81 | inline StkFloat Plucked :: tick( unsigned int ) 82 | { 83 | // Here's the whole inner loop of the instrument!! 84 | return lastFrame_[0] = 3.0 * delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ ) ); 85 | } 86 | 87 | inline StkFrames& Plucked :: tick( StkFrames& frames, unsigned int channel ) 88 | { 89 | unsigned int nChannels = lastFrame_.channels(); 90 | #if defined(_STK_DEBUG_) 91 | if ( channel > frames.channels() - nChannels ) { 92 | oStream_ << "Plucked::tick(): channel and StkFrames arguments are incompatible!"; 93 | handleError( StkError::FUNCTION_ARGUMENT ); 94 | } 95 | #endif 96 | 97 | StkFloat *samples = &frames[channel]; 98 | unsigned int j, hop = frames.channels() - nChannels; 99 | if ( nChannels == 1 ) { 100 | for ( unsigned int i=0; i= 1.0 ) { 36 | oStream_ << "PoleZero::setCoefficients: a1 argument (" << a1 << ") should be less than 1.0!"; 37 | handleError( StkError::WARNING ); return; 38 | } 39 | 40 | b_[0] = b0; 41 | b_[1] = b1; 42 | a_[1] = a1; 43 | 44 | if ( clearState ) this->clear(); 45 | } 46 | 47 | void PoleZero :: setAllpass( StkFloat coefficient ) 48 | { 49 | if ( std::abs( coefficient ) >= 1.0 ) { 50 | oStream_ << "PoleZero::setAllpass: argument (" << coefficient << ") makes filter unstable!"; 51 | handleError( StkError::WARNING ); return; 52 | } 53 | 54 | b_[0] = coefficient; 55 | b_[1] = 1.0; 56 | a_[0] = 1.0; // just in case 57 | a_[1] = coefficient; 58 | } 59 | 60 | void PoleZero :: setBlockZero( StkFloat thePole ) 61 | { 62 | if ( std::abs( thePole ) >= 1.0 ) { 63 | oStream_ << "PoleZero::setBlockZero: argument (" << thePole << ") makes filter unstable!"; 64 | handleError( StkError::WARNING ); return; 65 | } 66 | 67 | b_[0] = 1.0; 68 | b_[1] = -1.0; 69 | a_[0] = 1.0; // just in case 70 | a_[1] = -thePole; 71 | } 72 | 73 | } // stk namespace 74 | -------------------------------------------------------------------------------- /stk/PoleZero.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_POLEZERO_H 2 | #define STK_POLEZERO_H 3 | 4 | #include "Filter.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class PoleZero 10 | \brief STK one-pole, one-zero filter class. 11 | 12 | This class implements a one-pole, one-zero digital filter. A 13 | method is provided for creating an allpass filter with a given 14 | coefficient. Another method is provided to create a DC blocking 15 | filter. 16 | 17 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 18 | */ 19 | /***************************************************/ 20 | 21 | class PoleZero : public Filter 22 | { 23 | public: 24 | 25 | //! Default constructor creates a first-order pass-through filter. 26 | PoleZero(); 27 | 28 | //! Class destructor. 29 | ~PoleZero(); 30 | 31 | //! Set the b[0] coefficient value. 32 | void setB0( StkFloat b0 ) { b_[0] = b0; }; 33 | 34 | //! Set the b[1] coefficient value. 35 | void setB1( StkFloat b1 ) { b_[1] = b1; }; 36 | 37 | //! Set the a[1] coefficient value. 38 | void setA1( StkFloat a1 ) { a_[1] = a1; }; 39 | 40 | //! Set all filter coefficients. 41 | void setCoefficients( StkFloat b0, StkFloat b1, StkFloat a1, bool clearState = false ); 42 | 43 | //! Set the filter for allpass behavior using \e coefficient. 44 | /*! 45 | This method uses \e coefficient to create an allpass filter, 46 | which has unity gain at all frequencies. Note that the 47 | \e coefficient magnitude must be less than one to maintain 48 | filter stability. 49 | */ 50 | void setAllpass( StkFloat coefficient ); 51 | 52 | //! Create a DC blocking filter with the given pole position in the z-plane. 53 | /*! 54 | This method sets the given pole position, together with a zero 55 | at z=1, to create a DC blocking filter. The argument magnitude 56 | should be close to (but less than) one to minimize low-frequency 57 | attenuation. 58 | */ 59 | void setBlockZero( StkFloat thePole = 0.99 ); 60 | 61 | //! Return the last computed output value. 62 | StkFloat lastOut( void ) const { return lastFrame_[0]; }; 63 | 64 | //! Input one sample to the filter and return one output. 65 | StkFloat tick( StkFloat input ); 66 | 67 | //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs. 68 | /*! 69 | The \c channel argument must be less than the number of 70 | channels in the StkFrames argument (the first channel is specified 71 | by 0). However, range checking is only performed if _STK_DEBUG_ 72 | is defined during compilation, in which case an out-of-range value 73 | will trigger an StkError exception. 74 | */ 75 | StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); 76 | 77 | }; 78 | 79 | inline StkFloat PoleZero :: tick( StkFloat input ) 80 | { 81 | inputs_[0] = gain_ * input; 82 | lastFrame_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] - a_[1] * outputs_[1]; 83 | inputs_[1] = inputs_[0]; 84 | outputs_[1] = lastFrame_[0]; 85 | 86 | return lastFrame_[0]; 87 | } 88 | 89 | inline StkFrames& PoleZero :: tick( StkFrames& frames, unsigned int channel ) 90 | { 91 | #if defined(_STK_DEBUG_) 92 | if ( channel >= frames.channels() ) { 93 | oStream_ << "PoleZero::tick(): channel and StkFrames arguments are incompatible!"; 94 | handleError( StkError::FUNCTION_ARGUMENT ); 95 | } 96 | #endif 97 | 98 | StkFloat *samples = &frames[channel]; 99 | unsigned int hop = frames.channels(); 100 | for ( unsigned int i=0; ikeyOn(); 43 | this->setResonance( frequency, poleRadius_ ); 44 | } 45 | 46 | void Resonate :: noteOff( StkFloat amplitude ) 47 | { 48 | this->keyOff(); 49 | } 50 | 51 | void Resonate :: setResonance( StkFloat frequency, StkFloat radius ) 52 | { 53 | if ( frequency < 0.0 ) { 54 | oStream_ << "Resonate::setResonance: frequency parameter is less than zero!"; 55 | handleError( StkError::WARNING ); return; 56 | } 57 | 58 | if ( radius < 0.0 || radius >= 1.0 ) { 59 | std::cerr << "Resonate::setResonance: radius parameter is out of range!"; 60 | handleError( StkError::WARNING ); return; 61 | } 62 | 63 | poleFrequency_ = frequency; 64 | poleRadius_ = radius; 65 | filter_.setResonance( poleFrequency_, poleRadius_, true ); 66 | } 67 | 68 | void Resonate :: setNotch( StkFloat frequency, StkFloat radius ) 69 | { 70 | if ( frequency < 0.0 ) { 71 | oStream_ << "Resonate::setNotch: frequency parameter is less than zero ... setting to 0.0!"; 72 | handleError( StkError::WARNING ); return; 73 | } 74 | 75 | if ( radius < 0.0 ) { 76 | oStream_ << "Resonate::setNotch: radius parameter is less than 0.0!"; 77 | handleError( StkError::WARNING ); return; 78 | } 79 | 80 | zeroFrequency_ = frequency; 81 | zeroRadius_ = radius; 82 | filter_.setNotch( zeroFrequency_, zeroRadius_ ); 83 | } 84 | 85 | void Resonate :: controlChange( int number, StkFloat value ) 86 | { 87 | #if defined(_STK_DEBUG_) 88 | if ( Stk::inRange( value, 0.0, 128.0 ) == false ) { 89 | oStream_ << "Resonate::controlChange: value (" << value << ") is out of range!"; 90 | handleError( StkError::WARNING ); return; 91 | } 92 | #endif 93 | 94 | StkFloat normalizedValue = value * ONE_OVER_128; 95 | if (number == 2) // 2 96 | setResonance( normalizedValue * Stk::sampleRate() * 0.5, poleRadius_ ); 97 | else if (number == 4) // 4 98 | setResonance( poleFrequency_, normalizedValue * 0.9999 ); 99 | else if (number == 11) // 11 100 | this->setNotch( normalizedValue * Stk::sampleRate() * 0.5, zeroRadius_ ); 101 | else if (number == 1) 102 | this->setNotch( zeroFrequency_, normalizedValue ); 103 | else if (number == __SK_AfterTouch_Cont_) // 128 104 | adsr_.setTarget( normalizedValue ); 105 | #if defined(_STK_DEBUG_) 106 | else { 107 | oStream_ << "Resonate::controlChange: undefined control number (" << number << ")!"; 108 | handleError( StkError::WARNING ); 109 | } 110 | #endif 111 | } 112 | 113 | } // stk namespace 114 | -------------------------------------------------------------------------------- /stk/Rhodey.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Rhodey 3 | \brief STK Fender Rhodes-like electric piano FM 4 | synthesis instrument. 5 | 6 | This class implements two simple FM Pairs 7 | summed together, also referred to as algorithm 8 | 5 of the TX81Z. 9 | 10 | \code 11 | Algorithm 5 is : 4->3--\ 12 | + --> Out 13 | 2->1--/ 14 | \endcode 15 | 16 | Control Change Numbers: 17 | - Modulator Index One = 2 18 | - Crossfade of Outputs = 4 19 | - LFO Speed = 11 20 | - LFO Depth = 1 21 | - ADSR 2 & 4 Target = 128 22 | 23 | The basic Chowning/Stanford FM patent expired 24 | in 1995, but there exist follow-on patents, 25 | mostly assigned to Yamaha. If you are of the 26 | type who should worry about this (making 27 | money) worry away. 28 | 29 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 30 | */ 31 | /***************************************************/ 32 | 33 | #include "Rhodey.h" 34 | 35 | namespace stk { 36 | 37 | Rhodey :: Rhodey( void ) 38 | : FM() 39 | { 40 | // Concatenate the STK rawwave path to the rawwave files 41 | for ( unsigned int i=0; i<3; i++ ) 42 | waves_[i] = new FileLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true ); 43 | waves_[3] = new FileLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true ); 44 | 45 | this->setRatio(0, 1.0); 46 | this->setRatio(1, 0.5); 47 | this->setRatio(2, 1.0); 48 | this->setRatio(3, 15.0); 49 | 50 | gains_[0] = fmGains_[99]; 51 | gains_[1] = fmGains_[90]; 52 | gains_[2] = fmGains_[99]; 53 | gains_[3] = fmGains_[67]; 54 | 55 | adsr_[0]->setAllTimes( 0.001, 1.50, 0.0, 0.04); 56 | adsr_[1]->setAllTimes( 0.001, 1.50, 0.0, 0.04); 57 | adsr_[2]->setAllTimes( 0.001, 1.00, 0.0, 0.04); 58 | adsr_[3]->setAllTimes( 0.001, 0.25, 0.0, 0.04); 59 | 60 | twozero_.setGain( 1.0 ); 61 | } 62 | 63 | Rhodey :: ~Rhodey( void ) 64 | { 65 | } 66 | 67 | void Rhodey :: setFrequency( StkFloat frequency ) 68 | { 69 | #if defined(_STK_DEBUG_) 70 | if ( frequency <= 0.0 ) { 71 | oStream_ << "Rhodey::setFrequency: argument is less than or equal to zero!"; 72 | handleError( StkError::WARNING ); return; 73 | } 74 | #endif 75 | 76 | baseFrequency_ = frequency * 2.0; 77 | 78 | for (unsigned int i=0; isetFrequency( baseFrequency_ * ratios_[i] ); 80 | } 81 | 82 | void Rhodey :: noteOn( StkFloat frequency, StkFloat amplitude ) 83 | { 84 | gains_[0] = amplitude * fmGains_[99]; 85 | gains_[1] = amplitude * fmGains_[90]; 86 | gains_[2] = amplitude * fmGains_[99]; 87 | gains_[3] = amplitude * fmGains_[67]; 88 | this->setFrequency( frequency ); 89 | this->keyOn(); 90 | } 91 | 92 | } // stk namespace 93 | -------------------------------------------------------------------------------- /stk/RtError.h: -------------------------------------------------------------------------------- 1 | /************************************************************************/ 2 | /*! \class RtError 3 | \brief Exception handling class for RtAudio & RtMidi. 4 | 5 | The RtError class is quite simple but it does allow errors to be 6 | "caught" by RtError::Type. See the RtAudio and RtMidi 7 | documentation to know which methods can throw an RtError. 8 | 9 | */ 10 | /************************************************************************/ 11 | 12 | #ifndef RTERROR_H 13 | #define RTERROR_H 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | class RtError : public std::exception 20 | { 21 | public: 22 | //! Defined RtError types. 23 | enum Type { 24 | WARNING, /*!< A non-critical error. */ 25 | DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ 26 | UNSPECIFIED, /*!< The default, unspecified error type. */ 27 | NO_DEVICES_FOUND, /*!< No devices found on system. */ 28 | INVALID_DEVICE, /*!< An invalid device ID was specified. */ 29 | MEMORY_ERROR, /*!< An error occured during memory allocation. */ 30 | INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ 31 | INVALID_USE, /*!< The function was called incorrectly. */ 32 | DRIVER_ERROR, /*!< A system driver error occured. */ 33 | SYSTEM_ERROR, /*!< A system error occured. */ 34 | THREAD_ERROR /*!< A thread error occured. */ 35 | }; 36 | 37 | //! The constructor. 38 | RtError( const std::string& message, Type type = RtError::UNSPECIFIED ) throw() : message_(message), type_(type) {} 39 | 40 | //! The destructor. 41 | virtual ~RtError( void ) throw() {} 42 | 43 | //! Prints thrown error message to stderr. 44 | virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } 45 | 46 | //! Returns the thrown error message type. 47 | virtual const Type& getType(void) const throw() { return type_; } 48 | 49 | //! Returns the thrown error message string. 50 | virtual const std::string& getMessage(void) const throw() { return message_; } 51 | 52 | //! Returns the thrown error message as a c-style string. 53 | virtual const char* what( void ) const throw() { return message_.c_str(); } 54 | 55 | protected: 56 | std::string message_; 57 | Type type_; 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /stk/RtWvOut.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_RTWVOUT_H 2 | #define STK_RTWVOUT_H 3 | 4 | #include "WvOut.h" 5 | #include "RtAudio.h" 6 | #include "Mutex.h" 7 | 8 | namespace stk { 9 | 10 | /***************************************************/ 11 | /*! \class RtWvOut 12 | \brief STK realtime audio (blocking) output class. 13 | 14 | This class provides a simplified interface to RtAudio for realtime 15 | audio output. It is a subclass of WvOut. This class makes use of 16 | RtAudio's callback functionality by creating a large ring-buffer 17 | into which data is written. This class should not be used when 18 | low-latency is desired. 19 | 20 | RtWvOut supports multi-channel data in interleaved format. It is 21 | important to distinguish the tick() method that outputs a single 22 | sample to all channels in a sample frame from the overloaded one 23 | that takes a reference to an StkFrames object for multi-channel 24 | and/or multi-frame data. 25 | 26 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 27 | */ 28 | /***************************************************/ 29 | 30 | class RtWvOut : public WvOut 31 | { 32 | public: 33 | 34 | //! Default constructor. 35 | /*! 36 | The default \e device argument value (zero) will select the 37 | default output device on your system. The first device enumerated 38 | by the underlying audio API is specified with a value of one. The 39 | default buffer size of RT_BUFFER_SIZE is defined in Stk.h. An 40 | StkError will be thrown if an error occurs duing instantiation. 41 | */ 42 | RtWvOut( unsigned int nChannels = 1, StkFloat sampleRate = Stk::sampleRate(), 43 | int device = 0, int bufferFrames = RT_BUFFER_SIZE, int nBuffers = 20 ); 44 | 45 | //! Class destructor. 46 | ~RtWvOut(); 47 | 48 | //! Start the audio output stream. 49 | /*! 50 | The stream is started automatically, if necessary, when a 51 | tick() method is called. 52 | */ 53 | void start( void ); 54 | 55 | //! Stop the audio output stream. 56 | /*! 57 | It may be necessary to use this method to avoid undesireable 58 | audio buffer cycling if you wish to temporarily stop audio output. 59 | */ 60 | void stop( void ); 61 | 62 | //! Output a single sample to all channels in a sample frame. 63 | /*! 64 | If the device is "stopped", it is "started". 65 | */ 66 | void tick( const StkFloat sample ); 67 | 68 | //! Output the StkFrames data. 69 | /*! 70 | If the device is "stopped", it is "started". The number of 71 | channels in the StkFrames argument must equal the number of 72 | channels specified during instantiation. However, this is only 73 | checked if _STK_DEBUG_ is defined during compilation, in which 74 | case an incompatibility will trigger an StkError exception. 75 | */ 76 | void tick( const StkFrames& frames ); 77 | 78 | // This function is not intended for general use but must be 79 | // public for access from the audio callback function. 80 | int readBuffer( void *buffer, unsigned int frameCount ); 81 | 82 | protected: 83 | 84 | RtAudio dac_; 85 | Mutex mutex_; 86 | bool stopped_; 87 | unsigned int readIndex_; 88 | unsigned int writeIndex_; 89 | long framesFilled_; 90 | unsigned int status_; // running = 0, emptying buffer = 1, finished = 2 91 | 92 | }; 93 | 94 | } // stk namespace 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /stk/Sampler.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Sampler 3 | \brief STK sampling synthesis abstract base class. 4 | 5 | This instrument provides an ADSR envelope, a one-pole filter, and 6 | structures for an arbitrary number of attack and looped files. 7 | 8 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 9 | */ 10 | /***************************************************/ 11 | 12 | #include "Sampler.h" 13 | 14 | namespace stk { 15 | 16 | Sampler :: Sampler( void ) 17 | { 18 | // We don't make the waves here yet, because 19 | // we don't know what they will be. 20 | baseFrequency_ = 440.0; 21 | attackGain_ = 0.25; 22 | loopGain_ = 0.25; 23 | } 24 | 25 | Sampler :: ~Sampler( void ) 26 | { 27 | unsigned int i; 28 | for ( i=0; ireset(); 37 | 38 | // Start the envelope. 39 | adsr_.keyOn(); 40 | 41 | } 42 | 43 | void Sampler :: keyOff( void ) 44 | { 45 | adsr_.keyOff(); 46 | } 47 | 48 | void Sampler :: noteOff( StkFloat amplitude ) 49 | { 50 | this->keyOff(); 51 | } 52 | 53 | } // stk namespace 54 | -------------------------------------------------------------------------------- /stk/Sampler.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_SAMPLER_H 2 | #define STK_SAMPLER_H 3 | 4 | #include "Instrmnt.h" 5 | #include "ADSR.h" 6 | #include "FileLoop.h" 7 | #include "OnePole.h" 8 | 9 | namespace stk { 10 | 11 | /***************************************************/ 12 | /*! \class Sampler 13 | \brief STK sampling synthesis abstract base class. 14 | 15 | This instrument provides an ADSR envelope, a one-pole filter, and 16 | structures for an arbitrary number of attack and looped files. 17 | 18 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 19 | */ 20 | /***************************************************/ 21 | 22 | class Sampler : public Instrmnt 23 | { 24 | public: 25 | //! Default constructor. 26 | Sampler( void ); 27 | 28 | //! Class destructor. 29 | virtual ~Sampler( void ); 30 | 31 | //! Reset and clear all internal state. 32 | void clear( void ); 33 | 34 | //! Set instrument parameters for a particular frequency. 35 | virtual void setFrequency( StkFloat frequency ) = 0; 36 | 37 | //! Initiate the envelopes with a key-on event and reset the attack waves. 38 | void keyOn( void ); 39 | 40 | //! Signal a key-off event to the envelopes. 41 | void keyOff( void ); 42 | 43 | //! Stop a note with the given amplitude (speed of decay). 44 | virtual void noteOff( StkFloat amplitude ); 45 | 46 | //! Perform the control change specified by \e number and \e value (0.0 - 128.0). 47 | virtual void controlChange( int number, StkFloat value ) = 0; 48 | 49 | //! Compute and return one output sample. 50 | virtual StkFloat tick( unsigned int channel = 0 ) = 0; 51 | 52 | //! Fill a channel of the StkFrames object with computed outputs. 53 | /*! 54 | The \c channel argument must be less than the number of 55 | channels in the StkFrames argument (the first channel is specified 56 | by 0). However, range checking is only performed if _STK_DEBUG_ 57 | is defined during compilation, in which case an out-of-range value 58 | will trigger an StkError exception. 59 | */ 60 | virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ) = 0; 61 | 62 | protected: 63 | 64 | ADSR adsr_; 65 | std::vector attacks_; 66 | std::vector loops_; 67 | OnePole filter_; 68 | StkFloat baseFrequency_; 69 | std::vector attackRatios_; 70 | std::vector loopRatios_; 71 | StkFloat attackGain_; 72 | StkFloat loopGain_; 73 | 74 | }; 75 | 76 | } // stk namespace 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /stk/Simple.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Simple 3 | \brief STK wavetable/noise instrument. 4 | 5 | This class combines a looped wave, a 6 | noise source, a biquad resonance filter, 7 | a one-pole filter, and an ADSR envelope 8 | to create some interesting sounds. 9 | 10 | Control Change Numbers: 11 | - Filter Pole Position = 2 12 | - Noise/Pitched Cross-Fade = 4 13 | - Envelope Rate = 11 14 | - Gain = 128 15 | 16 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 17 | */ 18 | /***************************************************/ 19 | 20 | #include "Simple.h" 21 | #include "SKINI.msg" 22 | 23 | namespace stk { 24 | 25 | Simple :: Simple( void ) 26 | { 27 | // Concatenate the STK rawwave path to the rawwave file 28 | loop_ = new FileLoop( (Stk::rawwavePath() + "impuls10.raw").c_str(), true ); 29 | 30 | filter_.setPole( 0.5 ); 31 | baseFrequency_ = 440.0; 32 | setFrequency( baseFrequency_ ); 33 | loopGain_ = 0.5; 34 | } 35 | 36 | Simple :: ~Simple( void ) 37 | { 38 | delete loop_; 39 | } 40 | 41 | void Simple :: keyOn( void ) 42 | { 43 | adsr_.keyOn(); 44 | } 45 | 46 | void Simple :: keyOff( void ) 47 | { 48 | adsr_.keyOff(); 49 | } 50 | 51 | void Simple :: noteOn( StkFloat frequency, StkFloat amplitude ) 52 | { 53 | this->keyOn(); 54 | this->setFrequency( frequency ); 55 | filter_.setGain( amplitude ); 56 | } 57 | void Simple :: noteOff( StkFloat amplitude ) 58 | { 59 | this->keyOff(); 60 | } 61 | 62 | void Simple :: setFrequency( StkFloat frequency ) 63 | { 64 | #if defined(_STK_DEBUG_) 65 | if ( frequency <= 0.0 ) { 66 | oStream_ << "Simple::setFrequency: argument is less than or equal to zero!"; 67 | handleError( StkError::WARNING ); return; 68 | } 69 | #endif 70 | 71 | biquad_.setResonance( frequency, 0.98, true ); 72 | loop_->setFrequency( frequency ); 73 | } 74 | 75 | void Simple :: controlChange( int number, StkFloat value ) 76 | { 77 | #if defined(_STK_DEBUG_) 78 | if ( Stk::inRange( value, 0.0, 128.0 ) == false ) { 79 | oStream_ << "Simple::controlChange: value (" << value << ") is out of range!"; 80 | handleError( StkError::WARNING ); return; 81 | } 82 | #endif 83 | 84 | StkFloat normalizedValue = value * ONE_OVER_128; 85 | if (number == __SK_Breath_) // 2 86 | filter_.setPole( 0.99 * (1.0 - (normalizedValue * 2.0)) ); 87 | else if (number == __SK_NoiseLevel_) // 4 88 | loopGain_ = normalizedValue; 89 | else if (number == __SK_ModFrequency_) { // 11 90 | normalizedValue /= 0.2 * Stk::sampleRate(); 91 | adsr_.setAttackRate( normalizedValue ); 92 | adsr_.setDecayRate( normalizedValue ); 93 | adsr_.setReleaseRate( normalizedValue ); 94 | } 95 | else if (number == __SK_AfterTouch_Cont_) // 128 96 | adsr_.setTarget( normalizedValue ); 97 | #if defined(_STK_DEBUG_) 98 | else { 99 | oStream_ << "Simple::controlChange: undefined control number (" << number << ")!"; 100 | handleError( StkError::WARNING ); 101 | } 102 | #endif 103 | } 104 | 105 | } // stk namespace 106 | -------------------------------------------------------------------------------- /stk/Simple.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_SIMPLE_H 2 | #define STK_SIMPLE_H 3 | 4 | #include "Instrmnt.h" 5 | #include "ADSR.h" 6 | #include "FileLoop.h" 7 | #include "OnePole.h" 8 | #include "BiQuad.h" 9 | #include "Noise.h" 10 | 11 | namespace stk { 12 | 13 | /***************************************************/ 14 | /*! \class Simple 15 | \brief STK wavetable/noise instrument. 16 | 17 | This class combines a looped wave, a 18 | noise source, a biquad resonance filter, 19 | a one-pole filter, and an ADSR envelope 20 | to create some interesting sounds. 21 | 22 | Control Change Numbers: 23 | - Filter Pole Position = 2 24 | - Noise/Pitched Cross-Fade = 4 25 | - Envelope Rate = 11 26 | - Gain = 128 27 | 28 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 29 | */ 30 | /***************************************************/ 31 | 32 | class Simple : public Instrmnt 33 | { 34 | public: 35 | //! Class constructor. 36 | /*! 37 | An StkError will be thrown if the rawwave path is incorrectly set. 38 | */ 39 | Simple( void ); 40 | 41 | //! Class destructor. 42 | ~Simple( void ); 43 | 44 | //! Clear internal states. 45 | void clear( void ); 46 | 47 | //! Set instrument parameters for a particular frequency. 48 | void setFrequency( StkFloat frequency ); 49 | 50 | //! Start envelope toward "on" target. 51 | void keyOn( void ); 52 | 53 | //! Start envelope toward "off" target. 54 | void keyOff( void ); 55 | 56 | //! Start a note with the given frequency and amplitude. 57 | void noteOn( StkFloat frequency, StkFloat amplitude ); 58 | 59 | //! Stop a note with the given amplitude (speed of decay). 60 | void noteOff( StkFloat amplitude ); 61 | 62 | //! Perform the control change specified by \e number and \e value (0.0 - 128.0). 63 | void controlChange( int number, StkFloat value ); 64 | 65 | //! Compute and return one output sample. 66 | StkFloat tick( unsigned int channel = 0 ); 67 | 68 | //! Fill a channel of the StkFrames object with computed outputs. 69 | /*! 70 | The \c channel argument must be less than the number of 71 | channels in the StkFrames argument (the first channel is specified 72 | by 0). However, range checking is only performed if _STK_DEBUG_ 73 | is defined during compilation, in which case an out-of-range value 74 | will trigger an StkError exception. 75 | */ 76 | StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); 77 | 78 | protected: 79 | 80 | ADSR adsr_; 81 | FileLoop *loop_; 82 | OnePole filter_; 83 | BiQuad biquad_; 84 | Noise noise_; 85 | StkFloat baseFrequency_; 86 | StkFloat loopGain_; 87 | 88 | }; 89 | 90 | inline StkFloat Simple :: tick( unsigned int ) 91 | { 92 | lastFrame_[0] = loopGain_ * loop_->tick(); 93 | biquad_.tick( noise_.tick() ); 94 | lastFrame_[0] += (1.0 - loopGain_) * biquad_.lastOut(); 95 | lastFrame_[0] = filter_.tick( lastFrame_[0] ); 96 | lastFrame_[0] *= adsr_.tick(); 97 | return lastFrame_[0]; 98 | } 99 | 100 | inline StkFrames& Simple :: tick( StkFrames& frames, unsigned int channel ) 101 | { 102 | unsigned int nChannels = lastFrame_.channels(); 103 | #if defined(_STK_DEBUG_) 104 | if ( channel > frames.channels() - nChannels ) { 105 | oStream_ << "Simple::tick(): channel and StkFrames arguments are incompatible!"; 106 | handleError( StkError::FUNCTION_ARGUMENT ); 107 | } 108 | #endif 109 | 110 | StkFloat *samples = &frames[channel]; 111 | unsigned int j, hop = frames.channels() - nChannels; 112 | if ( nChannels == 1 ) { 113 | for ( unsigned int i=0; i 18 | 19 | namespace stk { 20 | 21 | StkFrames SineWave :: table_; 22 | 23 | SineWave :: SineWave( void ) 24 | : time_(0.0), rate_(1.0), phaseOffset_(0.0) 25 | { 26 | if ( table_.empty() ) { 27 | table_.resize( TABLE_SIZE + 1, 1 ); 28 | StkFloat temp = 1.0 / TABLE_SIZE; 29 | for ( unsigned long i=0; i<=TABLE_SIZE; i++ ) 30 | table_[i] = sin( TWO_PI * i * temp ); 31 | } 32 | 33 | Stk::addSampleRateAlert( this ); 34 | } 35 | 36 | SineWave :: ~SineWave() 37 | { 38 | Stk::removeSampleRateAlert( this ); 39 | } 40 | 41 | void SineWave :: sampleRateChanged( StkFloat newRate, StkFloat oldRate ) 42 | { 43 | if ( !ignoreSampleRateChange_ ) 44 | this->setRate( oldRate * rate_ / newRate ); 45 | } 46 | 47 | void SineWave :: reset( void ) 48 | { 49 | time_ = 0.0; 50 | lastFrame_[0] = 0; 51 | } 52 | 53 | void SineWave :: setFrequency( StkFloat frequency ) 54 | { 55 | // This is a looping frequency. 56 | this->setRate( TABLE_SIZE * frequency / Stk::sampleRate() ); 57 | } 58 | 59 | void SineWave :: addTime( StkFloat time ) 60 | { 61 | // Add an absolute time in samples. 62 | time_ += time; 63 | } 64 | 65 | void SineWave :: addPhase( StkFloat phase ) 66 | { 67 | // Add a time in cycles (one cycle = TABLE_SIZE). 68 | time_ += TABLE_SIZE * phase; 69 | } 70 | 71 | void SineWave :: addPhaseOffset( StkFloat phaseOffset ) 72 | { 73 | // Add a phase offset relative to any previous offset value. 74 | time_ += ( phaseOffset - phaseOffset_ ) * TABLE_SIZE; 75 | phaseOffset_ = phaseOffset; 76 | } 77 | 78 | } // stk namespace 79 | -------------------------------------------------------------------------------- /stk/SingWave.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class SingWave 3 | \brief STK "singing" looped soundfile class. 4 | 5 | This class loops a specified soundfile and modulates it both 6 | periodically and randomly to produce a pitched musical sound, like 7 | a simple voice or violin. In general, it is not be used alone 8 | because of "munchkinification" effects from pitch shifting. 9 | Within STK, it is used as an excitation source for other 10 | instruments. 11 | 12 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 13 | */ 14 | /***************************************************/ 15 | 16 | #include "SingWave.h" 17 | 18 | namespace stk { 19 | 20 | SingWave :: SingWave( std::string fileName, bool raw ) 21 | { 22 | // An exception could be thrown here. 23 | wave_.openFile( fileName, raw ); 24 | 25 | rate_ = 1.0; 26 | sweepRate_ = 0.001; 27 | 28 | modulator_.setVibratoRate( 6.0 ); 29 | modulator_.setVibratoGain( 0.04 ); 30 | modulator_.setRandomGain( 0.005 ); 31 | 32 | this->setFrequency( 75.0 ); 33 | pitchEnvelope_.setRate( 1.0 ); 34 | this->tick(); 35 | this->tick(); 36 | pitchEnvelope_.setRate( sweepRate_ * rate_ ); 37 | } 38 | 39 | SingWave :: ~SingWave() 40 | { 41 | } 42 | 43 | void SingWave :: setFrequency( StkFloat frequency ) 44 | { 45 | StkFloat temp = rate_; 46 | rate_ = wave_.getSize() * frequency / Stk::sampleRate(); 47 | temp -= rate_; 48 | if ( temp < 0) temp = -temp; 49 | pitchEnvelope_.setTarget( rate_ ); 50 | pitchEnvelope_.setRate( sweepRate_ * temp ); 51 | } 52 | 53 | } // stk namespace 54 | -------------------------------------------------------------------------------- /stk/Sitar.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Sitar 3 | \brief STK sitar string model class. 4 | 5 | This class implements a sitar plucked string 6 | physical model based on the Karplus-Strong 7 | algorithm. 8 | 9 | This is a digital waveguide model, making its 10 | use possibly subject to patents held by 11 | Stanford University, Yamaha, and others. 12 | There exist at least two patents, assigned to 13 | Stanford, bearing the names of Karplus and/or 14 | Strong. 15 | 16 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 17 | */ 18 | /***************************************************/ 19 | 20 | #include "Sitar.h" 21 | 22 | namespace stk { 23 | 24 | Sitar :: Sitar( StkFloat lowestFrequency ) 25 | { 26 | if ( lowestFrequency <= 0.0 ) { 27 | oStream_ << "Sitar::Sitar: argument is less than or equal to zero!"; 28 | handleError( StkError::FUNCTION_ARGUMENT ); 29 | } 30 | 31 | unsigned long length = (unsigned long) ( Stk::sampleRate() / lowestFrequency + 1 ); 32 | delayLine_.setMaximumDelay( length ); 33 | delay_ = 0.5 * length; 34 | delayLine_.setDelay( delay_ ); 35 | targetDelay_ = delay_; 36 | 37 | loopFilter_.setZero( 0.01 ); 38 | loopGain_ = 0.999; 39 | 40 | envelope_.setAllTimes( 0.001, 0.04, 0.0, 0.5 ); 41 | this->clear(); 42 | } 43 | 44 | Sitar :: ~Sitar( void ) 45 | { 46 | } 47 | 48 | void Sitar :: clear( void ) 49 | { 50 | delayLine_.clear(); 51 | loopFilter_.clear(); 52 | } 53 | 54 | void Sitar :: setFrequency( StkFloat frequency ) 55 | { 56 | #if defined(_STK_DEBUG_) 57 | if ( frequency <= 0.0 ) { 58 | oStream_ << "Sitar::setFrequency: parameter is less than or equal to zero!"; 59 | handleError( StkError::WARNING ); return; 60 | } 61 | #endif 62 | 63 | targetDelay_ = (Stk::sampleRate() / frequency); 64 | delay_ = targetDelay_ * (1.0 + (0.05 * noise_.tick())); 65 | delayLine_.setDelay( delay_ ); 66 | loopGain_ = 0.995 + (frequency * 0.0000005); 67 | if ( loopGain_ > 0.9995 ) loopGain_ = 0.9995; 68 | } 69 | 70 | void Sitar :: pluck( StkFloat amplitude ) 71 | { 72 | envelope_.keyOn(); 73 | } 74 | 75 | void Sitar :: noteOn( StkFloat frequency, StkFloat amplitude ) 76 | { 77 | this->setFrequency( frequency ); 78 | this->pluck( amplitude ); 79 | amGain_ = 0.1 * amplitude; 80 | } 81 | 82 | void Sitar :: noteOff( StkFloat amplitude ) 83 | { 84 | if ( amplitude < 0.0 || amplitude > 1.0 ) { 85 | oStream_ << "Sitar::noteOff: amplitude is out of range!"; 86 | handleError( StkError::WARNING ); return; 87 | } 88 | 89 | loopGain_ = (StkFloat) 1.0 - amplitude; 90 | } 91 | 92 | } // stk namespace 93 | -------------------------------------------------------------------------------- /stk/Sitar.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_SITAR_H 2 | #define STK_SITAR_H 3 | 4 | #include "Instrmnt.h" 5 | #include "DelayA.h" 6 | #include "OneZero.h" 7 | #include "Noise.h" 8 | #include "ADSR.h" 9 | #include 10 | 11 | namespace stk { 12 | 13 | /***************************************************/ 14 | /*! \class Sitar 15 | \brief STK sitar string model class. 16 | 17 | This class implements a sitar plucked string 18 | physical model based on the Karplus-Strong 19 | algorithm. 20 | 21 | This is a digital waveguide model, making its 22 | use possibly subject to patents held by 23 | Stanford University, Yamaha, and others. 24 | There exist at least two patents, assigned to 25 | Stanford, bearing the names of Karplus and/or 26 | Strong. 27 | 28 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 29 | */ 30 | /***************************************************/ 31 | 32 | class Sitar : public Instrmnt 33 | { 34 | public: 35 | //! Class constructor, taking the lowest desired playing frequency. 36 | Sitar( StkFloat lowestFrequency = 8.0 ); 37 | 38 | //! Class destructor. 39 | ~Sitar( void ); 40 | 41 | //! Reset and clear all internal state. 42 | void clear( void ); 43 | 44 | //! Set instrument parameters for a particular frequency. 45 | void setFrequency( StkFloat frequency ); 46 | 47 | //! Pluck the string with the given amplitude using the current frequency. 48 | void pluck( StkFloat amplitude ); 49 | 50 | //! Start a note with the given frequency and amplitude. 51 | void noteOn( StkFloat frequency, StkFloat amplitude ); 52 | 53 | //! Stop a note with the given amplitude (speed of decay). 54 | void noteOff( StkFloat amplitude ); 55 | 56 | //! Compute and return one output sample. 57 | StkFloat tick( unsigned int channel = 0 ); 58 | 59 | //! Fill a channel of the StkFrames object with computed outputs. 60 | /*! 61 | The \c channel argument must be less than the number of 62 | channels in the StkFrames argument (the first channel is specified 63 | by 0). However, range checking is only performed if _STK_DEBUG_ 64 | is defined during compilation, in which case an out-of-range value 65 | will trigger an StkError exception. 66 | */ 67 | StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); 68 | 69 | protected: 70 | 71 | DelayA delayLine_; 72 | OneZero loopFilter_; 73 | Noise noise_; 74 | ADSR envelope_; 75 | 76 | StkFloat loopGain_; 77 | StkFloat amGain_; 78 | StkFloat delay_; 79 | StkFloat targetDelay_; 80 | 81 | }; 82 | 83 | inline StkFloat Sitar :: tick( unsigned int ) 84 | { 85 | if ( fabs(targetDelay_ - delay_) > 0.001 ) { 86 | if ( targetDelay_ < delay_ ) 87 | delay_ *= 0.99999; 88 | else 89 | delay_ *= 1.00001; 90 | delayLine_.setDelay( delay_ ); 91 | } 92 | 93 | lastFrame_[0] = delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ ) + 94 | (amGain_ * envelope_.tick() * noise_.tick())); 95 | 96 | return lastFrame_[0]; 97 | } 98 | 99 | inline StkFrames& Sitar :: tick( StkFrames& frames, unsigned int channel ) 100 | { 101 | unsigned int nChannels = lastFrame_.channels(); 102 | #if defined(_STK_DEBUG_) 103 | if ( channel > frames.channels() - nChannels ) { 104 | oStream_ << "Sitar::tick(): channel and StkFrames arguments are incompatible!"; 105 | handleError( StkError::FUNCTION_ARGUMENT ); 106 | } 107 | #endif 108 | 109 | StkFloat *samples = &frames[channel]; 110 | unsigned int j, hop = frames.channels() - nChannels; 111 | if ( nChannels == 1 ) { 112 | for ( unsigned int i=0; iclose( soket_ ); 25 | 26 | #if defined(__OS_WINDOWS__) 27 | 28 | WSACleanup(); 29 | 30 | #endif 31 | } 32 | 33 | void Socket :: close( int socket ) 34 | { 35 | if ( !isValid( socket ) ) return; 36 | 37 | #if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) 38 | 39 | ::close( socket ); 40 | 41 | #elif defined(__OS_WINDOWS__) 42 | 43 | ::closesocket( socket ); 44 | 45 | #endif 46 | } 47 | 48 | void Socket :: setBlocking( int socket, bool enable ) 49 | { 50 | if ( !isValid( socket ) ) return; 51 | 52 | #if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) 53 | 54 | int tmp = ::fcntl( socket, F_GETFL, 0 ); 55 | if ( tmp >= 0 ) 56 | tmp = ::fcntl( socket, F_SETFL, enable ? (tmp &~ O_NONBLOCK) : (tmp | O_NONBLOCK) ); 57 | 58 | #elif defined(__OS_WINDOWS__) 59 | 60 | unsigned long non_block = !enable; 61 | ioctlsocket( socket, FIONBIO, &non_block ); 62 | 63 | #endif 64 | } 65 | 66 | int Socket :: writeBuffer(int socket, const void *buffer, long bufferSize, int flags ) 67 | { 68 | if ( !isValid( socket ) ) return -1; 69 | return send( socket, (const char *)buffer, bufferSize, flags ); 70 | } 71 | 72 | int Socket :: readBuffer(int socket, void *buffer, long bufferSize, int flags ) 73 | { 74 | if ( !isValid( socket ) ) return -1; 75 | return recv( socket, (char *)buffer, bufferSize, flags ); 76 | } 77 | 78 | } // stk namespace 79 | -------------------------------------------------------------------------------- /stk/Socket.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_SOCKET_H 2 | #define STK_SOCKET_H 3 | 4 | #include "Stk.h" 5 | 6 | #if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #elif defined(__OS_WINDOWS__) 18 | 19 | #include 20 | 21 | #endif 22 | 23 | namespace stk { 24 | 25 | /***************************************************/ 26 | /*! \class Socket 27 | \brief STK internet socket abstract base class. 28 | 29 | This class provides common functionality for TCP and UDP internet 30 | socket server and client subclasses. This class also provides a 31 | number of static functions for use with external socket 32 | descriptors. 33 | 34 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 35 | */ 36 | /***************************************************/ 37 | 38 | class Socket : public Stk 39 | { 40 | public: 41 | 42 | enum ProtocolType { 43 | PROTO_TCP, 44 | PROTO_UDP 45 | }; 46 | 47 | //! Class constructor 48 | Socket(); 49 | 50 | //! Class destructor. 51 | virtual ~Socket(); 52 | 53 | //! Close the socket. 54 | static void close( int socket ); 55 | 56 | //! Return the socket descriptor. 57 | int id( void ) const { return soket_; }; 58 | 59 | //! Return the socket port number. 60 | int port( void ) const { return port_; }; 61 | 62 | //! Returns true if the socket descriptor is valid. 63 | static bool isValid( int socket ) { return socket != -1; }; 64 | 65 | //! If enable = false, the socket is set to non-blocking mode. When first created, sockets are by default in blocking mode. 66 | static void setBlocking( int socket, bool enable ); 67 | 68 | //! Write a buffer over the socket connection. Returns the number of bytes written or -1 if an error occurs. 69 | virtual int writeBuffer(const void *buffer, long bufferSize, int flags = 0) = 0; 70 | 71 | //! Read an input buffer, up to length \e bufferSize. Returns the number of bytes read or -1 if an error occurs. 72 | virtual int readBuffer(void *buffer, long bufferSize, int flags = 0) = 0; 73 | 74 | //! Write a buffer via the specified socket. Returns the number of bytes written or -1 if an error occurs. 75 | static int writeBuffer(int socket, const void *buffer, long bufferSize, int flags ); 76 | 77 | //! Read a buffer via the specified socket. Returns the number of bytes read or -1 if an error occurs. 78 | static int readBuffer(int socket, void *buffer, long bufferSize, int flags ); 79 | 80 | protected: 81 | 82 | int soket_; 83 | int port_; 84 | 85 | }; 86 | 87 | } // stk namespace 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /stk/Sphere.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Sphere 3 | \brief STK sphere class. 4 | 5 | This class implements a spherical ball with 6 | radius, mass, position, and velocity parameters. 7 | 8 | by Perry R. Cook, 1995-2011. 9 | */ 10 | /***************************************************/ 11 | 12 | #include "Sphere.h" 13 | #include 14 | 15 | namespace stk { 16 | 17 | Vector3D* Sphere::getRelativePosition( Vector3D* position ) 18 | { 19 | workingVector_.setXYZ(position->getX() - position_.getX(), 20 | position->getY() - position_.getY(), 21 | position->getZ() - position_.getZ()); 22 | return &workingVector_; 23 | }; 24 | 25 | StkFloat Sphere::getVelocity( Vector3D* velocity ) 26 | { 27 | velocity->setXYZ( velocity_.getX(), velocity_.getY(), velocity_.getZ() ); 28 | return velocity_.getLength(); 29 | }; 30 | 31 | StkFloat Sphere::isInside( Vector3D *position ) 32 | { 33 | // Return directed distance from aPosition to spherical boundary ( < 34 | // 0 if inside). 35 | StkFloat distance; 36 | Vector3D *tempVector; 37 | 38 | tempVector = this->getRelativePosition( position ); 39 | distance = tempVector->getLength(); 40 | return distance - radius_; 41 | }; 42 | 43 | void Sphere::addVelocity(StkFloat x, StkFloat y, StkFloat z) 44 | { 45 | velocity_.setX(velocity_.getX() + x); 46 | velocity_.setY(velocity_.getY() + y); 47 | velocity_.setZ(velocity_.getZ() + z); 48 | } 49 | 50 | } // stk namespace 51 | -------------------------------------------------------------------------------- /stk/Sphere.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_SPHERE_H 2 | #define STK_SPHERE_H 3 | 4 | #include "Stk.h" 5 | #include "Vector3D.h" 6 | 7 | namespace stk { 8 | 9 | /***************************************************/ 10 | /*! \class Sphere 11 | \brief STK sphere class. 12 | 13 | This class implements a spherical ball with 14 | radius, mass, position, and velocity parameters. 15 | 16 | by Perry R. Cook, 1995-2011. 17 | */ 18 | /***************************************************/ 19 | 20 | class Sphere : public Stk 21 | { 22 | public: 23 | //! Constructor taking an initial radius value. 24 | Sphere( StkFloat radius = 1.0 ) { radius_ = radius; mass_ = 1.0; }; 25 | 26 | //! Set the 3D center position of the sphere. 27 | void setPosition( StkFloat x, StkFloat y, StkFloat z ) { position_.setXYZ(x, y, z); }; 28 | 29 | //! Set the 3D velocity of the sphere. 30 | void setVelocity( StkFloat x, StkFloat y, StkFloat z ) { velocity_.setXYZ(x, y, z); }; 31 | 32 | //! Set the radius of the sphere. 33 | void setRadius( StkFloat radius ) { radius_ = radius; }; 34 | 35 | //! Set the mass of the sphere. 36 | void setMass( StkFloat mass ) { mass_ = mass; }; 37 | 38 | //! Get the current position of the sphere as a 3D vector. 39 | Vector3D* getPosition( void ) { return &position_; }; 40 | 41 | //! Get the relative position of the given point to the sphere as a 3D vector. 42 | Vector3D* getRelativePosition( Vector3D *position ); 43 | 44 | //! Set the velcoity of the sphere as a 3D vector. 45 | StkFloat getVelocity( Vector3D* velocity ); 46 | 47 | //! Returns the distance from the sphere boundary to the given position (< 0 if inside). 48 | StkFloat isInside( Vector3D *position ); 49 | 50 | //! Get the current sphere radius. 51 | StkFloat getRadius( void ) { return radius_; }; 52 | 53 | //! Get the current sphere mass. 54 | StkFloat getMass( void ) { return mass_; }; 55 | 56 | //! Increase the current sphere velocity by the given 3D components. 57 | void addVelocity( StkFloat x, StkFloat y, StkFloat z ); 58 | 59 | //! Move the sphere for the given time increment. 60 | void tick( StkFloat timeIncrement ); 61 | 62 | private: 63 | Vector3D position_; 64 | Vector3D velocity_; 65 | Vector3D workingVector_; 66 | StkFloat radius_; 67 | StkFloat mass_; 68 | }; 69 | 70 | inline void Sphere::tick( StkFloat timeIncrement ) 71 | { 72 | position_.setX(position_.getX() + (timeIncrement * velocity_.getX())); 73 | position_.setY(position_.getY() + (timeIncrement * velocity_.getY())); 74 | position_.setZ(position_.getZ() + (timeIncrement * velocity_.getZ())); 75 | }; 76 | 77 | } // stk namespace 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /stk/TapDelay.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class TapDelay 3 | \brief STK non-interpolating tapped delay line class. 4 | 5 | This class implements a non-interpolating digital delay-line with 6 | an arbitrary number of output "taps". If the maximum length and 7 | tap delays are not specified during instantiation, a fixed maximum 8 | length of 4095 and a single tap delay of zero is set. 9 | 10 | A non-interpolating delay line is typically used in fixed 11 | delay-length applications, such as for reverberation. 12 | 13 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 14 | */ 15 | /***************************************************/ 16 | 17 | #include "TapDelay.h" 18 | 19 | namespace stk { 20 | 21 | TapDelay :: TapDelay( std::vector taps, unsigned long maxDelay ) 22 | { 23 | // Writing before reading allows delays from 0 to length-1. 24 | // If we want to allow a delay of maxDelay, we need a 25 | // delayline of length = maxDelay+1. 26 | if ( maxDelay < 1 ) { 27 | oStream_ << "TapDelay::TapDelay: maxDelay must be > 0!\n"; 28 | handleError( StkError::FUNCTION_ARGUMENT ); 29 | } 30 | 31 | for ( unsigned int i=0; i maxDelay ) { 33 | oStream_ << "TapDelay::TapDelay: maxDelay must be > than all tap delay values!\n"; 34 | handleError( StkError::FUNCTION_ARGUMENT ); 35 | } 36 | } 37 | 38 | if ( ( maxDelay + 1 ) > inputs_.size() ) 39 | inputs_.resize( maxDelay + 1, 1, 0.0 ); 40 | 41 | inPoint_ = 0; 42 | this->setTapDelays( taps ); 43 | } 44 | 45 | TapDelay :: ~TapDelay() 46 | { 47 | } 48 | 49 | void TapDelay :: setMaximumDelay( unsigned long delay ) 50 | { 51 | if ( delay < inputs_.size() ) return; 52 | 53 | for ( unsigned int i=0; i taps ) 64 | { 65 | for ( unsigned int i=0; i inputs_.size() - 1 ) { // The value is too big. 67 | oStream_ << "TapDelay::setTapDelay: argument (" << taps[i] << ") greater than maximum!\n"; 68 | handleError( StkError::WARNING ); return; 69 | } 70 | 71 | if ( taps[i] < 0 ) { 72 | oStream_ << "TapDelay::setDelay: argument (" << taps[i] << ") less than zero!\n"; 73 | handleError( StkError::WARNING ); return; 74 | } 75 | } 76 | 77 | if ( taps.size() != outPoint_.size() ) { 78 | outPoint_.resize( taps.size() ); 79 | delays_.resize( taps.size() ); 80 | lastFrame_.resize( 1, taps.size(), 0.0 ); 81 | } 82 | 83 | for ( unsigned int i=0; i= taps[i] ) outPoint_[i] = inPoint_ - taps[i]; 86 | else outPoint_[i] = inputs_.size() + inPoint_ - taps[i]; 87 | delays_[i] = taps[i]; 88 | } 89 | } 90 | 91 | } // stk namespace 92 | 93 | -------------------------------------------------------------------------------- /stk/TcpClient.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class TcpClient 3 | \brief STK TCP socket client class. 4 | 5 | This class provides a uniform cross-platform TCP socket client 6 | interface. Methods are provided for reading or writing data 7 | buffers to/from connections. 8 | 9 | TCP sockets are reliable and connection-oriented. A TCP socket 10 | client must be connected to a TCP server before data can be sent 11 | or received. Data delivery is guaranteed in order, without loss, 12 | error, or duplication. That said, TCP transmissions tend to be 13 | slower than those using the UDP protocol and data sent with 14 | multiple \e write() calls can be arbitrarily combined by the 15 | underlying system. 16 | 17 | The user is responsible for checking the values 18 | returned by the read/write methods. Values 19 | less than or equal to zero indicate a closed 20 | or lost connection or the occurence of an error. 21 | 22 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 23 | */ 24 | /***************************************************/ 25 | 26 | #include "TcpClient.h" 27 | #include 28 | #include 29 | 30 | namespace stk { 31 | 32 | TcpClient :: TcpClient( int port, std::string hostname ) 33 | { 34 | #if defined(__OS_WINDOWS__) // windoze-only stuff 35 | WSADATA wsaData; 36 | WORD wVersionRequested = MAKEWORD(1,1); 37 | 38 | WSAStartup( wVersionRequested, &wsaData ); 39 | if ( wsaData.wVersion != wVersionRequested ) { 40 | oStream_ << "TcpClient: Incompatible Windows socket library version!"; 41 | handleError( StkError::PROCESS_SOCKET ); 42 | } 43 | #endif 44 | 45 | // Create a socket client connection. 46 | connect( port, hostname ); 47 | } 48 | 49 | TcpClient :: ~TcpClient( void ) 50 | { 51 | } 52 | 53 | int TcpClient :: connect( int port, std::string hostname ) 54 | { 55 | // Close any existing connections. 56 | this->close( soket_ ); 57 | 58 | // Create the client-side socket 59 | soket_ = ::socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); 60 | if ( soket_ < 0 ) { 61 | oStream_ << "TcpClient: Couldn't create socket client!"; 62 | handleError( StkError::PROCESS_SOCKET ); 63 | } 64 | 65 | int flag = 1; 66 | int result = setsockopt( soket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int) ); 67 | if ( result < 0 ) { 68 | oStream_ << "TcpClient: Error setting socket options!"; 69 | handleError( StkError::PROCESS_SOCKET ); 70 | } 71 | 72 | struct hostent *hostp; 73 | if ( ( hostp = gethostbyname( hostname.c_str() ) ) == 0 ) { 74 | oStream_ << "TcpClient: unknown host (" << hostname << ")!"; 75 | handleError( StkError::PROCESS_SOCKET_IPADDR ); 76 | } 77 | 78 | // Fill in the address structure 79 | struct sockaddr_in server_address; 80 | server_address.sin_family = AF_INET; 81 | memcpy( (void *)&server_address.sin_addr, hostp->h_addr, hostp->h_length ); 82 | server_address.sin_port = htons(port); 83 | 84 | // Connect to the server 85 | if ( ::connect( soket_, (struct sockaddr *)&server_address, sizeof(server_address) ) < 0 ) { 86 | oStream_ << "TcpClient: Couldn't connect to socket server!"; 87 | handleError( StkError::PROCESS_SOCKET ); 88 | } 89 | 90 | return soket_; 91 | } 92 | 93 | int TcpClient :: writeBuffer( const void *buffer, long bufferSize, int flags ) 94 | { 95 | if ( !isValid( soket_ ) ) return -1; 96 | return send( soket_, (const char *)buffer, bufferSize, flags ); 97 | } 98 | 99 | int TcpClient :: readBuffer( void *buffer, long bufferSize, int flags ) 100 | { 101 | if ( !isValid( soket_ ) ) return -1; 102 | return recv( soket_, (char *)buffer, bufferSize, flags ); 103 | } 104 | 105 | } // stk namespace 106 | -------------------------------------------------------------------------------- /stk/TcpClient.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_TCPCLIENT_H 2 | #define STK_TCPCLIENT_H 3 | 4 | #include "Socket.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class TcpClient 10 | \brief STK TCP socket client class. 11 | 12 | This class provides a uniform cross-platform TCP socket client 13 | interface. Methods are provided for reading or writing data 14 | buffers to/from connections. 15 | 16 | TCP sockets are reliable and connection-oriented. A TCP socket 17 | client must be connected to a TCP server before data can be sent 18 | or received. Data delivery is guaranteed in order, without loss, 19 | error, or duplication. That said, TCP transmissions tend to be 20 | slower than those using the UDP protocol and data sent with 21 | multiple \e write() calls can be arbitrarily combined by the 22 | underlying system. 23 | 24 | The user is responsible for checking the values 25 | returned by the read/write methods. Values 26 | less than or equal to zero indicate a closed 27 | or lost connection or the occurence of an error. 28 | 29 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 30 | */ 31 | /***************************************************/ 32 | 33 | class TcpClient : public Socket 34 | { 35 | public: 36 | //! Default class constructor creates a socket client connection to the specified host and port. 37 | /*! 38 | An StkError will be thrown if a socket error occurs during instantiation. 39 | */ 40 | TcpClient( int port, std::string hostname = "localhost" ); 41 | 42 | //! The class destructor closes the socket instance, breaking any existing connections. 43 | ~TcpClient(); 44 | 45 | //! Connect the socket client to the specified host and port and returns the resulting socket descriptor. 46 | /*! 47 | If the socket client is already connected, that connection is 48 | terminated and a new connection is attempted. An StkError will be 49 | thrown if a socket error occurs. 50 | */ 51 | int connect( int port, std::string hostname = "localhost" ); 52 | 53 | //! Write a buffer over the socket connection. Returns the number of bytes written or -1 if an error occurs. 54 | int writeBuffer(const void *buffer, long bufferSize, int flags = 0); 55 | 56 | //! Read a buffer from the socket connection, up to length \e bufferSize. Returns the number of bytes read or -1 if an error occurs. 57 | int readBuffer(void *buffer, long bufferSize, int flags = 0); 58 | 59 | protected: 60 | 61 | }; 62 | 63 | } // stk namespace 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /stk/TcpServer.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class TcpServer 3 | \brief STK TCP socket server class. 4 | 5 | This class provides a uniform cross-platform TCP socket server 6 | interface. Methods are provided for reading or writing data 7 | buffers to/from connections. 8 | 9 | TCP sockets are reliable and connection-oriented. A TCP socket 10 | server must accept a connection from a TCP client before data can 11 | be sent or received. Data delivery is guaranteed in order, 12 | without loss, error, or duplication. That said, TCP transmissions 13 | tend to be slower than those using the UDP protocol and data sent 14 | with multiple \e write() calls can be arbitrarily combined by the 15 | underlying system. 16 | 17 | The user is responsible for checking the values 18 | returned by the read/write methods. Values 19 | less than or equal to zero indicate a closed 20 | or lost connection or the occurence of an error. 21 | 22 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 23 | */ 24 | /***************************************************/ 25 | 26 | #include "TcpServer.h" 27 | 28 | namespace stk { 29 | 30 | TcpServer :: TcpServer( int port ) 31 | { 32 | // Create a socket server. 33 | #if defined(__OS_WINDOWS__) // windoze-only stuff 34 | WSADATA wsaData; 35 | WORD wVersionRequested = MAKEWORD(1,1); 36 | 37 | WSAStartup(wVersionRequested, &wsaData); 38 | if (wsaData.wVersion != wVersionRequested) { 39 | oStream_ << "TcpServer: Incompatible Windows socket library version!"; 40 | handleError( StkError::PROCESS_SOCKET ); 41 | } 42 | #endif 43 | 44 | // Create the server-side socket 45 | soket_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 46 | if (soket_ < 0) { 47 | oStream_ << "TcpServer: Couldn't create socket server!"; 48 | handleError( StkError::PROCESS_SOCKET ); 49 | } 50 | 51 | int flag = 1; 52 | int result = setsockopt( soket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int) ); 53 | if (result < 0) { 54 | oStream_ << "TcpServer: Error setting socket options!"; 55 | handleError( StkError::PROCESS_SOCKET ); 56 | } 57 | 58 | struct sockaddr_in address; 59 | address.sin_family = AF_INET; 60 | address.sin_addr.s_addr = INADDR_ANY; 61 | address.sin_port = htons( port ); 62 | 63 | // Bind socket to the appropriate port and interface (INADDR_ANY) 64 | if ( bind( soket_, (struct sockaddr *)&address, sizeof(address) ) < 0 ) { 65 | oStream_ << "TcpServer: Couldn't bind socket!"; 66 | handleError( StkError::PROCESS_SOCKET ); 67 | } 68 | 69 | // Listen for incoming connection(s) 70 | if ( listen( soket_, 1 ) < 0 ) { 71 | oStream_ << "TcpServer: Couldn't start server listening!"; 72 | handleError( StkError::PROCESS_SOCKET ); 73 | } 74 | 75 | port_ = port; 76 | } 77 | 78 | TcpServer :: ~TcpServer() 79 | { 80 | } 81 | 82 | int TcpServer :: accept( void ) 83 | { 84 | return ::accept( soket_, NULL, NULL ); 85 | } 86 | 87 | int TcpServer :: writeBuffer(const void *buffer, long bufferSize, int flags ) 88 | { 89 | if ( !isValid( soket_ ) ) return -1; 90 | return send( soket_, (const char *)buffer, bufferSize, flags ); 91 | } 92 | 93 | int TcpServer :: readBuffer(void *buffer, long bufferSize, int flags ) 94 | { 95 | if ( !isValid( soket_ ) ) return -1; 96 | return recv( soket_, (char *)buffer, bufferSize, flags ); 97 | } 98 | 99 | } // stk namespace 100 | -------------------------------------------------------------------------------- /stk/TcpServer.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_TCPSERVER_H 2 | #define STK_TCPSERVER_H 3 | 4 | #include "Socket.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class TcpServer 10 | \brief STK TCP socket server class. 11 | 12 | This class provides a uniform cross-platform TCP socket server 13 | interface. Methods are provided for reading or writing data 14 | buffers to/from connections. 15 | 16 | TCP sockets are reliable and connection-oriented. A TCP socket 17 | server must accept a connection from a TCP client before data can 18 | be sent or received. Data delivery is guaranteed in order, 19 | without loss, error, or duplication. That said, TCP transmissions 20 | tend to be slower than those using the UDP protocol and data sent 21 | with multiple \e write() calls can be arbitrarily combined by the 22 | underlying system. 23 | 24 | The user is responsible for checking the values 25 | returned by the read/write methods. Values 26 | less than or equal to zero indicate a closed 27 | or lost connection or the occurence of an error. 28 | 29 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 30 | */ 31 | /***************************************************/ 32 | 33 | class TcpServer : public Socket 34 | { 35 | public: 36 | //! Default constructor creates a local socket server on port 2006 (or the specified port number). 37 | /*! 38 | An StkError will be thrown if a socket error occurs during instantiation. 39 | */ 40 | TcpServer( int port = 2006 ); 41 | 42 | //! The class destructor closes the socket instance, breaking any existing connections. 43 | ~TcpServer(); 44 | 45 | //! Extract the first pending connection request from the queue and create a new connection, returning the descriptor for the accepted socket. 46 | /*! 47 | If no connection requests are pending and the socket has not 48 | been set non-blocking, this function will block until a connection 49 | is present. If an error occurs, -1 is returned. 50 | */ 51 | int accept( void ); 52 | 53 | //! Write a buffer over the socket connection. Returns the number of bytes written or -1 if an error occurs. 54 | int writeBuffer(const void *buffer, long bufferSize, int flags = 0); 55 | 56 | //! Read a buffer from the socket connection, up to length \e bufferSize. Returns the number of bytes read or -1 if an error occurs. 57 | int readBuffer(void *buffer, long bufferSize, int flags = 0); 58 | 59 | protected: 60 | 61 | }; 62 | 63 | } // stk namespace 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /stk/Thread.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Thread 3 | \brief STK thread class. 4 | 5 | This class provides a uniform interface for cross-platform 6 | threads. On unix systems, the pthread library is used. Under 7 | Windows, the C runtime threadex functions are used. 8 | 9 | Each instance of the Thread class can be used to control a single 10 | thread process. Routines are provided to signal cancelation 11 | and/or joining with a thread, though it is not possible for this 12 | class to know the running status of a thread once it is started. 13 | 14 | For cross-platform compatability, thread functions should be 15 | declared as follows: 16 | 17 | THREAD_RETURN THREAD_TYPE thread_function(void *ptr) 18 | 19 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 20 | */ 21 | /***************************************************/ 22 | 23 | #include "Thread.h" 24 | 25 | namespace stk { 26 | 27 | Thread :: Thread() 28 | { 29 | thread_ = 0; 30 | } 31 | 32 | Thread :: ~Thread() 33 | { 34 | } 35 | 36 | bool Thread :: start( THREAD_FUNCTION routine, void * ptr ) 37 | { 38 | if ( thread_ ) { 39 | oStream_ << "Thread:: a thread is already running!"; 40 | handleError( StkError::WARNING ); 41 | return false; 42 | } 43 | 44 | #if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) 45 | 46 | if ( pthread_create(&thread_, NULL, *routine, ptr) == 0 ) 47 | return true; 48 | 49 | #elif defined(__OS_WINDOWS__) 50 | unsigned thread_id; 51 | thread_ = _beginthreadex(NULL, 0, routine, ptr, 0, &thread_id); 52 | if ( thread_ ) return true; 53 | 54 | #endif 55 | return false; 56 | } 57 | 58 | bool Thread :: cancel() 59 | { 60 | #if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) 61 | 62 | if ( pthread_cancel(thread_) == 0 ) { 63 | return true; 64 | } 65 | 66 | #elif defined(__OS_WINDOWS__) 67 | 68 | TerminateThread((HANDLE)thread_, 0); 69 | return true; 70 | 71 | #endif 72 | return false; 73 | } 74 | 75 | bool Thread :: wait() 76 | { 77 | #if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) 78 | 79 | if ( pthread_join(thread_, NULL) == 0 ) { 80 | thread_ = 0; 81 | return true; 82 | } 83 | 84 | #elif defined(__OS_WINDOWS__) 85 | 86 | long retval = WaitForSingleObject( (HANDLE)thread_, INFINITE ); 87 | if ( retval == WAIT_OBJECT_0 ) { 88 | CloseHandle( (HANDLE)thread_ ); 89 | thread_ = 0; 90 | return true; 91 | } 92 | 93 | #endif 94 | return false; 95 | } 96 | 97 | void Thread :: testCancel(void) 98 | { 99 | #if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) 100 | 101 | pthread_testcancel(); 102 | 103 | #endif 104 | } 105 | 106 | } // stk namespace 107 | -------------------------------------------------------------------------------- /stk/Thread.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_THREAD_H 2 | #define STK_THREAD_H 3 | 4 | #include "Stk.h" 5 | 6 | #if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__)) 7 | 8 | #include 9 | #define THREAD_TYPE 10 | typedef pthread_t THREAD_HANDLE; 11 | typedef void * THREAD_RETURN; 12 | typedef void * (*THREAD_FUNCTION)(void *); 13 | 14 | #elif defined(__OS_WINDOWS__) 15 | 16 | #include 17 | #include 18 | #define THREAD_TYPE __stdcall 19 | typedef unsigned long THREAD_HANDLE; 20 | typedef unsigned THREAD_RETURN; 21 | typedef unsigned (__stdcall *THREAD_FUNCTION)(void *); 22 | 23 | #endif 24 | 25 | namespace stk { 26 | 27 | /***************************************************/ 28 | /*! \class Thread 29 | \brief STK thread class. 30 | 31 | This class provides a uniform interface for cross-platform 32 | threads. On unix systems, the pthread library is used. Under 33 | Windows, the C runtime threadex functions are used. 34 | 35 | Each instance of the Thread class can be used to control a single 36 | thread process. Routines are provided to signal cancelation 37 | and/or joining with a thread, though it is not possible for this 38 | class to know the running status of a thread once it is started. 39 | 40 | For cross-platform compatability, thread functions should be 41 | declared as follows: 42 | 43 | THREAD_RETURN THREAD_TYPE thread_function(void *ptr) 44 | 45 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 46 | */ 47 | /***************************************************/ 48 | 49 | class Thread : public Stk 50 | { 51 | public: 52 | //! Default constructor. 53 | Thread(); 54 | 55 | //! The class destructor does not attempt to cancel or join a thread. 56 | ~Thread(); 57 | 58 | //! Begin execution of the thread \e routine. Upon success, true is returned. 59 | /*! 60 | A data pointer can be supplied to the thread routine via the 61 | optional \e ptr argument. If the thread cannot be created, the 62 | return value is false. 63 | */ 64 | bool start( THREAD_FUNCTION routine, void * ptr = NULL ); 65 | 66 | //! Signal cancellation of a thread routine, returning \e true on success. 67 | /*! 68 | This function only signals thread cancellation. It does not 69 | wait to verify actual routine termination. A \e true return value 70 | only signifies that the cancellation signal was properly executed, 71 | not thread cancellation. A thread routine may need to make use of 72 | the testCancel() function to specify a cancellation point. 73 | */ 74 | bool cancel(void); 75 | 76 | //! Block the calling routine indefinitely until the thread terminates. 77 | /*! 78 | This function suspends execution of the calling routine until the thread has terminated. It will return immediately if the thread was already terminated. A \e true return value signifies successful termination. A \e false return value indicates a problem with the wait call. 79 | */ 80 | bool wait(void); 81 | 82 | //! Create a cancellation point within a thread routine. 83 | /*! 84 | This function call checks for thread cancellation, allowing the 85 | thread to be terminated if a cancellation request was previously 86 | signaled. 87 | */ 88 | void testCancel(void); 89 | 90 | protected: 91 | 92 | THREAD_HANDLE thread_; 93 | 94 | }; 95 | 96 | } // stk namespace 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /stk/TubeBell.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class TubeBell 3 | \brief STK tubular bell (orchestral chime) FM 4 | synthesis instrument. 5 | 6 | This class implements two simple FM Pairs 7 | summed together, also referred to as algorithm 8 | 5 of the TX81Z. 9 | 10 | \code 11 | Algorithm 5 is : 4->3--\ 12 | + --> Out 13 | 2->1--/ 14 | \endcode 15 | 16 | Control Change Numbers: 17 | - Modulator Index One = 2 18 | - Crossfade of Outputs = 4 19 | - LFO Speed = 11 20 | - LFO Depth = 1 21 | - ADSR 2 & 4 Target = 128 22 | 23 | The basic Chowning/Stanford FM patent expired 24 | in 1995, but there exist follow-on patents, 25 | mostly assigned to Yamaha. If you are of the 26 | type who should worry about this (making 27 | money) worry away. 28 | 29 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 30 | */ 31 | /***************************************************/ 32 | 33 | #include "TubeBell.h" 34 | 35 | namespace stk { 36 | 37 | TubeBell :: TubeBell( void ) 38 | : FM() 39 | { 40 | // Concatenate the STK rawwave path to the rawwave files 41 | for ( unsigned int i=0; i<3; i++ ) 42 | waves_[i] = new FileLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true ); 43 | waves_[3] = new FileLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true ); 44 | 45 | this->setRatio(0, 1.0 * 0.995); 46 | this->setRatio(1, 1.414 * 0.995); 47 | this->setRatio(2, 1.0 * 1.005); 48 | this->setRatio(3, 1.414 * 1.000); 49 | 50 | gains_[0] = fmGains_[94]; 51 | gains_[1] = fmGains_[76]; 52 | gains_[2] = fmGains_[99]; 53 | gains_[3] = fmGains_[71]; 54 | 55 | adsr_[0]->setAllTimes( 0.005, 4.0, 0.0, 0.04); 56 | adsr_[1]->setAllTimes( 0.005, 4.0, 0.0, 0.04); 57 | adsr_[2]->setAllTimes( 0.001, 2.0, 0.0, 0.04); 58 | adsr_[3]->setAllTimes( 0.004, 4.0, 0.0, 0.04); 59 | 60 | twozero_.setGain( 0.5 ); 61 | vibrato_.setFrequency( 2.0 ); 62 | } 63 | 64 | TubeBell :: ~TubeBell( void ) 65 | { 66 | } 67 | 68 | void TubeBell :: noteOn( StkFloat frequency, StkFloat amplitude ) 69 | { 70 | gains_[0] = amplitude * fmGains_[94]; 71 | gains_[1] = amplitude * fmGains_[76]; 72 | gains_[2] = amplitude * fmGains_[99]; 73 | gains_[3] = amplitude * fmGains_[71]; 74 | this->setFrequency( frequency ); 75 | this->keyOn(); 76 | } 77 | 78 | } // stk namespace 79 | -------------------------------------------------------------------------------- /stk/TubeBell.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_TUBEBELL_H 2 | #define STK_TUBEBELL_H 3 | 4 | #include "FM.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class TubeBell 10 | \brief STK tubular bell (orchestral chime) FM 11 | synthesis instrument. 12 | 13 | This class implements two simple FM Pairs 14 | summed together, also referred to as algorithm 15 | 5 of the TX81Z. 16 | 17 | \code 18 | Algorithm 5 is : 4->3--\ 19 | + --> Out 20 | 2->1--/ 21 | \endcode 22 | 23 | Control Change Numbers: 24 | - Modulator Index One = 2 25 | - Crossfade of Outputs = 4 26 | - LFO Speed = 11 27 | - LFO Depth = 1 28 | - ADSR 2 & 4 Target = 128 29 | 30 | The basic Chowning/Stanford FM patent expired 31 | in 1995, but there exist follow-on patents, 32 | mostly assigned to Yamaha. If you are of the 33 | type who should worry about this (making 34 | money) worry away. 35 | 36 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 37 | */ 38 | /***************************************************/ 39 | 40 | class TubeBell : public FM 41 | { 42 | public: 43 | //! Class constructor. 44 | /*! 45 | An StkError will be thrown if the rawwave path is incorrectly set. 46 | */ 47 | TubeBell( void ); 48 | 49 | //! Class destructor. 50 | ~TubeBell( void ); 51 | 52 | //! Start a note with the given frequency and amplitude. 53 | void noteOn( StkFloat frequency, StkFloat amplitude ); 54 | 55 | //! Compute and return one output sample. 56 | StkFloat tick( unsigned int channel = 0 ); 57 | 58 | //! Fill a channel of the StkFrames object with computed outputs. 59 | /*! 60 | The \c channel argument must be less than the number of 61 | channels in the StkFrames argument (the first channel is specified 62 | by 0). However, range checking is only performed if _STK_DEBUG_ 63 | is defined during compilation, in which case an out-of-range value 64 | will trigger an StkError exception. 65 | */ 66 | StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ); 67 | 68 | protected: 69 | 70 | }; 71 | 72 | inline StkFloat TubeBell :: tick( unsigned int ) 73 | { 74 | StkFloat temp, temp2; 75 | 76 | temp = gains_[1] * adsr_[1]->tick() * waves_[1]->tick(); 77 | temp = temp * control1_; 78 | 79 | waves_[0]->addPhaseOffset( temp ); 80 | waves_[3]->addPhaseOffset( twozero_.lastOut() ); 81 | temp = gains_[3] * adsr_[3]->tick() * waves_[3]->tick(); 82 | twozero_.tick( temp ); 83 | 84 | waves_[2]->addPhaseOffset( temp ); 85 | temp = ( 1.0 - (control2_ * 0.5)) * gains_[0] * adsr_[0]->tick() * waves_[0]->tick(); 86 | temp += control2_ * 0.5 * gains_[2] * adsr_[2]->tick() * waves_[2]->tick(); 87 | 88 | // Calculate amplitude modulation and apply it to output. 89 | temp2 = vibrato_.tick() * modDepth_; 90 | temp = temp * (1.0 + temp2); 91 | 92 | lastFrame_[0] = temp * 0.5; 93 | return lastFrame_[0]; 94 | } 95 | 96 | inline StkFrames& TubeBell :: tick( StkFrames& frames, unsigned int channel ) 97 | { 98 | unsigned int nChannels = lastFrame_.channels(); 99 | #if defined(_STK_DEBUG_) 100 | if ( channel > frames.channels() - nChannels ) { 101 | oStream_ << "TubeBell::tick(): channel and StkFrames arguments are incompatible!"; 102 | handleError( StkError::FUNCTION_ARGUMENT ); 103 | } 104 | #endif 105 | 106 | StkFloat *samples = &frames[channel]; 107 | unsigned int j, hop = frames.channels() - nChannels; 108 | if ( nChannels == 1 ) { 109 | for ( unsigned int i=0; isetLowestFrequency( lowestFrequency ); 36 | 37 | std::vector coefficients( 2, 0.5 ); 38 | loopFilter_.setCoefficients( coefficients ); 39 | 40 | lastFrame_.resize( 1, 1, 0.0 ); 41 | 42 | loopGain_ = 0.995; 43 | pluckPosition_ = 0.4; 44 | this->setFrequency( 220.0 ); 45 | } 46 | 47 | Twang :: ~Twang( void ) 48 | { 49 | } 50 | 51 | void Twang :: clear( void ) 52 | { 53 | delayLine_.clear(); 54 | combDelay_.clear(); 55 | loopFilter_.clear(); 56 | lastFrame_[0] = 0.0; 57 | } 58 | 59 | void Twang :: setLowestFrequency( StkFloat frequency ) 60 | { 61 | unsigned long nDelays = (unsigned long) ( Stk::sampleRate() / frequency ); 62 | delayLine_.setMaximumDelay( nDelays + 1 ); 63 | combDelay_.setMaximumDelay( nDelays + 1 ); 64 | } 65 | 66 | void Twang :: setFrequency( StkFloat frequency ) 67 | { 68 | #if defined(_STK_DEBUG_) 69 | if ( frequency <= 0.0 ) { 70 | oStream_ << "Twang::setFrequency: argument is less than or equal to zero!"; 71 | handleError( StkError::WARNING ); return; 72 | } 73 | #endif 74 | 75 | // Delay = length - filter delay. 76 | StkFloat delay = ( Stk::sampleRate() / frequency ) - loopFilter_.phaseDelay( frequency ); 77 | delayLine_.setDelay( delay ); 78 | 79 | this->setLoopGain( loopGain_ ); 80 | 81 | // Set the pluck position, which puts zeroes at position * length. 82 | combDelay_.setDelay( 0.5 * pluckPosition_ * delay ); 83 | } 84 | 85 | void Twang :: setLoopGain( StkFloat loopGain ) 86 | { 87 | if ( loopGain < 0.0 || loopGain >= 1.0 ) { 88 | oStream_ << "Twang::setLoopGain: parameter is out of range!"; 89 | handleError( StkError::WARNING ); return; 90 | } 91 | 92 | loopGain_ = loopGain; 93 | StkFloat gain = loopGain_ + (frequency_ * 0.000005); 94 | if ( gain >= 1.0 ) gain = 0.99999; 95 | loopFilter_.setGain( gain ); 96 | } 97 | 98 | void Twang :: setPluckPosition( StkFloat position ) 99 | { 100 | if ( position < 0.0 || position > 1.0 ) { 101 | oStream_ << "Twang::setPluckPosition: argument (" << position << ") is out of range!"; 102 | handleError( StkError::WARNING ); return; 103 | } 104 | 105 | pluckPosition_ = position; 106 | } 107 | 108 | } // stk namespace 109 | -------------------------------------------------------------------------------- /stk/TwoPole.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class TwoPole 3 | \brief STK two-pole filter class. 4 | 5 | This class implements a two-pole digital filter. A method is 6 | provided for creating a resonance in the frequency response while 7 | maintaining a nearly constant filter gain. 8 | 9 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 10 | */ 11 | /***************************************************/ 12 | 13 | #include "TwoPole.h" 14 | #include 15 | 16 | namespace stk { 17 | 18 | TwoPole :: TwoPole( void ) 19 | { 20 | b_.resize( 1 ); 21 | a_.resize( 3 ); 22 | inputs_.resize( 1, 1, 0.0 ); 23 | outputs_.resize( 3, 1, 0.0 ); 24 | b_[0] = 1.0; 25 | a_[0] = 1.0; 26 | 27 | Stk::addSampleRateAlert( this ); 28 | } 29 | 30 | TwoPole :: ~TwoPole() 31 | { 32 | Stk::removeSampleRateAlert( this ); 33 | } 34 | 35 | void TwoPole :: sampleRateChanged( StkFloat newRate, StkFloat oldRate ) 36 | { 37 | if ( !ignoreSampleRateChange_ ) { 38 | oStream_ << "TwoPole::sampleRateChanged: you may need to recompute filter coefficients!"; 39 | handleError( StkError::WARNING ); 40 | } 41 | } 42 | 43 | void TwoPole :: setResonance( StkFloat frequency, StkFloat radius, bool normalize ) 44 | { 45 | #if defined(_STK_DEBUG_) 46 | if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) { 47 | oStream_ << "TwoPole::setResonance: frequency argument (" << frequency << ") is out of range!"; 48 | handleError( StkError::WARNING ); return; 49 | } 50 | if ( radius < 0.0 || radius >= 1.0 ) { 51 | oStream_ << "TwoPole::setResonance: radius argument (" << radius << ") is out of range!"; 52 | handleError( StkError::WARNING ); return; 53 | } 54 | #endif 55 | 56 | a_[2] = radius * radius; 57 | a_[1] = (StkFloat) -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate()); 58 | 59 | if ( normalize ) { 60 | // Normalize the filter gain ... not terribly efficient. 61 | StkFloat real = 1 - radius + (a_[2] - radius) * cos(TWO_PI * 2 * frequency / Stk::sampleRate()); 62 | StkFloat imag = (a_[2] - radius) * sin(TWO_PI * 2 * frequency / Stk::sampleRate()); 63 | b_[0] = sqrt( pow(real, 2) + pow(imag, 2) ); 64 | } 65 | } 66 | 67 | void TwoPole :: setCoefficients( StkFloat b0, StkFloat a1, StkFloat a2, bool clearState ) 68 | { 69 | b_[0] = b0; 70 | a_[1] = a1; 71 | a_[2] = a2; 72 | 73 | if ( clearState ) this->clear(); 74 | } 75 | 76 | } // stk namespace 77 | -------------------------------------------------------------------------------- /stk/TwoZero.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class TwoZero 3 | \brief STK two-zero filter class. 4 | 5 | This class implements a two-zero digital filter. A method is 6 | provided for creating a "notch" in the frequency response while 7 | maintaining a constant filter gain. 8 | 9 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 10 | */ 11 | /***************************************************/ 12 | 13 | #include "TwoZero.h" 14 | #include 15 | 16 | namespace stk { 17 | 18 | TwoZero :: TwoZero( void ) 19 | { 20 | b_.resize( 3, 0.0 ); 21 | inputs_.resize( 3, 1, 0.0 ); 22 | b_[0] = 1.0; 23 | 24 | Stk::addSampleRateAlert( this ); 25 | } 26 | 27 | TwoZero :: ~TwoZero() 28 | { 29 | Stk::removeSampleRateAlert( this ); 30 | } 31 | 32 | void TwoZero :: sampleRateChanged( StkFloat newRate, StkFloat oldRate ) 33 | { 34 | if ( !ignoreSampleRateChange_ ) { 35 | oStream_ << "TwoZero::sampleRateChanged: you may need to recompute filter coefficients!"; 36 | handleError( StkError::WARNING ); 37 | } 38 | } 39 | 40 | void TwoZero :: setCoefficients( StkFloat b0, StkFloat b1, StkFloat b2, bool clearState ) 41 | { 42 | b_[0] = b0; 43 | b_[1] = b1; 44 | b_[2] = b2; 45 | 46 | if ( clearState ) this->clear(); 47 | } 48 | 49 | void TwoZero :: setNotch( StkFloat frequency, StkFloat radius ) 50 | { 51 | #if defined(_STK_DEBUG_) 52 | if ( frequency < 0.0 || frequency > 0.5 * Stk::sampleRate() ) { 53 | oStream_ << "TwoZero::setNotch: frequency argument (" << frequency << ") is out of range!"; 54 | handleError( StkError::WARNING ); return; 55 | } 56 | if ( radius < 0.0 ) { 57 | oStream_ << "TwoZero::setNotch: radius argument (" << radius << ") is negative!"; 58 | handleError( StkError::WARNING ); return; 59 | } 60 | #endif 61 | 62 | b_[2] = radius * radius; 63 | b_[1] = -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate()); 64 | 65 | // Normalize the filter gain. 66 | if ( b_[1] > 0.0 ) // Maximum at z = 0. 67 | b_[0] = 1.0 / ( 1.0 + b_[1] + b_[2] ); 68 | else // Maximum at z = -1. 69 | b_[0] = 1.0 / ( 1.0 - b_[1] + b_[2] ); 70 | b_[1] *= b_[0]; 71 | b_[2] *= b_[0]; 72 | } 73 | 74 | } // stk namespace 75 | -------------------------------------------------------------------------------- /stk/UdpSocket.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_UDPSOCKET_H 2 | #define STK_UDPSOCKET_H 3 | 4 | #include "Socket.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class UdpSocket 10 | \brief STK UDP socket server/client class. 11 | 12 | This class provides a uniform cross-platform UDP socket 13 | server/client interface. Methods are provided for reading or 14 | writing data buffers. The constructor creates a UDP socket and 15 | binds it to the specified port. Note that only one socket can be 16 | bound to a given port on the same machine. 17 | 18 | UDP sockets provide unreliable, connection-less service. Messages 19 | can be lost, duplicated, or received out of order. That said, 20 | data transmission tends to be faster than with TCP connections and 21 | datagrams are not potentially combined by the underlying system. 22 | 23 | The user is responsible for checking the values returned by the 24 | read/write methods. Values less than or equal to zero indicate 25 | the occurence of an error. 26 | 27 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 28 | */ 29 | /***************************************************/ 30 | 31 | class UdpSocket : public Socket 32 | { 33 | public: 34 | //! Default constructor creates a local UDP socket on port 2006 (or the specified port number). 35 | /*! 36 | An StkError will be thrown if a socket error occurs during instantiation. 37 | */ 38 | UdpSocket( int port = 2006 ); 39 | 40 | //! The class destructor closes the socket instance. 41 | ~UdpSocket(); 42 | 43 | //! Set the address for subsequent outgoing data sent via the \e writeBuffer() function. 44 | /*! 45 | An StkError will be thrown if the host is unknown. 46 | */ 47 | void setDestination( int port = 2006, std::string hostname = "localhost" ); 48 | 49 | //! Send a buffer to the address specified with the \e setDestination() function. Returns the number of bytes written or -1 if an error occurs. 50 | /*! 51 | This function will fail if the default address (set with \e setDestination()) is invalid or has not been specified. 52 | */ 53 | int writeBuffer(const void *buffer, long bufferSize, int flags = 0); 54 | 55 | //! Read an input buffer, up to length \e bufferSize. Returns the number of bytes read or -1 if an error occurs. 56 | int readBuffer(void *buffer, long bufferSize, int flags = 0); 57 | 58 | //! Write a buffer to the specified socket. Returns the number of bytes written or -1 if an error occurs. 59 | int writeBufferTo(const void *buffer, long bufferSize, int port, std::string hostname = "localhost", int flags = 0 ); 60 | 61 | protected: 62 | 63 | //! A protected function for use in writing a socket address structure. 64 | /*! 65 | An StkError will be thrown if the host is unknown. 66 | */ 67 | void setAddress( struct sockaddr_in *address, int port = 2006, std::string hostname = "localhost" ); 68 | 69 | struct sockaddr_in address_; 70 | bool validAddress_; 71 | 72 | }; 73 | 74 | } // stk namespace 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /stk/Vector3D.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_VECTOR3D_H 2 | #define STK_VECTOR3D_H 3 | 4 | #include "Stk.h" 5 | #include 6 | 7 | namespace stk { 8 | 9 | /***************************************************/ 10 | /*! \class Vector3D 11 | \brief STK 3D vector class. 12 | 13 | This class implements a three-dimensional vector. 14 | 15 | by Perry R. Cook, 1995-2011. 16 | */ 17 | /***************************************************/ 18 | 19 | class Vector3D : public Stk 20 | { 21 | 22 | public: 23 | //! Default constructor taking optional initial X, Y, and Z values. 24 | Vector3D( StkFloat x = 0.0, StkFloat y = 0.0, StkFloat z = 0.0 ) { setXYZ( x, y, z ); }; 25 | 26 | //! Get the current X value. 27 | StkFloat getX( void ) { return X_; }; 28 | 29 | //! Get the current Y value. 30 | StkFloat getY( void ) { return Y_; }; 31 | 32 | //! Get the current Z value. 33 | StkFloat getZ( void ) { return Z_; }; 34 | 35 | //! Calculate the vector length. 36 | StkFloat getLength( void ); 37 | 38 | //! Set the X, Y, and Z values simultaniously. 39 | void setXYZ( StkFloat x, StkFloat y, StkFloat z ) { X_ = x; Y_ = y; Z_ = z; }; 40 | 41 | //! Set the X value. 42 | void setX( StkFloat x ) { X_ = x; }; 43 | 44 | //! Set the Y value. 45 | void setY( StkFloat y ) { Y_ = y; }; 46 | 47 | //! Set the Z value. 48 | void setZ( StkFloat z ) { Z_ = z; }; 49 | 50 | protected: 51 | StkFloat X_; 52 | StkFloat Y_; 53 | StkFloat Z_; 54 | }; 55 | 56 | inline StkFloat Vector3D :: getLength( void ) 57 | { 58 | StkFloat temp; 59 | temp = X_ * X_; 60 | temp += Y_ * Y_; 61 | temp += Z_ * Z_; 62 | temp = sqrt( temp ); 63 | return temp; 64 | } 65 | 66 | } // stk namespace 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /stk/Wurley.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************/ 2 | /*! \class Wurley 3 | \brief STK Wurlitzer electric piano FM 4 | synthesis instrument. 5 | 6 | This class implements two simple FM Pairs 7 | summed together, also referred to as algorithm 8 | 5 of the TX81Z. 9 | 10 | \code 11 | Algorithm 5 is : 4->3--\ 12 | + --> Out 13 | 2->1--/ 14 | \endcode 15 | 16 | Control Change Numbers: 17 | - Modulator Index One = 2 18 | - Crossfade of Outputs = 4 19 | - LFO Speed = 11 20 | - LFO Depth = 1 21 | - ADSR 2 & 4 Target = 128 22 | 23 | The basic Chowning/Stanford FM patent expired 24 | in 1995, but there exist follow-on patents, 25 | mostly assigned to Yamaha. If you are of the 26 | type who should worry about this (making 27 | money) worry away. 28 | 29 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 30 | */ 31 | /***************************************************/ 32 | 33 | #include "Wurley.h" 34 | 35 | namespace stk { 36 | 37 | Wurley :: Wurley( void ) 38 | : FM() 39 | { 40 | // Concatenate the STK rawwave path to the rawwave files 41 | for ( unsigned int i=0; i<3; i++ ) 42 | waves_[i] = new FileLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true ); 43 | waves_[3] = new FileLoop( (Stk::rawwavePath() + "fwavblnk.raw").c_str(), true ); 44 | 45 | this->setRatio(0, 1.0); 46 | this->setRatio(1, 4.0); 47 | this->setRatio(2, -510.0); 48 | this->setRatio(3, -510.0); 49 | 50 | gains_[0] = fmGains_[99]; 51 | gains_[1] = fmGains_[82]; 52 | gains_[2] = fmGains_[92]; 53 | gains_[3] = fmGains_[68]; 54 | 55 | adsr_[0]->setAllTimes( 0.001, 1.50, 0.0, 0.04); 56 | adsr_[1]->setAllTimes( 0.001, 1.50, 0.0, 0.04); 57 | adsr_[2]->setAllTimes( 0.001, 0.25, 0.0, 0.04); 58 | adsr_[3]->setAllTimes( 0.001, 0.15, 0.0, 0.04); 59 | 60 | twozero_.setGain( 2.0 ); 61 | vibrato_.setFrequency( 8.0 ); 62 | } 63 | 64 | Wurley :: ~Wurley( void ) 65 | { 66 | } 67 | 68 | void Wurley :: setFrequency( StkFloat frequency ) 69 | { 70 | #if defined(_STK_DEBUG_) 71 | if ( frequency <= 0.0 ) { 72 | oStream_ << "Wurley::setFrequency: argument is less than or equal to zero!"; 73 | handleError( StkError::WARNING ); return; 74 | } 75 | #endif 76 | 77 | baseFrequency_ = frequency; 78 | waves_[0]->setFrequency( baseFrequency_ * ratios_[0]); 79 | waves_[1]->setFrequency( baseFrequency_ * ratios_[1]); 80 | waves_[2]->setFrequency( ratios_[2] ); // Note here a 'fixed resonance'. 81 | waves_[3]->setFrequency( ratios_[3] ); 82 | } 83 | 84 | void Wurley :: noteOn( StkFloat frequency, StkFloat amplitude ) 85 | { 86 | gains_[0] = amplitude * fmGains_[99]; 87 | gains_[1] = amplitude * fmGains_[82]; 88 | gains_[2] = amplitude * fmGains_[82]; 89 | gains_[3] = amplitude * fmGains_[68]; 90 | this->setFrequency( frequency ); 91 | this->keyOn(); 92 | } 93 | 94 | } // stk namespace 95 | -------------------------------------------------------------------------------- /stk/WvIn.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_WVIN_H 2 | #define STK_WVIN_H 3 | 4 | #include "Stk.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class WvIn 10 | \brief STK audio input abstract base class. 11 | 12 | This class provides common functionality for a variety of audio 13 | data input subclasses. 14 | 15 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 16 | */ 17 | /***************************************************/ 18 | 19 | class WvIn : public Stk 20 | { 21 | public: 22 | //! Return the number of audio channels in the data or stream. 23 | unsigned int channelsOut( void ) const { return data_.channels(); }; 24 | 25 | //! Return an StkFrames reference to the last computed sample frame. 26 | /*! 27 | If no file data is loaded, an empty container is returned. 28 | */ 29 | const StkFrames& lastFrame( void ) const { return lastFrame_; }; 30 | 31 | //! Compute one sample frame and return the specified \c channel value. 32 | virtual StkFloat tick( unsigned int channel = 0 ) = 0; 33 | 34 | //! Fill the StkFrames argument with computed frames and return the same reference. 35 | virtual StkFrames& tick( StkFrames& frames ) = 0; 36 | 37 | protected: 38 | 39 | StkFrames data_; 40 | StkFrames lastFrame_; 41 | 42 | }; 43 | 44 | } // stk namespace 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /stk/WvOut.h: -------------------------------------------------------------------------------- 1 | #ifndef STK_WVOUT_H 2 | #define STK_WVOUT_H 3 | 4 | #include "Stk.h" 5 | 6 | namespace stk { 7 | 8 | /***************************************************/ 9 | /*! \class WvOut 10 | \brief STK audio output abstract base class. 11 | 12 | This class provides common functionality for a variety of audio 13 | data output subclasses. 14 | 15 | Currently, WvOut is non-interpolating and the output rate is 16 | always Stk::sampleRate(). 17 | 18 | by Perry R. Cook and Gary P. Scavone, 1995-2011. 19 | */ 20 | /***************************************************/ 21 | 22 | class WvOut : public Stk 23 | { 24 | public: 25 | 26 | //! Default constructor. 27 | WvOut( void ) : frameCounter_(0), clipping_(false) {}; 28 | 29 | //! Return the number of sample frames output. 30 | unsigned long getFrameCount( void ) const { return frameCounter_; }; 31 | 32 | //! Return the number of seconds of data output. 33 | StkFloat getTime( void ) const { return (StkFloat) frameCounter_ / Stk::sampleRate(); }; 34 | 35 | //! Returns \c true if clipping has been detected during output since instantiation or the last reset. 36 | bool clipStatus( void ) { return clipping_; }; 37 | 38 | //! Reset the clipping status to \c false. 39 | void resetClipStatus( void ) { clipping_ = false; }; 40 | 41 | //! Output a single sample to all channels in a sample frame. 42 | /*! 43 | An StkError is thrown if an output error occurs. 44 | */ 45 | virtual void tick( const StkFloat sample ) = 0; 46 | 47 | //! Output the StkFrames data. 48 | virtual void tick( const StkFrames& frames ) = 0; 49 | 50 | protected: 51 | 52 | // Check for sample clipping and clamp. 53 | StkFloat& clipTest( StkFloat& sample ); 54 | 55 | StkFrames data_; 56 | unsigned long frameCounter_; 57 | bool clipping_; 58 | 59 | }; 60 | 61 | inline StkFloat& WvOut :: clipTest( StkFloat& sample ) 62 | { 63 | bool clip = false; 64 | if ( sample > 1.0 ) { 65 | sample = 1.0; 66 | clip = true; 67 | } 68 | else if ( sample < -1.0 ) { 69 | sample = -1.0; 70 | clip = true; 71 | } 72 | 73 | if ( clip == true && clipping_ == false ) { 74 | // First occurrence of clipping since instantiation or reset. 75 | clipping_ = true; 76 | oStream_ << "WvOut: data value(s) outside +-1.0 detected ... clamping at outer bound!"; 77 | handleError( StkError::WARNING ); 78 | } 79 | 80 | return sample; 81 | } 82 | 83 | } // stk namespace 84 | 85 | #endif 86 | --------------------------------------------------------------------------------