-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathauto_loudness_by_vibrato.js
220 lines (197 loc) · 7.94 KB
/
auto_loudness_by_vibrato.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
var SCRIPT_TITLE = "auto loudness by vibrato";
var debug_count = 0;
function getClientInfo() {
return {
"name": SV.T(SCRIPT_TITLE),
"category": "tool",
"author": "Rin von Rheinhauss",
"versionNumber": 2,
"minEditorVersion": 66049
};
}
function getTranslations(langCode) {
if (langCode == "zh-cn") {
return [
// getClientInfo()
["auto loudness by vibrato", "根据颤音设置响度"],
// warning_save()
["auto loudness by vibrato: WARNING", "根据颤音设置响度:警告"],
["Please save or backup the project file in advance!", "请预先保存或备份工程文件!"],
["This script may override your own loudness parameters!", "本脚本可能会覆盖您的响度参数!"],
["Press OK to proceed, Cancel to cancel.", "点击确认以继续,或取消以取消。"],
// alert_no_note_selected()
["No note is selected. This script will not execute.", "没有选择音符,因此脚本并不会执行。"],
// main()
["Notice", "注意"],
["There is some point that over 12dB which involves in something like 'Clipping distortion' in parameter panel.",
"某些参数点因为计算时超过了上限12dB,因此参数面板上会有类似削波失真的情况"],
["Strength(dB)", "强度(dB)"],
["Points per quarter", "每四分音符 参数点的数量"],
["mode", "模式"],
["overwrite", "覆盖"],
["add", "叠加"],
["simplify the curve", "简化参数曲线"],
[" notes edited.", " 个音符已修改。"]
];
}
return [];
}
function warning_save() {
var result = SV.showOkCancelBox(
SV.T("auto loudness by vibrato: WARNING"),
SV.T("This script may override your own loudness parameters!") + "\n"
+ SV.T("Please save or backup the project file in advance!") + "\n"
+ SV.T("Press OK to proceed, Cancel to cancel.")
);
return result;
}
function alert_no_note_selected() {
SV.showMessageBox(
SV.T("auto loudness by vibrato: WARNING"),
SV.T("No note is selected. This script will not execute.")
);
SV.finish();
}
function modify_loudness(option) {
var co_old = 1, co_new = 0;
var flagOverPeakWarning = false;
switch (option.mode) { // SV.T("add"), SV.T("overwrite")
case 0:
co_old = 1;
co_new = 1;
break;
case 1:
co_old = 0;
co_new = 1;
break;
default:
co_old = 1;
co_new = 0;
break;
}
var selection = SV.getMainEditor().getSelection();
var selectedNotes = selection.getSelectedNotes();
if (selectedNotes.length == 0)
alert_no_note_selected();
selectedNotes.sort(function (noteA, noteB) {
return noteA.getOnset() - noteB.getOnset();
});
var num_notes = selectedNotes.length;
var step = Math.floor(SV.QUARTER / option.density);
var loudness = SV.getMainEditor().getCurrentGroup().getTarget().getParameter("loudness");
var loudnesscopy = loudness.clone();
var vibratoEnv = SV.getMainEditor().getCurrentGroup().getTarget().getParameter("vibratoEnv");
var attrDefault = SV.getMainEditor().getCurrentGroup().getVoice();
if (attrDefault.tF0VbrStart === undefined) attrDefault.tF0VbrStart = 0.250;
if (attrDefault.tF0VbrLeft === undefined) attrDefault.tF0VbrLeft = 0.20;
if (attrDefault.tF0VbrRight === undefined) attrDefault.tF0VbrRight = 0.20;
if (attrDefault.dF0Vbr === undefined) attrDefault.dF0Vbr = 1;
if (attrDefault.fF0Vbr === undefined) attrDefault.fF0Vbr = 5.50;
for (var i = 0; i < num_notes; i++) {
var n = {
"attr": selectedNotes[i].getAttributes(),
"start": selectedNotes[i].getOnset(),
"end": selectedNotes[i].getEnd(),
"duration": selectedNotes[i].getDuration(),
};
loudness.remove(n.start, n.end);
if (isNaN(n.attr.tF0VbrStart)) n.attr.tF0VbrStart = attrDefault.tF0VbrStart;
if (isNaN(n.attr.tF0VbrLeft)) n.attr.tF0VbrLeft = attrDefault.tF0VbrLeft;
if (isNaN(n.attr.tF0VbrRight)) n.attr.tF0VbrRight = attrDefault.tF0VbrRight;
if (isNaN(n.attr.dF0Vbr)) n.attr.dF0Vbr = attrDefault.dF0Vbr;
if (isNaN(n.attr.pF0Vbr)) n.attr.pF0Vbr = 0;
if (isNaN(n.attr.fF0Vbr)) n.attr.fF0Vbr = attrDefault.fF0Vbr;
var project = SV.getProject();
var tAxis = project.getTimeAxis();
var tempomark = tAxis.getTempoMarkAt(n.start);
var bpm = tempomark.bpm;
var pb = [
n.start,
n.start + SV.seconds2Blick(n.attr.tF0VbrStart, bpm),
n.start + SV.seconds2Blick(n.attr.tF0VbrStart + n.attr.tF0VbrLeft, bpm),
n.end - SV.seconds2Blick(n.attr.tF0VbrRight, bpm),
n.end
];
for (var b = pb[0]; b <= pb[4]; b += step) {
s = SV.blick2Seconds(b - pb[0], bpm);
var t = loudnesscopy.get(b);
var lScale_1 = vibratoEnv.get(b); // 颤音包络 vibratoEnv
var lScale_2 = 0; // 音符属性 note properties
if (b >= pb[0] && b <= pb[1]) lScale_2 = 0;
else if (b > pb[1] && b <= pb[2]) lScale_2 = (b - pb[1]) / (pb[2] - pb[1]);
else if (b > pb[2] && b <= pb[3]) lScale_2 = 1;
else if (b > pb[3] && b <= pb[4]) lScale_2 = -(b - pb[4]) / (pb[4] - pb[3]);
else lScale_2 = 0;
var v = co_old * t + co_new * Math.sin(2 * Math.PI * n.attr.fF0Vbr * (s - n.attr.tF0VbrStart) + n.attr.pF0Vbr)
* lScale_1 * lScale_2 * option.strength;
if (v > 12) { v = 12; flagOverPeakWarning = true; }
loudness.add(b, v);
}
if (option.simp) loudness.simplify(n.start, n.end, 0.001);
}
return {
"flagOverPeakWarning": flagOverPeakWarning,
"num_processed": num_notes
};
}
function main() {
if (warning_save() == false) { SV.finish(); return; };
// custom dialog
var form = {
title: SV.T(SCRIPT_TITLE),
message: "",
buttons: "OkCancel",
widgets: [
{
"name": "strength",
"type": "Slider",
"label": SV.T("Strength(dB)"),
"format": "%1.2f",
"minValue": 0,
"maxValue": 6,
"interval": 0.05,
"default": 1
},
{
"name": "density",
"type": "Slider",
"label": SV.T("Points per quarter"),
"format": "%3.0f",
"minValue": 4,
"maxValue": 256,
"interval": 1,
"default": 32
},
{
"name": "mode", "type": "ComboBox",
"label": SV.T("mode"),
"choices": [SV.T("add"), SV.T("overwrite")],
"default": 0
},
{
"name": "simp", "type": "CheckBox",
"text": SV.T("simplify the curve"),
"default": true
}
]
};
var result = SV.showCustomDialog(form);
if (result.status) {
var option = {
"density": result.answers.density,
"strength": result.answers.strength,
"mode": result.answers.mode,
"simp": result.answers.simp
};
var r = modify_loudness(option);
if (r.flagOverPeakWarning) {
SV.showMessageBox(SCRIPT_TITLE + " ",
SV.T("There is some point that over 12dB which involves in something like 'Clipping distortion' in parameter panel.") + "\n"
+ r.num_processed.toString() + SV.T(" notes edited."));
}
else {
SV.showMessageBox(SCRIPT_TITLE + " ", r.num_processed.toString() + SV.T(" notes edited."));
}
}
SV.finish();
}