Changing snapshots doesn't change zones -- how to make zones persistent?

Reid115
Reid115 Member Posts: 47 Member

My script has an area to drop an audio file into a waveform. But when I save snapshots and switch between them, whatever the last dropped audio file was remains. I know it's not just a graphical issue with the waveform because when I play MIDI I still hear the same sample as well. How do I make my zones persistent? I think making the ui_waveform and ui_mouse_area persistent isn't doing anything. Here's the relavent code:

on init
    set_num_user_zones(3)
    declare $c := 0
    while ($c < 3)
        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)
        set_zone_par(%NI_USER_ZONE_IDS[$c], $ZONE_PAR_ROOT_KEY, 60)
        set_zone_par(%NI_USER_ZONE_IDS[$c], $ZONE_PAR_SAMPLE_MOD_RANGE, 0)
        inc($c)
    end while

    declare ui_waveform $dnd_wf (1, 1)
    make_persistent($dnd_wf)
    set_control_par(get_ui_id($dnd_wf), $CONTROL_PAR_PARENT_PANEL, get_ui_id($dnd_panel))
    move_control_px($dnd_wf, 0, 0)
    set_control_par(get_ui_id($dnd_wf), $CONTROL_PAR_WIDTH, 553)
    set_control_par(get_ui_id($dnd_wf), $CONTROL_PAR_HEIGHT, 100)
    set_control_par(get_ui_id($dnd_wf), $CONTROL_PAR_WF_VIS_MODE, $NI_WF_VIS_MODE_1)
    set_control_par(get_ui_id($dnd_wf), $CONTROL_PAR_BG_COLOR, 950504dh) {50565c} {55585b} {50504d}
    set_control_par(get_ui_id($dnd_wf), $CONTROL_PAR_WAVE_COLOR, 9d9dee0h) {ffffff}
    set_control_par(get_ui_id($dnd_wf), $CONTROL_PAR_WAVE_CURSOR_COLOR, 9ff0080h) {ff0080}
    set_control_par_str(get_ui_id($dnd_wf), $CONTROL_PAR_PICTURE, "wf")
    attach_zone($dnd_wf, %NI_USER_ZONE_IDS[0], 0)
    
    declare ui_mouse_area $dnd_area
    make_persistent($dnd_area)
    set_control_par(get_ui_id($dnd_area), $CONTROL_PAR_PARENT_PANEL, get_ui_id($dnd_panel))
    move_control_px($dnd_wf, 0, 0)
    set_control_par(get_ui_id($dnd_area), $CONTROL_PAR_WIDTH, 553)
    set_control_par(get_ui_id($dnd_area), $CONTROL_PAR_HEIGHT, 100)
    set_control_par(get_ui_id($dnd_area), $CONTROL_PAR_DND_ACCEPT_AUDIO, $NI_DND_ACCEPT_ONE)
    set_control_par(get_ui_id($dnd_area), $CONTROL_PAR_DND_ACCEPT_ARRAY, $NI_DND_ACCEPT_ONE)
    set_control_par(get_ui_id($dnd_area), $CONTROL_PAR_RECEIVE_DRAG_EVENTS, 1)
    
    declare ui_panel $dnd_label_panel
    set_control_par(get_ui_id($dnd_label_panel), $CONTROL_PAR_PARENT_PANEL, get_ui_id($dnd_panel))
    move_control_px($dnd_label_panel, 2, 97)
    
    declare ui_label $dnd_label (1, 1)
    make_persistent($dnd_label)
    set_control_par(get_ui_id($dnd_label), $CONTROL_PAR_PARENT_PANEL, get_ui_id($dnd_label_panel))
    move_control_px($dnd_label, 1, 1)
    set_control_par(get_ui_id($dnd_label), $CONTROL_PAR_WIDTH, 370)
    set_control_par(get_ui_id($dnd_label), $CONTROL_PAR_HEIGHT, 19)
    set_control_par(get_ui_id($dnd_label), $CONTROL_PAR_FONT_TYPE, 11)
    hide_part($dnd_label, $HIDE_PART_BG)
end on

function dnd_changed
    {attach_zone($dnd_wf, %NI_USER_ZONE_IDS[0], 0)}
    $sample_length := get_sample_length(%NI_USER_ZONE_IDS[0])
    if ($sample_length = 0)
        set_text($dnd_label, "     ^  Drop audio file!  ^")
    else
        set_text($dnd_label, "     " & get_sample(%NI_USER_ZONE_IDS[0], $NI_FILE_NAME)) { & "." & get_sample(%NI_USER_ZONE_IDS[0], $NI_FILE_EXTENSION)) }
    end if
    call pos_changed
end function
on ui_control ($dnd_area)
    if ($NI_MOUSE_EVENT_TYPE = $NI_MOUSE_EVENT_TYPE_DROP)
        if (num_elements(!NI_DND_ITEMS_AUDIO) = 1)
            wait_async(set_sample(%NI_USER_ZONE_IDS[0], !NI_DND_ITEMS_AUDIO[0]))
            wait_async(set_sample(%NI_USER_ZONE_IDS[1], !NI_DND_ITEMS_AUDIO[0]))
            wait_async(set_sample(%NI_USER_ZONE_IDS[2], !NI_DND_ITEMS_AUDIO[0]))
            {$pos_knob := 0}
            call dnd_changed
        end if
    end if
end on

on persistence_changed
    call dnd_changed
end on

Best Answers

  • medusa
    medusa Member Posts: 83 Helper
    Answer ✓

    You will need a persistent @string to store the path to the user sample for each Snapshot. Then when you recall the snapshot, that will be used in the persistence_changed callback to load it. When the DND happens, you assign the dropped item path to that @string, and then your function can use that string to assign the samples. In that way the same function can be used on the DND and the persistence_changed... but in persistence_changed it will use the stored @string, in DND it will use the new version of the @string.

  • soundtrax
    soundtrax Member Posts: 14 Member
    Answer ✓

    I had the same problem and came up with this solution:

    In on_persistence, it is actually possible to load a user zone sample with a relative path or - if the sample can't be found at the relative path location - with the usual absolute path instead.

    So you could set up a "Samples" folder next to the nki where you put all your factory snapshot samples, but the user drag & drop from any location would still work when saving and loading a snapshot.

    To make it work, you need to retrieve and store both the file name + extension and also its absolute sample path when dropping an audio into the user zone:

    @filename= get_sample(%NI_USER_ZONE_IDS[0], $NI_FILE_NAME) & "." & get_sample(%NI_USER_ZONE_IDS[0], $NI_FILE_EXTENSION)
    @abssamplepath := !NI_DND_ITEMS_AUDIO[0]
    

    then on persistence:

    - clear the user zone first:

    wait_async(set_sample(%NI_USER_ZONE_IDS[0],""))				
    

    - try to load the audio file from relative path:

    wait_async(set_sample(%NI_USER_ZONE_IDS[0],get_folder($GET_FOLDER_PATCH_DIR) & "Samples/"& @filename)) 
    

    - check if any audio could be loaded

    if ((is_zone_empty(%NI_USER_ZONE_IDS[0]) = 1)) 
    

    - if the zone is still empty, load the absolute path instead:

    wait_async (set_sample(%NI_USER_ZONE_IDS[0],@abssamplepath))
    end if
    

Answers

  • Paule
    Paule Member Posts: 1,328 Expert
    edited January 2022

    Is like at Reaktor? To save the path from where your samples come must be, in Reaktor a folder beneath the ensemble, in Kontakt a folder beneath the instrument? The folders name is Samples and can contains several subfolders.

  • medusa
    medusa Member Posts: 83 Helper
    Answer ✓

    You will need a persistent @string to store the path to the user sample for each Snapshot. Then when you recall the snapshot, that will be used in the persistence_changed callback to load it. When the DND happens, you assign the dropped item path to that @string, and then your function can use that string to assign the samples. In that way the same function can be used on the DND and the persistence_changed... but in persistence_changed it will use the stored @string, in DND it will use the new version of the @string.

  • Reid115
    Reid115 Member Posts: 47 Member
    edited January 2022

    That did the trick medusa, thanks. One other question -- is there any way to automatically save the sample, either embedded in the snapshot, or have the sample be copied into the directory where the snapshot is saved? Because if I take a snapshot and load it on another computer, it's not going to find the sample.

  • medusa
    medusa Member Posts: 83 Helper

    No, there isn't. Moving user sample presets to another computer is tricky.

    Even if it were in the same directory, that won't work on another computer because the absolute path will most likely be different.

  • Reid115
    Reid115 Member Posts: 47 Member

    Good point. Thanks again.

  • soundtrax
    soundtrax Member Posts: 14 Member
    Answer ✓

    I had the same problem and came up with this solution:

    In on_persistence, it is actually possible to load a user zone sample with a relative path or - if the sample can't be found at the relative path location - with the usual absolute path instead.

    So you could set up a "Samples" folder next to the nki where you put all your factory snapshot samples, but the user drag & drop from any location would still work when saving and loading a snapshot.

    To make it work, you need to retrieve and store both the file name + extension and also its absolute sample path when dropping an audio into the user zone:

    @filename= get_sample(%NI_USER_ZONE_IDS[0], $NI_FILE_NAME) & "." & get_sample(%NI_USER_ZONE_IDS[0], $NI_FILE_EXTENSION)
    @abssamplepath := !NI_DND_ITEMS_AUDIO[0]
    

    then on persistence:

    - clear the user zone first:

    wait_async(set_sample(%NI_USER_ZONE_IDS[0],""))				
    

    - try to load the audio file from relative path:

    wait_async(set_sample(%NI_USER_ZONE_IDS[0],get_folder($GET_FOLDER_PATCH_DIR) & "Samples/"& @filename)) 
    

    - check if any audio could be loaded

    if ((is_zone_empty(%NI_USER_ZONE_IDS[0]) = 1)) 
    

    - if the zone is still empty, load the absolute path instead:

    wait_async (set_sample(%NI_USER_ZONE_IDS[0],@abssamplepath))
    end if
    
  • medusa
    medusa Member Posts: 83 Helper

    This is a great solution, thank you!

Back To Top