1 //=============================================================================
2 // Zerberus
3 // Zample player
4 //
5 // Copyright (C) 2013 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12
13 #include "zerberus.h"
14 #include "channel.h"
15 #include "voice.h"
16 #include "instrument.h"
17 #include "zone.h"
18
19 #include "midi/event.h"
20
21 // static const float PI_2 = 1.57079632679489661923; /* pi/2 */
22
23 //---------------------------------------------------------
24 // Channel
25 //---------------------------------------------------------
26
Channel(Zerberus * ms,int i)27 Channel::Channel(Zerberus* ms, int i)
28 {
29 _msynth = ms;
30 _idx = i;
31 _instrument = 0;
32 _gain = 1.0;
33 _midiVolume = 1.0;
34 _panLeftGain = cosf(static_cast<float>(M_PI_2 * 64.0/126.0));
35 _panRightGain = sinf(static_cast<float>(M_PI_2 * 64.0/126.0));
36 memset(ctrl, 0, 128 * sizeof(char));
37 ctrl[Ms::CTRL_EXPRESSION] = 127;
38 }
39
40 //---------------------------------------------------------
41 // pitchBend
42 //---------------------------------------------------------
43
pitchBend(int)44 void Channel::pitchBend(int)
45 {
46 }
47
48 //---------------------------------------------------------
49 // controller
50 // realtime
51 //---------------------------------------------------------
52
controller(int c,int val)53 void Channel::controller(int c, int val)
54 {
55 ctrl[c] = val;
56 if (c == Ms::CTRL_SUSTAIN) {
57 if (val < 0x40) {
58 for (Voice* v = _msynth->getActiveVoices(); v; v = v->next()) {
59 if (v->isSustained()) {
60 //printf("sustain off %p\n", v);
61 v->stop();
62 }
63 }
64 }
65 }
66 else if (c == Ms::CTRL_PANPOT) {
67 val -= 1;
68 if (val < 0)
69 val = 0;
70 _panLeftGain = cosf(M_PI_2 * float(val)/126.0);
71 _panRightGain = sinf(M_PI_2 * float(val)/126.0);
72 }
73 else if (c == Ms::CTRL_VOLUME) {
74 // This was previously:
75 // (float(val) * float(ctrl[Ms::CTRL_EXPRESSION])) / (127.0 * 127.0);
76 // which was a hack to include CC11 support for SFZ. If necessary, revert to this.
77 _midiVolume = float(val) / 127.0;
78 }
79 else if (c == Ms::CTRL_ALL_NOTES_OFF) {
80 for (Voice* v = _msynth->getActiveVoices(); v; v = v->next()) {
81 if (!v->isOff())
82 v->stop();
83 }
84 }
85 else if (c == Ms::CTRL_PROGRAM) {
86 printf("Zerberus: program %d\n", val);
87 ZInstrument* zi = _msynth->instrument(val);
88 if (zi == 0)
89 printf(" not found\n");
90 if (zi && zi != _instrument) {
91 for (Voice* v = _msynth->getActiveVoices(); v; v = v->next())
92 v->off();
93 _instrument = zi;
94 resetCC();
95 }
96 }
97
98 for (Zone *z : instrument()->zones())
99 z->updateCCGain(this);
100 // else
101 // qDebug("Zerberus: ctrl 0x%02x 0x%02x", ctrl, val);
102 }
103
104 //---------------------------------------------------------
105 // sustain
106 //---------------------------------------------------------
107
sustain() const108 int Channel::sustain() const
109 {
110 return ctrl[Ms::CTRL_SUSTAIN];
111 }
112
getCtrl(int CTRL) const113 int Channel::getCtrl(int CTRL) const
114 {
115 return ctrl[CTRL];
116 }
117
118
resetCC()119 void Channel::resetCC()
120 {
121 if (!_instrument)
122 return;
123 for (int i = 0; i < 128; i++) {
124 if (_instrument->getSetCC(i) != -1)
125 ctrl[i] = _instrument->getSetCC(i);
126 }
127 }
128