projectM-visualizer / projectm

projectM - Cross-platform Music Visualization Library. Open-source and Milkdrop-compatible.
https://discord.gg/mMrxAqaa3W
GNU Lesser General Public License v2.1
3.22k stars 364 forks source link

Add support for variable monitoring in per-frame equations #664

Open kblaschke opened 1 year ago

kblaschke commented 1 year ago

In the original Milkdrop, a simple monitoring feature exists that preset authors can use to watch how a single value in a preset evolves over time. This is done by pressing "N", and also adding a monitor = EXPR line in any per-frame equation in the preset. The value is then displayed on screen.

projectM currently lacks this feature. Since the on-screen UI has been removed recently, an API-driven debug feature would be more convenient, which might even go beyond what Milkdrop provided. Here's my porposal:

Per-Frame debugging

This will implement the debug feature similar to what Milkdrop provides with the monitor variable, but a bit more flexibility and without the requirement to add a line in the preset file. This is accomplished by adding three new API functions, e.g. in a separate "debug.h" header:

Theoretically, the get_value method would suffice, but since the variables need to be copied into another context after preset evaluation, copying all possible values (e.g. predefined and locally defined variables) without knowing they're being used will incur a slight performance drop and is not necessary for general use.

Embedding applications can then request the variable contents after calling projectm_render_frame() and display or store the values as required, for example display them on screen, using them to plot a graph or store them in a CSV file.

Per-Vertex equation debugging

By watching a single variable per frame, it's not possible to see the values from per-vertex/per-shape equations, as these are evaluated hundreds or thousands of times per frame. With a slightly larger performance impact, it would be possible to store all these values as arrays and pass them to the application. A real-time display of this large number of values could be challenging, but for graphing and storage purposes it should be a great tool. The above add/remove functions could be reused by adding more enum values in the second parameter, e.g. CUSTOM_WAVE_1_PER_FRAME for the above suggestion and CUSTOM_WAVE_1_PER_VERTEX for monitoring all values calculated for each waveform vertex.

The get_value function would only work with single values, for the per_vertex/per_shape equations, two more functions would be required to properly retrieve the data into a buffer:

Unsupported watches

Since it would add a lot of runtime overhead to projectM's expression parser to support "step-by-step" debugging, for example by registering callbacks that are run each time a variable changes, only the final state of a variable after the equation block has finished running will be visible after the frame has been rendered. There won't be a way to watch variable changes during loops, or record changes from line to line.

The proposed debug features above are already a huge improvement in comparison to what Milkdrop provides, and should already help preset authors enough to fix issues.