~ubuntu-branches/ubuntu/karmic/muse/karmic-proposed

« back to all changes in this revision

Viewing changes to synti/stklib/BlowHole.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2002-04-23 17:28:23 UTC
  • Revision ID: james.westby@ubuntu.com-20020423172823-w8yplzr81a759xa3
Tags: upstream-0.5.2
ImportĀ upstreamĀ versionĀ 0.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***********************************************/
 
2
/*
 
3
   Waveguide "reed" instrument model with a
 
4
   register hole and one tonehole
 
5
 
 
6
   by Gary P. Scavone, 2000.
 
7
*/
 
8
/***********************************************/
 
9
 
 
10
#include "BlowHole.h"
 
11
#include "SKINI11.msg"
 
12
 
 
13
BlowHole :: BlowHole(MY_FLOAT lowestFreq)
 
14
{
 
15
  length = (long) (SRATE / lowestFreq + 1);
 
16
  delays = (DLineL *) new DLineL[3];
 
17
  // delays[0] is the delay line between the reed and the register vent
 
18
  delays[0].setDelay(5.0);
 
19
  // delays[1] is the delay line between the register vent and the tonehole
 
20
  delays[1].setDelay(length >> 1);
 
21
  // delays[2] is the delay line between the tonehole and the end of the bore
 
22
  delays[2].setDelay(4.0);
 
23
  reedTable = new ReedTabl;
 
24
  reedTable->setOffset((MY_FLOAT) 0.7);
 
25
  reedTable->setSlope((MY_FLOAT) -0.3);
 
26
  filter = new OneZero;
 
27
  envelope = new Envelope;
 
28
  noise = new Noise;
 
29
 
 
30
  // Calculate the initial tonehole three-port scattering coefficient
 
31
  double r_b = 0.0075;    /* main bore radius */
 
32
  r_th = 0.003;          /* tonehole radius */
 
33
  scatter = -pow(r_th,2) / ( pow(r_th,2) + 2*pow(r_b,2) );
 
34
 
 
35
  // Calculate tonehole coefficients
 
36
  MY_FLOAT te = 1.4 * r_th;    /* effective length of the open hole */
 
37
  th_coeff = (te*2*SRATE - 347.23) / (te*2*SRATE + 347.23);
 
38
  tonehole = new PoleZero;
 
39
  // Start with tonehole open
 
40
  tonehole->setA1(-th_coeff);
 
41
  tonehole->setB0(th_coeff);
 
42
  tonehole->setB1(-1.0);
 
43
 
 
44
  // Calculate register hole filter coefficients
 
45
  double r_rh = 0.0015;    /* register vent radius */
 
46
  te = 1.4 * r_rh;       /* effective length of the open hole */
 
47
  double xi = 0.0;         /* series resistance term */
 
48
  double zeta = 347.23 + 2*PI*pow(r_b,2)*xi/1.1769;
 
49
  double psi = 2*PI*pow(r_b,2)*te / (PI*pow(r_rh,2));
 
50
  rh_coeff = (zeta - 2*SRATE*psi) / (zeta + 2*SRATE*psi);
 
51
  rh_gain = -347.23 / (zeta + 2*SRATE*psi);
 
52
  vent = new PoleZero;
 
53
  vent->setA1(rh_coeff);
 
54
  vent->setB0(1.0);
 
55
  vent->setB1(1.0);
 
56
  // Start with register vent closed
 
57
  vent->setGain(0.0);
 
58
 
 
59
  // Concatenate the STK RAWWAVE_PATH to the rawwave file
 
60
  char file[128];
 
61
  strcpy(file, RAWWAVE_PATH);
 
62
  vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
 
63
  vibr->setFreq((MY_FLOAT) 5.735);
 
64
  outputGain = (MY_FLOAT) 1.0;
 
65
  noiseGain = (MY_FLOAT) 0.2;
 
66
  vibrGain = (MY_FLOAT) 0.01;
 
67
}
 
68
 
 
69
BlowHole :: ~BlowHole()
 
70
{
 
71
  delete [] delays;
 
72
  delete reedTable;
 
73
  delete filter;
 
74
  delete tonehole;
 
75
  delete vent;
 
76
  delete envelope;
 
77
  delete noise;
 
78
  delete vibr;
 
79
}
 
80
 
 
81
void BlowHole :: clear()
 
82
{
 
83
  delays[0].clear();
 
84
  delays[1].clear();
 
85
  filter->tick((MY_FLOAT) 0.0);
 
86
  tonehole->tick((MY_FLOAT) 0.0);
 
87
  vent->tick((MY_FLOAT) 0.0);
 
88
}
 
89
 
 
90
void BlowHole :: setFreq(MY_FLOAT frequency)
 
91
{
 
92
  MY_FLOAT new_length = (SRATE / frequency) * (MY_FLOAT) 0.5 - (MY_FLOAT) 1.5;
 
93
  new_length -= 9;
 
94
 
 
95
  if (new_length <= 1.0) new_length = 1.0;
 
96
  else if (new_length >= length) new_length = length;
 
97
  delays[1].setDelay(new_length);
 
98
}
 
99
 
 
100
void BlowHole :: setVent(MY_FLOAT newValue)
 
101
{
 
102
  /*
 
103
    This method allows setting of the register vent "open-ness" at
 
104
    any point between "Open" (newValue = 1) and "Closed"
 
105
    (newValue = 0).
 
106
  */
 
107
 
 
108
  MY_FLOAT gain;
 
109
 
 
110
  if (newValue <= 0.0) gain = 0.0;
 
111
  else if (newValue >= 1.0) gain = rh_gain;
 
112
  else gain = newValue * rh_gain;
 
113
  vent->setGain(gain);
 
114
}
 
115
 
 
116
void BlowHole :: setTonehole(MY_FLOAT newValue)
 
117
{
 
118
  /*
 
119
    This method allows setting of the tonehole "open-ness" at
 
120
    any point between "Open" (newValue = 1) and "Closed"
 
121
    (newValue = 0).
 
122
  */
 
123
  MY_FLOAT new_coeff;
 
124
 
 
125
  if (newValue <= 0.0) new_coeff = 0.9995;
 
126
  else if (newValue >= 1.0) new_coeff = th_coeff;
 
127
  else new_coeff = (newValue * (th_coeff - 0.9995)) + 0.9995;
 
128
  tonehole->setA1(-new_coeff);
 
129
  tonehole->setB0(new_coeff);
 
130
}
 
131
 
 
132
void BlowHole :: startBlowing(MY_FLOAT amplitude,MY_FLOAT rate)
 
133
{
 
134
  envelope->setRate(rate);
 
135
  envelope->setTarget(amplitude); 
 
136
}
 
137
 
 
138
void BlowHole :: stopBlowing(MY_FLOAT rate)
 
139
{
 
140
  envelope->setRate(rate);
 
141
  envelope->setTarget((MY_FLOAT) 0.0); 
 
142
}
 
143
 
 
144
void BlowHole :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
 
145
{
 
146
  this->setFreq(freq);
 
147
  this->startBlowing((MY_FLOAT) 0.55 + (amp * (MY_FLOAT) 0.30),amp * (MY_FLOAT) 0.005);
 
148
  outputGain = amp + (MY_FLOAT) 0.001;
 
149
}
 
150
 
 
151
void BlowHole :: noteOff(MY_FLOAT amp)
 
152
{
 
153
  this->stopBlowing(amp * (MY_FLOAT) 0.01);
 
154
}
 
155
 
 
156
MY_FLOAT BlowHole :: tick()
 
157
{
 
158
  MY_FLOAT pressureDiff;
 
159
  MY_FLOAT breathPressure;
 
160
  MY_FLOAT temp;
 
161
 
 
162
  // Calculate the breath pressure (envelope + noise + vibrator)
 
163
  breathPressure = envelope->tick(); 
 
164
  breathPressure += breathPressure * noiseGain * noise->tick();
 
165
  breathPressure += breathPressure * vibrGain * vibr->tick();
 
166
 
 
167
  // Calculate the differential pressure = reflected - mouthpiece pressures
 
168
  pressureDiff = delays[0].lastOut() - breathPressure;
 
169
 
 
170
  // Do two-port junction scattering for register vent
 
171
  MY_FLOAT pa = breathPressure + pressureDiff * reedTable->lookup(pressureDiff);
 
172
  MY_FLOAT pb = delays[1].lastOut();
 
173
  vent->tick(pa+pb);
 
174
 
 
175
  lastOutput = delays[0].tick(vent->lastOut()+pb);
 
176
  lastOutput *= outputGain;
 
177
 
 
178
  // Do three-port junction scattering (under tonehole)
 
179
  pa += vent->lastOut();
 
180
  pb = delays[2].lastOut();
 
181
  MY_FLOAT pth = tonehole->lastOut();
 
182
  temp = scatter * (pa + pb - 2 * pth);
 
183
 
 
184
  delays[2].tick(filter->tick(pa + temp) * -0.95);
 
185
  delays[1].tick(pb + temp);
 
186
  tonehole->tick(pa + pb - pth + temp);
 
187
 
 
188
  return lastOutput;
 
189
}
 
190
 
 
191
void BlowHole :: controlChange(int number, MY_FLOAT value)
 
192
{
 
193
  if (number == __SK_ReedStiffness_)
 
194
    reedTable->setSlope((MY_FLOAT) -0.44 + ((MY_FLOAT) 0.26 * value * NORM_7));
 
195
  else if (number == __SK_NoiseLevel_)
 
196
    noiseGain = (value * NORM_7 * (MY_FLOAT) 0.4);
 
197
  else if (number == __SK_ModFrequency_)
 
198
    //vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
 
199
    this->setTonehole(value * NORM_7);
 
200
  else if (number == __SK_ModWheel_)
 
201
    //vibrGain = (value * NORM_7 * (MY_FLOAT) 0.5);
 
202
    this->setVent(value * NORM_7);
 
203
  else if (number == __SK_AfterTouch_Cont_) {
 
204
    envelope->setValue(value * NORM_7);
 
205
  }
 
206
  else  {
 
207
    printf("BlowHole : Undefined Control Number!!\n");
 
208
  }
 
209
}