Is there a built-in parameter or functionality in HALion to enable a “toggle” mode for note playback? Specifically, I would like a note to behave as follows:
When I press and release the note, the loop continues to play.
If I press the same note again, the loop stops.
Is this possible using HALion’s existing features, or would it require scripting?
I have looked inside HALion and in the manual but I can’t find it.
noteIds = {}
function onNote(e)
if noteIds[e.note] then
releaseVoice(noteIds[e.note])
noteIds[e.note] = nil
else
noteIds[e.note] = playNote(e.note, e.velocity, 0)
end
end
function onRelease(e)
-- do nothing
end
Thanks, it works great! In my UI, I’ve set up an animation that pulses on the beat while the loop is playing. It works perfectly when the loop is set to “Continuous” because pressing the note again stops both the loop and the animation. However, when the loop is set to “No Loop,” I can’t find a way to stop the animation when the loop reaches the end and stops playing.
Is there a function or method to detect when the loop ends and stops playing that I can use to stop the animation too? I’ve searched through the HALion Developer Resource but couldn’t find anything. Any ideas or suggestions?
Not that I know of. You could try checking the playback position. Do you have a single zone? I tried to detect the loop end using onIdle callback and amp envelope playback position. But maybe there is a better way to do it.
noteIds = {}
zone = this.parent:getZone()
watchEnd = false
function onNote(e)
if noteIds[e.note] then
releaseVoice(noteIds[e.note])
noteIds[e.note] = nil
else
noteIds[e.note] = playNote(e.note, e.velocity, 0)
if zone:getParameter("SampleOsc.SustainLoopModeA") == 0 then
watchEnd = true
end
end
end
function onRelease(e)
-- do nothing
end
function onIdle()
if watchEnd == true and zone:getParameter("Amp Env.PlaybackPos") == 0 then
watchEnd = false
print("Finished")
end
end
“Thanks, this works! Now I’m trying to figure out how to make a loop in ‘toggle’ mode and synchronized with the host tempo stop automatically when the host playback stops. I tried using the isPlaying function, but it doesn’t seem to work. Is there a better approach to achieve this?”
I tried like this but I am not sure how much this would affect performance.
noteIds = {}
zone = this.parent:getZone()
watchEnd = false
playing = false
function onNote(e)
if noteIds[e.note] then
releaseVoice(noteIds[e.note])
noteIds[e.note] = nil
else
noteIds[e.note] = playNote(e.note, e.velocity, 0)
if zone:getParameter("SampleOsc.SustainLoopModeA") == 0 then
watchEnd = true
end
end
end
function onRelease(e)
-- do nothing
end
function releaseAllVoices()
for note, id in pairs(noteIds) do
releaseVoice(id)
noteIds[note] = nil
end
end
function onIdle()
if watchEnd == true and zone:getParameter("Amp Env.PlaybackPos") == 0 then
watchEnd = false
print("Finished")
end
if isPlaying() ~= playing then
playing = isPlaying()
if playing == false then
print("Playback stopped")
runSync(releaseAllVoices)
end
end
end