OpenNoteBlockStudio icon indicating copy to clipboard operation
OpenNoteBlockStudio copied to clipboard

Improve note selections and macro operations

Open IoeCmcomc opened this issue 2 months ago • 2 comments

This pull request aims to improve the performance of selection-related actions, macro operations and song loading. It also allows users to undo and redo macro changes.

Changes

  • Reimplement array_to_selection(), selection_code_update(), selection_load(), selection_load_ext(), selection_to_array(), region_code_get() and region_code_load() to utilize buffers because buffer functions are much faster than string functions.
  • The program will now try to compress selection code strings and encode them to base64 before saving them to the history in order to reduce memory usage. The strings will be decompressed when needed. ~~The selection_code string is kept uncompressed.~~ The selection_code variable is also compressed as well. Selection code (de)compression is implemented in try_compress_selection() and try_decompress_selection(). (De)compression overhead is insignificant. A selection code will not be compressed if the compressed string is longer than the original string or if the original string is short (less than 16 characters).
  • "Set panning", "Set pitch", "Set velocity", "Replace key" and "Reset all properties" macros are now either reimplemented or changed to call existing functions, which makes these macros as fast as "Change instrument..." command can be.
  • Other macros also have performance changes, which improve the macro speed for the selection of less than 20k notes.
    • Previously, a nonsimple macro had the following steps: selection data -> selection code -> selection code array -> macro -> altered selection code array -> altered selection code -> altered selection data.
    • This PR changes the pipeline to the following steps: selection data -> selection code array -> macro -> altered selection code array -> altered selection data. Two steps are skipped.
  • Replace if else statements in action_undo() and action_redo() with switch case statements.
  • Use array_length(arr_data) instead of string_count("|", str) to calculate total_vals; use macro_column_count() to replace string_count("-1", ...) in some macros;
  • Selection codes created by macro operations will now be added to the history, which effectively enables macro undoing/redoing.
  • All macros now will deselect selected notes after being applied unless Alt is pressed.
  • Call functions directly instead of using script_execute(), and disable surface depth.
  • Improve the speed when pasting a large selection to an existing area by using the @ accessor or turning off copy-on-write. Because copy-on-write is a project-wide option that will affect all arrays in the program, I decided to keep it on;
  • Move the code to check and extend the selection_exists array to separate functions.
  • Improve song opening performance by 6x, by initializing arrays in the reverse orders and reading notes to a temporal array before adding notes in the reverse orders.
  • Add a new function array_grow_then_set() to set a value at an index to an array and grow the array by the factor of 1.5 when necessary, which should give a better time complexity than array_push().

Bugfixes

  • Fix the solo property of layers not taken into account when displaying and playing back if the layers are loaded from a file.
  • Fix a pattern file that can't be drag-dropped two times in a row.
  • Fix playback looping doesn't respect the "Times to loop" property.

IoeCmcomc avatar Apr 16 '24 16:04 IoeCmcomc