Ported Saturation plugin to tracktion engine - #80
Conversation
* Branch commit log: ui/b/trackview.js: add 'Add MIDI Clip' menu item to track context menu ase/project.cc: emit all_tracks notification on track add/remove ase/track.cc: emit launcher_clips notification on clip added/removal ase/track.cc: only collect MIDI clips when listing launcher_clips ui/startup.js: include exception stack trace in test error logging ui/wrapper.js: expand JSDoc for wrap_ase_object to document reactive caching behavior electron/main.js: refactor trycatch & tryelse to handle sync and async errors electron/main.js: resolve source code locations in exception stack traces
Move the remove_self() method from Device to Gadget so that all gadget types (Device, Clip, Monitor, etc.) can be removed from their parent container.
…mpl::remove_self()
…rectly - Remove Project::remove_track() from the API interface - Update UI caller (trackview.js) to use track.remove_self() directly - Auto-generated IPC bindings updated accordingly
…s/test-setup.cc - Moved load_audio_file_as_clip, loop_around_clip, and test_setup from project.cc to ase/tests/test-setup.cc - Removed test_setup call from ProjectImpl constructor - Added friend declaration for test_audio_sample_load in project.hh - Added test to TestList.g.mk
…ualBase*ase_obj_; pointer
- Add register_ase_obj, unregister_ase_obj and find_ase_obj helpers to use ase_obj_ field - Replace SelectableHandle with ase_obj_ pointer registration - Update ClipImpl, ProjectImpl, and TrackImpl to use new registration helpers - Remove SelectableHandle class and its associated map-based lookup logic
* Branch commit log: ase/: refactor Ase object registration with trkn objects - Add register_ase_obj, unregister_ase_obj and find_ase_obj helpers to use ase_obj_ field - Replace SelectableHandle with ase_obj_ pointer registration - Update ClipImpl, ProjectImpl, and TrackImpl to use new registration helpers - Remove SelectableHandle class and its associated map-based lookup logic trkn/tracktion_engine/selection/tracktion_Selectable.h: add Ase::VirtualBase*ase_obj_; pointer trkn/tracktion_decls.hh: add Ase::VirtualBase forward declaration ase/project.cc: move test_setup test code from project.cc to ase/tests/test-setup.cc - Moved load_audio_file_as_clip, loop_around_clip, and test_setup from project.cc to ase/tests/test-setup.cc - Removed test_setup call from ProjectImpl constructor - Added friend declaration for test_audio_sample_load in project.hh - Added test to TestList.g.mk ase/clip.cc: simplify, use clip->removeFromParent() ase/track.cc: simplify, use edit.deleteTrack() directly ui/tests/project_test.ts: add test for track removal ase/api.hh: remove Track::remove_track(), use Track::remove_self() directly - Remove Project::remove_track() from the API interface - Update UI caller (trackview.js) to use track.remove_self() directly - Auto-generated IPC bindings updated accordingly ase/track.cc: make TrackImpl::remove_self() self-contained like ClipImpl::remove_self() ase/: move remove_self() from Device to Gadget Move the remove_self() method from Device to Gadget so that all gadget types (Device, Clip, Monitor, etc.) can be removed from their parent container.
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
* Branch commit log: ase/Makefile.mk: use libsndfile dependencies from SNDFILEDEPS_PACKAGES misc/config-checks.mk: use pkg-config for SNDFILEDEPS_PACKAGES ase/Makefile.mk: fix libsndfile support for flac, ogg and opus files
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
* Branch commit log: ase/liquidsfz.cc: update liquidsfz to 0.4.1 external/Makefile.mk: update liquidsfz to 0.4.1 external/Makefile.mk: update liquidsfz to 0.4.0
* ase/track.cc: add TODO Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
* ase/liquidsfzplugin.*: initial version of LiquidSFZ plugin * Move liquidsfz plugin to devices/. * devices/liquidsfz/liquidsfzplugin.cc: add TODO comments, get rid of usleep Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
* project.cc: add LiquidSFZ test function * ase/project.cc: use TrackP / ClipP to setup SFZ test clip * ase/project.cc: no longer need tracktion::literals Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
* Branch commit log: ase/project.cc: use TrackP / ClipP to setup SFZ test clip * project.cc: add LiquidSFZ test function * ase/project.cc: use TrackP / ClipP to setup SFZ test clip * ase/project.cc: no longer need tracktion::literals devices/liquidsfz/: initial version of LiquidSFZ plugin * ase/liquidsfzplugin.*: initial version of LiquidSFZ plugin * Move liquidsfz plugin to devices/. * devices/liquidsfz/liquidsfzplugin.cc: add TODO comments, get rid of usleep ase/track: add helper function to create plugin on track * ase/track.cc: add TODO
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
There was a problem hiding this comment.
Code Review
This pull request introduces the SaturationPlugin, integrating it into the build system and test suite. Key changes include the implementation of the plugin using the Tracktion engine, adding missing reset logic in the DSP code, and updating the track plugin insertion logic to append new plugins to the end of the list. Review feedback highlights a potential null pointer dereference in the test code, suggests using defined identifiers instead of magic strings for parameter IDs, and recommends removing redundant cleanup calls in the plugin destructor. Additionally, using a scoped enum for plugin modes was suggested to improve code clarity.
Signed-off-by: Stefan Westerfeld <stefan@space.twc.de>
|
Several issues:
|
|
I'll address your issues in different comments. About detaching parameters.
Ok, LLMs often answer something like (this one is grok): i have a tracktion plugin with a parameter drive, i used drive->attachToCurrentValue (drive_value); in the constructor, do i need to detach in the destructor? why? Yes, you should call drive->detachFromCurrentValue(); in the destructor. Why? attachToCurrentValue() (on AutomatableParameter or similar Tracktion parameter objects) creates a bidirectional link between the parameter and your juce::Value (or CachedValue) object (drive_value in your case). This attachment:
If you don't detach:
[...] I tried to trigger this: Basically, the AutomatableParameter for the property (i.e. drive) is ref-counted. So it can live longer than the Plugin itself. So if a juce::ValueTree change on the property happens after the plugin is destroyed, it tries to notify the juce::CachedValue for the parameter. Then, I get an address-sanitizer use-after-free crash. This is my minimal code to make it crash: Now whether this could happen in production, I am not entierly certain, because I assume that usually the parameters would not be referenced elsewhere after the plugin has been deleted, and even if they were, a ValueTree update would be uncommon. But I can't exclude the possibility, and even if it doesn't happen now, it could happen in 5 years if we add a fancy new UI feature or update the tracktion engine to a higher version. And these bugs are extremely nasty in practice because this could trigger only in 1 of 1000 cases in some scenario. So I would recommend to always detach, which is what the other plugins do. I must admit that I don't like the silent cleanup that the tracktion engine does if you forget to detach, maybe it would be better to at least print a message if the plugin fails to detach(), like so: Then we at least would get a notification if we ever forget to detach one of the parameters. |
Yes, I totally agree. As soon as the UI gets better, we can step by step reduce and finally remove the hacks. Steps would be
I guess at least steps 1 and 2 (and maybe 4) would be necessary before trying to port BlepSynth to tracktion engine, because I doubt I would be able to get the whole plugin port up and running correctly without even being able to test it once. |
Well if you look at the file, it is basically code that is shared between the plugin implementations (which are all in .cc files). So what this does is just declaring a few It is btw possible to just re-declare the juce::Identifiers for each plugin (they will de-duplicate the string under the hood), so if you really just want to get rid of this header, we could do it. But I assume that we'll later on have other code that is shared between plugin implementations (and that needs juce or tracktion) so I don't think doing this would be helpful in the long run. Edit: This is just what |
Using printf() pollutes the programs stdout stream, that destroys and entire class of use cases for unix programs (usually the main use cases). Always print warnings / errors / info to stderr. That said, we also dont spam stderr in an uncontrolled fashion, we have a logging system and tracktion is integrated with it. So simply use the tracktion logging macros to print that message. You may be right that having such a message should be in order, so that we can enforce cleaner code, or maybe it'll trigger way too often in tracktion and we don't want it. The only way to find out is to add it in and see what happens. Make this a separate PR and lets see what happens... |
Ok, then help with getting the needed UI pieces in order first. |
|
The only way the "trkn/tracktion.hh" (or "trkn/juce.hh") header may be included is as the second line in a .cc file right after the license, i.e.:
This is by design, it's simple and won't change. |
I ported the saturation device to the tracktion engine. The only thing that we may want to deal with is that I currently use what the other tracktion plugins use for enum valued properties and that is officially declared to be internal API. So we may want to duplicate the tracktion code in Ase later. The device is tested if you set
SFZ=/path/to/some.sfz make run, then a 24db tanh saturation is added automatically (as we currently don't have the UI to do this).