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