# Dual Layer Instrument with independent Waveform display (Need Help!)



## Troy M (Mar 29, 2021)

Hi Everyone! I'm hoping someone can help me out with this one... many Thanks

I have two Menus/Layers to select different groups for playback and I have a waveform display for each one. I almost have the setup I am looking for but its just not working correctly? Layer1 seems to change its Waveform display when I change groups but Layer 2 Doesn't and neither Waveforms update when playing different keys, its just the same wave all the time. I am also getting a SCRIPT WARNING (Line 93) array index out of bounds (using default value 0)


```
on init
    set_ui_height_px(300)
    set_ui_width_px(400)
    make_perfview
    set_script_title("")
    message("")
  
    declare const $LAYER1_FIRST := 0
    declare const $LAYER1_LAST := 1
    declare const $LAYER2_FIRST := 2
    declare const $LAYER2_LAST := 3
    
    declare %layer1groups[2] := (0,1)
    declare %layer2groups[2] := (2,3)

    declare $i   
    declare $waveforms := 0
    declare $zoneID 
    declare $noteID
    declare $play_pos
    declare const $VOICE_1 := 0
    declare const $VOICE_2 := 1
    declare $REBUILD_WAVEFORMS := 0
    declare $wait_time := 1000

{----------------------------------------------------------------}

    declare ui_menu $Layer1
          set_control_par_str(get_ui_id($Layer1),$CONTROL_PAR_TEXT,"")
          set_control_par_str(get_ui_id($Layer1),$CONTROL_PAR_PICTURE,"")
          set_control_par(get_ui_id($Layer1),$CONTROL_PAR_TEXT_ALIGNMENT,1)
          set_control_par(get_ui_id($Layer1), $CONTROL_PAR_TEXTPOS_Y,4)
          make_persistent($Layer1)


              $i := $LAYER1_FIRST
           while ($i<=$LAYER1_LAST)
             add_menu_item($Layer1,group_name($i),$i)
             inc($i)
           end while

    declare ui_menu $Layer2
          set_control_par_str(get_ui_id($Layer2),$CONTROL_PAR_TEXT,"")
          set_control_par_str(get_ui_id($Layer2),$CONTROL_PAR_PICTURE,"")
          set_control_par(get_ui_id($Layer2),$CONTROL_PAR_TEXT_ALIGNMENT,1)
          set_control_par(get_ui_id($Layer2), $CONTROL_PAR_TEXTPOS_Y,4)
          make_persistent($Layer2)

                $i := $LAYER2_FIRST
             while ($i<=$LAYER2_LAST)
               add_menu_item($Layer2,group_name($i),$i)
               inc($i)
             end while

{----------------------------------------------------------------}


    declare !ZoneName[16000]
    load_array(!ZoneName,2)

    declare %ZoneID[2] := (0,1)
      make_persistent(%ZoneID)  
    declare %ZoneID2[2] := (2,3)
      make_persistent(%ZoneID2)

      if ($REBUILD_WAVEFORMS = 1)
          $i := 0
        while ($i <= $NUM_GROUPS+1)
          %ZoneID[$i] := find_zone(!ZoneName[$i])
          inc($i)
        end while
      end if
 
    declare %Event_Group[128]
      make_persistent(%Event_Group)
      read_persistent_var(%Event_Group)
 
    declare $last_sample_sel := -1
    declare $zone_ID := -1
      make_persistent($zoneID)


    declare ui_waveform $Waveform1(1,1)
      set_control_par(get_ui_id($Waveform1),$CONTROL_PAR_WIDTH,170)
      set_control_par(get_ui_id($Waveform1),$CONTROL_PAR_HEIGHT,100)
      set_control_par(get_ui_id($Waveform1),$CONTROL_PAR_BG_ALPHA,100)
      set_control_par (get_ui_id($Waveform1),$CONTROL_PAR_BG_COLOR, 9F9BC53h)
      set_control_par (get_ui_id($Waveform1), $CONTROL_PAR_WAVE_COLOR, 9EED2A2h)
      attach_zone($Waveform1, %ZoneID[$layer1], 0)

    declare ui_waveform $Waveform2(1,1)
      set_control_par(get_ui_id($Waveform2),$CONTROL_PAR_WIDTH,170)
      set_control_par(get_ui_id($Waveform2),$CONTROL_PAR_HEIGHT,100)
      set_control_par(get_ui_id($Waveform2),$CONTROL_PAR_BG_ALPHA,100)
      set_control_par (get_ui_id($Waveform2),$CONTROL_PAR_BG_COLOR, 9F9BC53h)
      set_control_par (get_ui_id($Waveform2), $CONTROL_PAR_WAVE_COLOR, 9EED2A2h)
      attach_zone($Waveform2, %ZoneID2[$layer2], 0)

      move_control_px($Waveform1,80,160)
      move_control_px($Waveform2,300,160)
      move_control_px($Layer1,80,100)
      move_control_px($Layer2,300,100)
end on 
  

function GUI_AttachZone
        attach_zone($waveform1,%ZoneID[%Event_Group[$VOICE_1]-1],0)
        set_control_par(get_ui_id($waveform1),$CONTROL_PAR_WT_ZONE,%ZoneID[%Event_Group[$VOICE_1]-1])

        attach_zone($waveform2,%ZoneID2[%Event_Group[$VOICE_2]-1],0)
        set_control_par(get_ui_id($waveform2),$CONTROL_PAR_WT_ZONE,%ZoneID2[%Event_Group[$VOICE_2]-1])
end function


on persistence_changed
        attach_zone($waveform1,$zoneID,0)
        attach_zone ($waveform2,$zoneID,0)
        call GUI_AttachZone

end on

on note
        disallow_group($ALL_GROUPS)
        allow_group($Layer1)
        allow_group($Layer2)
    
        ignore_event($EVENT_ID)
        $noteID := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
        wait(1)
        $zoneID := get_event_par($noteID,$EVENT_PAR_ZONE_ID)

          while ($NOTE_HELD = 1)

                  $play_pos := get_event_par($noteID,$EVENT_PAR_PLAY_POS)
                  set_ui_wf_property($Waveform1,$UI_WF_PROP_PLAY_CURSOR,0,$play_pos)
                  {message(get_ui_wf_property($Waveform1,$UI_WF_PROP_PLAY_CURSOR,0))}

                  set_ui_wf_property($Waveform2,$UI_WF_PROP_PLAY_CURSOR,0,$play_pos)
                  {message(get_ui_wf_property($Waveform2,$UI_WF_PROP_PLAY_CURSOR,0))}
                  wait (10000)
          end while
end on


{---------------------------Callbacks------------------------------}


on ui_control ($Layer1)
   $i := $LAYER1_FIRST
   while ($i<=$LAYER1_LAST)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($Layer1,1)
attach_zone($Waveform1, %ZoneID[$layer1], 0)
end on

on ui_control ($Layer2)
   $i := $LAYER2_FIRST
   while ($i<=$LAYER2_LAST)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($Layer2,1)
attach_zone($Waveform2, %ZoneID2[$layer2], 0)
end on
```


----------



## soundtrax (Mar 30, 2021)

have you already checked out this thread? https://www.native-instruments.com/...rom-two-layers-in-different-waveforms.409171/


----------



## Troy M (Mar 30, 2021)

soundtrax said:


> have you already checked out this thread? https://www.native-instruments.com/...rom-two-layers-in-different-waveforms.409171/


Brilliant thanks!


----------



## Troy M (Mar 30, 2021)

ok I have checked and triple checked this thread. But even by using that script as its printed there it throws the groups all over the place?? I've adapted it a little to try to fix the issue but all of my groups only display in waveform 2? or sometimes both but after a few hits only waveform 2 again. makes no sense?


```
on init
set_ui_height_px(150)
set_ui_width_px(550)
make_perfview
message ("")

declare $i
declare %layer_1[2] := (0,1)
declare %layer_2[2] := (2,3)
declare %zones1[2] := (0,1)
declare %zones2[2] := (2,3)
declare $noteID
declare $zoneID
declare $event_ID
declare $play_pos

declare const $layer_1first := 0
declare const $layer_1last := 1
declare const $layer_2first := 2
declare const $layer_2last := 3

declare ui_menu $menu_layer1
make_persistent($menu_layer1)
      $i := $layer_1first
   while ($i<=$layer_1last)
     add_menu_item($menu_layer1,group_name($i),$i)
     inc($i)
   end while

declare ui_menu $menu_layer2
  make_persistent($menu_layer2)
      $i := $layer_2first
   while ($i<=$layer_2last)
     add_menu_item($menu_layer2,group_name($i),$i)
     inc($i)
   end while

declare ui_waveform $waveform_1 (6,6)
set_control_par(get_ui_id($waveform_1),$CONTROL_PAR_WIDTH,300)
set_control_par(get_ui_id($waveform_1),$CONTROL_PAR_HEIGHT,100)
move_control_px($waveform_1, 5, 30)

declare ui_waveform $waveform_2 (6,6)
set_control_par(get_ui_id($waveform_2),$CONTROL_PAR_WIDTH,300)
set_control_par(get_ui_id($waveform_2),$CONTROL_PAR_HEIGHT,100)
move_control_px($waveform_2, 305, 30)
end on

on persistence_changed
        
        attach_zone($waveform_1,$zoneID,0)
        attach_zone ($waveform_2,$zoneID,0)
        
end on


on ui_control ($menu_layer1)
   $i := $layer_1first
   while ($i<=$layer_1last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer1,1)  
$event_ID := play_note (60, 1, 0, 1)
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer1)
wait(1)
$zoneID := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_1, $zoneID, 0)
end on

on ui_control ($menu_layer2)
   $i := $layer_2first
   while ($i<=$layer_2last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer2,1)
$event_ID := play_note (60, 1, 0, 1)  
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer2)
wait(1)
$zoneID := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_2, $zoneID, 0)
end on

on note
        disallow_group($ALL_GROUPS)
        allow_group($menu_layer1)
        allow_group($menu_layer2)
        ignore_event($event_ID)
        $noteID := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
        wait(1)
        $zoneID := get_event_par($noteID,$EVENT_PAR_ZONE_ID)


          while ($NOTE_HELD = 1)

                  $play_pos := get_event_par($noteID,$EVENT_PAR_PLAY_POS)
                  set_ui_wf_property($Waveform_1,$UI_WF_PROP_PLAY_CURSOR,0,$play_pos)
                  {message(get_ui_wf_property($Waveform1,$UI_WF_PROP_PLAY_CURSOR,0))}

                  set_ui_wf_property($Waveform_2,$UI_WF_PROP_PLAY_CURSOR,0,$play_pos)
                  {message(get_ui_wf_property($Waveform2,$UI_WF_PROP_PLAY_CURSOR,0))}
                  wait (10000)
          end while

    if ($zoneID < 2)
        attach_zone($waveform_1, $zoneID, 0)
     end if
     if ($zoneID > 1)
        attach_zone($waveform_2, $zoneID, 0)
    end if
end on
```


----------



## soundtrax (Mar 30, 2021)

It works if you delete your whole on note CB (at least here) - Not sure why you added that part to the original script.
If you need waveform cursors I'd put them in the on listener CB (but I never tried to script two cursors, so I don't know how difficult this actually is).


----------



## soundtrax (Mar 30, 2021)

Okay, I just tried and it works quite nicely with 2 waveform cursors.

Btw. If you want the waveforms to instantly appear when you load the nki, you need to repeat the menu ui_controls in an on persistence CB.

Here's the code including the wf-cursors:

```
on init
set_ui_height_px(150)
set_ui_width_px(550)
make_perfview
message ("")
declare $i
set_listener($NI_SIGNAL_TIMER_MS,10000)
declare $play_pos
declare $cursornote
declare %layer_1[2] := (0,1)
declare %layer_2[2] := (2,3)
declare %zones1[2] := (0,1)
declare %zones2[2] := (2,3)
declare $noteID
declare $zoneID
declare $event_ID
declare const $layer_1first := 0
declare const $layer_1last := 1
declare const $layer_2first := 2
declare const $layer_2last := 3
declare ui_menu $menu_layer1
make_persistent($menu_layer1)
      $i := $layer_1first
   while ($i<=$layer_1last)
     add_menu_item($menu_layer1,group_name($i),$i)
     inc($i)
   end while
declare ui_menu $menu_layer2
  make_persistent($menu_layer2)
      $i := $layer_2first
   while ($i<=$layer_2last)
     add_menu_item($menu_layer2,group_name($i),$i)
     inc($i)
   end while
declare ui_waveform $waveform_1 (6,6)
set_control_par(get_ui_id($waveform_1),$CONTROL_PAR_WIDTH,300)
set_control_par(get_ui_id($waveform_1),$CONTROL_PAR_HEIGHT,100)
move_control_px($waveform_1, 5, 30)
declare ui_waveform $waveform_2 (6,6)
set_control_par(get_ui_id($waveform_2),$CONTROL_PAR_WIDTH,300)
set_control_par(get_ui_id($waveform_2),$CONTROL_PAR_HEIGHT,100)
move_control_px($waveform_2, 305, 30)
end on

on ui_control ($menu_layer1)
   $i := $layer_1first
   while ($i<=$layer_1last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer1,1)
$event_ID := play_note (60, 1, 0, 1)
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer1)
wait(1)
$zoneID := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_1, $zoneID, 0)
end on

on ui_control ($menu_layer2)
   $i := $layer_2first
   while ($i<=$layer_2last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer2,1)
$event_ID := play_note (60, 1, 0, 1)
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer2)
wait(1)
$zoneID := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_2, $zoneID, 0)
end on

on note
$cursornote := $EVENT_ID
end on

on listener
if ($PLAYED_VOICES_INST # 0 )
       $play_pos := (get_event_par($cursornote,$EVENT_PAR_PLAY_POS))
       set_ui_wf_property($Waveform_1,$UI_WF_PROP_PLAY_CURSOR,0,$play_pos)
    set_ui_wf_property($Waveform_2,$UI_WF_PROP_PLAY_CURSOR,0,$play_pos)
end if

end on
```

EDIT:I just noticed a little mistake: make_persistent($menu_layer1) was missing - so menu1 was always loading group0 on init - it's corrected now!


----------



## Troy M (Mar 31, 2021)

I must be missing something here? I use this script unchanged I even built a new instrument with new groups and yet I get absolutely nothing, I can select the groups and they play correctly but neither waveforms display anything? 

Only by adding....
attach_zone($waveform_1,$zoneID,0)
attach_zone($waveform_2,$zoneID,0)
to the {on note} section does it display a waveform, but only one waveform and not the correct one.


----------



## soundtrax (Mar 31, 2021)

hm, I really have no idea why you don't get it working - it works here (in K5 and K6)


----------



## EvilDragon (Mar 31, 2021)

You're putting the same zone ID to the two waveform displays... each of them needs to show a different zone ID based on which group you have selected...


----------



## Troy M (Mar 31, 2021)

EvilDragon said:


> You're putting the same zone ID to the two waveform displays... each of them needs to show a different zone ID based on which group you have selected...


How come it works for him but not for me? Could you please show me exactly what you mean with the zone ID? I've been at this for days.


----------



## Troy M (Mar 31, 2021)

soundtrax said:


> hm, I really have no idea why you don't get it working - it works here (in K5 and K6)


I think the issue here is that I am not just using one sample stretched, this is for a sound design library so the waveform need to update for every key pressed.


----------



## EvilDragon (Mar 31, 2021)

```
$noteID := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
        wait(1)
        $zoneID := get_event_par($noteID,$EVENT_PAR_ZONE_ID)
```

That zone ID.


----------



## Troy M (Mar 31, 2021)

EvilDragon said:


> ```
> $noteID := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
> wait(1)
> $zoneID := get_event_par($noteID,$EVENT_PAR_ZONE_ID)
> ...


I do not know what I am supposed to do with that?


----------



## soundtrax (Mar 31, 2021)

yeah, the script works only for one zone per group, and the waveform gets updated when choosing a different group from the menu. I have no idea how to add an on note update for both of the waveforms. Maybe Mario knows more.


----------



## EvilDragon (Mar 31, 2021)

You do the same thing as above, but with two play_notes(), each targetting different group.


----------



## Troy M (Mar 31, 2021)

EvilDragon said:


> You do the same thing as above, but with two play_notes(), each targetting different group.


Can you please show me? I have tried everything I can think of and it just doesn't work.


----------



## Troy M (Mar 31, 2021)

I am so close with this!! Both waves are displaying in wave 1 but are actually working ALMOST!
I just need a little more guidance with the on note i think 


```
on init
set_ui_height_px(150)
set_ui_width_px(550)
make_perfview
message ("")

declare $i
declare $b
set_listener($NI_SIGNAL_TIMER_MS,10000)
declare $zzone
declare $play_pos
declare $cursornote
declare %layer_1[2] := (0,1)
declare %layer_2[2] := (2,3)
declare %zones1[2] := (0,1)
declare %zones2[2] := (2,3)
declare $noteID
declare $zoneID
declare $event_ID
declare const $layer_1first := 0
declare const $layer_1last := 1
declare const $layer_2first := 2
declare const $layer_2last := 3

{MENUS------------------------------------------}

declare ui_menu $menu_layer1
make_persistent($menu_layer1)
      $i := $layer_1first
   while ($i<=$layer_1last)
     add_menu_item($menu_layer1,group_name($i),$i)
     inc($i)
   end while

declare ui_menu $menu_layer2
  make_persistent($menu_layer2)
      $i := $layer_2first
   while ($i<=$layer_2last)
     add_menu_item($menu_layer2,group_name($i),$i)
     inc($i)
   end while

{WAVEFORMS------------------------------------------}

declare ui_waveform $waveform_1 (6,6)
set_control_par(get_ui_id($waveform_1),$CONTROL_PAR_WIDTH,300)
set_control_par(get_ui_id($waveform_1),$CONTROL_PAR_HEIGHT,100)
move_control_px($waveform_1, 5, 30)

declare ui_waveform $waveform_2 (6,6)
set_control_par(get_ui_id($waveform_2),$CONTROL_PAR_WIDTH,300)
set_control_par(get_ui_id($waveform_2),$CONTROL_PAR_HEIGHT,100)
move_control_px($waveform_2, 305, 30)
end on

on persistence_changed
  attach_zone($waveform_1, %zones1[$menu_layer1], 0)
   $i := $layer_1first
   while ($i<=$layer_1last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer1,1)
$event_ID := play_note (60, 1, 0, 1)  
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer1)
wait(1)
$zoneID := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_1, $zoneID, 0)

attach_zone($waveform_2, %zones1[$menu_layer2], 0)
   $i := $layer_2first
   while ($i<=$layer_2last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer2,1)
$event_ID := play_note (60, 1, 0, 1)  
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer2)
wait(1)
$zoneID := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_2, $zoneID, 0)
end on

{CALLBACKS------------------------------------------}

on ui_control ($menu_layer1)
   $i := $layer_1first
   while ($i<=$layer_1last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer1,1)
$event_ID := play_note (60, 1, 0, 1)
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer1)
wait(1)
$zoneID := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_1, $zoneID, 0)
end on

on ui_control ($menu_layer2)
   $i := $layer_2first
   while ($i<=$layer_2last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer2,1)
$event_ID := play_note (60, 1, 0, 1)
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer2)
wait(1)
$zoneID := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_2, $zoneID, 0)
end on

on note
$cursornote := $EVENT_ID

    $noteID := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
    wait(1)
    $zoneID := get_event_par($noteID,$EVENT_PAR_ZONE_ID)

    $zzone := get_event_par($EVENT_ID,$EVENT_PAR_ZONE_ID)
        $b := get_sample_length($zzone)
        if($b > 0)
            attach_zone($Waveform_1,$zoneID,0)
        end if
end on 


on listener
if ($PLAYED_VOICES_INST # 0 )
       $play_pos := (get_event_par($cursornote,$EVENT_PAR_PLAY_POS))
       set_ui_wf_property($Waveform_1,$UI_WF_PROP_PLAY_CURSOR,0,$play_pos)
    set_ui_wf_property($Waveform_2,$UI_WF_PROP_PLAY_CURSOR,0,$play_pos)
end if
end on
```


----------



## EvilDragon (Mar 31, 2021)

You need to play_note() with just the first selected group allowed (use set_control_par_arr($EVENT_ID, $EVENT_PAR_ALLOW_GROUP, group id, value) on the $noteID. Then do the same for the second selected group.


----------



## Troy M (Mar 31, 2021)

EvilDragon said:


> You need to play_note() with just the first selected group allowed (use set_control_par_arr($EVENT_ID, $EVENT_PAR_ALLOW_GROUP, group id, value) on the $noteID. Then do the same for the second selected group.


Do you mean like this? it works but waveform 2 isn't responding correctly. the zzone thing is working on waveform 1 but how do i adapt it for both? thanks


```
on note
$cursornote := $EVENT_ID

    $noteID := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
    set_control_par_arr($EVENT_ID, $EVENT_PAR_ALLOW_GROUP, $menu_layer1, 0)
    wait(1)
    $zoneID := get_event_par($noteID,$EVENT_PAR_ZONE_ID)

    $noteID := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
    set_control_par_arr($EVENT_ID, $EVENT_PAR_ALLOW_GROUP, $menu_layer2, 0)
    wait(1)
    $zoneID := get_event_par($noteID,$EVENT_PAR_ZONE_ID)

    $zzone := get_event_par($EVENT_ID,$EVENT_PAR_ZONE_ID)
        $b := get_sample_length($zzone)
        if($b > 0)
            attach_zone($Waveform_1,$zoneID,0)
        end if
end on
```


----------



## EvilDragon (Mar 31, 2021)

You need to first attach zone for the first group, THEN for the second ggroup. If it's confusing, use copies of variables ($noteID1, $noteID2, etc).


----------



## Troy M (Apr 2, 2021)

EvilDragon said:


> You need to first attach zone for the first group, THEN for the second ggroup. If it's confusing, use copies of variables ($noteID1, $noteID2, etc).


Again I am trying really hard to figure this out, I just can't figure this out. I am begging you Please can you fix this?

```
on init
        set_ui_width_px(1000)
        set_ui_height_px(350)
        make_perfview
        set_script_title("")
        message("")

        set_control_par_str($INST_WALLPAPER_ID,$CONTROL_PAR_PICTURE,"wallpaper")
        set_control_par_str($INST_ICON_ID,$CONTROL_PAR_PICTURE,"icon")
        set_skin_offset(0)

    declare $counter
    declare %key_color[128]
    
    declare $i
    set_listener($NI_SIGNAL_TIMER_MS,10000)
    
    declare $play_pos
    declare $cursornote
    declare $item_idx

    declare $zzone
    declare $zzone2
    declare $zzone_wave1
    declare $zzone_wave2
    declare $zoneID1
    declare $zoneID2
    declare $noteID1
    declare $noteID2
    declare $event_ID

    declare %layer1[2] := (0,1)
    declare %layer2[2] := (2,3) 
    declare %zones1[2] := (0,1)
    declare %zones2[2] := (2,3)
        declare const $LAYER_1first := 0
        declare const $LAYER_1last := 1
        declare const $LAYER_2first := 2
        declare const $LAYER_2last := 3

    declare ui_menu $menu_layer1
        set_control_par_str(get_ui_id($menu_layer1),$CONTROL_PAR_TEXT,"")
        set_control_par_str(get_ui_id($menu_layer1),$CONTROL_PAR_PICTURE,"Menu2")
        set_control_par(get_ui_id($menu_layer1),$CONTROL_PAR_TEXT_ALIGNMENT,1)
        set_control_par(get_ui_id($menu_layer1), $CONTROL_PAR_TEXTPOS_Y,4)
        set_control_par(get_ui_id($menu_layer1),$CONTROL_PAR_HEIGHT,20)
        set_control_par(get_ui_id($menu_layer1),$CONTROL_PAR_WIDTH,200)
        make_persistent($menu_layer1)
      $i := $layer_1first
   while ($i<=$layer_1last)
     add_menu_item($menu_layer1,group_name($i),$i)
     inc($i)
   end while

  declare ui_menu $menu_layer2
        set_control_par_str(get_ui_id($menu_layer2),$CONTROL_PAR_TEXT,"")
        set_control_par_str(get_ui_id($menu_layer2),$CONTROL_PAR_PICTURE,"Menu2")
        set_control_par(get_ui_id($menu_layer2),$CONTROL_PAR_TEXT_ALIGNMENT,1)
        set_control_par(get_ui_id($menu_layer2), $CONTROL_PAR_TEXTPOS_Y,4)
        set_control_par(get_ui_id($menu_layer2),$CONTROL_PAR_HEIGHT,20)
        set_control_par(get_ui_id($menu_layer2),$CONTROL_PAR_WIDTH,200)
        make_persistent($menu_layer2)
      $i := $layer_2first
   while ($i<=$layer_2last)
     add_menu_item($menu_layer2,group_name($i),$i)
     inc($i)
   end while

   declare ui_waveform $waveform_1 (6,6)

        set_control_par(get_ui_id($Waveform_1),$CONTROL_PAR_WIDTH,280)
        set_control_par(get_ui_id($Waveform_1),$CONTROL_PAR_HEIGHT,120)
        set_control_par(get_ui_id($Waveform_1),$CONTROL_PAR_BG_ALPHA,250)
        set_control_par (get_ui_id($Waveform_1),$CONTROL_PAR_BG_COLOR, 0000000)
        set_control_par (get_ui_id($Waveform_1), $CONTROL_PAR_WAVE_COLOR, 6222222)


    declare ui_waveform $waveform_2 (6,6)

    set_control_par(get_ui_id($Waveform_2),$CONTROL_PAR_WIDTH,280)
    set_control_par(get_ui_id($Waveform_2),$CONTROL_PAR_HEIGHT,120)
    set_control_par(get_ui_id($Waveform_2),$CONTROL_PAR_BG_ALPHA,250)
    set_control_par (get_ui_id($Waveform_2),$CONTROL_PAR_BG_COLOR, 0000000)
    set_control_par (get_ui_id($Waveform_2), $CONTROL_PAR_WAVE_COLOR, 6222222)

        move_control_px($menu_layer1,75,41)   
        move_control_px($menu_layer2,671,41) 

        move_control_px($Waveform_1,60,70)
        move_control_px($Waveform_2,657,70)
end on 
    
on persistence_changed  

attach_zone($waveform_1, %zones1[$menu_layer1], 0)
   $i := $layer_1first
   while ($i<=$layer_1last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer1,1)
$event_ID := play_note (60, 1, 0, 1)  
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer1)
wait(1)
$zoneID1 := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_1, $zoneID1, 0)

attach_zone($waveform_2, %zones2[$menu_layer2], 0)
   $i := $layer_2first
   while ($i<=$layer_2last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer2,1)
$event_ID := play_note (60, 1, 0, 1)  
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer2)
wait(1)
$zoneID2 := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_2, $zoneID2, 0)
end on 

on note
    {message($EVENT_NOTE) {Displays Note ID}  
    disallow_group($ALL_GROUPS)
    allow_group($menu_layer1)
    allow_group($menu_layer2)
    $cursornote := $EVENT_ID

    $noteID1 := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
    set_control_par_arr($EVENT_ID, $EVENT_PAR_ALLOW_GROUP, $menu_layer1, 0)
    wait(1)
    $zoneID1 := get_event_par($noteID1,$EVENT_PAR_ZONE_ID)

    $noteID2 := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
    set_control_par_arr($EVENT_ID, $EVENT_PAR_ALLOW_GROUP, $menu_layer2, 0)
    wait(1)
    $zoneID2 := get_event_par($noteID2,$EVENT_PAR_ZONE_ID)

    $zzone := get_event_par($EVENT_ID,$EVENT_PAR_ZONE_ID)
        $zzone_wave1 := get_sample_length($zzone)
        if($zzone_wave1 > 0)
            attach_zone($Waveform_1,$zoneID1,0)
        end if
    $zzone2 := get_event_par($EVENT_ID,$EVENT_PAR_ZONE_ID)
        $zzone_wave2 := get_sample_length($zzone2)
        if($zzone_wave2 > 0)
            attach_zone($Waveform_2,$zoneID2,0)
        end if
end on

on listener
if ($PLAYED_VOICES_INST # 0 )
       $play_pos := (get_event_par($cursornote,$EVENT_PAR_PLAY_POS))
       set_ui_wf_property($Waveform_1,$UI_WF_PROP_PLAY_CURSOR,0,$play_pos)
    set_ui_wf_property($Waveform_2,$UI_WF_PROP_PLAY_CURSOR,0,$play_pos)
end if
end on

on ui_control ($menu_layer1)
   $i := $layer_1first
   while ($i<=$layer_1last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer1,1)
$event_ID := play_note (60, 1, 0, 1)
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer1)
wait(1)
$zoneID1 := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_1, $zoneID1, 0)
end on

on ui_control ($menu_layer2)
   $i := $layer_2first
   while ($i<=$layer_2last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer2,1)
$event_ID := play_note (60, 1, 0, 1)
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer2)
wait(1)
$zoneID2 := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_2, $zoneID2, 0)
end on
```


----------



## soundtrax (Apr 2, 2021)

The problem is that you changed the order of the commands in your on note CB (and you added a disallow / allow_groups at the beginning - please delete these lines).
It should simply be:

1. retrieve noteID (with play_note)
2. disallow all groups (with 'set_event_par_arr' not 'set_control_par_arr)
3. allow the selected group (with 'set_event_par_arr')
4. wait
5. $zoneID := ....
6. attach the zone
- Then do the same for the second menu!

(btw. You don't even need two different "noteID"s - but it doesn't hurt either)

do you really need the sample_length check when attaching? because there won't be a waveform if there is no sample loaded (even without this).

Also double-check your on_persistence CB, the attach_zone line at the beginning doesn't seem to make much sense.

Hope you get this finally sorted!


----------



## Troy M (Apr 2, 2021)

soundtrax said:


> The problem is that you changed the order of the commands in your on note CB (and you added a disallow / allow_groups at the beginning - please delete these lines).
> It should simply be:
> 
> 1. retrieve noteID (with play_note)
> ...


Thanks for the help but I'm still not getting anywhere? the disallow groups in this position stops curser playback altogether and individual key wave display is non existent also. Maybe I am just writing this wrong? would you mind changing the on note and on persistence CB for me to see?


----------



## soundtrax (Apr 2, 2021)

this should work:

```
on note

if (in_range($EVENT_NOTE,36,60)) {or whatever your note range is}

$cursornote := $EVENT_ID

$noteID1 := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
set_event_par_arr($noteID1, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($noteID1, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer1)
wait(1)
$zoneID1 := get_event_par($noteID1,$EVENT_PAR_ZONE_ID)
attach_zone($Waveform_1,$zoneID1,0)

$noteID2 := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
set_event_par_arr($noteID2, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($noteID2, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer2)
wait(1)
$zoneID2 := get_event_par($noteID2,$EVENT_PAR_ZONE_ID)
attach_zone($Waveform_2,$zoneID2,0)

end if
end on
```
(I see now why you included the sample length check - without it, you get an error message if a zone is empty.)

EDIT: your 'if sample_length..." check didn't work here, I'd rather suggest a if (in range...). I've corrected the script.

So far, I have no solution for the cursors. I didn't notice it first, but somehow they interfere with each other.


----------



## Troy M (Apr 3, 2021)

We are actually really incredibly close with this now. I thought maybe my on persistence CB is not quite correct? I'm not sure cause the only real issue now is that only one waveform display works at a time, other blacks out when one is displaying, but both work perfectly by themselves. The setup is one group is playing on the left side of the keyboard and the other from the right so really we need both of those waveform displays working together. Any further assistance is massively appreciated. Thank you so much! OH NO Iv'e just noticed this has messed up the volume controls for two outputs. 

```
on init
        set_ui_width_px(1000)
        set_ui_height_px(350)
        make_perfview
        set_script_title("")
        message("")

        set_control_par_str($INST_WALLPAPER_ID,$CONTROL_PAR_PICTURE,"wallpaper")
        set_control_par_str($INST_ICON_ID,$CONTROL_PAR_PICTURE,"icon")
        set_skin_offset(0)

    declare $counter
    declare %key_color[128]
   
    declare $i
    set_listener($NI_SIGNAL_TIMER_MS,10000)
   
    declare $play_pos
    declare $cursornote
    declare $item_idx

    declare $zzone
    declare $zzone2
    declare $zzone_wave1
    declare $zzone_wave2
    declare $zoneID1
    declare $zoneID2
    declare $noteID1
    declare $noteID2
    declare $event_ID

    declare %layer1[2] := (0,1)
    declare %layer2[2] := (2,3)
    declare %zones1[2] := (0,1)
    declare %zones2[2] := (2,3)
        declare const $LAYER_1first := 0
        declare const $LAYER_1last := 1
        declare const $LAYER_2first := 2
        declare const $LAYER_2last := 3

    declare ui_menu $menu_layer1
        set_control_par_str(get_ui_id($menu_layer1),$CONTROL_PAR_TEXT,"")
        set_control_par_str(get_ui_id($menu_layer1),$CONTROL_PAR_PICTURE,"Menu2")
        set_control_par(get_ui_id($menu_layer1),$CONTROL_PAR_TEXT_ALIGNMENT,1)
        set_control_par(get_ui_id($menu_layer1), $CONTROL_PAR_TEXTPOS_Y,4)
        set_control_par(get_ui_id($menu_layer1),$CONTROL_PAR_HEIGHT,20)
        set_control_par(get_ui_id($menu_layer1),$CONTROL_PAR_WIDTH,200)
        make_persistent($menu_layer1)
      $i := $layer_1first
   while ($i<=$layer_1last)
     add_menu_item($menu_layer1,group_name($i),$i)
     inc($i)
   end while

  declare ui_menu $menu_layer2
        set_control_par_str(get_ui_id($menu_layer2),$CONTROL_PAR_TEXT,"")
        set_control_par_str(get_ui_id($menu_layer2),$CONTROL_PAR_PICTURE,"Menu2")
        set_control_par(get_ui_id($menu_layer2),$CONTROL_PAR_TEXT_ALIGNMENT,1)
        set_control_par(get_ui_id($menu_layer2), $CONTROL_PAR_TEXTPOS_Y,4)
        set_control_par(get_ui_id($menu_layer2),$CONTROL_PAR_HEIGHT,20)
        set_control_par(get_ui_id($menu_layer2),$CONTROL_PAR_WIDTH,200)
        make_persistent($menu_layer2)
      $i := $layer_2first
   while ($i<=$layer_2last)
     add_menu_item($menu_layer2,group_name($i),$i)
     inc($i)
   end while

   declare ui_waveform $waveform_1 (6,6)

        set_control_par(get_ui_id($Waveform_1),$CONTROL_PAR_WIDTH,280)
        set_control_par(get_ui_id($Waveform_1),$CONTROL_PAR_HEIGHT,120)
        set_control_par(get_ui_id($Waveform_1),$CONTROL_PAR_BG_ALPHA,250)
        set_control_par (get_ui_id($Waveform_1),$CONTROL_PAR_BG_COLOR, 0000000)
        set_control_par (get_ui_id($Waveform_1), $CONTROL_PAR_WAVE_COLOR, 6222222)


    declare ui_waveform $waveform_2 (6,6)

    set_control_par(get_ui_id($Waveform_2),$CONTROL_PAR_WIDTH,280)
    set_control_par(get_ui_id($Waveform_2),$CONTROL_PAR_HEIGHT,120)
    set_control_par(get_ui_id($Waveform_2),$CONTROL_PAR_BG_ALPHA,250)
    set_control_par (get_ui_id($Waveform_2),$CONTROL_PAR_BG_COLOR, 0000000)
    set_control_par (get_ui_id($Waveform_2), $CONTROL_PAR_WAVE_COLOR, 6222222)

        move_control_px($menu_layer1,75,41)  
        move_control_px($menu_layer2,671,41)

        move_control_px($Waveform_1,60,70)
        move_control_px($Waveform_2,657,70)
end on
   
on persistence_changed 

attach_zone($Waveform_1,$zoneID1,0)
   $i := $layer_1first
   while ($i<=$layer_1last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer1,1)
$event_ID := play_note (60, 1, 0, 1) 
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer1)
wait(1)
$zoneID1 := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_1, $zoneID1, 0)

attach_zone($Waveform_2,$zoneID2,0)
   $i := $layer_2first
   while ($i<=$layer_2last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer2,1)
$event_ID := play_note (60, 1, 0, 1) 
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer2)
wait(1)
$zoneID2 := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_2, $zoneID2, 0)
end on

on note

if (in_range($EVENT_NOTE,0,128)) {or whatever your note range is}

$cursornote := $EVENT_ID

$noteID1 := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
set_event_par_arr($noteID1, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($noteID1, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer1)
wait(1)
$zoneID1 := get_event_par($noteID1,$EVENT_PAR_ZONE_ID)
attach_zone($Waveform_1,$zoneID1,0)

$noteID2 := play_note($EVENT_NOTE,$EVENT_VELOCITY,0,-1)
set_event_par_arr($noteID2, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($noteID2, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer2)
wait(1)
$zoneID2 := get_event_par($noteID2,$EVENT_PAR_ZONE_ID)
attach_zone($Waveform_2,$zoneID2,0)

end if
end on

on listener
if ($PLAYED_VOICES_INST # 0 )
       $play_pos := (get_event_par($cursornote,$EVENT_PAR_PLAY_POS))
       set_ui_wf_property($Waveform_1,$UI_WF_PROP_PLAY_CURSOR,0,$play_pos)
    set_ui_wf_property($Waveform_2,$UI_WF_PROP_PLAY_CURSOR,0,$play_pos)
end if
end on

on ui_control ($menu_layer1)
   $i := $layer_1first
   while ($i<=$layer_1last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer1,1)
$event_ID := play_note (60, 1, 0, 1)
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer1)
wait(1)
$zoneID1 := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_1, $zoneID1, 0)
end on

on ui_control ($menu_layer2)
   $i := $layer_2first
   while ($i<=$layer_2last)
     purge_group($i,0)
     inc($i)
   end while
   purge_group($menu_layer2,1)
$event_ID := play_note (60, 1, 0, 1)
change_vol($event_ID, -200000, 0)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 0, $ALL_GROUPS)
set_event_par_arr($event_ID, $EVENT_PAR_ALLOW_GROUP, 1, $menu_layer2)
wait(1)
$zoneID2 := get_event_par($event_ID,$EVENT_PAR_ZONE_ID)
attach_zone($waveform_2, $zoneID2, 0)
end on
```


----------



## soundtrax (Apr 3, 2021)

on persistence CB: You need to delete the "attach_zone..." lines you added for both menus in the beginning.
And you should also adjust the note numbers triggering the zones. $event_ID := play_note (60, 1, 0, 1) Right know it is 60 (C3) for both menus. 
In your case 36 (for the first menu) and 60 (for the second) might be a better choice (in the on_persistence CB and also in the ui_controls!)
These silent notes trigger the waveforms you see on init and after you change one of the menus.

and btw. I guess it's not the greatest idea to expand the nki width to 1000px BEFORE sorting out the basic functions. Right now it is not really possible to check what happens when you hit the 'apply' button.


----------



## Troy M (Apr 3, 2021)

soundtrax said:


> on persistence CB: You need to delete the "attach_zone..." lines you added for both menus in the beginning.
> And you should also adjust the note numbers triggering the zones. $event_ID := play_note (60, 1, 0, 1) Right know it is 60 (C3) for both menus.
> In your case 36 (for the first menu) and 60 (for the second) might be a better choice (in the on_persistence CB and also in the ui_controls!)
> These silent notes trigger the waveforms you see on init and after you change one of the menus.
> ...


Yeh good point with the width. I will work through these points over the next few days. Hopefully get the results .. thanjs


----------

