Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve note selections and macro operations #448

Merged
merged 17 commits into from
Jul 8, 2024

Conversation

IoeCmcomc
Copy link

@IoeCmcomc IoeCmcomc commented Apr 16, 2024

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.

- Reimplement `array_to_selection()`, `selection_code_update()`, `selection_load()`, `selection_load_ext()` and `selection_to_array()` to utilize buffers;
- The program will now try to compress selection code strings and encode to base64 before saving to the history;
- A selection code will not be compressed if the compressed string is longer than the original string;
- Selection code (de)compression is implemented in `try_compress_selection()` and `try_decompress_selection()`;
- Replace if else statements in `action_redo()` and `action_redo()` with switch case statements.
This will effectively allow users to undo and redo macro operations.
"Set panning", "Set pitch", "Set velocity", "Replace key" and "Reset" macros are now much faster.
@Bentroen
Copy link
Member

Thank you for the pull request! These are some great improvements.
I'm gonna review it soon, but since it touches some vital parts of the NBS workflow, I'd like to make sure everything works as expected before merging :)

@Bentroen Bentroen self-assigned this Apr 16, 2024
@Bentroen Bentroen added this to the v3.10.1 milestone Apr 16, 2024
- This should reduce memory usage when there is a selection and reduce the amount of `try_compress_selection()` calls;
- Add a new function `macro_column_count()` to replace `string_count("-1", ...)` in some macros;
- The selection code will be decompressed when exporting to a pattern file or displaying in the "Secret clipboard editor" dialog.
- Add a new function `selection_to_array_ext()` which generate a selection code array based from the current selections;
- Utilize `selection_to_array_ext()` in macros instead of `selection_to_array()` for selection code;
- This method works well for selection of less than 20k notes.
…tion

- The text "(CANNOT BE UNDONE)" is changed to "(CAN BE UNDONE)"
…ng area

- This also improve the speed when pasting large selection to a existing area;
- This doesn't happen when the copy-on-write option is turned off, but it will affect all arrays so I keep it on;
- Move the code to check and extend the `selection_exists` array to separate functions.
- Initialize cells in the `add_block()` function in the reverse order;
- When opening a song, the song's notes will be put into a custom-growth array before being added to the program in the reverse order/
- Move `array_grow_then_set()` to a separate file;
- Utilize `array_grow_then_set()` in `selection_to_array_ext()` function;
- Introduce a new function `selection_load_from_array()` to load the selection directly from a selection code array, which is the opposite of `selection_to_array_ext()`;
- Use `selection_to_array_ext()` in nonsimple macros.
@IoeCmcomc
Copy link
Author

Ready to merge if no problems are found. I updated the first comment, so please re-read it.

Copy link
Member

@Bentroen Bentroen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!! Thanks a lot for working on these changes. 😄

I think we can draft a pre-release soon so folks can test these changes more thorougly before we roll them out to everyone. :)

@Bentroen Bentroen merged commit 641f066 into OpenNBS:development Jul 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants