1/* 2 * Copyright (c) 2015-2021 Meltytech, LLC 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18import QtQuick 2.12 19import QtQuick.Layouts 1.12 20import QtQuick.Controls 2.12 21import Shotcut.Controls 1.0 as Shotcut 22 23Item { 24 width: 350 25 height: 300 26 Component.onCompleted: { 27 if (filter.isNew) { 28 // Set default parameter values 29 filter.set('0', 0) 30 filter.set('1', 100) 31 filter.set('2', 400) 32 filter.set('3', 0) 33 filter.set('4', 1) 34 filter.set('5', 3.25) 35 filter.set('6', 0) 36 filter.savePreset(preset.parameters) 37 } 38 setControls() 39 timer.start() 40 } 41 42 function setControls() { 43 sliderPeak.value = filter.getDouble('0') * sliderPeak.maximumValue 44 sliderAttack.value = filter.getDouble('1') 45 sliderRelease.value = filter.getDouble('2') 46 sliderThreshold.value = filter.getDouble('3') 47 sliderRatio.value = filter.getDouble('4') 48 sliderRadius.value = filter.getDouble('5') 49 sliderGain.value = filter.getDouble('6') 50 } 51 52 Timer { 53 id: timer 54 interval: 100 55 running: false 56 repeat: true 57 onTriggered: { 58 grGauge.value = filter.getDouble('8[0]') 59 } 60 } 61 62 GridLayout { 63 anchors.fill: parent 64 anchors.margins: 8 65 columns: 3 66 67 Label { 68 text: qsTr('Preset') 69 Layout.alignment: Qt.AlignRight 70 } 71 Shotcut.Preset { 72 id: preset 73 parameters: ['0', '1', '2', '3', '4', '5', '6'] 74 Layout.columnSpan: 2 75 onPresetSelected: setControls() 76 } 77 78 Label { 79 text: qsTr('RMS') 80 Layout.alignment: Qt.AlignRight 81 Shotcut.HoverTip {text: qsTr('The balance between the RMS and peak envelope followers. RMS is generally better for subtle, musical compression and peak is better for heavier, fast compression and percussion.')} 82 } 83 Shotcut.SliderSpinner { 84 id: sliderPeak 85 minimumValue: 0 86 maximumValue: 100 87 decimals: 1 88 label: qsTr('Peak') 89 suffix: ' %' 90 value: filter.getDouble('0') * maximumValue 91 onValueChanged: { 92 filter.set('0', value / maximumValue) 93 } 94 } 95 Shotcut.UndoButton { 96 onClicked: sliderPeak.value = sliderPeak.minimumValue 97 } 98 99 Label { 100 text: qsTr('Attack') 101 Layout.alignment: Qt.AlignRight 102 } 103 Shotcut.SliderSpinner { 104 id: sliderAttack 105 minimumValue: 2 106 maximumValue: 400 107 suffix: ' ms' 108 value: filter.getDouble('1') 109 onValueChanged: { 110 filter.set('1', value) 111 } 112 } 113 Shotcut.UndoButton { 114 onClicked: sliderAttack.value = 100 115 } 116 117 Label { 118 text: qsTr('Release') 119 Layout.alignment: Qt.AlignRight 120 } 121 Shotcut.SliderSpinner { 122 id: sliderRelease 123 minimumValue: 2 124 maximumValue: 800 125 suffix: ' ms' 126 value: filter.getDouble('2') 127 onValueChanged: { 128 filter.set('2', value) 129 } 130 } 131 Shotcut.UndoButton { 132 onClicked: sliderRelease.value = 400 133 } 134 135 Label { 136 text: qsTr('Threshold') 137 Layout.alignment: Qt.AlignRight 138 Shotcut.HoverTip {text: qsTr('The point at which the compressor will start to kick in.')} 139 } 140 Shotcut.SliderSpinner { 141 id: sliderThreshold 142 minimumValue: -30 143 maximumValue: 0 144 decimals: 1 145 suffix: ' dB' 146 value: filter.getDouble('3') 147 onValueChanged: { 148 filter.set('3', value) 149 } 150 } 151 Shotcut.UndoButton { 152 onClicked: sliderThreshold.value = 0 153 } 154 155 Label { 156 text: qsTr('Ratio') 157 Layout.alignment: Qt.AlignRight 158 Shotcut.HoverTip {text: qsTr('The gain reduction ratio used when the signal level exceeds the threshold.')} 159 } 160 Shotcut.SliderSpinner { 161 id: sliderRatio 162 minimumValue: 1 163 maximumValue: 20 164 prefix: ' 1:' 165 value: filter.getDouble('4') 166 onValueChanged: { 167 filter.set('4', value) 168 } 169 } 170 Shotcut.UndoButton { 171 onClicked: sliderRatio.value = 1 172 } 173 174 Label { 175 text: qsTr('Knee radius') 176 Layout.alignment: Qt.AlignRight 177 Shotcut.HoverTip {text: qsTr('The distance from the threshold where the knee curve starts.')} 178 } 179 Shotcut.SliderSpinner { 180 id: sliderRadius 181 minimumValue: 1 182 maximumValue: 10 183 decimals: 1 184 suffix: ' dB' 185 value: filter.getDouble('5') 186 onValueChanged: { 187 filter.set('5', value) 188 } 189 } 190 Shotcut.UndoButton { 191 onClicked: sliderRadius.value = 3.25 192 } 193 194 Label { 195 text: qsTr('Makeup gain') 196 Layout.alignment: Qt.AlignRight 197 Shotcut.HoverTip {text: qsTr('The gain of the makeup input signal.')} 198 } 199 Shotcut.SliderSpinner { 200 id: sliderGain 201 minimumValue: 0 202 maximumValue: 24 203 decimals: 1 204 suffix: ' dB' 205 value: filter.getDouble('6') 206 onValueChanged: { 207 filter.set('6', value) 208 } 209 } 210 Shotcut.UndoButton { 211 onClicked: sliderGain.value = 0 212 } 213 214 Rectangle { 215 Layout.columnSpan: 3 216 Layout.fillWidth: true 217 Layout.minimumHeight: 12 218 color: 'transparent' 219 Rectangle { 220 anchors.verticalCenter: parent.verticalCenter 221 width: parent.width 222 height: 2 223 radius: 2 224 color: activePalette.text 225 } 226 } 227 228 Label { 229 id: grLabel 230 text: qsTr('Gain Reduction') 231 Layout.alignment: Qt.AlignRight | Qt.AlignTop 232 Shotcut.HoverTip {text: qsTr('Status indicator showing the gain reduction applied by the compressor.')} 233 } 234 Shotcut.Gauge { 235 Layout.columnSpan: 2 236 Layout.fillWidth: true 237 id: grGauge 238 from: -24 239 value: 0 240 to: 0 241 orientation: Qt.Horizontal 242 decimals: 0 243 } 244 245 Label { 246 id: link_Text 247 Layout.columnSpan: 3 248 text: qsTr('About dynamic range compression') 249 font.underline: true 250 MouseArea { 251 anchors.fill: parent 252 onClicked: Qt.openUrlExternally('https://en.wikipedia.org/wiki/Dynamic_range_compression') 253 } 254 } 255 256 Item { 257 Layout.fillHeight: true; 258 } 259 } 260} 261