1 /***************************************************/
2 /*! \class ModalBar
3     \brief STK resonant bar instrument class.
4 
5     This class implements a number of different
6     struck bar instruments.  It inherits from the
7     Modal class.
8 
9     Control Change Numbers:
10        - Stick Hardness = 2
11        - Stick Position = 4
12        - Vibrato Gain = 8
13        - Vibrato Frequency = 11
14        - Direct Stick Mix = 1
15        - Volume = 128
16        - Modal Presets = 16
17          - Marimba = 0
18          - Vibraphone = 1
19          - Agogo = 2
20          - Wood1 = 3
21          - Reso = 4
22          - Wood2 = 5
23          - Beats = 6
24          - Two Fixed = 7
25          - Clump = 8
26 
27     by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
28 */
29 /***************************************************/
30 
31 #include "ModalBar.h"
32 #include "SKINI.msg"
33 #include <cmath>
34 
35 using namespace Nyq;
36 
ModalBar()37 ModalBar :: ModalBar()
38   : Modal()
39 {
40   // Concatenate the STK rawwave path to the rawwave file
41   wave_ = new FileWvIn( (Stk::rawwavePath() + "marmstk1.raw").c_str(), true );
42   wave_->setRate( 0.5 * 22050.0 / Stk::sampleRate() );
43 
44   // Set the resonances for preset 0 (marimba).
45   this->setPreset( 0 );
46 }
47 
~ModalBar()48 ModalBar :: ~ModalBar()
49 {
50   delete wave_;
51 }
52 
setStickHardness(StkFloat hardness)53 void ModalBar :: setStickHardness(StkFloat hardness)
54 {
55   stickHardness_ = hardness;
56   if ( hardness < 0.0 ) {
57     errorString_ << "ModalBar::setStickHardness: parameter is less than zero ... setting to 0.0!";
58     handleError( StkError::WARNING );
59     stickHardness_ = 0.0;
60   }
61   else if ( hardness > 1.0 ) {
62     errorString_ << "ModalBar::setStickHarness: parameter is greater than one ... setting to 1.0!";
63     handleError( StkError::WARNING );
64     stickHardness_ = 1.0;
65   }
66 
67   wave_->setRate( (0.25 * pow(4.0, stickHardness_) ) );
68   masterGain_ = 0.1 + (1.8 * stickHardness_);
69 }
70 
setStrikePosition(StkFloat position)71 void ModalBar :: setStrikePosition(StkFloat position)
72 {
73   strikePosition_ = position;
74   if ( position < 0.0 ) {
75     errorString_ << "ModalBar::setStrikePosition: parameter is less than zero ... setting to 0.0!";
76     handleError( StkError::WARNING );
77     strikePosition_ = 0.0;
78   }
79   else if ( position > 1.0 ) {
80     errorString_ << "ModalBar::setStrikePosition: parameter is greater than one ... setting to 1.0!";
81     handleError( StkError::WARNING );
82     strikePosition_ = 1.0;
83   }
84 
85   // Hack only first three modes.
86   StkFloat temp2 = position * PI;
87   StkFloat temp = sin(temp2);
88   this->setModeGain(0, 0.12 * temp);
89 
90   temp = sin(0.05 + (3.9 * temp2));
91   this->setModeGain(1, -0.03 * temp);
92 
93   temp = sin(-0.05 + (11 * temp2));
94   this->setModeGain(2, 0.11 * temp);
95 }
96 
setPreset(int preset)97 void ModalBar :: setPreset(int preset)
98 {
99   // Presets:
100   //     First line:  relative modal frequencies (negative number is
101   //                  a fixed mode that doesn't scale with frequency
102   //     Second line: resonances of the modes
103   //     Third line:  mode volumes
104   //     Fourth line: stickHardness, strikePosition, and direct stick
105   //                  gain (mixed directly into the output
106   static StkFloat presets[9][4][4] = {
107     {{1.0, 3.99, 10.65, -2443},		// Marimba
108      {0.9996, 0.9994, 0.9994, 0.999},
109      {0.04, 0.01, 0.01, 0.008},
110      {0.429688, 0.445312, 0.093750}},
111     {{1.0, 2.01, 3.9, 14.37}, 		// Vibraphone
112      {0.99995, 0.99991, 0.99992, 0.9999},
113      {0.025, 0.015, 0.015, 0.015 },
114      {0.390625,0.570312,0.078125}},
115     {{1.0, 4.08, 6.669, -3725.0},		// Agogo
116      {0.999, 0.999, 0.999, 0.999},
117      {0.06, 0.05, 0.03, 0.02},
118      {0.609375,0.359375,0.140625}},
119     {{1.0, 2.777, 7.378, 15.377},		// Wood1
120      {0.996, 0.994, 0.994, 0.99},
121      {0.04, 0.01, 0.01, 0.008},
122      {0.460938,0.375000,0.046875}},
123     {{1.0, 2.777, 7.378, 15.377},		// Reso
124      {0.99996, 0.99994, 0.99994, 0.9999},
125      {0.02, 0.005, 0.005, 0.004},
126      {0.453125,0.250000,0.101562}},
127     {{1.0, 1.777, 2.378, 3.377},		// Wood2
128      {0.996, 0.994, 0.994, 0.99},
129      {0.04, 0.01, 0.01, 0.008},
130      {0.312500,0.445312,0.109375}},
131     {{1.0, 1.004, 1.013, 2.377},		// Beats
132      {0.9999, 0.9999, 0.9999, 0.999},
133      {0.02, 0.005, 0.005, 0.004},
134      {0.398438,0.296875,0.070312}},
135     {{1.0, 4.0, -1320.0, -3960.0},		// 2Fix
136      {0.9996, 0.999, 0.9994, 0.999},
137      {0.04, 0.01, 0.01, 0.008},
138      {0.453125,0.453125,0.070312}},
139     {{1.0, 1.217, 1.475, 1.729},		// Clump
140      {0.999, 0.999, 0.999, 0.999},
141      {0.03, 0.03, 0.03, 0.03 },
142      {0.390625,0.570312,0.078125}},
143   };
144 
145   int temp = (preset % 9);
146   for (unsigned int i=0; i<nModes_; i++) {
147     this->setRatioAndRadius(i, presets[temp][0][i], presets[temp][1][i]);
148     this->setModeGain(i, presets[temp][2][i]);
149   }
150 
151   this->setStickHardness(presets[temp][3][0]);
152   this->setStrikePosition(presets[temp][3][1]);
153   directGain_ = presets[temp][3][2];
154 
155   if (temp == 1) // vibraphone
156     vibratoGain_ = 0.2;
157   else
158     vibratoGain_ = 0.0;
159 }
160 
controlChange(int number,StkFloat value)161 void ModalBar :: controlChange(int number, StkFloat value)
162 {
163   StkFloat norm = value * ONE_OVER_128;
164   if ( norm < 0 ) {
165     norm = 0.0;
166     errorString_ << "ModalBar::controlChange: control value less than zero ... setting to zero!";
167     handleError( StkError::WARNING );
168   }
169   else if ( norm > 1.0 ) {
170     norm = 1.0;
171     errorString_ << "ModalBar::controlChange: control value greater than 128.0 ... setting to 128.0!";
172     handleError( StkError::WARNING );
173   }
174 
175   if (number == __SK_StickHardness_) // 2
176     this->setStickHardness( norm );
177   else if (number == __SK_StrikePosition_) // 4
178     this->setStrikePosition( norm );
179   else if (number == __SK_ProphesyRibbon_) // 16
180 		this->setPreset((int) value);
181   else if (number == __SK_Balance_) // 8
182     vibratoGain_ = norm * 0.3;
183   else if (number == __SK_ModWheel_) // 1
184     directGain_ = norm;
185   else if (number == __SK_ModFrequency_) // 11
186     vibrato_.setFrequency( norm * 12.0 );
187   else if (number == __SK_AfterTouch_Cont_)	// 128
188     envelope_.setTarget( norm );
189   else {
190     errorString_ << "ModalBar::controlChange: undefined control number (" << number << ")!";
191     handleError( StkError::WARNING );
192   }
193 
194 #if defined(_STK_DEBUG_)
195     errorString_ << "ModalBar::controlChange: number = " << number << ", value = " << value << '.';
196     handleError( StkError::DEBUG_WARNING );
197 #endif
198 }
199