add original mdaPiano files by Paul Kellett
[software/lv2-mdametapiano.git] / src / mdaPiano.cpp
1 //
2 // VST2 Plug-in: "mda Piano" v1.0
3 //
4 // Copyright(c)1999-2000 Paul Kellett (maxim digital audio)
5 // Based on VST2 SDK (c)1996-1999 Steinberg Soft und Hardware GmbH, All Rights Reserved
6 //
7
8 #include "mdaPianoData.h"
9 #include "mdaPiano.h"
10
11 #include <stdio.h>
12 #include <math.h>
13
14
15 //#include "AEffEditor.hpp" ////for GUI
16
17 AudioEffect *createEffectInstance(audioMasterCallback audioMaster)
18 {
19 return new mdaPiano(audioMaster);
20 }
21
22 mdaPianoProgram::mdaPianoProgram()
23 {
24 param[0] = 0.50f; //Decay
25 param[1] = 0.50f; //Release
26 param[2] = 0.50f; //Hardness
27
28 param[3] = 0.50f; //Vel>Hard
29 param[4] = 1.00f; //Muffle
30 param[5] = 0.50f; //Vel>Muff
31
32 param[6] = 0.33f; //Vel Curve
33 param[7] = 0.50f; //Stereo
34 param[8] = 0.33f; //Max Poly
35
36 param[9] = 0.50f; //Tune
37 param[10] = 0.00f; //Random
38 param[11] = 0.50f; //Stretch
39
40 strcpy (name, "mda Piano");
41 }
42
43
44 mdaPiano::mdaPiano(audioMasterCallback audioMaster) : AudioEffectX(audioMaster, NPROGS, NPARAMS)
45 {
46 Fs = 44100.0f; iFs = 1.0f/Fs; cmax = 0x7F; //just in case...
47
48 programs = new mdaPianoProgram[NPROGS];
49 if(programs)
50 {
51 //fill patches...
52 VstInt32 i=0;
53 fillpatch(i++, "mda Piano", 0.500f, 0.500f, 0.500f, 0.5f, 0.803f, 0.251f, 0.376f, 0.500f, 0.330f, 0.500f, 0.246f, 0.500f);
54 fillpatch(i++, "Plain Piano", 0.500f, 0.500f, 0.500f, 0.5f, 0.751f, 0.000f, 0.452f, 0.000f, 0.000f, 0.500f, 0.000f, 0.500f);
55 fillpatch(i++, "Compressed Piano", 0.902f, 0.399f, 0.623f, 0.5f, 1.000f, 0.331f, 0.299f, 0.499f, 0.330f, 0.500f, 0.000f, 0.500f);
56 fillpatch(i++, "Dance Piano", 0.399f, 0.251f, 1.000f, 0.5f, 0.672f, 0.124f, 0.127f, 0.249f, 0.330f, 0.500f, 0.283f, 0.667f);
57 fillpatch(i++, "Concert Piano", 0.648f, 0.500f, 0.500f, 0.5f, 0.298f, 0.602f, 0.550f, 0.850f, 0.356f, 0.500f, 0.339f, 0.660f);
58 fillpatch(i++, "Dark Piano", 0.500f, 0.602f, 0.000f, 0.5f, 0.304f, 0.200f, 0.336f, 0.651f, 0.330f, 0.500f, 0.317f, 0.500f);
59 fillpatch(i++, "School Piano", 0.450f, 0.598f, 0.626f, 0.5f, 0.603f, 0.500f, 0.174f, 0.331f, 0.330f, 0.500f, 0.421f, 0.801f);
60 fillpatch(i++, "Broken Piano", 0.050f, 0.957f, 0.500f, 0.5f, 0.299f, 1.000f, 0.000f, 0.500f, 0.330f, 0.450f, 0.718f, 0.000f);
61
62 setProgram(0);
63 }
64
65 if(audioMaster)
66 {
67 setNumInputs(0);
68 setNumOutputs(NOUTS);
69 canProcessReplacing();
70 isSynth();
71 setUniqueID('MDAp'); ///
72 }
73
74 waves = pianoData;
75
76
77 //Waveform data and keymapping is hard-wired in *this* version
78 kgrp[ 0].root = 36; kgrp[ 0].high = 37; kgrp[ 0].pos = 0; kgrp[ 0].end = 36275; kgrp[ 0].loop = 14774;
79 kgrp[ 1].root = 40; kgrp[ 1].high = 41; kgrp[ 1].pos = 36278; kgrp[ 1].end = 83135; kgrp[ 1].loop = 16268;
80 kgrp[ 2].root = 43; kgrp[ 2].high = 45; kgrp[ 2].pos = 83137; kgrp[ 2].end = 146756; kgrp[ 2].loop = 33541;
81 kgrp[ 3].root = 48; kgrp[ 3].high = 49; kgrp[ 3].pos = 146758; kgrp[ 3].end = 204997; kgrp[ 3].loop = 21156;
82 kgrp[ 4].root = 52; kgrp[ 4].high = 53; kgrp[ 4].pos = 204999; kgrp[ 4].end = 244908; kgrp[ 4].loop = 17191;
83 kgrp[ 5].root = 55; kgrp[ 5].high = 57; kgrp[ 5].pos = 244910; kgrp[ 5].end = 290978; kgrp[ 5].loop = 23286;
84 kgrp[ 6].root = 60; kgrp[ 6].high = 61; kgrp[ 6].pos = 290980; kgrp[ 6].end = 342948; kgrp[ 6].loop = 18002;
85 kgrp[ 7].root = 64; kgrp[ 7].high = 65; kgrp[ 7].pos = 342950; kgrp[ 7].end = 391750; kgrp[ 7].loop = 19746;
86 kgrp[ 8].root = 67; kgrp[ 8].high = 69; kgrp[ 8].pos = 391752; kgrp[ 8].end = 436915; kgrp[ 8].loop = 22253;
87 kgrp[ 9].root = 72; kgrp[ 9].high = 73; kgrp[ 9].pos = 436917; kgrp[ 9].end = 468807; kgrp[ 9].loop = 8852;
88 kgrp[10].root = 76; kgrp[10].high = 77; kgrp[10].pos = 468809; kgrp[10].end = 492772; kgrp[10].loop = 9693;
89 kgrp[11].root = 79; kgrp[11].high = 81; kgrp[11].pos = 492774; kgrp[11].end = 532293; kgrp[11].loop = 10596;
90 kgrp[12].root = 84; kgrp[12].high = 85; kgrp[12].pos = 532295; kgrp[12].end = 560192; kgrp[12].loop = 6011;
91 kgrp[13].root = 88; kgrp[13].high = 89; kgrp[13].pos = 560194; kgrp[13].end = 574121; kgrp[13].loop = 3414;
92 kgrp[14].root = 93; kgrp[14].high = 999; kgrp[14].pos = 574123; kgrp[14].end = 586343; kgrp[14].loop = 2399;
93
94 //initialise...
95 for(VstInt32 v=0; v<NVOICES; v++)
96 {
97 voice[v].env = 0.0f;
98 voice[v].dec = 0.99f; //all notes off
99 }
100 notes[0] = EVENTS_DONE;
101 volume = 0.2f;
102 muff = 160.0f;
103 cpos = sustain = activevoices = 0;
104 comb = new float[256];
105
106 guiUpdate = 0;
107
108 update();
109 suspend();
110 }
111
112
113 void mdaPiano::update() //parameter change
114 {
115 float * param = programs[curProgram].param;
116 size = (VstInt32)(12.0f * param[2] - 6.0f);
117 sizevel = 0.12f * param[3];
118 muffvel = param[5] * param[5] * 5.0f;
119
120 velsens = 1.0f + param[6] + param[6];
121 if(param[6] < 0.25f) velsens -= 0.75f - 3.0f * param[6];
122
123 fine = param[9] - 0.5f;
124 random = 0.077f * param[10] * param[10];
125 stretch = 0.000434f * (param[11] - 0.5f);
126
127 cdep = param[7] * param[7];
128 trim = 1.50f - 0.79f * cdep;
129 width = 0.04f * param[7]; if(width > 0.03f) width = 0.03f;
130
131 poly = 8 + (VstInt32)(24.9f * param[8]);
132 }
133
134
135 void mdaPiano::resume()
136 {
137 Fs = getSampleRate();
138 iFs = 1.0f / Fs;
139 if(Fs > 64000.0f) cmax = 0xFF; else cmax = 0x7F;
140 memset(comb, 0, sizeof(float) * 256);
141
142 DECLARE_VST_DEPRECATED (wantEvents) ();
143 }
144
145
146 mdaPiano::~mdaPiano () //destroy any buffers...
147 {
148 if(programs) delete [] programs;
149 if(comb) delete[] comb;
150 }
151
152
153 void mdaPiano::setProgram(VstInt32 program)
154 {
155 curProgram = program;
156 update();
157
158 // TODO: guiUpdate ???
159 }
160
161
162 void mdaPiano::setParameter(VstInt32 index, float value)
163 {
164 programs[curProgram].param[index] = value;
165 update();
166
167 // if(editor) editor->postUpdate(); //For GUI
168
169 guiUpdate = index + 0x100 + (guiUpdate & 0xFFFF00);
170 }
171
172
173 void mdaPiano::fillpatch(VstInt32 p, char *name, float p0, float p1, float p2, float p3, float p4,
174 float p5, float p6, float p7, float p8, float p9, float p10,float p11)
175 {
176 strcpy(programs[p].name, name);
177 programs[p].param[0] = p0; programs[p].param[1] = p1;
178 programs[p].param[2] = p2; programs[p].param[3] = p3;
179 programs[p].param[4] = p4; programs[p].param[5] = p5;
180 programs[p].param[6] = p6; programs[p].param[7] = p7;
181 programs[p].param[8] = p8; programs[p].param[9] = p9;
182 programs[p].param[10]= p10; programs[p].param[11] = p11;
183 }
184
185
186 float mdaPiano::getParameter(VstInt32 index) { return programs[curProgram].param[index]; }
187 void mdaPiano::setProgramName(char *name) { strcpy(programs[curProgram].name, name); }
188 void mdaPiano::getProgramName(char *name) { strcpy(name, programs[curProgram].name); }
189 void mdaPiano::setBlockSize(VstInt32 blockSize) { AudioEffectX::setBlockSize(blockSize); }
190 bool mdaPiano::getEffectName(char* name) { strcpy(name, "Piano"); return true; }
191 bool mdaPiano::getVendorString(char* text) { strcpy(text, "mda"); return true; }
192 bool mdaPiano::getProductString(char* text) { strcpy(text, "mda Piano"); return true; }
193
194
195 bool mdaPiano::getOutputProperties(VstInt32 index, VstPinProperties* properties)
196 {
197 if(index<NOUTS)
198 {
199 if(index) sprintf(properties->label, "Piano R");
200 else sprintf(properties->label, "Piano L");
201 properties->flags = kVstPinIsActive;
202 if(index<2) properties->flags |= kVstPinIsStereo; //make channel 1+2 stereo
203 return true;
204 }
205 return false;
206 }
207
208
209 bool mdaPiano::getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text)
210 {
211 if ((unsigned int)index < NPROGS)
212 {
213 strcpy(text, programs[index].name);
214 return true;
215 }
216 return false;
217 }
218
219
220 bool mdaPiano::copyProgram(VstInt32 destination)
221 {
222 if(destination<NPROGS)
223 {
224 programs[destination] = programs[curProgram];
225 return true;
226 }
227 return false;
228 }
229
230
231 VstInt32 mdaPiano::canDo(char* text)
232 {
233 if(strcmp(text, "receiveVstEvents") == 0) return 1;
234 if(strcmp(text, "receiveVstMidiEvent") == 0) return 1;
235 return -1;
236 }
237
238
239 void mdaPiano::getParameterName(VstInt32 index, char *label)
240 {
241 switch (index)
242 {
243 case 0: strcpy(label, "Envelope Decay"); break;
244 case 1: strcpy(label, "Envelope Release"); break;
245 case 2: strcpy(label, "Hardness Offset"); break;
246
247 case 3: strcpy(label, "Velocity to Hardness"); break;
248 case 4: strcpy(label, "Muffling Filter"); break;
249 case 5: strcpy(label, "Velocity to Muffling"); break;
250
251 case 6: strcpy(label, "Velocity Sensitivity"); break;
252 case 7: strcpy(label, "Stereo Width"); break;
253 case 8: strcpy(label, "Polyphony"); break;
254
255 case 9: strcpy(label, "Fine Tuning"); break;
256 case 10: strcpy(label, "Random Detuning"); break;
257 default: strcpy(label, "Stretch Tuning"); break;
258 }
259 }
260
261
262 void mdaPiano::getParameterDisplay(VstInt32 index, char *text)
263 {
264 char string[16];
265 float * param = programs[curProgram].param;
266
267 switch(index)
268 {
269 case 4: sprintf(string, "%.0f", 100.0f - 100.0f * param[index]); break;
270 case 7: sprintf(string, "%.0f", 200.0f * param[index]); break;
271 case 8: sprintf(string, "%d", poly); break;
272 case 10: sprintf(string, "%.1f", 50.0f * param[index] * param[index]); break;
273 case 2:
274 case 9:
275 case 11: sprintf(string, "%+.1f", 100.0f * param[index] - 50.0f); break;
276 default: sprintf(string, "%.0f", 100.0f * param[index]);
277 }
278 string[8] = 0;
279 strcpy(text, (char *)string);
280 }
281
282
283 void mdaPiano::getParameterLabel(VstInt32 index, char *label)
284 {
285 switch(index)
286 {
287 case 8: strcpy(label, "voices"); break;
288 case 9:
289 case 10:
290 case 11: strcpy(label, "cents"); break;
291 default: strcpy(label, "%");
292 }
293 }
294
295
296 void mdaPiano::guiGetDisplay(VstInt32 index, char *label)
297 {
298 getParameterName(index, label);
299 strcat(label, " = ");
300 getParameterDisplay(index, label + strlen(label));
301 getParameterLabel(index, label + strlen(label));
302 }
303
304
305
306 void mdaPiano::process(float **inputs, float **outputs, VstInt32 sampleFrames)
307 {
308 float* out0 = outputs[0];
309 float* out1 = outputs[1];
310 VstInt32 event=0, frame=0, frames, v;
311 float x, l, r;
312 VstInt32 i;
313
314 while(frame<sampleFrames)
315 {
316 frames = notes[event++];
317 if(frames>sampleFrames) frames = sampleFrames;
318 frames -= frame;
319 frame += frames;
320
321 while(--frames>=0)
322 {
323 VOICE *V = voice;
324 l = r = 0.0f;
325
326 for(v=0; v<activevoices; v++)
327 {
328 V->frac += V->delta; //integer-based linear interpolation
329 V->pos += V->frac >> 16;
330 V->frac &= 0xFFFF;
331 if(V->pos > V->end) V->pos -= V->loop;
332 i = waves[V->pos];
333 i = (i << 7) + (V->frac >> 9) * (waves[V->pos + 1] - i) + 0x40400000;
334 x = V->env * (*(float *)&i - 3.0f); //fast int->float
335
336 V->env = V->env * V->dec; //envelope
337 V->f0 += V->ff * (x + V->f1 - V->f0); //muffle filter
338 V->f1 = x;
339
340 l += V->outl * V->f0;
341 r += V->outr * V->f0;
342
343 V++;
344 }
345 comb[cpos] = l + r;
346 ++cpos &= cmax;
347 x = cdep * comb[cpos]; //stereo simulator
348
349 *out0++ += l + x;
350 *out1++ += r - x;
351 }
352
353 if(frame<sampleFrames)
354 {
355 VstInt32 note = notes[event++];
356 VstInt32 vel = notes[event++];
357 noteOn(note, vel);
358 }
359 }
360 for(v=0; v<activevoices; v++) if(voice[v].env < SILENCE) voice[v] = voice[--activevoices];
361 notes[0] = EVENTS_DONE; //mark events buffer as done
362 }
363
364
365 void mdaPiano::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames)
366 {
367 float* out0 = outputs[0];
368 float* out1 = outputs[1];
369 VstInt32 event=0, frame=0, frames, v;
370 float x, l, r;
371 VstInt32 i;
372
373 while(frame<sampleFrames)
374 {
375 frames = notes[event++];
376 if(frames>sampleFrames) frames = sampleFrames;
377 frames -= frame;
378 frame += frames;
379
380 while(--frames>=0)
381 {
382 VOICE *V = voice;
383 l = r = 0.0f;
384
385 for(v=0; v<activevoices; v++)
386 {
387 V->frac += V->delta; //integer-based linear interpolation
388 V->pos += V->frac >> 16;
389 V->frac &= 0xFFFF;
390 if(V->pos > V->end) V->pos -= V->loop;
391 //i = (i << 7) + (V->frac >> 9) * (waves[V->pos + 1] - i) + 0x40400000; //not working on intel mac !?!
392 i = waves[V->pos] + ((V->frac * (waves[V->pos + 1] - waves[V->pos])) >> 16);
393 x = V->env * (float)i / 32768.0f;
394 //x = V->env * (*(float *)&i - 3.0f); //fast int->float
395
396 V->env = V->env * V->dec; //envelope
397 V->f0 += V->ff * (x + V->f1 - V->f0); //muffle filter
398 V->f1 = x;
399
400 l += V->outl * V->f0;
401 r += V->outr * V->f0;
402
403 if(!(l > -2.0f) || !(l < 2.0f))
404 {
405 printf("what is this shit? %d, %f, %f\n", i, x, V->f0);
406 l = 0.0f;
407 }
408 if(!(r > -2.0f) || !(r < 2.0f))
409 {
410 r = 0.0f;
411 }
412
413 V++;
414 }
415 comb[cpos] = l + r;
416 ++cpos &= cmax;
417 x = cdep * comb[cpos]; //stereo simulator
418
419 *out0++ = l + x;
420 *out1++ = r - x;
421 }
422
423 if(frame<sampleFrames)
424 {
425 VstInt32 note = notes[event++];
426 VstInt32 vel = notes[event++];
427 noteOn(note, vel);
428 }
429 }
430 for(v=0; v<activevoices; v++) if(voice[v].env < SILENCE) voice[v] = voice[--activevoices];
431 notes[0] = EVENTS_DONE; //mark events buffer as done
432 }
433
434
435 void mdaPiano::noteOn(VstInt32 note, VstInt32 velocity)
436 {
437 float * param = programs[curProgram].param;
438 float l=99.0f;
439 VstInt32 v, vl=0, k, s;
440
441 if(velocity>0)
442 {
443 if(activevoices < poly) //add a note
444 {
445 vl = activevoices;
446 activevoices++;
447 }
448 else //steal a note
449 {
450 for(v=0; v<poly; v++) //find quietest voice
451 {
452 if(voice[v].env < l) { l = voice[v].env; vl = v; }
453 }
454 }
455
456 k = (note - 60) * (note - 60);
457 l = fine + random * ((float)(k % 13) - 6.5f); //random & fine tune
458 if(note > 60) l += stretch * (float)k; //stretch
459
460 s = size;
461 if(velocity > 40) s += (VstInt32)(sizevel * (float)(velocity - 40));
462
463 k = 0;
464 while(note > (kgrp[k].high + s)) k++; //find keygroup
465
466 l += (float)(note - kgrp[k].root); //pitch
467 l = 22050.0f * iFs * (float)exp(0.05776226505 * l);
468 voice[vl].delta = (VstInt32)(65536.0f * l);
469 voice[vl].frac = 0;
470 voice[vl].pos = kgrp[k].pos;
471 voice[vl].end = kgrp[k].end;
472 voice[vl].loop = kgrp[k].loop;
473
474 voice[vl].env = (0.5f + velsens) * (float)pow(0.0078f * velocity, velsens); //velocity
475
476 l = 50.0f + param[4] * param[4] * muff + muffvel * (float)(velocity - 64); //muffle
477 if(l < (55.0f + 0.25f * (float)note)) l = 55.0f + 0.25f * (float)note;
478 if(l > 210.0f) l = 210.0f;
479 voice[vl].ff = l * l * iFs;
480 voice[vl].f0 = voice[vl].f1 = 0.0f;
481
482 voice[vl].note = note; //note->pan
483 if(note < 12) note = 12;
484 if(note > 108) note = 108;
485 l = volume * trim;
486 voice[vl].outr = l + l * width * (float)(note - 60);
487 voice[vl].outl = l + l - voice[vl].outr;
488
489 if(note < 44) note = 44; //limit max decay length
490 l = 2.0f * param[0];
491 if(l < 1.0f) l += 0.25f - 0.5f * param[0];
492 voice[vl].dec = (float)exp(-iFs * exp(-0.6 + 0.033 * (double)note - l));
493 }
494 else //note off
495 {
496 for(v=0; v<NVOICES; v++) if(voice[v].note==note) //any voices playing that note?
497 {
498 if(sustain==0)
499 {
500 if(note < 94 || note == SUSTAIN) //no release on highest notes
501 voice[v].dec = (float)exp(-iFs * exp(2.0 + 0.017 * (double)note - 2.0 * param[1]));
502 }
503 else voice[v].note = SUSTAIN;
504 }
505 }
506 }
507
508
509 VstInt32 mdaPiano::processEvents(VstEvents* ev)
510 {
511 VstInt32 npos=0;
512
513 for (VstInt32 i=0; i<ev->numEvents; i++)
514 {
515 if((ev->events[i])->type != kVstMidiType) continue;
516 VstMidiEvent* event = (VstMidiEvent*)ev->events[i];
517 char* midiData = event->midiData;
518
519 switch(midiData[0] & 0xf0) //status byte (all channels)
520 {
521 case 0x80: //note off
522 notes[npos++] = event->deltaFrames; //delta
523 notes[npos++] = midiData[1] & 0x7F; //note
524 notes[npos++] = 0; //vel
525 break;
526
527 case 0x90: //note on
528 notes[npos++] = event->deltaFrames; //delta
529 notes[npos++] = midiData[1] & 0x7F; //note
530 notes[npos++] = midiData[2] & 0x7F; //vel
531 break;
532
533 case 0xB0: //controller
534 switch(midiData[1])
535 {
536 case 0x01: //mod wheel
537 case 0x43: //soft pedal
538 muff = 0.01f * (float)((127 - midiData[2]) * (127 - midiData[2]));
539 break;
540
541 case 0x07: //volume
542 volume = 0.00002f * (float)(midiData[2] * midiData[2]);
543 break;
544
545 case 0x40: //sustain pedal
546 case 0x42: //sustenuto pedal
547 sustain = midiData[2] & 0x40;
548 if(sustain==0)
549 {
550 notes[npos++] = event->deltaFrames;
551 notes[npos++] = SUSTAIN; //end all sustained notes
552 notes[npos++] = 0;
553 }
554 break;
555
556 default: //all notes off
557 if(midiData[1]>0x7A)
558 {
559 for(VstInt32 v=0; v<NVOICES; v++) voice[v].dec=0.99f;
560 sustain = 0;
561 muff = 160.0f;
562 }
563 break;
564 }
565 break;
566
567 case 0xC0: //program change
568 if(midiData[1]<NPROGS) setProgram(midiData[1]);
569 break;
570
571 default: break;
572 }
573
574 if(npos>EVENTBUFFER) npos -= 3; //discard events if buffer full!!
575 event++; //?
576 }
577 notes[npos] = EVENTS_DONE;
578 return 1;
579 }
580