Reloading duplicate samples efficiently, wait_async confusion

Reid115
Reid115 Member Posts: 47 Member

In my instrument, you can load up to 16 samples. The instrument itself can be in one of three sample modes ("time machine", sampler mode w/ reverse on, or "wavetable") set from a ui_menu. Because there's no way to change the sample mode from the script, I have to have 16 * 3 = 48 groups, each with it's own user zone and loop parameters. The problem is that the samples could be several minutes long, so reloading the instrument with the '!' button -- and to a lesser degree, loading a single sample -- could take a really long time. Even when the sample paths are all set to "", it still takes a solid second or two. This is basically what the relavent code looks like:

on init
    ...
    define NUM_ZONES := 48
    set_num_user_zones(NUM_ZONES)
    for c := 0 to NUM_ZONES - 1
        set_zone_par(NI_USER_ZONE_IDS[c], ZONE_PAR_GROUP, c)
        set_zone_par(NI_USER_ZONE_IDS[c], ZONE_PAR_LOW_KEY, 0)
        set_zone_par(NI_USER_ZONE_IDS[c], ZONE_PAR_HIGH_KEY, 127)
        set_zone_par(NI_USER_ZONE_IDS[c], ZONE_PAR_LOW_VELO, 0)
        set_zone_par(NI_USER_ZONE_IDS[c], ZONE_PAR_HIGH_VELO, 127)
    end for
end on

on persistence_changed
    ...
    for c := 0 to NUM_ZONES - 1 // 48 iterations
        wait_async(set_sample(NI_USER_ZONE_IDS[c], !sample_paths[c / 3]))
        wait_async(set_loop_par(NI_USER_ZONE_IDS[c], 0, LOOP_PAR_MODE, loop_button))
        wait_async(set_loop_par(NI_USER_ZONE_IDS[c], 0, LOOP_PAR_START, 0))
        wait_async(set_loop_par(NI_USER_ZONE_IDS[c], 0, LOOP_PAR_LENGTH, 2147483647))
    end for
end on

Questions:

1. Is there any way to load each sample once and put it into 3 groups instead of loading the same sample 3 times? Because the latter triples my loading time. Would it make more sense to only load each sample into the current sample mode's group, and then load all 16 again each time the user changes the ui_menu?

2. What exactly does wait_async() do? I've read the manual and forum posts about it but I still don't understand what it does vs. just doing the operations without it. I ask because if I do those 4 operations in the PCCB loop without it, it loads significantly faster. And I realized that all this time I haven't been using it in the ICB for the zone parameters and it's been fine. If the idea is that it waits until the current operation is completely done before moving on to the next, isn't that how programming languages already work by default, running instructions serially?

Thanks.

Comments

  • EvilDragon
    EvilDragon Moderator Posts: 1,023 mod
    1. AFAIK, no. Each user zone is unique and requires loading its own sample.
    2. wait_async() obviates the need for using the async_complete callback - it waits until the operation you put in its parentheses is complete, then continues the callback. You can use the loop variant of it (as explained in KSP reference) to parallelize several async operations.
  • Reid115
    Reid115 Member Posts: 47 Member
    edited August 2022

    @EvilDragon

    OK, I read some more about wait_async() and I think I get it now. I realized my ICB mention is a moot point because things only run asynchronously outside the ICB. I put my PCCB operations into an asyncid array as outlined in the reference manual and now it only takes a tiny fraction of the time, so problem solved. Thanks!

    Lastly, I also realized (and correct me if I'm wrong) that reloading the samples and zone/loop properties is only necessary when a snapshot is loaded (which will have new samples), NOT when I press the "!" button which doesn't change the current samples. Is there any way I can distinguish a snapshot load from a "!" load?

  • EvilDragon
    EvilDragon Moderator Posts: 1,023 mod

    Not really, both snapshot load and "!" will run PCCB.

Back To Top