📄 stifkarp.cpp
字号:
/***************************************************//*! \class StifKarp \brief STK plucked stiff string instrument. This class implements a simple plucked string algorithm (Karplus Strong) with enhancements (Jaffe-Smith, Smith, and others), including string stiffness and pluck position controls. The stiffness is modeled with allpass filters. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Pickup Position = 4 - String Sustain = 11 - String Stretch = 1 by Perry R. Cook and Gary P. Scavone, 1995 - 2005.*//***************************************************/#include "StifKarp.h"#include "SKINI.msg"#if !defined(SYMBIAN)#include <cmath>#else#include "symbmath.h"#endifStifKarp :: StifKarp(StkFloat lowestFrequency){ length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1); delayLine_.setMaximumDelay( length_ ); delayLine_.setDelay( 0.5 * length_ ); combDelay_.setMaximumDelay( length_ ); combDelay_.setDelay( 0.2 * length_ ); pluckAmplitude_ = 0.3; pickupPosition_ = 0.4; lastFrequency_ = lowestFrequency * 2.0; lastLength_ = length_ * 0.5; stretching_ = 0.9999; baseLoopGain_ = 0.995; loopGain_ = 0.999; this->clear();}StifKarp :: ~StifKarp(){}void StifKarp :: clear(){ delayLine_.clear(); combDelay_.clear(); filter_.clear();}void StifKarp :: setFrequency(StkFloat frequency){ lastFrequency_ = frequency; if ( frequency <= 0.0 ) {#if !defined(SYMBIAN) errorString_ << "StifKarp::setFrequency: parameter is less than or equal to zero!"; handleError( StkError::WARNING );#endif lastFrequency_ = 220.0; } lastLength_ = Stk::sampleRate() / lastFrequency_; StkFloat delay = lastLength_ - 0.5; if (delay <= 0.0) delay = 0.3; else if (delay > length_) delay = length_; delayLine_.setDelay( delay ); loopGain_ = baseLoopGain_ + (frequency * 0.000005); if (loopGain_ >= 1.0) loopGain_ = 0.99999; setStretch(stretching_); combDelay_.setDelay( 0.5 * pickupPosition_ * lastLength_ ); }void StifKarp :: setStretch(StkFloat stretch){ stretching_ = stretch; StkFloat coefficient; StkFloat freq = lastFrequency_ * 2.0; StkFloat dFreq = ( (0.5 * Stk::sampleRate()) - freq ) * 0.25; StkFloat temp = 0.5 + (stretch * 0.5); if (temp > 0.9999) temp = 0.9999; for (int i=0; i<4; i++) { coefficient = temp * temp; biquad_[i].setA2( coefficient ); biquad_[i].setB0( coefficient ); biquad_[i].setB2( 1.0 ); coefficient = -2.0 * temp * cos(TWO_PI * freq / Stk::sampleRate()); biquad_[i].setA1( coefficient ); biquad_[i].setB1( coefficient ); freq += dFreq; }}void StifKarp :: setPickupPosition(StkFloat position) { pickupPosition_ = position; if ( position < 0.0 ) {#if !defined(SYMBIAN) errorString_ << "StifKarp::setPickupPosition: parameter is less than zero ... setting to 0.0!"; handleError( StkError::WARNING );#endif pickupPosition_ = 0.0; } else if ( position > 1.0 ) {#if !defined(SYMBIAN) errorString_ << "StifKarp::setPickupPosition: parameter is greater than 1.0 ... setting to 1.0!"; handleError( StkError::WARNING );#endif pickupPosition_ = 1.0; } // Set the pick position, which puts zeroes at position * length. combDelay_.setDelay( 0.5 * pickupPosition_ * lastLength_ );}void StifKarp :: setBaseLoopGain(StkFloat aGain){ baseLoopGain_ = aGain; loopGain_ = baseLoopGain_ + (lastFrequency_ * 0.000005); if ( loopGain_ > 0.99999 ) loopGain_ = (StkFloat) 0.99999;}void StifKarp :: pluck(StkFloat amplitude){ StkFloat gain = amplitude; if ( gain > 1.0 ) {#if !defined(SYMBIAN) errorString_ << "StifKarp::pluck: amplitude is greater than 1.0 ... setting to 1.0!"; handleError( StkError::WARNING );#endif gain = 1.0; } else if ( gain < 0.0 ) {#if !defined(SYMBIAN) errorString_ << "StifKarp::pluck: amplitude is less than zero ... setting to 0.0!"; handleError( StkError::WARNING );#endif gain = 0.0; } pluckAmplitude_ = amplitude; for (unsigned long i=0; i<length_; i++) { // Fill delay with noise additively with current contents. delayLine_.tick( (delayLine_.lastOut() * 0.6) + 0.4 * noise_.tick() * pluckAmplitude_ ); //delayLine_.tick( combDelay_.tick((delayLine_.lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude_) ); }}void StifKarp :: noteOn(StkFloat frequency, StkFloat amplitude){ this->setFrequency( frequency ); this->pluck( amplitude );#if defined(_STK_DEBUG_) errorString_ << "StifKarp::NoteOn: frequency = " << frequency << ", amplitude = " << amplitude << "."; handleError( StkError::DEBUG_WARNING );#endif}void StifKarp :: noteOff(StkFloat amplitude){ StkFloat gain = amplitude; if ( gain > 1.0 ) {#if !defined(SYMBIAN) errorString_ << "StifKarp::noteOff: amplitude is greater than 1.0 ... setting to 1.0!"; handleError( StkError::WARNING );#endif gain = 1.0; } else if ( gain < 0.0 ) {#if !defined(SYMBIAN) errorString_ << "StifKarp::noteOff: amplitude is < 0.0 ... setting to 0.0!"; handleError( StkError::WARNING );#endif gain = 0.0; } loopGain_ = (1.0 - gain) * 0.5;#if defined(_STK_DEBUG_) errorString_ << "StifKarp::NoteOff: amplitude = " << amplitude << "."; handleError( StkError::DEBUG_WARNING );#endif}StkFloat StifKarp :: computeSample(){ StkFloat temp = delayLine_.lastOut() * loopGain_; // Calculate allpass stretching. for (int i=0; i<4; i++) temp = biquad_[i].tick(temp); // Moving average filter. temp = filter_.tick(temp); lastOutput_ = delayLine_.tick(temp); lastOutput_ = lastOutput_ - combDelay_.tick( lastOutput_ ); return lastOutput_;}void StifKarp :: controlChange(int number, StkFloat value){ StkFloat norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0;#if !defined(SYMBIAN) errorString_ << "StifKarp::controlChange: control value less than zero ... setting to zero!"; handleError( StkError::WARNING );#endif } else if ( norm > 1.0 ) { norm = 1.0;#if !defined(SYMBIAN) errorString_ << "StifKarp::controlChange: control value greater than 128.0 ... setting to 128.0!"; handleError( StkError::WARNING );#endif } if (number == __SK_PickPosition_) // 4 this->setPickupPosition( norm ); else if (number == __SK_StringDamping_) // 11 this->setBaseLoopGain( 0.97 + (norm * 0.03) ); else if (number == __SK_StringDetune_) // 1 this->setStretch( 0.9 + (0.1 * (1.0 - norm)) ); else {#if !defined(SYMBIAN) errorString_ << "StifKarp::controlChange: undefined control number (" << number << ")!"; handleError( StkError::WARNING );#endif }#if defined(_STK_DEBUG_) errorString_ << "StifKarp::controlChange: number = " << number << ", value = " << value << "."; handleError( StkError::DEBUG_WARNING );#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -