1
/******************************************/
2
/* Simple Voice Manager (Mangler) */
3
/* for ToolKit96, 1996 Perry R. Cook */
4
/* Princeton University */
6
/* Make one of these by telling it the */
7
/* maximum number of voices you'll want, */
8
/* and also what flavor instrument */
9
/* group it will be mangling. Pipe SKINI*/
10
/* messages into it and it will return */
11
/* the mixed channel signal each tick. */
12
/* For multi-channel (multi-timbral), */
13
/* make one for each channel and mix */
16
/* Each note on returns a unique tag, */
17
/* (credits to the NeXT MusicKit here), */
18
/* so you can send control changes to */
19
/* unique instances of instruments */
20
/* within an ensemble. */
22
/* SKINI (Synthesis toolKit Instrument */
23
/* Network Interface) is like MIDI, but */
24
/* allows for floating point control */
25
/* changes, note numbers, etc. Example: */
26
/* noteOn 60.01 111.132 plays a sharp */
27
/* middle C with a velocity of 111.132 */
28
/* See SKINI09.txt for more information */
30
/******************************************/
47
VoicMang :: VoicMang(int maxVoices, char *instrType)
50
max_voices = maxVoices;
51
if (max_voices > __VMang_MAX_) {
52
printf("You ask for too many voices, setting to %i\n",__VMang_MAX_);
53
max_voices = __VMang_MAX_;
55
if (!strcmp(instrType,"Mandolin")) {
56
for (i=0;i<max_voices;i++)
57
instrument[i] = new Mandolin((MY_FLOAT) 50.0);
60
else if (!strcmp(instrType,"Plucked")) {
61
for (i=0;i<max_voices;i++)
62
instrument[i] = new Plucked(50.0);
65
else if (!strcmp(instrType,"Clarinet")) {
66
for (i=0;i<max_voices;i++)
67
instrument[i] = new Clarinet(50.0);
70
else if (!strcmp(instrType,"Flute")) {
71
for (i=0;i<max_voices;i++)
72
instrument[i] = new Flute(50.0);
75
else if (!strcmp(instrType,"Brass")) {
76
for (i=0;i<max_voices;i++)
77
instrument[i] = new Brass(50.0);
80
else if (!strcmp(instrType,"Bowed")) {
81
for (i=0;i<max_voices;i++)
82
instrument[i] = new Bowed(50.0);
85
else if (!strcmp(instrType,"Rhodey")) {
86
for (i=0;i<max_voices;i++)
87
instrument[i] = new Rhodey;
90
else if (!strcmp(instrType,"Wurley")) {
91
for (i=0;i<max_voices;i++)
92
instrument[i] = new Wurley;
95
else if (!strcmp(instrType,"TubeBell")) {
96
for (i=0;i<max_voices;i++)
97
instrument[i] = new TubeBell;
100
else if (!strcmp(instrType,"HeavyMtl")) {
101
for (i=0;i<max_voices;i++)
102
instrument[i] = new HeavyMtl;
105
else if (!strcmp(instrType,"PercFlut")) {
106
for (i=0;i<max_voices;i++)
107
instrument[i] = new PercFlut;
110
else if (!strcmp(instrType,"BeeThree")) {
111
for (i=0;i<max_voices;i++)
112
instrument[i] = new BeeThree;
115
else if (!strcmp(instrType,"Moog1")) {
116
for (i=0;i<max_voices;i++)
117
instrument[i] = new Moog1;
121
pitch_bend = (MY_FLOAT) 1.0;
123
for (i=0;i<max_voices;i++) {
126
freqBases[i] = (MY_FLOAT) 1.0;
127
frequencies[i] = (MY_FLOAT) 0.0;
131
VoicMang :: ~VoicMang()
134
for (i=0;i<max_voices;i++)
135
delete instrument[i];
138
long VoicMang :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
141
temp = freq / (MY_FLOAT) 220.0;
142
temp = (MY_FLOAT) (log(temp) / log(2.0));
143
temp = (temp * (MY_FLOAT) 12.0) + 57;
144
return this->noteOn(temp,amp);
147
#define ONE_OVER_12 0.083333
149
long VoicMang :: noteOnN(MY_FLOAT note_num, MY_FLOAT amp)
153
freq = (MY_FLOAT) 220.0 * pow(2.0,(note_num - 57.0) * ONE_OVER_12);
155
for (i=0;i<max_voices;i++) {
156
if (notesOn[i] < 0) { /* find a dormant instrument */
157
voicesOn[i] = newTag;
159
notesOn[i] = (int) (note_num + (MY_FLOAT) 0.5); /* Nearest Neighbor MIDI Note# */
160
instrument[i]->noteOn(freq,amp*(MY_FLOAT) NORM_7);
161
frequencies[i] = freq;
166
if (!gotOne) { /* if can't find a free one */
167
return -1; /* report back */
172
long VoicMang :: oldestVoice()
178
for (i=0;i<max_voices;i++) {
180
if (temp2 > 0 && temp2 < newTag) {
187
long VoicMang :: noteOffN(int note_num, MY_FLOAT amp)
191
for (i=0;i<max_voices;i++) {
192
if (notesOn[i]==note_num) {
193
instrument[i]->noteOff(amp * (MY_FLOAT) NORM_7);
194
gotOne = voicesOn[i];
195
voicesOn[i] = -mute_time - 2;
201
void VoicMang :: noteOffT(long tag, MY_FLOAT amp)
204
for (i=0;i<max_voices;i++) {
205
if (voicesOn[i]==tag) {
206
instrument[i]->noteOff(amp * (MY_FLOAT) NORM_7);
207
voicesOn[i] = -mute_time - 2;
212
void VoicMang :: kill(long tag)
215
for (i=0;i<max_voices;i++) {
216
if (voicesOn[i]==tag) {
217
instrument[i]->noteOff((MY_FLOAT) 1.0);
224
void VoicMang :: pitchBend(MY_FLOAT value)
228
for (i=0;i<max_voices;i++) {
229
freqBases[i] = pitch_bend;
230
instrument[i]->setFreq(freqBases[i]*frequencies[i]);
234
void VoicMang :: pitchBendT(long tag, MY_FLOAT value)
237
for (i=0;i<max_voices;i++) {
238
if (voicesOn[i] == tag) {
239
freqBases[i] = value;
240
instrument[i]->setFreq(freqBases[i]*frequencies[i]);
246
MY_FLOAT VoicMang :: tick()
250
temp = (MY_FLOAT) 0.0;
251
for (i=0;i<max_voices;i++) {
252
if (voicesOn[i] != 0) {
253
temp += instrument[i]->tick();
255
if (voicesOn[i] < 0) {
257
if (voicesOn[i] == 0) {
259
frequencies[i] = (MY_FLOAT) 0.0;
260
freqBases[i] = (MY_FLOAT) 1.0;
267
void VoicMang :: controlChange(int number, MY_FLOAT value)
270
for (i=0;i<max_voices;i++) {
271
instrument[i]->controlChange(number,value);
275
void VoicMang :: controlChangeT(long tag, int number, MY_FLOAT value)
278
for (i=0;i<max_voices;i++) {
279
if (voicesOn[i] == tag) {
280
instrument[i]->controlChange(number,value);