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.Controls 2.12
20import QtQuick.Layouts 1.12
21import Shotcut.Controls 1.0 as Shotcut
22
23Item {
24    width: 350
25    height: 250
26    Component.onCompleted: {
27        filter.blockSignals = true
28        if (filter.isNew) {
29            // Set preset parameter values
30            filter.set('0', 40)
31            filter.set('1', 4)
32            filter.set('2', 0.9)
33            filter.set('3', 0.75)
34            filter.set('4', 0)
35            filter.set('5', -22)
36            filter.set('6', -28)
37            filter.savePreset(preset.parameters, qsTr('Quick fix'))
38
39            filter.set('0', 50)
40            filter.set('1', 1.5)
41            filter.set('2', 0.1)
42            filter.set('3', 0.75)
43            filter.set('4', -1.5)
44            filter.set('5', -10)
45            filter.set('6', -20)
46            filter.savePreset(preset.parameters, qsTr('Small hall'))
47
48            filter.set('0', 40)
49            filter.set('1', 20)
50            filter.set('2', 0.5)
51            filter.set('3', 0.75)
52            filter.set('4', 0)
53            filter.set('5', -10)
54            filter.set('6', -30)
55            filter.savePreset(preset.parameters, qsTr('Large hall'))
56
57            filter.set('0', 6)
58            filter.set('1', 15)
59            filter.set('2', 0.9)
60            filter.set('3', 0.1)
61            filter.set('4', -10)
62            filter.set('5', -10)
63            filter.set('6', -10)
64            filter.savePreset(preset.parameters, qsTr('Sewer'))
65
66            filter.set('0', 6)
67            filter.set('1', 15)
68            filter.set('2', 0.9)
69            filter.set('3', .1)
70            filter.set('4', -10)
71            filter.set('5', -10)
72            filter.set('6', -10)
73            filter.savePreset(preset.parameters, qsTr('Church'))
74
75            // Set default parameter values
76            filter.set('0', 30)
77            filter.set('1', 7.5)
78            filter.set('2', 0.5)
79            filter.set('3', 0.75)
80            filter.set('4', 0)
81            filter.set('5', -10)
82            filter.set('6', -17.5)
83            filter.savePreset(preset.parameters)
84        }
85        filter.blockSignals = false
86        filter.changed()
87        setControls()
88    }
89
90    function setControls() {
91        sliderRoom.value = filter.getDouble('0')
92        sliderTime.value = filter.getDouble('1')
93        sliderDamp.value = filter.getDouble('2') * sliderDamp.maximumValue
94        sliderInput.value = filter.getDouble('3') * sliderInput.maximumValue
95        sliderDry.value = filter.getDouble('4')
96        sliderReflection.value = filter.getDouble('5')
97        sliderTail.value = filter.getDouble('6')
98    }
99
100    GridLayout {
101        anchors.fill: parent
102        anchors.margins: 8
103        columns: 3
104
105        Label {
106            text: qsTr('Preset')
107            Layout.alignment: Qt.AlignRight
108        }
109        Shotcut.Preset {
110            id: preset
111            parameters: ['0', '1', '2', '3', '4', '5', '6']
112            Layout.columnSpan: 2
113            onPresetSelected: setControls()
114        }
115
116        Label {
117            text: qsTr('Room size')
118            Layout.alignment: Qt.AlignRight
119            Shotcut.HoverTip {text: qsTr('The size of the room, in meters. Excessively large, and excessively small values will make it sound a bit unrealistic. Values of around 30 sound good.')}
120        }
121        Shotcut.SliderSpinner {
122            id: sliderRoom
123            minimumValue: 1
124            maximumValue: 300
125            suffix: ' m'
126            value: filter.getDouble('0')
127            onValueChanged: {
128                filter.set('0', value)
129            }
130        }
131        Shotcut.UndoButton {
132            onClicked: sliderRoom.value = 30
133        }
134
135        Label {
136            text: qsTr('Reverb time')
137            Layout.alignment: Qt.AlignRight
138        }
139        Shotcut.SliderSpinner {
140            id: sliderTime
141            minimumValue: .1
142            maximumValue: 30
143            decimals: 1
144            suffix: ' s'
145            value: filter.getDouble('1')
146            onValueChanged: {
147                filter.set('1', value)
148            }
149        }
150        Shotcut.UndoButton {
151            onClicked: sliderTime.value = 7.5
152        }
153
154        Label {
155            text: qsTr('Damping')
156            Layout.alignment: Qt.AlignRight
157            Shotcut.HoverTip {text: qsTr('This controls the high frequency damping (a lowpass filter), values near 1 will make it sound very bright, values near 0 will make it sound very dark.')}
158        }
159        Shotcut.SliderSpinner {
160            id: sliderDamp
161            minimumValue: 0
162            maximumValue: 100
163            decimals: 1
164            suffix: ' %'
165            value: filter.getDouble('2') * maximumValue
166            onValueChanged: {
167                filter.set('2', value / maximumValue)
168            }
169        }
170        Shotcut.UndoButton {
171            onClicked: sliderDamp.value = 0.5 * sliderDamp.maximumValue
172        }
173
174        Label {
175            text: qsTr('Input bandwidth')
176            Layout.alignment: Qt.AlignRight
177            Shotcut.HoverTip {text: qsTr('This is like a damping control for the input, it has a similar effect to the damping control, but is subtly different.')}
178        }
179        Shotcut.SliderSpinner {
180            id: sliderInput
181            minimumValue: 0
182            maximumValue: 100
183            decimals: 1
184            suffix: ' %'
185            value: filter.getDouble('3') * maximumValue
186            onValueChanged: {
187                filter.set('3', value / maximumValue)
188            }
189        }
190        Shotcut.UndoButton {
191            onClicked: sliderInput.value = 0.75 * sliderInput.maximumValue
192        }
193
194        Label {
195            text: qsTr('Dry signal level')
196            Layout.alignment: Qt.AlignRight
197            Shotcut.HoverTip {text: qsTr('The amount of dry signal to be mixed with the reverberated signal.')}
198        }
199        Shotcut.SliderSpinner {
200            id: sliderDry
201            minimumValue: -70
202            maximumValue: 0
203            suffix: ' dB'
204            decimals: 1
205            value: filter.getDouble('4')
206            onValueChanged: {
207                filter.set('4', value)
208            }
209        }
210        Shotcut.UndoButton {
211            onClicked: sliderDry.value = 0
212        }
213
214        Label {
215            text: qsTr('Early reflection level')
216            Layout.alignment: Qt.AlignRight
217            Shotcut.HoverTip {text: qsTr('The distance from the threshold where the knee curve starts.')}
218        }
219        Shotcut.SliderSpinner {
220            id: sliderReflection
221            minimumValue: -70
222            maximumValue: 0
223            suffix: ' dB'
224            value: filter.getDouble('5')
225            onValueChanged: {
226                filter.set('5', value)
227            }
228        }
229
230        Shotcut.UndoButton {
231            onClicked: sliderReflection.value = -10
232        }
233        Label {
234            text: qsTr('Tail level')
235            Layout.alignment: Qt.AlignRight
236            Shotcut.HoverTip {text: qsTr('The quantity of early reflections (scatter reflections directly from the source).')}
237        }
238        Shotcut.SliderSpinner {
239            id: sliderTail
240            minimumValue: -70
241            maximumValue: 0
242            decimals: 1
243            suffix: ' dB'
244            value: filter.getDouble('6')
245            onValueChanged: {
246                filter.set('6', value)
247            }
248        }
249        Shotcut.UndoButton {
250            onClicked: sliderTail.value = -17.5
251        }
252
253        Label {
254            Layout.columnSpan: 3
255            text: qsTr('About reverb')
256            font.underline: true
257            MouseArea {
258                anchors.fill: parent
259                onClicked: Qt.openUrlExternally('https://wiki.audacityteam.org/wiki/GVerb')
260            }
261        }
262
263        Item {
264            Layout.fillHeight: true;
265        }
266    }
267}
268