In my script I use both: playNote with -1 and playNote with certain duration. And I found out that a playNote with -1 ignores physical release of a key if onRelease function is present in the script (even an empty one). So once it’s there must I handle all releases myself with a fade function?
It works ok here. Can you post an example?
This code gives hanging notes:
layers = this.parent:findLayers(true)
played_note_id={}
for i = 0, 127 do
played_note_id[i] = {}
end
function onRelease(event)
end
function onNote(event)
played_note_id[event.note][15]= playNote(event.note, event.velocity, -1, layers[15])
played_note_id[event.note][18]= playNote(event.note, event.velocity, -1, layers[18])
end
However proper release works if I remove either
function onRelease(event)
end
or one of these two lines:
played_note_id[event.note][15]= playNote(event.note, event.velocity, -1, layers[15])
played_note_id[event.note][18]= playNote(event.note, event.velocity, -1, layers[18])
This is strange. Just tried it and it works ok here. With or without onRelease
.
Are you sure there’s nothing else going on there? You said you also use playNote
with duration other than -1.
You don’t have the onNote
function twice in the same script, do you?
Ok, after more trials I’ve traced that problem originates in the layer’s structure of my patch. For example, the code above works fine, without hangingn notes, for this structure (no sublayers):
However notes are hung up for the structure below (with sublayers and additional busses):
If you add search function to findLayers
?
layers = this.parent:findLayers(true, function(layer) return layer.level == this.level + 2 end)
for i, layer in ipairs(layers) do
print(layer.name)
end
They code return the following list and some layers are missed:
01_Tonal_src1
02_Tonal_src2
03_Tonal_src3
04_Noise_src1
05_Noise_src2
06_Noise_src3
07_mic_FX_src1
08_mic_FX_src2
09_mic_FX_src3
10_Damper_strings_down_src1
11_Damper_strings_down_src2
12_Damper_strings_down_src3
13_Damper_strings_up_src1
14_Damper_strings_up_src2
15_Damper_strings_up_src3
Release_tonal
Release_noise
Res_Tonal
Res_Noise
28_keys_FX_down_src1
29_keys_FX_down_src2
30_keys_FX_down_src3
31_keys_FX_up_src1
32_keys_FX_up_src2
33_keys_FX_up_src3
34_pedal_foot_FX_down_src1
35_pedal_foot_FX_down_src2
36_pedal_foot_FX_down_src3
37_pedal_foot_FX_up_src1
38_pedal_foot_FX_up_src2
39_pedal_foot_FX_up_src3
40_harmonics_2_up_src1
41_harmonics_2_up_src2
42_harmonics_2_up_src3
43_harmonics_3_up_src1
44_harmonics_3_up_src2
45_harmonics_3_up_src3
46_harmonics_4_up_src1
47_harmonics_4_up_src2
48_harmonics_4_up_src3
49_harmonics_5_up_src1
50_harmonics_5_up_src2
51_harmonics_5_up_src3
52_harmonics_6_up_src1
53_harmonics_6_up_src2
54_harmonics_6_up_src3
55_harmonics_7_up_src1
56_harmonics_7_up_src2
57_harmonics_7_up_src3
58_harmonics_8_up_src1
59_harmonics_8_up_src2
60_harmonics_8_up_src3
61_Res_Tonal_src1
62_Res_Tonal_src2
63_Res_Tonal_src3
The missing layers - are they at the same hierarchy level?
Script module and your Main layer are at the same level. Each nested sublayer adds 1 to the level. So the idea was to only include the sublayers.
If you use findLayers(true)
it will return all layers including the parent layers. So layers[1]
would probably be your Main layer.
For the reference I used this short script to get layers’ numbers:
layers = this.parent:findLayers(true)
layerNames = {}
for i = 1, #layers do
layerNames[i] = layers[i].name
print(i .. ", " .. layerNames[i])
end
And the returned list was like this:
1, Main
2, Tonal
3, Noise
4, Mic_FX
5, Damper_down
6, Damper_up
7, Release_General
8, Res_General
9, Keys_FX_down
10, Keys_FX_up
11, Pedal_foot_down
12, Pedal_foot_up
13, Harmonics
14, Res_Tonal_2
15, 01_Tonal_src1
16, 02_Tonal_src2
17, 03_Tonal_src3
18, 04_Noise_src1
19, 05_Noise_src2
20, 06_Noise_src3
21, 07_mic_FX_src1
22, 08_mic_FX_src2
23, 09_mic_FX_src3
24, 10_Damper_strings_down_src1
25, 11_Damper_strings_down_src2
26, 12_Damper_strings_down_src3
27, 13_Damper_strings_up_src1
28, 14_Damper_strings_up_src2
29, 15_Damper_strings_up_src3
30, Release_tonal
31, Release_noise
32, 16_Release_tonal_src1
33, 17_Release_tonal_src2
34, 18_Release_tonal_src3
35, 19_Release_noise_src1
36, 20_Release_niose_src2
37, 21_Release_noise_src3
38, Res_Tonal
39, Res_Noise
40, 22_Res_Tonal_src1
41, 23_Res_Tonal_src2
42, 24_Res_Tonal_src3
43, 25_Res_Noise_src1
44, 26_Res_Noise_src2
45, 27_Res_Noise_src3
46, 28_keys_FX_down_src1
47, 29_keys_FX_down_src2
48, 30_keys_FX_down_src3
49, 31_keys_FX_up_src1
50, 32_keys_FX_up_src2
51, 33_keys_FX_up_src3
52, 34_pedal_foot_FX_down_src1
53, 35_pedal_foot_FX_down_src2
54, 36_pedal_foot_FX_down_src3
55, 37_pedal_foot_FX_up_src1
56, 38_pedal_foot_FX_up_src2
57, 39_pedal_foot_FX_up_src3
58, 40_harmonics_2_up_src1
59, 41_harmonics_2_up_src2
60, 42_harmonics_2_up_src3
61, 43_harmonics_3_up_src1
62, 44_harmonics_3_up_src2
63, 45_harmonics_3_up_src3
64, 46_harmonics_4_up_src1
65, 47_harmonics_4_up_src2
66, 48_harmonics_4_up_src3
67, 49_harmonics_5_up_src1
68, 50_harmonics_5_up_src2
69, 51_harmonics_5_up_src3
70, 52_harmonics_6_up_src1
71, 53_harmonics_6_up_src2
72, 54_harmonics_6_up_src3
73, 55_harmonics_7_up_src1
74, 56_harmonics_7_up_src2
75, 57_harmonics_7_up_src3
76, 58_harmonics_8_up_src1
77, 59_harmonics_8_up_src2
78, 60_harmonics_8_up_src3
79, 61_Res_Tonal_src1
80, 62_Res_Tonal_src2
81, 63_Res_Tonal_src3
And in my initial script (1st message) I would like to play layers #15 and #18, which is 15, 01_Tonal_src1 and 18, 04_Noise_src1. I’m puzzled why notes are hanging?
I see. That looks correct.
I still cannot reproduce the hanging notes. I tried to recreate the same program structure with nested layers as in your picture and it works ok. No hanging notes. I tried the script exactly as you posted it. So this is strange. You don’t have the samples set to oneshot mode, maybe by mistake?
Have checked it. No, all zones have Normal playback mode.
The patch was created with a script, because I have a lot of layers and tons of zones. The only thing comes to my mind is that when I added all zones I noticed that they had Sample End set to 0. So I had to run another script to set Sample End as a really big number, since I didn’t know how to get the actual sample length and relay it to Sample End parameter. Maybe that’s the issue?
You can use AudioFile.open
to get information about sample and use that to set sample end. I would use the .length
for sample end.
AudioFile - HALion Script - Steinberg Developer Help
But this shouldn’t cause hanging notes.
Ok, I simplified the patch to this structure:
and then replaced -1 in PlayNote to a certain duration value:
layers = this.parent:findLayers(true)
function onRelease(event)
end
function onNote(event)
playNote(event.note, event.velocity, 1000, layers[4])
playNote(event.note, event.velocity, 1000, layers[7])
end
Now with this if I release a key sooner than 1 sec I got a hanging voice. If I keep holding the key, release happens after 1 sec.
If I remove either the empty
function onRelease(event)
end
or remove one of playNote lines, say:
playNote(event.note, event.velocity, 1000, layers[7])
the hanging notes are gone.
When you say you get hanging voice, do you mean it plays indefinitely or it plays for 1 second as specified by duration?
The empty onRelease
eats the note off. So it plays until duration has passed. Removing the empty onRelease
fixes it, as you say. So does if you post the note off.
function onRelease(e)
postEvent(e)
end
It is a bit confusing because it behaves differently when duration is -1. In this case it doesn’t matter if empty onRelease
is present or not.
I couldn’t reproduce this. It made no difference when I tried. But the onRelease
did.
Hanging voice plays until the end of the sample, not 1 sec as it should.
Ok, the postEvent(event) does iliminate the problem.
Could you please explain me more detailed what postEvent exactly means? In documentation it’s said “Function to post the event to the engine”. What is the contextual meaning of “to post”? to send? And what is "the engine? Halion underhood?
Can you upload an example preset?
postEvent
means to post (play) the event as is. You can do the same with onNote
, onConttoller
…
function onNote(e)
postEvent(e)
end
If you used empty onNote
then Halion would play no notes. As the script wouldn’t pass (post) any note on messages.
v14-short-2.vstpreset (692.8 KB)
So post means like “send the event through”, bypassing the script?
Yes.
Although it’s not bypassing the script. You can still inspect the event, store the values in variables…
I guess this is what happens when you don’t use onRelease
, it just sends the event through.
Thanks for the example preset. It really behaves as you describe. If I use empty onRelease
and set the duration of playNote
to 1000, one voice stops after 1 second but the other one keeps playing indefinitely.
To me this looks like a bug. It seems to be caused by sostenuto setting of your layers. You have this set to off. To fix this turn the sostenuto on for all your layers.
This is the default setting when you create new layer:
- repedaling off
- sustain off
- sostenuto on
Why it affects the playNote
? I don’t know.
But after changing the sostenuto for all layers (actually it doesn’t matter for the Main layer, but for all other sublayers it does) playNote
works reliably. When I used the empty onRelease
then playNote
with duration -1 played notes until release and playNote
with specified duration played notes for the given duration.
I think I couldn’t reproduce this before because I created the layers manually and the sostenuto was on by default.