Hello,
Something I do in my workflow often in Izotope RX editor is return to the "initial state" in the history window to copy something like a breath, consonant, etc. and then return to the most recent history version, line up the selection and paste it in. I find this helpful for dialogue editing if I have to do heavy noise reduction. Would it be possible to create a script with soundflow where you just make a selection and it immediately converts it to the initial state? This would be so incredibly time saving for me. Thanks!
- Dustin Harris @Dustin_Harris
This is a great idea and should be possible… I’ll try to see if I can make this script this weekend!
- In reply toNoah_Kowalski7⬆:Dustin Harris @Dustin_Harris
Couldn't help myself so I did this between sessions.
it will only work on rectangular selections as lasso selections cannot be easily recreated. Try it out and let me know how it goes:
function getSelection() { let mainWindow = 'RX' + sf.ui.izotope.activeBundleID.slice(-1) + " Main Window"; let editorSelectionPanel = sf.ui.izotope.mainWindow.groups.whoseDescription.is(mainWindow).first.groups.whoseDescription.is('App Footer').first.groups.whoseDescription.is('Editor Selection Panel').first let selection = { startTime: editorSelectionPanel.buttons.whoseDescription.is('Selection start time').first.value.value, endTime: editorSelectionPanel.buttons.whoseDescription.is('Selection end time').first.value.value, lowFrequency: editorSelectionPanel.buttons.whoseDescription.is('Selection starting frequency').first.value.value, highFrequency: editorSelectionPanel.buttons.whoseDescription.is('Selection ending frequency').first.value.value, } return selection } /** * @param {{ startTime: string; endTime: string; lowFrequency: string; highFrequency: string; }} selection */ function setSelection(selection) { let { startTime, endTime, lowFrequency, highFrequency } = selection; let mainWindow = 'RX' + sf.ui.izotope.activeBundleID.slice(-1) + " Main Window"; let editorSelectionPanel = sf.ui.izotope.mainWindow.groups.whoseDescription.is(mainWindow).first.groups.whoseDescription.is('App Footer').first.groups.whoseDescription.is('Editor Selection Panel').first editorSelectionPanel.buttons.whoseDescription.is('Selection start time').first.elementSetTextAreaValue({ value: startTime, }); editorSelectionPanel.buttons.whoseDescription.is('Selection end time').first.elementSetTextAreaValue({ value: endTime, }); editorSelectionPanel.buttons.whoseDescription.is('Selection starting frequency').first.elementSetTextAreaValue({ value: lowFrequency, }); editorSelectionPanel.buttons.whoseDescription.is('Selection ending frequency').first.elementSetTextAreaValue({ value: highFrequency, }); } function main() { sf.ui.izotope.appActivate(); let mainWindow = 'RX' + sf.ui.izotope.activeBundleID.slice(-1) + " Main Window"; let undoHistoryItems = sf.ui.izotope.mainWindow.groups.whoseDescription.is(mainWindow).first.groups.whoseDescription.is("Undo Panel").invalidate().first.radioButtons let selection = getSelection(); let currentUndoHistoryIndex = undoHistoryItems.map((button, index) => { if (button.isCheckBoxChecked) return index }).filter(button => button)[0] undoHistoryItems[0].elementClick() setSelection(selection); sf.ui.izotope.menuClick({ menuPath: ["Edit", "Copy"] }) undoHistoryItems[currentUndoHistoryIndex].elementClick() setSelection(selection); sf.ui.izotope.menuClick({ menuPath: ["Edit", "Paste"] }) } main();
- NNoah Kowalski @Noah_Kowalski7
This is amazing! Thank you man. Have been wanting this for so long.
Dustin Harris @Dustin_Harris
It’s a sweet idea! I’ve never considered pasting sections from different processing states. I use a similar script for copying/pasting across channels (like the bottom end of the boom onto the lav channel, etc)
- In reply toNoah_Kowalski7⬆:
Dustin Harris @Dustin_Harris
bonus content: this one gets copies the selection from the undo history of the previous step to the current one.
function getSelection() { let mainWindow = 'RX' + sf.ui.izotope.activeBundleID.slice(-1) + " Main Window"; let editorSelectionPanel = sf.ui.izotope.mainWindow.groups.whoseDescription.is(mainWindow).first.groups.whoseDescription.is('App Footer').first.groups.whoseDescription.is('Editor Selection Panel').first let selection = { startTime: editorSelectionPanel.buttons.whoseDescription.is('Selection start time').first.value.value, endTime: editorSelectionPanel.buttons.whoseDescription.is('Selection end time').first.value.value, lowFrequency: editorSelectionPanel.buttons.whoseDescription.is('Selection starting frequency').first.value.value, highFrequency: editorSelectionPanel.buttons.whoseDescription.is('Selection ending frequency').first.value.value, } return selection } /** * @param {{ startTime: string; endTime: string; lowFrequency: string; highFrequency: string; }} selection */ function setSelection(selection) { let { startTime, endTime, lowFrequency, highFrequency } = selection; let mainWindow = 'RX' + sf.ui.izotope.activeBundleID.slice(-1) + " Main Window"; let editorSelectionPanel = sf.ui.izotope.mainWindow.groups.whoseDescription.is(mainWindow).first.groups.whoseDescription.is('App Footer').first.groups.whoseDescription.is('Editor Selection Panel').first editorSelectionPanel.buttons.whoseDescription.is('Selection start time').first.elementSetTextAreaValue({ value: startTime, }); editorSelectionPanel.buttons.whoseDescription.is('Selection end time').first.elementSetTextAreaValue({ value: endTime, }); editorSelectionPanel.buttons.whoseDescription.is('Selection starting frequency').first.elementSetTextAreaValue({ value: lowFrequency, }); editorSelectionPanel.buttons.whoseDescription.is('Selection ending frequency').first.elementSetTextAreaValue({ value: highFrequency, }); } function clickTheTimeFreqTool() { let rxMainWindowVersion = 'RX' + sf.ui.izotope.activeBundleID.slice(-1) + " Main Window"; let mainWindow = sf.ui.izotope.mainWindow.groups.whoseDescription.is(rxMainWindowVersion).first; let editorToolBarPanel = mainWindow.groups.whoseDescription.is("EditorToolbarPanel").first; let timeFreqButton = editorToolBarPanel.buttons.whoseDescription.is("Editor Toolbar Button 5").first; timeFreqButton.elementClick(); } function main() { sf.ui.izotope.appActivate(); let mainWindow = 'RX' + sf.ui.izotope.activeBundleID.slice(-1) + " Main Window"; let mousePosition = sf.mouse.getPosition().position; let undoHistoryItems = sf.ui.izotope.mainWindow.groups.whoseDescription.is(mainWindow).first.groups.whoseDescription.is("Undo Panel").invalidate().first.radioButtons let selection = getSelection(); let currentUndoHistoryIndex = undoHistoryItems.map((button, index) => { if (button.isCheckBoxChecked) return index }).filter(button => button)[0]; undoHistoryItems[currentUndoHistoryIndex - 1].elementClick() setSelection(selection); sf.ui.izotope.menuClick({ menuPath: ["Edit", "Copy"] }) undoHistoryItems[currentUndoHistoryIndex].elementClick() setSelection(selection); sf.ui.izotope.menuClick({ menuPath: ["Edit", "Paste"] }) //remove keyboard focus from the history panel clickTheTimeFreqTool(); sf.mouse.setPosition({ position: mousePosition }) } main();
- KIn reply toNoah_Kowalski7⬆:Karel Dewaele @Karel_Dewaele
Hi,
I really love this script but with my upgrade to RX10 it stopped working.
I'm new to scripting so I was wandering if somebody could help me out getting this script back to work.
I'm getting this error:20.09.2022 10:37:01.73 [Backend]: #StreamDeck: KeyDown (2,4) -> Selection initial state
20.09.2022 10:37:01.73 [Backend]: >> Command: Selection initial state [user:cl4a10n6q001kok10kqkpkaum:cl6oz5e970000iv10he81m7lq]
Checking for running apps with bundle 'com.izotope.RXPro'20.09.2022 10:37:01.74 [Backend]: NSArray.ArrayFromHandle count = 1
20.09.2022 10:37:01.76 [Backend]: !! Command Error: Selection initial state [user:cl4a10n6q001kok10kqkpkaum:cl6oz5e970000iv10he81m7lq]:
Couldn't locate AxElementArrayIndexedItem (Selection initial state: Line 7)<< Command: Selection initial state [user:cl4a10n6q001kok10kqkpkaum:cl6oz5e970000iv10he81m7lq]
20.09.2022 10:37:17.64 [Backend]: [SF_FIREBASE_WS]: Sending keep-alive
A bit of help would be great.
Thanks,
KarelDustin Harris @Dustin_Harris
Here's my updated script for 'copying from initial state', let me know how it works for you!
/** * @return {{ rxApp: AxIzotope | AxRefApplication, rxVersion: string, rxMainWindowName: string, rxMenuName: string}} */ function getRXVersionInfo() { if (!sf.ui.izotope.exists) throw `izotope RX isn't open`; /* for use with early betas as ternary operator */ const rxApp = sf.ui.izotope; // || or another version const rxVersion = (rxApp.activeBundleID == 'com.izotope.RXPro') ? "PRO" : rxApp.activeBundleID.slice(-1); const rxMainWindowName = `RX${rxVersion} Main Window`; const rxMenuName = (rxVersion == "PRO") ? `iZotope RX 10` : `iZotope RX ${rxVersion}`; return { rxApp, rxVersion, rxMainWindowName, rxMenuName } } const { rxApp, rxMainWindowName } = getRXVersionInfo(); const editorSelectionPanel = rxApp.mainWindow.groups.whoseDescription.is(rxMainWindowName).first.groups.whoseDescription.is("App Footer").first.groups.whoseDescription.is("Editor Selection Panel").first; /** * @param {{"Selection start time": string, "Selection end time": string, "Selection starting frequency": string, "Selection ending frequency": string}} selection */ function setRXSelection(selection) { for (let selectionType in selection) { editorSelectionPanel.buttons.whoseDescription.is(selectionType).first.elementSetTextAreaValue({ value: selection[selectionType], }); } } function getRXSelection() { const getPanelElement = (/** @type {string} */ element) => editorSelectionPanel.buttons.whoseDescription.is(element).first.value.invalidate().value; const selection = { "Selection start time": getPanelElement('Selection start time'), "Selection end time": getPanelElement('Selection end time'), "Selection starting frequency": getPanelElement('Selection starting frequency'), "Selection ending frequency": getPanelElement('Selection ending frequency'), }; return selection; } function clickTheTimeFreqTool() { const mainWindow = rxApp.mainWindow.groups.whoseDescription.is(rxMainWindowName).first; const editorToolBarPanel = mainWindow.groups.whoseDescription.is("EditorToolbarPanel").first; const timeFreqButton = editorToolBarPanel.buttons.whoseDescription.is("Editor Toolbar Button 5").first; timeFreqButton.elementClick(); } /* Get Main Counter so we can change it back when we're done */ function getCurrentTimeFormat() { let menuItems = rxApp.getMenuItem('View', 'Time Format').children.first.children.allItems for (let i = 0; i < menuItems.length; i++) { let currentMenuItem = menuItems[i] if (currentMenuItem.isMenuChecked) { return currentMenuItem.title.value } } } const setTimeFormatToSamples = () => { rxApp.menuClick({menuPath: ["View", "Time Format", "Samples"]}); } function main() { rxApp.appActivate(); let undoHistoryItems = rxApp.mainWindow.groups.whoseDescription.is(rxMainWindowName).first.groups.whoseDescription.is("Undo Panel").invalidate().first.radioButtons; const currentTimeFormat = getCurrentTimeFormat(); setTimeFormatToSamples(); const selection = getRXSelection(); let currentUndoHistoryIndex = undoHistoryItems.map((button, index) => { if (button.isCheckBoxChecked) return index }).filter(button => button)[0]; undoHistoryItems[0].elementClick(); setRXSelection(selection); rxApp.menuClick({ menuPath: ["Edit", "Copy"] }); undoHistoryItems[currentUndoHistoryIndex].elementClick(); setRXSelection(selection); rxApp.menuClick({ menuPath: ["Edit", "Paste"] }); rxApp.menuClick({ menuPath: ["View", "Time Format", currentTimeFormat], }); /* remove keyboard focus from the history panel */ clickTheTimeFreqTool(); } main();
- NIn reply toNoah_Kowalski7⬆:Noah Kowalski @Noah_Kowalski3
@Dustin_Harris Hey there! I have returned after being a way for a while. Newer versions of RX have a function where you can click the star symbol in the history, or you can also assign a keyboard shortcut to restore something to initial state. I feel that there is probably a more elegant way to do this now instead of going back to the original selection and copying/pasting. What do you think?