-
Notifications
You must be signed in to change notification settings - Fork 3
/
SineWave.cpp
112 lines (91 loc) · 2.53 KB
/
SineWave.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
109
110
111
112
/***************************************************/
/*! \class SineWave
\brief STK sinusoid oscillator class.
This class computes and saves a static sine "table" that can be
shared by multiple instances. It has an interface similar to the
WaveLoop class but inherits from the Generator class. Output
values are computed using linear interpolation.
The "table" length, set in SineWave.h, is 2048 samples by default.
by Perry R. Cook and Gary P. Scavone, 1995 - 2007.
*/
/***************************************************/
#include "SineWave.h"
#include <cmath>
StkFrames SineWave :: table_;
SineWave :: SineWave( void )
: time_(0.0), rate_(1.0), phaseOffset_(0.0)
{
if ( table_.empty() ) {
table_.resize( TABLE_SIZE + 1, 1 );
StkFloat temp = 1.0 / TABLE_SIZE;
for ( unsigned long i=0; i<=TABLE_SIZE; i++ )
table_[i] = sin( TWO_PI * i * temp );
}
Stk::addSampleRateAlert( this );
}
SineWave :: ~SineWave()
{
Stk::removeSampleRateAlert( this );
}
void SineWave :: sampleRateChanged( StkFloat newRate, StkFloat oldRate )
{
if ( !ignoreSampleRateChange_ )
this->setRate( oldRate * rate_ / newRate );
}
void SineWave :: reset(void)
{
time_ = 0.0;
lastOutput_ = 0;
}
void SineWave :: setFrequency( StkFloat frequency )
{
// This is a looping frequency.
this->setRate( TABLE_SIZE * frequency / Stk::sampleRate() );
}
void SineWave :: addTime( StkFloat time )
{
// Add an absolute time in samples.
time_ += time;
while ( time_ < 0.0 )
time_ += TABLE_SIZE;
while ( time_ >= TABLE_SIZE )
time_ -= TABLE_SIZE;
}
void SineWave :: addPhase( StkFloat angle )
{
// Add a time in cycles (one cycle = TABLE_SIZE).
time_ += TABLE_SIZE * angle;
while ( time_ < 0.0 )
time_ += TABLE_SIZE;
while ( time_ >= TABLE_SIZE )
time_ -= TABLE_SIZE;
}
void SineWave :: addPhaseOffset( StkFloat angle )
{
// Add a phase offset in cycles, where 1.0 = TABLE_SIZE.
phaseOffset_ = TABLE_SIZE * angle;
}
StkFloat SineWave :: computeSample( void )
{
// Check limits of time address ... if necessary, recalculate modulo
// TABLE_SIZE.
while ( time_ < 0.0 )
time_ += TABLE_SIZE;
while ( time_ >= TABLE_SIZE )
time_ -= TABLE_SIZE;
StkFloat tyme;
if ( phaseOffset_ ) {
tyme = time_ + phaseOffset_;
while ( tyme < 0.0 )
tyme += TABLE_SIZE;
while ( tyme >= TABLE_SIZE )
tyme -= TABLE_SIZE;
}
else {
tyme = time_;
}
lastOutput_ = table_.interpolate( tyme );
// Increment time, which can be negative.
time_ += rate_;
return lastOutput_;
}