Weird Constructor / Posts / HexoSynth 2022 - Devlog #8 - A Visual DSP Programming Language

HexoSynth 2022 - Devlog #8 - A Visual DSP Programming Language

The HexoSynth modular synthesizer (programmed in Rust) got a visual DSP programming language, named WBlockDSP and it's first contribution from a contributor!

If you don't want to dig through the detailed log:

TLDR: Skip to the Devlog 8 Conclusion Section

Detailed Log

This is the day by day log of my progress. If this is too verbose for your interest, please skip down to the Devlog 8 Conclusion Section.

2022-08-03

HexoTK: Aside from publishing the previous devlog, I fixed a bug introduced by some dependencies of HexoTK. winit recently got an update, which broke some feature settings in the dependency tree because my glutin version was outdated. I successfully removed glutin as one of HexoTK's dependencies now.

HexoTK: Fixed an annoying behavior with popups, where clicking somewhere else did not just close the popup, but also activated something. Second I added PopupPos::MouseOffs for specifying a small offset to open a context menu relative to the mouse cursor. This helps with popups where the mouse cursor would be in the way after opening.

HexoDSP: As I'm more and more testing the WBlockDSP language directly from HexoSynth I started working on serializing the WBlockDSP state. So that I could reopen previous patches when testing. Only started working on it, I'm a bit too tired today to finish that.

2022-08-04

HexoDSP: WBlockDSP can now be serialized and deserialized properly. It's now part of the saveable HexoSynth patch. Still need to work on the automated tests though, to make sure this feature stays functional.

HexoDSP/synfx-dsp-jit: Worked on the WBlockDSP compiler more. Better error handling and fixed some bugs in synfx-dsp-jit and also in the compiler itself. More corner cases are covered now properly.

WBlockDSP testing patch in HexoSynth
WBlockDSP testing patch in HexoSynth

Devlog: Worked on the website a bit more. The embedded YouTube videos should be properly centered now and have a proper size too.

2022-08-05

HexoDSP/synfx-dsp-jit: Added a 'phase' node to synfx-dsp-jit and wrote a test for HexoDSP to cover an end-to-end test for audio output. The 'phase' node is a sawtooth oscillator that goes from 0.0 to 1.0. In the following demonstration you see me swapping out the input of the 'phase' node, which is the frequency of that oscillator in Hz.

HexoSynth showing 'phase' node in synfx-dsp-jit with different frequencies

HexoTK: Later I adjusted the size of the blocks of WBlockDSP a bit. So that there is enough space for a proper label like "phase".

HexoSynth blockcode widget with wider blocks for WBlockDSP
HexoSynth blockcode widget with wider blocks for WBlockDSP

HexoDSP/synfx-dsp: I've factored out a lot of the DSP code into it's own crate and uploaded a new crate to crates.io: synfx-dsp. All the generic DSP code I collected is now there. No framework, just plain little pieces of DSP code.

Then I refactored HexoDSP to use synfx-dsp.

synfx-dsp-jit: I've also refactored the CodeEngine from hexodsp::wblockdsp over to synfx-dsp-jit and added an example that uses cpal to show off the JIT functionality:

https://github.com/WeirdConstructor/synfx-dsp-jit/blob/master/examples/cpal_jit_dsp.rs

// ...

loop {
    engine.query_returns();

    let freq = freqs[i];
    i = (i + 1) % freqs.len();

    engine
        .upload(stmts(&[assign(
            "&sig1",
            op_mul(literal(0.3),
                op_sub(
                    call("phase", 1, &[literal(freq)]),
                    literal(0.5))),
        )]))
        .expect("No compile error");
    println!("{}", engine.get_debug_info());

    std::thread::sleep(std::time::Duration::from_millis(300));
}

// ...

2022-08-06

Today I generally worked on merging the WBlockDSP development with the main branches of my repositories (HexoDSP, HexoTK, HexoSynth). I've also slightly improved the GUI situation with the WBlockDSP code editor, which can now be shown using the "Code" button at the top of the GUI.

WBlockDSP code editor now optionally visible in different sizes.

synfx-dsp-jit: Implemented a shared buffer of atomic floats that can be read/written by the DSP thread while the controlling thread can do the same. With this the threads can exchange values without reuploading new DSP functions. See this example:

https://github.com/WeirdConstructor/synfx-dsp-jit/blob/master/examples/cpal_jit_dsp_atoms.rs

2022-08-07

synfx-dsp-jit: I can't leave synfx-dsp-jit alone yet. First I wanted to implement sample buffers that can be declared from the JIT AST itself. And second I wanted to support uploading samples to the DSP function from outside. That is what I am working on today.

2022-08-08

synfx-dsp-jit: The buffers and tables abstraction in the JIT has been mostly finished. Buffer sizes can now freely be declared at JIT compilation time and are updated in the real time thread on the fly. Tables have been changed too, their size can also vary now and they are generally read only. They are suitable for providing audio samples and other read only control data to the JIT function.

This effort does not directly benefit HexoSynth right now. But I know that at some point these features might eventually be added. And then is not the time to go back and make such deep changes to synfx-dsp-jit. And I also still have the faint hope, that someone might want to pick this up and build a different frontend for synfx-dsp-jit, something that is more like Reaktor or PureData / MaxMSP. And buffers and tables will be a quite central feature for that too.

synfx-dsp-jit phase node reset input at -/+ 0 transition of sine wave

HexoDSP/HexoSynth: I helped to day the first contributor to merge the FormFM node. A formant oscillator based on FM synthesis. Big thanks to Dimas Leenman! I took the chance to enhance the "About" page styling a bit:

HexoSynth enhanced about page style and first contributor
HexoSynth enhanced about page style and first contributor

2022-08-09

HexoSynth Plugin: Today I worked on properly serializing the HexoSynth state. First tests looked very promising and I was able to store and load presets of HexoSynth patches in Renoise. Next I worked out a plan for external parameters from the DAW and how to handle MIDI properly. It will take some work and effort the next days to flesh those ideas out with some code.

A saved VST3 HexoSynth preset file
A saved VST3 HexoSynth preset file

HexoDSP: Later today I started actually writing code for handling MIDI notes. But it's still early concept code and not working at all yet.

YouTube Sound Demos

After the contribution of the FormFM node I noodled around a bit with it in HexoSynth. Nothing fancy, just a few scary and weird noises:

Devlog 8 Conclusion

First I want to welcome the first contributor Dimas Leenman who added the FormFM, a little FM synthesis node for formants. I took the chance to improve the HexoDSP documentation to support this and future contributions.

This week was devoted mostly to WBlockDSP, a little visual DSP programming language. The scope is, as earlier mentioned, a bit limited. And it is not a full blown general purpose programming language. But you can implement simple DSP algorithms with it. These little algorithms can be programmed and directly be used as DSP node/module from within HexoSynth.

At least that is the plan. I was not able to finish all the core features I wanted to it to have yet, and especially the UI side is still more a proof of concept than a finished user experience. But I wanted to have the core functionality done, and that was what I was able to achieve this week.

All this means, the road map point stabilize WBlockDSP is crossed off my road map for now. Even though there is still a lot of work to be done, I want to push forward and finish the core workflow with HexoSynth first. The WBlockDSP language is really just a small and optional part of the whole thing.

I also started with another point on the roadmap:

  • Finish the nih-plug integration. That means a better integration of HexoSynth as VST3/CLAP plugin into your favorite DAW.

That means next I want to be able to send MIDI and audio to HexoSynth from within a DAW. Importing and Exporting presets already works mostly.

The following points remain on the roadmap towards the first release of HexoSynth in 2022:

  • Add more automated test cases for the UI workflow.
  • Rewrite the online help.
  • Add inserting DSP chains that are to be pre-defined. And also inserting random DSP chains for a more explorative/experimental workflow.
  • Add back editing CV widgets.

Contact

In case you find this project interesting or have questions, you can reach me via Discord these days, check out the #hexosynth channel in the Rust Audio Discord. Optionally I'm also online on IRC (via Matrix) in the Linux Audio Developer channel #lad (nickname 'wct') on Libera.Chat: irc:#lad@irc.libera.chat.

Links

Weird Constructor Avatar
Weird Constructor

Nice end 30 y/o guy, geek and F(L)OSS developer that messes with: Linux, Windows, Networking, Interpreters/Compilers, Games, Audio, Music, GUIs, C/C++, Rust, Scheme/Lisp, 3D printing, electronics and more.


For updates follow me on Mastodon

All the F(L)OSS development on my projects happens in my spare time. If you find what I do useful, entertaining or just want to support me, you can do this via Liberapay:

Donate using Liberapay