-
Notifications
You must be signed in to change notification settings - Fork 180
/
Twang.cpp
108 lines (87 loc) · 2.95 KB
/
Twang.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/***************************************************/
/*! \class Twang
\brief STK enhanced plucked string class.
This class implements an enhanced plucked-string
physical model, a la Jaffe-Smith, Smith,
Karjalainen and others. It includes a comb
filter to simulate pluck position. The tick()
function takes an input sample, which is added
to the delayline input. This can be used to
implement commuted synthesis (if the input
samples are derived from the impulse response of
a body filter) or feedback (as in an electric
guitar model).
This is a digital waveguide model, making its
use possibly subject to patents held by Stanford
University, Yamaha, and others.
by Perry R. Cook and Gary P. Scavone, 1995--2023.
*/
/***************************************************/
#include "Twang.h"
namespace stk {
Twang :: Twang( StkFloat lowestFrequency )
{
if ( lowestFrequency <= 0.0 ) {
oStream_ << "Twang::Twang: argument is less than or equal to zero!";
handleError( StkError::FUNCTION_ARGUMENT );
}
this->setLowestFrequency( lowestFrequency );
std::vector<StkFloat> coefficients( 2, 0.5 );
loopFilter_.setCoefficients( coefficients );
loopGain_ = 0.995;
pluckPosition_ = 0.4;
this->setFrequency( 220.0 );
}
void Twang :: clear( void )
{
delayLine_.clear();
combDelay_.clear();
loopFilter_.clear();
lastOutput_ = 0.0;
}
void Twang :: setLowestFrequency( StkFloat frequency )
{
unsigned long nDelays = (unsigned long) ( Stk::sampleRate() / frequency );
delayLine_.setMaximumDelay( nDelays + 1 );
combDelay_.setMaximumDelay( nDelays + 1 );
}
void Twang :: setFrequency( StkFloat frequency )
{
#if defined(_STK_DEBUG_)
if ( frequency <= 0.0 ) {
oStream_ << "Twang::setFrequency: argument is less than or equal to zero!";
handleError( StkError::WARNING ); return;
}
#endif
frequency_ = frequency;
// Delay = length - filter delay.
StkFloat delay = ( Stk::sampleRate() / frequency ) - loopFilter_.phaseDelay( frequency );
delayLine_.setDelay( delay );
this->setLoopGain( loopGain_ );
// Set the pluck position, which puts zeroes at position * length.
combDelay_.setDelay( 0.5 * pluckPosition_ * delay );
}
void Twang :: setLoopGain( StkFloat loopGain )
{
if ( loopGain < 0.0 || loopGain >= 1.0 ) {
oStream_ << "Twang::setLoopGain: parameter is out of range!";
handleError( StkError::WARNING ); return;
}
loopGain_ = loopGain;
StkFloat gain = loopGain_ + (frequency_ * 0.000005);
if ( gain >= 1.0 ) gain = 0.99999;
loopFilter_.setGain( gain );
}
void Twang :: setLoopFilter( std::vector<StkFloat> coefficients )
{
loopFilter_.setCoefficients( coefficients, true );
}
void Twang :: setPluckPosition( StkFloat position )
{
if ( position < 0.0 || position > 1.0 ) {
oStream_ << "Twang::setPluckPosition: argument (" << position << ") is out of range!";
handleError( StkError::WARNING ); return;
}
pluckPosition_ = position;
}
} // stk namespace