Jump to content


Photo

[Solved] phrase keymap assing mapping.note_range whitout overlap

overlap keymap phrase mapping.note_range

  • Please log in to reply
2 replies to this topic

#1 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1525 posts
  • Gender:Male
  • Location:Spain

Posted 13 February 2018 - 15:49

Hi! Yesterday I was trying to build a function to configure the keymap of the selected phrase, with a specific range of notes, returned by two valueboxes:

function pht_phrase_keymap()
  local song = renoise.song()  
  if ( rna.window.active_middle_frame ~= renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_PHRASE_EDITOR ) or
     ( song.selected_instrument.phrase_editor_visible == false ) or
     ( song.selected_instrument.phrase_playback_mode ~= renoise.Instrument.PHRASES_PLAY_KEYMAP ) then
     pht_show_phrase_editor_keymap()
     return
  else
    local value_a = vws["PHT_VB_MAP_FIRST_NOTE"].value  --VALUEBOX 1
    local value_b = vws["PHT_VB_MAP_LAST_NOTE"].value   --VALUEBOX 2
    local ins = song.selected_instrument
    local id_ph_map = #ins.phrase_mappings + 1
    local sph = song.selected_phrase
    local sphi = song.selected_phrase_index

    --delete all phrases
    --for i = #song.selected_instrument.phrase_mappings, 1, -1 do
    --  song.selected_instrument:delete_phrase_mapping_at( i )
    --end

    print("id_ph_map", id_ph_map )
    print("sphi", sphi )

    --check if the index of keymap is free to insert a new map
    if ( ins:can_insert_phrase_mapping_at( id_ph_map ) == true ) then
      
      --check if the selected phrase is not mapped
      if ( sph.mapping == nil ) then
        --map the selected frase inside the index of keymap
        ins:insert_phrase_mapping_at( id_ph_map, sph )

        --assign the note range of the selected phrase with two valueboxes  --<----------------- RETURN ERROR of overlap
        sph.mapping.note_range = { value_a, value_b }
        
        --asign the base note of the selected phrase
        sph.mapping.base_note = value_a
        
        --autoseek & shuffle of the selected phrase
        sph.autoseek = vws["PHT_PHRASE_AUTOSEEK"].value 
        sph.shuffle = vws["PHT_PHRASE_SHUFFLE"].value / 100
      end
    end
  end
end

This line:

sph.mapping.note_range = { value_a, value_b }

use two valueboxes to return value_a and value_b, with range of 0 to 119, and always value_b >= value_a. The problem is that if there are already other phrases that occupy a certain and random range within the keymap, how to avoid overlap? I should put some condition that proves that the assigned range is free. It's possible?

 

The typical error message is this:

*** std::logic_error: 'phrase mappings may not overlap. prev. phrase mapping's end is '56'. this mappings start must be bigger than that.'
*** stack traceback:
***   [C]: ?
***   [C]: in function '__newindex'
***   [string "do..."]:22: in function <[string "do..."]:9>
***   .\lua/miscellaneous.lua:141: in function 'pht_phrase_keymap'
***   .\lua/miscellaneous.lua:233: in function <.\lua/miscellaneous.lua:233>

How to avoid this error?

 

The intention is to be able to select a random phrase and assign a random range of mapping inside keymap mode.

 

Thanks!!! :)


Edited by Raul (ulneiz), 15 February 2018 - 16:43.

:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#2 danoise

danoise

    Probably More God or Borg Than Human Member

  • Renoise Team
  • PipPipPipPipPipPipPipPipPipPipPipPipPipPipPip
  • 6942 posts
  • Gender:Male
  • Location:Berlin
  • Interests:wildlife + urban trekking

Posted 15 February 2018 - 15:17

I think you'll find the method xPhraseManager.get_available_slot in xLib handy

https://github.com/r...raseManager.lua

 

Just copy-paste if you don't want to include the whole class... smile.png


Tracking with Stuff. API wishlist | Soundcloud


#3 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1525 posts
  • Gender:Male
  • Location:Spain

Posted 15 February 2018 - 16:06

I think you'll find the method xPhraseManager.get_available_slot in xLib handy

https://github.com/r...raseManager.lua

 

Just copy-paste if you don't want to include the whole class... smile.png

 

Thanks Danoise! I'll review it, to understand how that function works  :lol:

 

Finally, I have chosen to rewrite my entire function, with a little more flexibility, so that it allows selecting the initial phrase, the initial note and the range of notes. As the editor of phrases already allows to drag and drop, I have preferred to do a more global function, so as not to complicate it too much and that it is easy to configure the keymap quickly.

 

Finally, the function that I have built is the following:

function pht_auto_keymap()
  local song = renoise.song()  
  local ins = song.selected_instrument
  if ( rna.window.active_middle_frame ~= renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_PHRASE_EDITOR ) or
     ( ins.phrase_editor_visible == false ) or
     ( ins.phrase_playback_mode ~= renoise.Instrument.PHRASES_PLAY_KEYMAP ) then
     pht_show_phrase_editor_keymap()
     return
  else
    local value_a = vws["PHT_VB_MAP_FIRST_NOTE"].value - 1
    local value_b = vws["PHT_VB_MAP_RANGE_NOTE"].value - 1
    local value_c = song.selected_phrase_index - 1
    --delete all phrases
    for i = #ins.phrase_mappings, 1, -1 do
      ins:delete_phrase_mapping_at( i )
    end
    --insert all phrases
    for i = 1, #ins.phrases do
      if ( value_a + i * vws["PHT_VB_MAP_RANGE_NOTE"].value <= 119 ) and ( i + value_c <= #ins.phrases ) then
        if ( ins:can_insert_phrase_mapping_at( i ) ) then
          local ph = ins:phrase( i + value_c )
          ins:insert_phrase_mapping_at( i, ph )
          if ( i == 1 ) then
            ph.mapping.note_range = { i + value_a, i + value_a + value_b }
          else
            ph.mapping.note_range = { ph.mapping.note_range[1], ph.mapping.note_range[1] + value_b }
          end
          ph.mapping.base_note = ph.mapping.note_range[1]
          ph.shuffle = vws["PHT_PHRASE_SHUFFLE"].value / 100
          ph.autoseek = vws["PHT_PHRASE_AUTOSEEK"].value 
          ph.mapping.looping = vws["PHT_PHRASE_LOOP"].value
          pht_change_status( "AutoKeymap has been executed successfully." )
        end
      end
    end
    if ( #ins.phrase_mappings == 0 ) then
      pht_change_status( "AutoKeymap is not possible. Reconfigure it!" )
    end
  end
end

 

"PHT_VB_MAP_FIRST_NOTE" is the id of a valuebox of range 0 to 119, "PHT_VB_MAP_RANGE_NOTE", is the id of other valuebox of range 1 to 24. After manually setting these values, you trigger the function with a button and you're done.

 
 
The reason for this choice is because, apparently, .insert_phrase_mapping_at covers every last note (119), and when you add a phrase to the left of an existing one, it will always overlap. Maybe it would be easier for the programmer that .insert_phrase_mapping_at only cover only a note, and then expand it after with .mapping.note_range.
 
Anyway, I'm very happy with this new function. It works fine with all the limits.

Edited by Raul (ulneiz), 15 February 2018 - 16:48.

:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler





Also tagged with one or more of these keywords: overlap keymap, phrase, mapping.note_range