This is a script I started work on but never finished. It uses the sliders like you wanted, but has a very basic randomizer which may not produce very nice results (linear distribution rather than gaussian distribution like hataori’s).
Actual ADT would have a sort of “drifting” behavior, for example if the base offset were -20ms it might slowly drift between -12ms and -28ms, but it would never go directly from one end of that range to the other like a randomizer would (regardless of the distribution model used). This is the main part that I never got around to implementing (ignoring that actual ADT drift would happen gradually rather than note-by-note).
I’ll paste the in-progress version of the script here, perhaps you can use some combination of the two:
/** ADTOffset.js
* Offsets the selected notes by a desired amount, ± a random variation.
* This is a simplified version of ADT (artificial double tracking) using each note's offset setting.
*/
var SCRIPT_TITLE = "ADT Offset";
var DEFAULT_BASE_OFFSET = 0;
var DEFAULT_VARIATION = 0;
function getClientInfo() {
return {
"name": SV.T(SCRIPT_TITLE),
"category": "Claire's Scripts - Automation",
"author": "claire",
"versionNumber": 1,
"minEditorVersion": 65537
}
}
var form = {
title: SV.T(SCRIPT_TITLE),
buttons: 'OkCancel',
message: 'Notes will be offset by the first number ± a random number between zero and the second number.',
widgets: [
{
name: 'baseOffset',
type: 'Slider',
label: SV.T('Base Offset'),
format: '%1.0fms',
default: DEFAULT_BASE_OFFSET,
minValue: -100,
maxValue: 100,
interval: 1
},
{
name: 'variation',
type: 'Slider',
label: SV.T('Variation'),
format: '%1.0fms',
default: DEFAULT_VARIATION,
minValue: 0,
maxValue: 100,
interval: 1
},
{
name: 'offsetPitch',
type: 'CheckBox',
text: 'Apply offset to pitch transition',
default: true
},
{
name: 'offsetPhonemes',
type: 'CheckBox',
text: 'Apply offset to phoneme timing',
default: true
},
{
name: 'keepCurrent',
type: 'CheckBox',
text: 'Add offset to existing value instead of zero',
default: false
}
]
};
function randomVariation(variation) {
return Math.floor(Math.random() * (variation - (-variation) + 1)) + (-variation);
}
function applyOffset(args) {
var baseOffset = args.baseOffset;
var variation = args.variation;
var selection = SV.getMainEditor().getSelection();
var selectedNotes = selection.getSelectedNotes();
if (selectedNotes.length == 0) {
SV.showMessageBox(SV.T(SCRIPT_TITLE), SV.T('No notes selected.'));
return;
}
for (var i = 0; i < selectedNotes.length; i++) {
var note = selectedNotes[i];
offset = (baseOffset + randomVariation(variation)) / 1000;
if (args.offsetPitch) {
var pitchOffset = offset;
if (args.keepCurrent) {
pitchOffset += note.getAttributes().tF0Offset || 0;
}
note.setAttributes({
tF0Offset: pitchOffset
});
}
if (args.offsetPhonemes) {
var phonemeOffset = offset;
if (args.keepCurrent) {
phonemeOffset += note.getAttributes().tNoteOffset || 0;
}
note.setAttributes({
tNoteOffset: phonemeOffset
});
}
}
}
function main() {
var result = SV.showCustomDialog(form);
if (result.status) {
applyOffset(result.answers);
}
SV.finish();
}