### Example: Setting Key Colors Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/getKeyProperties.html Demonstrates how to initialize key properties and assign colors to white keys starting from C1. ```APIDOC -- Set and clear colors on the keyboard. -- Initialize variabes. local keys = getKeyProperties() local keyColor = 1 local noteNumber = 36 -- C1 local blackKeys = { [1] = true, [3] = true, [6] = true, [8] = true, [10] = true } -- Assign all 24 colors to the white keys of the keyboard starting from C1. while keyColor <= 24 do -- get step in octave local step = noteNumber % 12 -- use only white keys if not blackKeys[step] then keys[noteNumber] = { color = keyColor } keyColor = keyColor + 1 end noteNumber = noteNumber + 1 end -- Clear the color of the played key. function onNote(event) postEvent(event) if keys[event.note] then keys[event.note].color = nil end end ``` -------------------------------- ### Get Quick Control Assignment Mode Example Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/Quick-Control-Assignment-Modes.html Demonstrates how to retrieve and interpret the quick control assignment mode for a specific assignment. ```APIDOC ## Example: Get QCAssignmentMode ### Description This script retrieves the assignment mode for a given quick control and assignment index, then prints its name. ### Code ```lua layer = this.parent qc = 1 assignment = 1 qcMode = layer:getQCAssignmentMode(qc, assignment) if qcMode == QCAssignmentMode.absolute then qcModeName = "Absolute" elseif qcMode == QCAssignmentMode.relative then qcModeName = "Relative" elseif qcMode == QCAssignmentMode.switch then qcModeName = "Switch" elseif qcMode == QCAssignmentMode.switchRelative then qcModeName = "Switch Relative" end print("Mode of '"..layer.name.."', QC "..qc..", assignment "..assignment..": "..qcModeName..".") ``` ### See also: - addQCAssignment - removeQCAssignment - getNumQCAssignments - getQCAssignmentParamId - getQCAssignmentScope - getQCAssignmentMin - getQCAssignmentMax - getQCAssignmentCurve - getQCAssignmentMode - getQCAssignmentBypass - setQCAssignmentParamId - setQCAssignmentScope - setQCAssignmentMin - setQCAssignmentMax - setQCAssignmentCurve - setQCAssignmentMode - setQCAssignmentBypass ``` -------------------------------- ### Asynchronous Layer Insertion Example Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/insertLayerAsync.html This example demonstrates how to use insertLayerAsync to load and insert a layer asynchronously. It includes setup for clearing existing layers, defining layer presets, and handling the insertion and removal of layers. ```lua __ -- Start with an empty program, remove all existing layers. layers = this.parent:findLayers() if layers then for i, layer in ipairs(layers) do this.parent:removeLayer(layer) end end -- Table with layer presets from Skylab. layerPresets = { { name = "Ambient Pad 01", path = "vstsound://EB86867EFF8E44FEA8FE366F676E25BE/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 01.vstpreset" }, { name = "Ambient Pad 02", path = "vstsound://EB86867EFF8E44FEA8FE366F676E25BE/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 02.vstpreset" }, { name = "Ambient Pad 03", path = "vstsound://EB86867EFF8E44FEA8FE366F676E25BE/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 03.vstpreset" }, { name = "Ambient Pad 04", path = "vstsound://EB86867EFF8E44FEA8FE366F676E25BE/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 04.vstpreset" }, } -- Create a table with the preset names. function getPresetNames() presetNames = {} for i, preset in ipairs(layerPresets) do presetNames[i] = preset.name end end getPresetNames() -- Remove the old layer after the new one was added. function removeOldLayer(progressInfo) local newPreset = progressInfo.root if oldPreset then this.parent:removeLayer(oldPreset) print(oldPreset.name.." removed.") end oldPreset = newPreset end -- Insert the preset in a separate thread. function insertNewLayer(progressInfo) if progressInfo.root then this.parent:insertLayerAsync(progressInfo.root, 1, removeOldLayer) print("Inserting "..progressInfo.root.name.."...") end end -- Load the preset in a separate thread. function onSelectPresetChanged(layerPreset) loadPresetAsync(layerPreset.path, insertNewLayer) print("Loading "..layerPreset.name.."...") end -- Define a parameter for selecting the preset to be loaded. defineParameter("SelectPreset", "Select Preset", 1, presetNames, function() onSelectPresetChanged(layerPresets[SelectPreset]) end) ``` -------------------------------- ### Example Script with onSave(), onLoad(), and onNote() Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/onSave.html This comprehensive example demonstrates how to use onSave() to store data, onLoad() to restore it, and onNote() to manage and display the last three notes played. The script maintains a 'lastNotes' table, ensuring it never exceeds three entries, and provides utility functions for printing note information. ```lua -- Print the last three notes when calling onNote, onSave or onLoad. -- The last three notes are remembered even after restoring the program. local lastNotes = {} function printLastNotes(callbackName) print("Last three notes when calling "..callbackName..":") for i = 1, 3 do if lastNotes[i] then print(i..":", "Note#:", lastNotes[i].noteNumber,", Velocity:", lastNotes[i].velocity) else print(i..":", "Note#: ---", "Velocity: ---") end end print() end -- Play some notes to fill the table. function onNote(event) postEvent(event) table.insert(lastNotes, 1, {noteNumber = event.note, velocity = event.velocity}) if #lastNotes > 3 then -- Store maximum three notes. table.remove(lastNotes) end printLastNotes("onNote") end -- This will be called when the program is saved. function onSave() local data = {} data.lastNotes = lastNotes printLastNotes("onSave") return data -- Any data in this table will be stored. end -- This will be called when the program is restored. function onLoad(data) lastNotes = data.lastNotes -- Read the values from the data table. printLastNotes("onLoad") end ``` -------------------------------- ### Find All Layers and Print Names Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/findLayers.html This example demonstrates how to find all layers recursively starting from the current program and print the name of each found layer. It includes a check to see if any layers were found before iterating. ```lua layers = this.program:findLayers(true) if layers[1] then for i, layer in ipairs(layers) do print(layer.name) end else print("Could not find any layers!") end ``` -------------------------------- ### Lua Syntax Highlighting Example Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/Lua-Syntax-Highlighting.html Illustrates comments, keywords, strings, numbers, and function calls in Lua syntax. ```lua --single line comment --[[ block comment --]] --keywords and break do else elseif end false for function goto if in local nil not or repeat return then true until while --strings a = 'alo\n123"' a = "alo\n123\"" a = '\97lo\10\04923"' a = [[alo 123"]] a = [==[ alo 123"] ==] --numbers 3 3.0 3.1416 314.16e-2 0.31416E1 0xff 0x0.1E 0xA23p-4 0X1.921FB54442D18P+1 --functions print(a) print("Hello") print(123) for k,v in ipairs(t) print(v) end ``` -------------------------------- ### Customized Message Box Example Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/messageBox.html This example demonstrates how to create and display a customized message box with a question icon and multiple buttons. It repeatedly shows the message box until the user selects the correct answer or cancels. ```lua -- Customized message box. myMessage = {} myMessage.type = MessageBoxType.question myMessage.text = "Click the button with the correct answer!\n1 + 1 = ?" myMessage.button1 = "1" myMessage.button2 = "2" myMessage.button3 = "3" repeat result = messageBox(myMessage) until result == MessageBoxResult.button2 or result == MessageBoxResult.escape ``` -------------------------------- ### Example Usage of LoadProgress Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/LoadProgress.html This example demonstrates how to use LoadProgress to load and append layers asynchronously, monitoring the progress and handling completion. ```APIDOC ## Example: Asynchronous Layer Loading with Progress Monitoring ### Description This script demonstrates loading VST presets asynchronously, appending them as layers, and monitoring the loading progress. It includes functionality to remove old layers and cancel loading if needed. ### Functions - **getPresetNames()**: Populates a table with the names of available layer presets. - **removeOldLayer(progressInfo)**: Callback function to remove the previously loaded layer once a new one is successfully appended. - **appendNewLayer(progressInfo)**: Callback function that appends the newly loaded preset as a layer. - **onSelectPresetChanged()**: Triggered when the selected preset changes, initiating the asynchronous loading process. - **onIdle()**: Called periodically to update and display the loading progress. ### Script Logic 1. Initializes by clearing existing layers. 2. Defines a list of layer presets with their names and paths. 3. Creates a function `getPresetNames` to extract preset names for a parameter. 4. Defines `removeOldLayer` to manage the removal of the previous layer. 5. Defines `appendNewLayer` to asynchronously append the loaded preset as a new layer. 6. Sets up `onSelectPresetChanged` to call `loadPresetAsync` with the selected preset path and the `appendNewLayer` callback. 7. Defines a parameter `SelectPreset` to allow users to choose which preset to load. 8. Implements `onIdle` to continuously check and display the loading progress using `progressInf.progress`. ### Code Snippet ```lua -- Start with an empty program, remove any existing layers. layers = this.parent:findLayers() if layers then for i, layer in ipairs(layers) do this.parent:removeLayer(layer) end end -- Table with layer presets from Skylab. layerPresets = { { name = "Ambient Pad 01", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 01.vstpreset" }, { name = "Ambient Pad 02", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 02.vstpreset" }, { name = "Ambient Pad 03", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 03.vstpreset" }, { name = "Ambient Pad 04", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 04.vstpreset" }, } -- Create a table with the preset names. function getPresetNames() presetNames = {} for i, preset in ipairs(layerPresets) do presetNames[i] = preset.name end end getPresetNames() -- Remove the old layer after the new one was added. function removeOldLayer(progressInfo) local newPreset = progressInfo.root if oldPreset then this.parent:removeLayer(oldPreset) print(oldPreset.name.." removed.") end oldPreset = newPreset end -- Append the preset in a separate thread. function appendNewLayer(progressInfo) if progressInfo.root then this.parent:appendLayerAsync(progressInfo.root, removeOldLayer) print("Appending "..progressInfo.root.name.."...") end end -- Load the preset in a separate thread. function onSelectPresetChanged() progress = 0 progressInf = loadPresetAsync(layerPresets[SelectPreset].path, appendNewLayer) print("Loading "..layerPresets[SelectPreset].name.."...") end -- Define a parameter for selecting the preset to be loaded. defineParameter("SelectPreset", "Select Preset", 1, presetNames, onSelectPresetChanged) -- Monitor the load progress with onIdle. progress = 1 function onIdle() if progress < 1 then progress = progressInf.progress print("Progress: "..(progressInf.progress * 100).."%") end end ``` ``` -------------------------------- ### HALion Script wait() Example Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/wait.html This example demonstrates using wait() to delay note release processing. It prevents notes from being re-triggered too quickly after being released. ```lua -- Delay notes which have not been released for 1000 ms. local initTime = getTime() local releaseTime = {} function onNote(event) local noteOnTime = getTime() wait(1000) if noteOnTime > (releaseTime[event.note] or initTime) then postEvent(event) end end function onRelease(event) releaseTime[event.note] = getTime() postEvent(event) end ``` -------------------------------- ### Parameter Example Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/Creating-Parameters.html This example demonstrates how to define a parameter named 'Scale' and use its value to modify the note-on velocity of MIDI events. It also shows how to update the parameter's value based on incoming MIDI controller messages. ```APIDOC -- Initialize variables. min = 0 max = 100 maxVel = 127 defVel = 100 default = defVel / maxVel * max maxCC = 127 -- Define Scale using the previous variables. defineParameter("Scale", nil, default, min, max) -- Use the value of Scale to replace the note-on velocity. function onNote(event) event.velocity = maxVel * Scale / max postEvent(event) end -- Change the value of Scale through the last incoming MIDI controller. function onController(event) Scale = event.value / maxCC * max end ``` -------------------------------- ### Example Usage Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/getScriptExecTimeOut.html This example demonstrates how to print the script execution time-out for the current context using getScriptExecTimeOut(). ```APIDOC ## Example ```halion -- Print the script execution time-out of the controller and the processor thread. print("Script execution time-out of "..getContext()..": "..getScriptExecTimeOut().." ms.") function onInit() print("Script execution time-out of "..getContext()..": "..getScriptExecTimeOut().." ms.") end ``` ``` -------------------------------- ### Print Plug-in Version using getProductVersion() Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/getProductVersion.html Use this snippet within the onInit() function to print the plug-in's version to the console when the script initializes. This function is available in Controller and Processor scripts. ```lua function onInit() print(getProductVersion()) end ``` -------------------------------- ### Insert Bus into Program Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/insertBus.html Demonstrates how to load a VST preset, retrieve a bus from it, and insert that bus into the current program's layer at a specific position. Ensure the preset file exists at the specified path. ```lua -- Insert the bus from Program.vstpreset into the current program. -- Get the file path for user VST presets. path = getUserPresetPath() -- Load the VST preset. loadedProgram = loadPreset(path.."/Program/Program.vstpreset") -- Get the first bus from the loaded program. bus = loadedProgram:getBus() -- Insert the bus. if bus then this.program:insertBus(bus, 1) end ``` -------------------------------- ### Convert Milliseconds to Beats using ms2beat Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/ms2beat.html This example demonstrates how to use the ms2beat function to get the note length in beats. It prints the result to the console. ```HALion Script -- Print the note length in number of beats. function onRelease(event) postEvent(event) local noteLength = ms2beat(getNoteDuration(event.note)) print(noteLength, "beats") end ``` -------------------------------- ### Load and Manage VST Presets Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/Instance.html Demonstrates loading a VST preset, setting it in the Program Table, and managing it in the Slot Rack. Includes clearing a slot. ```lua __ -- Set Program.vstpreset in slot 3 of the Program Table and slot 1 of the Slot Rack. -- Get the file path for user VST presets. path = getUserPresetPath() -- Load the VST preset. loadedProgram = loadPreset(path.."/Program/Program.vstpreset") -- Set loadedProgram in slot 3 of the Program Table. this.program.instance:setProgram(loadedProgram, 3) -- Set program in slot 1 of the Slot Rack. program = this.program.instance:getProgram(3) this.program.instance:getSlot(1):setProgram(program) -- Clear slot 2 of the Slot Rack. this.program.instance:getSlot(2):setProgram(nil) ``` -------------------------------- ### Example Lua Script for Debugging Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/Debugging-with-LDT.html This is a basic Lua function that prints an event and then posts it back. It's used as a starting point for debugging sessions in LDT. ```lua function onNote(ev) print(ev) postEvent(ev) end ``` -------------------------------- ### Load and Append VST Presets with Progress Monitoring Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/LoadProgress.html This script demonstrates loading a VST preset asynchronously, appending it as a new layer, and monitoring the loading progress. It includes functions to manage layer removal and updates the UI based on loading status. Use this for dynamically loading and managing VST layers within HALion. ```lua -- Start with an empty program, remove any existing layers. layers = this.parent:findLayers() if layers then for i, layer in ipairs(layers) do this.parent:removeLayer(layer) end end -- Table with layer presets from Skylab. layerPresets = { { name = "Ambient Pad 01", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 01.vstpreset" }, { name = "Ambient Pad 02", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 02.vstpreset" }, { name = "Ambient Pad 03", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 03.vstpreset" }, { name = "Ambient Pad 04", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 04.vstpreset" }, } -- Create a table with the preset names. function getPresetNames() presetNames = {} for i, preset in ipairs(layerPresets) do presetNames[i] = preset.name end end getPresetNames() -- Remove the old layer after the new one was added. function removeOldLayer(progressInfo) local newPreset = progressInfo.root if oldPreset then this.parent:removeLayer(oldPreset) print(oldPreset.name.." removed.") end oldPreset = newPreset end -- Append the preset in a separate thread. function appendNewLayer(progressInfo) if progressInfo.root then this.parent:appendLayerAsync(progressInfo.root, removeOldLayer) print("Appending "..progressInfo.root.name.."...") end end -- Load the preset in a separate thread. function onSelectPresetChanged() progress = 0 progressInf = loadPresetAsync(layerPresets[SelectPreset].path, appendNewLayer) print("Loading "..layerPresets[SelectPreset].name.."...") end -- Define a parameter for selecting the preset to be loaded. defineParameter("SelectPreset", "Select Preset", 1, presetNames, onSelectPresetChanged) -- Monitor the load progress with onIdle. progress = 1 function onIdle() if progress < 1 then progress = progressInf.progress print("Progress: "..(progressInf.progress * 100).."%") end end ``` -------------------------------- ### Get Quick Control Assignment Curve Value Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/Layer.html Retrieves the curve value of a specific quick control assignment. Indices for quick controls and assignments start from 1. ```lua __ -- Print the curve value of the qc assignment. layer = this.parent qc = 1 assignment = 1 qcCurve = layer:getQCAssignmentCurve(qc, assignment) print("Curve value of '"..layer.name.."', QC "..qc..", assignment "..assignment..": "..qcCurve..".") ``` -------------------------------- ### Print Host Version using getHostVersion() Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/getHostVersion.html This snippet demonstrates how to retrieve and print the host software's version using the getHostVersion() function within the onInit callback. ```HALion Script -- Print the version of the host software. function onInit() print(getHostVersion()) end ``` -------------------------------- ### Calling Methods on Objects in HALion Script Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/Working-with-Objects.html Address an object and then call its methods using colon notation. This example demonstrates how to get a Zone object and set its name. ```HALion Script -- Get the object of the first Zone after the script module. zone = this.parent:getZone() -- setName operates on the Zone object. zone:setName("MyZone") ``` -------------------------------- ### Get QC Assignment Parameter ID Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/getQCAssignmentParamId.html Retrieves the parameter ID for a given quick control and assignment index. Indices start from 1. Ensure the parent layer is correctly referenced. ```HALion Script -- Print the parameter ID of the parameter connected to the qc assignment. layer = this.parent qc = 1 assignment = 1 paramID = layer:getQCAssignmentParamId(qc, assignment) print("Parameter ID of '"..layer.name.."', QC "..qc..", assignment "..assignment..": "..paramID..".") ``` -------------------------------- ### Initialize and Print Host Time Signature and Tempo Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/onInit.html This snippet demonstrates how to retrieve and print the current time signature and tempo from the host software using HALion Script's built-in functions. Ensure the program is loaded in the Slot Rack with a zone for this to execute. ```HALion Script function onInit() num, denom = getTimeSignature() tempo = getTempo() print(num.."/"..denom) print(tempo.." BPM") end ``` -------------------------------- ### Get Quick Control Assignment Scope Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/getQCAssignmentScope.html Use this function to retrieve the scope of a quick control assignment. The indices for quick controls and assignments start from 1. The scope's name is then printed. ```lua -- Print the scope for the qc assignment. layer = this.parent qc = 1 assignment = 1 scope = layer:getQCAssignmentScope(qc, assignment).name -- use only the name of the returned element print("Scope of '"..layer.name.."', QC "..qc..", assignment "..assignment..": "..scope..".) ``` -------------------------------- ### Asynchronous VST Preset Loading with HALion Script Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/loadPresetAsync.html This script demonstrates how to load VST presets asynchronously using `loadPresetAsync`. It includes functions to manage layers, define presets, and handle the loading process with callbacks and progress monitoring. Use this for large presets that might otherwise block the UI. ```lua -- Start with an empty program, remove any existing layers. layers = this.parent:findLayers() if layers then for i, layer in ipairs(layers) do this.parent:removeLayer(layer) end end -- Table with layer presets from Skylab. layerPresets = { { name = "Ambient Pad 01", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 01.vstpreset" }, { name = "Ambient Pad 02", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 02.vstpreset" }, { name = "Ambient Pad 03", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 03.vstpreset" }, { name = "Ambient Pad 04", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 04.vstpreset" }, } -- Create a table with the preset names. function getPresetNames() presetNames = {} for i, preset in ipairs(layerPresets) do presetNames[i] = preset.name end end getPresetNames() -- Remove the old layer after the new one was added. function removeOldLayer(progressInfo) local newPreset = progressInfo.root if oldPreset then this.parent:removeLayer(oldPreset) print(oldPreset.name.." removed.") end oldPreset = newPreset end -- Append the preset in a separate thread. function appendNewLayer(progressInfo) if progressInfo.root then this.parent:appendLayerAsync(progressInfo.root, removeOldLayer) print("Appending "..progressInfo.root.name.."...") end end -- Load the preset in a separate thread. function onSelectPresetChanged() progress = 0 progressInf = loadPresetAsync(layerPresets[SelectPreset].path, appendNewLayer) print("Loading "..layerPresets[SelectPreset].name.."...") end -- Define a parameter for selecting the preset to be loaded. defineParameter("SelectPreset", "Select Preset", 1, presetNames, onSelectPresetChanged) -- Monitor the load progress with onIdle. progress = 1 function onIdle() if progress < 1 then progress = progressInf.progress print("Progress: "..(progressInf.progress * 100).."%") end end ``` -------------------------------- ### Get First MIDI Module by Name Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/getMidiModule.html Retrieves the first MIDI module in the current program and prints its name. If no module is found, it prints an error message. This example demonstrates the basic usage of getMidiModule without arguments. ```lua -- Locate the first MIDI module in the program and print its name. module = this.program:getMidiModule() if module then print(module.name) else print("Could not find a MIDI module!") end ``` -------------------------------- ### Example: Setting Tooltips and Drum Map Names Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/getKeyProperties.html Shows how to set tooltips and instrument names for Cubase's Drum Editor using the GM Standard Drum Map. ```APIDOC -- Set the GM drum map as tooltip and drummap name. local GMStandardDrumMap = { "Bass Drum 2", "Bass Drum 1", "Side Stick", "Snare Drum 1", "Hand Clap", "Snare Drum 2", "Low Tom 2", "Closed Hi-hat", "Low Tom 1", "Pedal Hi-hat", "Mid Tom 2", "Open Hi-hat", "Mid Tom 1", "High Tom 2", "Crash Cymbal 1", "High Tom 1", "Ride Cymbal 1", "Chinese Cymbal", "Ride Bell", "Tambourine", "Splash Cymbal", "Cowbell", "Crash Cymbal 2", "Vibra Slap", "Ride Cymbal 2", "High Bongo", "Low Bongo", "Mute High Conga", "Open High Conga", "Low Conga", "High Timbale", "Low Timbale", "High Agogo", "Low Agogo", "Cabasa", "Maracas", "Short Whistle", "Long Whistle", "Short Guiro", "Long Guiro", "Claves", "High Wood Block", "Low Wood Block", "Mute Cuica", "Open Cuica", "Mute Triangle", "Open Triangle", } -- Initialize variables. local keys = getKeyProperties() local noteNumber = 35 -- Note number of Bass Drum 2. -- Set the GM drum map. for i, drumName in ipairs(GMStandardDrumMap) do keys[noteNumber + (i - 1)] = { tooltip = drumName, drummap = drumName } end ``` -------------------------------- ### Demonstrate Script Initialization Order Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/Script-Initialization.html This script tests the initialization order of global statements and callbacks. The 'Global statement' is printed first, followed by 'onLoad', then 'onLoadIntoSlot', and finally 'onInit'. ```lua print("Global statement") -- This is printed first. function onLoad() print("onLoad") -- This is printed after the global statement. end function onLoadIntoSlot() print("onLoadIntoSlot") -- This is printed after onLoad. end function onInit() print("onInit") -- This is printed last, after onLoadIntoSlot. end ``` -------------------------------- ### Get Quick Control Assignment Mode Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/Layer.html Retrieves the mode of a specific quick control assignment. Indices for quick controls and assignments start from 1. Available modes include Absolute, Relative, Switch, and Switch Relative. ```lua __ -- Print the mode of the qc assignment. layer = this.parent qc = 1 assignment = 1 qcMode = layer:getQCAssignmentMode(qc, assignment) if qcMode == QCAssignmentMode.absolute then qcModeName = "Absolute" elseif qcMode == QCAssignmentMode.relative then qcModeName = "Relative" elseif qcMode == QCAssignmentMode.switch then qcModeName = "Switch" elseif qcMode == QCAssignmentMode.switchRelative then qcModeName = "Switch Relative" end print("Mode of '"..layer.name.."', QC "..qc..", assignment "..assignment..": "..qcModeName..".") ``` -------------------------------- ### Insert Zone into Program Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/insertZone.html This script demonstrates how to load a VST preset, extract its first zone, and then insert that zone into the current program's layer at position 1. Ensure the 'Program.vstpreset' file is accessible. ```lua -- Insert a zone from Program.vstpreset into the current program. -- Get the file path for user VST presets. path = getUserPresetPath() -- Load the VST preset. loadedProgram = loadPreset(path.."/Program/Program.vstpreset") -- Get the first zone from the loaded program. zone = loadedProgram:getZone() -- Insert the zone. if zone then this.program:insertZone(zone, 1) end ``` -------------------------------- ### Retrieve Quick Control Assignment Curve Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/getQCAssignmentCurve.html Use this snippet to get the curve value of a specific quick control assignment. Ensure the layer, QC index, and assignment index are correctly identified. Indices start from 1. ```HALion Script -- Print the curve value of the qc assignment. layer = this.parent qc = 1 assignment = 1 qcCurve = layer:getQCAssignmentCurve(qc, assignment) print("Curve value of '"..layer.name.."', QC "..qc..", assignment "..assignment..": "..qcCurve..".") ``` -------------------------------- ### Implement Drag-and-Drop Sample Import Logic Source: https://steinbergmedia.github.io/halion-script-api/HALion-Tutorials-Guidelines/pages/Drag-and-Drop-Sample-Import.html This script handles the logic for importing samples or regions dropped onto the 'SampleDropArea'. It includes functions to parse dropped data, validate audio files, and import them into the HALion zone, including loop information. ```lua -- Drag & Drop Sample Import zone = getElement():getZone() function firstRegion(data) if data then if data.files and data.files[1] then local af = AudioFile.open(data.files[1]) if af.valid then return af, 0, af.length end end if data.regions and data.regions[1] then local af = AudioFile.open(data.regions[1].filename) if af.valid then return af, data.regions[1].start, data.regions[1].length end end end return { valid = false }, 0, -1 end function onDropFeedback(viewname, draginfo, copy, data) if viewname == "SampleDropArea" then local af, start, length = firstRegion(data) return af.valid end end function onDropGetInfo(viewname, info) return { info = info, copy = true, move = false } end function importSample(sample, start, length) if sample.valid then startUndoBlock("Import Sample " .. sample.fileName) zone:setParameter("SampleOsc.Filename", sample.fileName) zone:setParameter("SampleOsc.SampleStart", start) zone:setParameter("SampleOsc.SampleEnd", start + length) -- check loops local loop = sample.loops[1] zone:setParameter("SampleOsc.SustainLoopModeA", 1) local ls = loop and (loop.loopStart < loop.loopEnd) and math.max(start, math.min(loop.loopStart, start + length)) or start local le = loop and (loop.loopStart < loop.loopEnd) and math.max(start, math.min(loop.loopEnd, start + length)) or start + length zone:setParameter("SampleOsc.SustainLoopStartA", ls) zone:setParameter("SampleOsc.SustainLoopEndA", le) endUndoBlock() SampleFileName = sample.fileName end end function onDropInsert(viewname, draginfo, copy, data) if viewname == "SampleDropArea" then local sample, start, length = firstRegion(data) importSample(sample, start, length) end end defineParameter("SampleFileName", nil, "Drag a sample onto the waveform display to import it.") ``` -------------------------------- ### Get Quick Control Assignment Bypass State Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/getQCAssignmentBypass.html Use this function to retrieve the bypass state of a specific quick control assignment. Ensure the layer, QC index, and assignment index are correctly identified. Indices start from 1. ```lua -- Print the bypass state of the qc assignment. layer = this.parent qc = 1 assignment = 1 qcBypass = layer:getQCAssignmentBypass(qc, assignment) print("Bypass of '"..layer.name.."', QC "..qc..", assignment "..assignment..": "..tostring(qcBypass)..".") ``` -------------------------------- ### Asynchronous Layer Appending Example Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/appendLayerAsync.html Demonstrates how to append a layer asynchronously using `appendLayerAsync`. It includes setup for removing existing layers, defining layer presets, and handling the loading and appending process with callbacks. A parameter is defined to select presets, and `onIdle` monitors the loading progress. ```lua -- Start with an empty program, remove any existing layers. layers = this.parent:findLayers() if layers then for i, layer in ipairs(layers) do this.parent:removeLayer(layer) end end -- Table with layer presets from Skylab. layerPresets = { { name = "Ambient Pad 01", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 01.vstpreset" }, { name = "Ambient Pad 02", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 02.vstpreset" }, { name = "Ambient Pad 03", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 03.vstpreset" }, { name = "Ambient Pad 04", path = "vstsound://724ACB205EFF46F885735D1B216C37AD/.AppData/Steinberg/Skylab/Sub Presets/Layer Presets/Ambient Pads/Ambient Pad 04.vstpreset" }, } -- Create a table with the preset names. function getPresetNames() presetNames = {} for i, preset in ipairs(layerPresets) do presetNames[i] = preset.name end end getPresetNames() -- Remove the old layer after the new one was added. function removeOldLayer(progressInfo) local newPreset = progressInfo.root if oldPreset then this.parent:removeLayer(oldPreset) print(oldPreset.name.." removed.") end oldPreset = newPreset end -- Append the preset in a separate thread. function appendNewLayer(progressInfo) if progressInfo.root then this.parent:appendLayerAsync(progressInfo.root, removeOldLayer) print("Appending "..progressInfo.root.name.."...") end end -- Load the preset in a separate thread. function onSelectPresetChanged() progress = 0 progressInf = loadPresetAsync(layerPresets[SelectPreset].path, appendNewLayer) print("Loading "..layerPresets[SelectPreset].name.."...") end -- Define a parameter for selecting the preset to be loaded. defineParameter("SelectPreset", "Select Preset", 1, presetNames, onSelectPresetChanged) -- Monitor the load progress with onIdle. progress = 1 function onIdle() if progress < 1 then progress = progressInf.progress print("Progress: "..(progressInf.progress * 100).."%") end end ``` -------------------------------- ### onInit() Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/onInit.html This callback function is called after executing any global statements and the onLoadIntoSlot callback function. It is the first callback function that is called when the processor thread is initialized. You can use this function to initialize variables with information from the context, for example. The program must be loaded in the Slot Rack and contain at least one zone. Otherwise, onInit won't be called. ```APIDOC ## onInit() ### Description This callback function is called after executing any global statements and the onLoadIntoSlot callback function. It is the first callback function that is called when the processor thread is initialized. You can use this function to initialize variables with information from the context, for example. ❕ The program must be loaded in the Slot Rack and contain at least one zone. Otherwise, onInit won't be called. **Available in:** Processor. ### Example ```halion -- Print the time signature and tempo of the host software. function onInit() num, denom = getTimeSignature() tempo = getTempo() print(num.."/"..denom) print(tempo.." BPM") end ``` ### See also: - onLoadIntoSlot ``` -------------------------------- ### Fade Out and In with Shorter Duration Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/fade.html This example demonstrates fading a note out and then fading it back in. If a fade starts from the current value of a running fade, its duration will be proportionally shorter based on the remaining fade distance. This snippet also shows how to kill voices upon reaching the target value. ```HALion Script function onNote(event) id = playNote(event.note, 100, 0) -- The fades affect all voices that are triggered by this note. fade(id, 1.0, 0.0, 1000) -- Start to fade out. wait(500) -- Wait for 500 ms, which is only half of the fade out. fade(id, nil, 1.0, 1000, true) -- The fade in is only 500 ms long, because it has to go only half of the distance. end function onRelease(event) -- postEvent(event), not used. end ``` -------------------------------- ### Analyze Audio File Levels with getPeak Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/getPeak.html This example demonstrates how to use the getPeak function to analyze both peak and RMS levels within an audio file. It includes a helper function to convert linear values to decibels. ```lua function lin2db(lin) return 20 * math.log(lin) / math.log(10) end fname = "vstsound://F29C895D6D8E4D6C9BCBBA5198412192/.samples/Ambient Pad 01/Ambient Pad 01 - C3.tg3c" af = AudioFile.open(fname) -- Analyze the peak level in the first 1000 samples. attpeak = af:getPeak(0, 1000, 0) -- Analyze the RMS level in the range from 1000 samples till the end of the file. susrms = af:getPeak(1000, -1, 1) print("Attack Peak:", attpeak, "(", lin2db(attpeak), "dB )") print("Sustain RMS:", susrms, "(", lin2db(susrms), "dB )") ``` -------------------------------- ### Program Constructor Source: https://steinbergmedia.github.io/halion-script-api/HALion-Script/pages/Program.html Demonstrates how to create a new Program object and append various elements like buses, layers, MIDI modules, and effects. ```APIDOC ## Program() ### Description Constructor to create a new Program object. ### Method Program() ### Parameters None ### Returns A new Program object. ### Example ```lua -- The following function creates different types of objects in the Program Tree. -- The objects in the Program Tree do not have a name. You will see only their icons. function createProgram() local inst = this.program.instance local prg = Program() local bus = Bus() prg:appendBus(bus) inst:setProgram(prg, 1) local layer = Layer() prg:appendLayer(layer) layer:appendZone(Zone()) local mm = MidiModule('MIDI Player') layer:appendMidiModule(mm) local fx = Effect('Distortion') bus:appendEffect(fx) end createProgram() ``` ```