1 /***************************************************************************
2 **                                                                        **
3 **  Polyphone, a soundfont editor                                         **
4 **  Copyright (C) 2013-2020 Davy Triponney                                **
5 **                                                                        **
6 **  This program is free software: you can redistribute it and/or modify  **
7 **  it under the terms of the GNU General Public License as published by  **
8 **  the Free Software Foundation, either version 3 of the License, or     **
9 **  (at your option) any later version.                                   **
10 **                                                                        **
11 **  This program is distributed in the hope that it will be useful,       **
12 **  but WITHOUT ANY WARRANTY; without even the implied warranty of        **
13 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the          **
14 **  GNU General Public License for more details.                          **
15 **                                                                        **
16 **  You should have received a copy of the GNU General Public License     **
17 **  along with this program. If not, see http://www.gnu.org/licenses/.    **
18 **                                                                        **
19 ****************************************************************************
20 **           Author: Davy Triponney                                       **
21 **  Website/Contact: https://www.polyphone-soundfonts.com                 **
22 **             Date: 01.01.2013                                           **
23 ***************************************************************************/
24 
25 #include "envelop.h"
26 #include <QGraphicsLineItem>
27 #include <QGraphicsScene>
28 #include "graphicsviewenvelop.h"
29 
Envelop(QCPGraph * graph1,QCPGraph * graph2)30 Envelop::Envelop(QCPGraph * graph1, QCPGraph * graph2) :
31     _graph1(graph1),
32     _graph2(graph2)
33 {
34     // Default values
35     _values[DELAY] = 0;
36     _values[ATTACK] = 0;
37     _values[HOLD] = 0;
38     _values[DECAY] = 0;
39     _values[SUSTAIN] = 0;
40     _values[RELEASE] = 0;
41     _values[KEYNUM_TO_HOLD] = 0;
42     _values[KEYNUM_TO_DECAY] = 0;
43     _values[KEY_MIN] = 0;
44     _values[KEY_MAX] = 0;
45 
46     _defined[DELAY] = false;
47     _defined[ATTACK] = false;
48     _defined[HOLD] = false;
49     _defined[DECAY] = false;
50     _defined[SUSTAIN] = false;
51     _defined[RELEASE] = false;
52     _defined[KEYNUM_TO_HOLD] = false;
53     _defined[KEYNUM_TO_DECAY] = false;
54     _values[KEYNUM_TO_DECAY] = false;
55     _values[KEYNUM_TO_DECAY] = false;
56 
57     _graph1->setChannelFillGraph(_graph2);
58 }
59 
set(ValueType type,double value,bool defined)60 void Envelop::set(ValueType type, double value, bool defined)
61 {
62     _values[type] = value;
63     _defined[type] = defined;
64 }
65 
getAttackDuration()66 double Envelop::getAttackDuration()
67 {
68     return _values[DELAY] + _values[ATTACK] +
69             qMax(getValueForKey(_values[HOLD], _values[KEYNUM_TO_HOLD], _values[KEY_MIN]),
70                  getValueForKey(_values[HOLD], _values[KEYNUM_TO_HOLD], _values[KEY_MAX])) +
71             qMax(getValueForKey(_values[DECAY], _values[KEYNUM_TO_DECAY], _values[KEY_MIN]),
72                  getValueForKey(_values[DECAY], _values[KEYNUM_TO_DECAY], _values[KEY_MAX]));
73 }
74 
getReleaseDuration()75 double Envelop::getReleaseDuration()
76 {
77     return _values[RELEASE];
78 }
79 
draw(double triggeredKeyDuration,double releasedKeyDuration)80 void Envelop::draw(double triggeredKeyDuration, double releasedKeyDuration)
81 {
82     // Style of the line
83     _color.setAlpha(255);
84     QPen pen(_color, _isThick ? 3 : 1);
85     _graph1->setPen(pen);
86     _graph2->setPen(pen);
87 
88     _color.setAlpha(100);
89     _graph1->setBrush(_color);
90 
91     // Compute data
92     double position = 0, position2;
93     QVector<double> vectX1(8), vectY1(8), vectX2(8), vectY2(8);
94 
95     // First point: origin
96     vectX1[0] = 0;
97     vectY1[0] = 0;
98     vectX2[0] = 0;
99     vectY2[0] = 0;
100 
101     // Second point: after delay
102     position += _values[DELAY];
103     vectX1[1] = position;
104     vectY1[1] = 0;
105     vectX2[1] = position;
106     vectY2[1] = 0;
107 
108     // Third point: after attack
109     position += _values[ATTACK];
110     position2 = position;
111     vectX1[2] = position;
112     vectY1[2] = 1;
113     vectX2[2] = position;
114     vectY2[2] = 1;
115 
116     // Fourth point: after hold
117     position += getValueForKey(_values[HOLD], _values[KEYNUM_TO_HOLD], _values[KEY_MIN]);
118     position2 += getValueForKey(_values[HOLD], _values[KEYNUM_TO_HOLD], _values[KEY_MAX]);
119     vectX1[3] = position;
120     vectY1[3] = 1;
121     vectX2[3] = position2;
122     vectY2[3] = 1;
123 
124     // Fifth point: after decay
125     position += getValueForKey(_values[DECAY], _values[KEYNUM_TO_DECAY], _values[KEY_MIN]);
126     position2 += getValueForKey(_values[DECAY], _values[KEYNUM_TO_DECAY], _values[KEY_MAX]);
127     vectX1[4] = position;
128     vectY1[4] = _values[SUSTAIN];
129     vectX2[4] = position2;
130     vectY2[4] = _values[SUSTAIN];
131 
132     // Sixth point: after sustain
133     position = triggeredKeyDuration;
134     vectX1[5] = position;
135     vectY1[5] = _values[SUSTAIN];
136     vectX2[5] = position;
137     vectY2[5] = _values[SUSTAIN];
138 
139     // Seventh point: after release
140     position += _values[RELEASE];
141     vectX1[6] = position;
142     vectY1[6] = 0;
143     vectX2[6] = position;
144     vectY2[6] = 0;
145 
146     // Heighth point: end
147     position = triggeredKeyDuration + releasedKeyDuration;
148     vectX1[7] = position;
149     vectY1[7] = 0;
150     vectX2[7] = position;
151     vectY2[7] = 0;
152 
153     _graph1->setData(vectX1, vectY1, true);
154     _graph2->setData(vectX2, vectY2, true);
155 }
156 
getValueForKey(double value,double keyModifier,int key)157 double Envelop::getValueForKey(double value, double keyModifier, int key)
158 {
159     return value * pow(2, (double)(keyModifier / 100) * ((60. - (double)key) / 12));
160 }
161