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