Home Artists Posts Import Register

Content

Send/Receive Blocks

I am almost ready now to finally release the new build I have been working on all month. The main new feature is the send/receive blocks. You can place a "Send" block anywhere in the workspace which will act as a sort of mobile recording buffer. The send block just records audio and doesn't produce any sound itself. Then you can connect any number of "Receive" blocks to it to play back then content of the buffer anywhere else in the workspace.

The original motivation behind this was as a way to implement a routing option that most other DAWs provide where you can split part of a signal chain and send it to some other effects track. You can do this in Blockhead by placing a receive block on another track and making sure it is lined up with the send block:

Colugo on Twitter: "send tracks in blockhead (wip) https://t.co/CQGAyChctV" / Twitter

Because the send/receive endpoints are just blocks they can also be moved around in time, and you can even feed the receive block back into the connected send block to create a feedback loop:

Colugo on Twitter: "heres my delay https://t.co/vLLqMOqI0c" / Twitter

The other weird thing you can do is move the receive block backwards in time to before the send block, and if baking is enabled then the receive block effectively looks ahead in the project and outputs the audio of the send block before it has even happened in realtime. The audio gets written to the send block during the baking process and then gets replicated to the connected receive block when it gets baked.

It took a while to actually figure out how the send/receive system was meant to interact with the baking system, particularly in situations involving feedback loops. In the end I took quite an aggressive approach and decided to completely disable baking for any blocks that fall inside a feedback loop. This means any time blocks are moved around, Blockhead is constantly checking for blocks being moved in or out of any feedback loops and enables or disables the baking process.

The system for checking for feedback loops proved to be so complex that I ended up making some heavy changes to the way Blockhead processes events and updates its internal state. Blockhead now has a system where various events (such as objects moving around, or being deleted etc), are all now logged to a big sort of hidden bookkeeping system and then at least once a frame Blockhead will look through that log and perform the updates it needs to do based on what changes have occurred.

An example of where this is useful is when many blocks are being dragged around in one operation, Blockhead can log all the block movement that occurred in one input frame and then perform one pass to figure out whether anything needs to be rebaked, whether anything entered or exited a feedback loop, etc.

Memory Allocation

There has been a problem in the input panel for ages, where if you create a very large input buffer then the entire application will freeze for a moment while it is created. This is because Blockhead is allocating one big contiguous block of memory for the audio data and the GUI thread can't do anything else while this is happening.

I knew this was going to be a problem for send blocks too, and I didn't want to put any kind of limit on how large the send/receive buses can be. So I developed a system where these buffers are split up into smaller sub-buffers, small enough that one sub-buffer can be allocated in a single GUI frame without any lag being visible to the human eye. This also allows me to display progress bars for the allocation process.

When buffers aren't needed anymore (e.g. when a send block is deleted), instead of the memory being freed entirely, the buffers are released to a pool so that they can be re-used later.

Colugo on Twitter: "i use this harold buffer to allocate very large audio buffers a little bit at a time to avoid blocking the GUI thread and display progress bars for the allocations. old buffers are returned to a pool for re-use https://t.co/Q2qoq7XvKh https://t.co/YMjXHsMiEm" / Twitter

This system is now also in use for the input system, so there's no lag anymore when creating input buffers. Adapting the input system to these new buffers ended up being a massive task which took me several days but I got there in the end.

Waveform Updates

Another thing which needed to be figured out was how to generate waveforms for audio data while the audio thread is busy writing to it. This is a complex problem because in audio applications the audio thread is not allowed to lock mutexes to synchronize data access with other threads, so lock-free solutions need to be found.

I was already technically doing this in the input panel, but in a pretty janky way. I knew that I would need to replace it with something better eventually, so while implementing the new send/receive system I made sure to write the waveform updating code in a way that could be re-used in other contexts.

The input system only had one other hurdle - in the input panel you can drag out those boxes and click on them to generate a sample from that region of the buffer. So there could actually be three threads working on the same region of memory at the same time - the audio thread which is writing audio data, the GUI thread which is generating waveform data, and a worker thread which is reading data to produce a new sample.

So a lot of care has to be taken to ensure that the threads are not interfering with each other, without any mutex locking. No two threads are ever actually accessing the same bit of memory, even though it looks like that's what is happening.

....and Bug Fixes

There are a few bugs that I have found or have been reported since v0.24.0 was released. It seems like v0.24.0 has been relatively stable but I have found and fixed a few crashes too. At the moment I am just working through the last few of these and then I will start doing my own testing before uploading the new build.

As usual I try to make a note of any bugs being fixed in the upcoming build, on the trello board: https://trello.com/b/MT1A3Zob/blockhead-issues 

Comments

No comments found for this post.