Script for quick volume automation dip
hi there, does anyone know how to create a quick 3 point 4db dip like the situation shown in the picture? Maybe the script create two points of automation with 6 frames and dip 4db in the middle? Please help, thank you!

Linked from:
- samuel henriques @samuel_henriques
Hello Shiheng Xu,
Select from the start to the position you want the dip to be, then run the script. To set the volume change the number in the end of the script in this linedipBydB(-4)
.
Here's a video with a demo.
https://youtu.be/_Xsu2L4q7-gHere you go, I hope this is it:
const writeToCurrent = () => sf.ui.proTools.menuClick({ menuPath: ["Edit", "Automation", "Write to Current"] }); const doubleEdit = () => sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Double Edit"] }); const halveEdit = () => sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Halve Edit"] }); const getSelection = () => sf.ui.proTools.selectionGetInSamples(); const clearAutomation = () => sf.ui.proTools.menuClick({ menuPath: ["Edit", "Clear Special", "All Automation"] }); const arrowUp = () => sf.keyboard.press({ keys: "up", fast: true }); /** * @param {"blocks"|"playlists"|"analysis"|"warp"|"waveform"|"volume"|"volume trim"|"mute"|"pan"} view */ function setAutomationView(view) { // view popup const viewSelector = sf.ui.proTools.selectedTrack.popupButtons.whoseTitle.is('Track View selector').first; const viewSelectorValue = viewSelector.value.invalidate().value; if (viewSelectorValue !== view) { viewSelector.popupMenuSelect({ menuPath: [view] }); }; return viewSelectorValue; }; /** * @param {number} volume */ function setFaderVolume(volume) { const volumeTextEl = sf.ui.proTools.mainTrackOutputWindow.textFields.first const currentVolume = volumeTextEl.value.invalidate().value const newVolume = +currentVolume + volume sf.ui.proTools.mainTrackOutputWindow.textFields.first.elementSetTextFieldWithAreaValue({ value: newVolume.toString(), useMouseKeyboard: true }); sf.keyboard.press({ keys: "return" }) }; /** * @param {number} [volume] * @param {'send a'|'send b'|'send c'|'send d'|'send e'|'send f'|'send g'|'send h'|'send i'|'send j'|'main out'} outputViewSelector */ function openOutputWindow(outputViewSelector, volume) { const outputViewSelectorBtn = sf.ui.proTools.mainTrackOutputWindow.buttons.whoseTitle.is("Output View selector").first; const selectedTrackName = sf.ui.proTools.selectedTrackNames[0]; const outWinTrackNameBtn = sf.ui.proTools.mainTrackOutputWindow.buttons.first; if (!outputViewSelectorBtn.exists) { sf.ui.proTools.selectedTrack.trackOutputToggleShow(); sf.ui.proTools.invalidate() } const outputViewSelectorValue = outputViewSelectorBtn.value.invalidate().value; const outWinTrackName = outWinTrackNameBtn.value.invalidate().value; // Set Output win to selected track if (selectedTrackName != outWinTrackName) { outWinTrackNameBtn.popupMenuSelect({ menuSelector: items => items.filter(item => item.element.title.value.startsWith(selectedTrackName))[0] }) }; // Set Output win to outputViewSelector if (!outputViewSelectorValue.startsWith(outputViewSelector)) { outputViewSelectorBtn.popupMenuSelect({ menuSelector: items => items.filter(item => item.element.title.value.startsWith(outputViewSelector))[0] }) }; if (volume) { setFaderVolume(volume) }; sf.ui.proTools.selectedTrack.trackOutputToggleShow(); }; /** * @param {number} dB */ function dipBydB(dB) { const userView = setAutomationView("volume"); const { selectionStart, selectionEnd } = getSelection(); doubleEdit(); writeToCurrent(); halveEdit(); arrowUp(); //Set fader to volume openOutputWindow("main out", dB); writeToCurrent(); sf.ui.proTools.selectionSetInSamples({ selectionStart }); clearAutomation(); // Set original view if not volume // @ts-ignore setAutomationView(userView) }; dipBydB(-4);
- Ddanielkassulke @danielkassulke
Hi @samuel_henriques , once again, this is amazing. This is very very close to something I've been searching for already, which is just a simpler 4-point edit where the selection is uniformly turned down by the same amount within the selection. I tried to tweak it to ignore the halve/double edit selection which I assume is just to create a breakpoint in the automation halfway through, but not it just creates a fadeout. Do you have any suggestions for where to adapt the script?
samuel henriques @samuel_henriques
There was a pretty stupid mistake on the first version, where instead of dipping by... it was setting at that value. I fixed it.
Here's a 4 point version. Frames for fade in/out must be calculated in samples, so frame length depends on session format. It's set as 1920 = 1 frame@48k@25fps. you can change this on line 75.
const writeToCurrent = () => sf.ui.proTools.menuClick({ menuPath: ["Edit", "Automation", "Write to Current"] }); const getSelection = () => sf.ui.proTools.selectionGetInSamples(); const cut = () => sf.ui.proTools.menuClick({ menuPath: ["Edit", "Cut"] }); /** * @param {"blocks"|"playlists"|"analysis"|"warp"|"waveform"|"volume"|"volume trim"|"mute"|"pan"} view */ function setAutomationView(view) { // view popup const viewSelector = sf.ui.proTools.selectedTrack.popupButtons.whoseTitle.is('Track View selector').first; const viewSelectorValue = viewSelector.value.invalidate().value; if (viewSelectorValue !== view) { viewSelector.popupMenuSelect({ menuPath: [view] }); }; return viewSelectorValue; }; /** * @param {number} volume */ function setFaderVolume(volume) { const volumeTextEl = sf.ui.proTools.mainTrackOutputWindow.textFields.first const currentVolume = volumeTextEl.value.invalidate().value const newVolume = +currentVolume + volume sf.ui.proTools.mainTrackOutputWindow.textFields.first.elementSetTextFieldWithAreaValue({ value: newVolume.toString(), useMouseKeyboard: true }); sf.keyboard.press({ keys: "return" }) }; /** * @param {number} [volume] * @param {'send a'|'send b'|'send c'|'send d'|'send e'|'send f'|'send g'|'send h'|'send i'|'send j'|'main out'} outputViewSelector */ function openOutputWindow(outputViewSelector, volume) { const outputViewSelectorBtn = sf.ui.proTools.mainTrackOutputWindow.buttons.whoseTitle.is("Output View selector").first; const selectedTrackName = sf.ui.proTools.selectedTrackNames[0]; const outWinTrackNameBtn = sf.ui.proTools.mainTrackOutputWindow.buttons.first; if (!outputViewSelectorBtn.exists) { sf.ui.proTools.selectedTrack.trackOutputToggleShow(); sf.ui.proTools.invalidate() } const outputViewSelectorValue = outputViewSelectorBtn.value.invalidate().value; const outWinTrackName = outWinTrackNameBtn.value.invalidate().value; // Set Output win to selected track if (selectedTrackName != outWinTrackName) { outWinTrackNameBtn.popupMenuSelect({ menuSelector: items => items.filter(item => item.element.title.value.startsWith(selectedTrackName))[0] }) }; // Set Output win to outputViewSelector if (!outputViewSelectorValue.startsWith(outputViewSelector)) { outputViewSelectorBtn.popupMenuSelect({ menuSelector: items => items.filter(item => item.element.title.value.startsWith(outputViewSelector))[0] }) }; if (volume) { setFaderVolume(volume) }; sf.ui.proTools.selectedTrack.trackOutputToggleShow(); }; /** * @param {object} obj * @param {number} obj.dB * @param {number} [obj.fadeLengthFrames] */ function dipBydB({ dB, fadeLengthFrames = 1 }) { const fadeLengthInSamples = (frames) => frames * 1920; //1920 = 1 frame@48k@25fps //Set Volume view and get original view for later const userView = setAutomationView("volume"); //Get user selection const { selectionStart, selectionEnd, selectionLength } = getSelection(); //If the original selecton is less than the fade length, probably user did't set a selection so return if (selectionLength < fadeLengthInSamples(fadeLengthFrames)) { alert("Please make a selection."); return; } try { writeToCurrent(); //Set fader to volume openOutputWindow("main out", dB); //Write start end automation break points writeToCurrent(); //Start fade sf.ui.proTools.selectionSetInSamples({ selectionStart, selectionEnd: +selectionStart + fadeLengthInSamples(fadeLengthFrames) }); cut(); //End fade sf.ui.proTools.selectionSetInSamples({ selectionStart: +selectionEnd - fadeLengthInSamples(fadeLengthFrames), selectionEnd }); cut(); } catch (err) { } finally { //Set original selection sf.ui.proTools.selectionSetInSamples({ selectionStart, selectionEnd }) // Set original view if not volume // @ts-ignore setAutomationView(userView) }; }; dipBydB({ dB: -4, fadeLengthFrames: 4 });
- Ddanielkassulke @danielkassulke
@samuel_henriques you are an absolute treasure! I am so grateful for your time and generosity.
- In reply tosamuel_henriques⬆:
Curtis Macdonald @Curtis_Macdonald
this is very cool!
Q: how can I make a similar dip using clip gain instead of volume automation?- OOwen Granich-Young @Owen_Granich_Young
Probably just tack a 'coalesce volume automation to clip gain' onto the end of the script or as a macro afterwards is the easiest way.
- In reply tosamuel_henriques⬆:
Anthony Bauman @Anthony_Bauman
What would need changed to set the fade length in Min:Secs instead of Frames?
samuel henriques @samuel_henriques
Hello Anthony.
The script actually sets samples, that's the best way.
So you just need to change the conversion from frames/samples to ms/samplesin this line:
const fadeLengthInSamples = (frames) => frames * 1920; //1920 = 1 frame@48k@25fps
change to:
const fadeLengthInSamples = (ms) => ms * 48; //48 samples = 1 Millisecond
48 if you are at a 48k. If you need more min:sec precision, we ned to change the script and add more actions.
Then at the end, If you want 1/2 sec, for example
dipBydB({ dB: -4, fadeLengthFrames: 500 })
Let me know if this is it.
Anthony Bauman @Anthony_Bauman
That worked perfectly, thank you so much!