Home Artists Posts Import Register

Content

I have been making pretty steady progress working on block saving/loading functionality. The existing sample list was only written to handle samples so I developed a generic list control which can handle different kinds of item. I can now save blocks and they will appear in the block list and can be manually triggered the same way samples can. The one-shot block playback system processes the saved blocks in real-time so in the future if I want to add ways to trigger blocks with different parameter settings (e.g. at different pitches) then that is possible. It's currently implemented using the existing snapshot system which is used for bouncing and rendering, which means when you click the button to trigger the block an exact copy of the block data is created in memory and then destroyed again when playback is finished. This is fast because it doesn't need to copy the sample data too.

As usual every time I add something to Blockhead I feel farther from the finish line because I think of ten more things I could add.

  • Obviously it makes sense to be able to trigger the one-shots via MIDI.
  • From there it makes sense to be able to organise blocks into groups or "instruments" with custom MIDI mappings and envelopes.
  • It's going to be possible to save and load any block type, probably except for tempo guides and start blocks. So one thing I had to think about was which types of block should have a trigger button on them.
  • Obviously sampler blocks and synth blocks should because they make a noise, but what about effect blocks? It could be possible to also trigger an effect block with a placeholder input such as white noise or something.
  • If I add that then why not also add the ability to trigger a block on a particular track while the song is playing back? With the ability to create custom MIDI instruments from combinations of blocks this would provide a way to build your own live triggered multi-effect machine.
  • You could even set up some weird instrument where for example, MIDI note C3 plays back a sampler block at a particular pitch, C#3 plays back a synth block, D3 triggers a filter sweep on Track #3 etc.


Block References

In previous posts I have talked about an issue that Blockhead currently has: It is common in electronic music to have many instances of a single sound (a kick drum on every beat for example). In a traditional DAW if you wanted to change a characteristic of every instance of that sound then it's usually trivial because often you have some sound-generating object such as a sampler or synthesizer which is responsible for triggering the sound in multiple places. You can change a parameter on that device and the change is reflected across all instances.

In Blockhead each block makes its own sound, they're not referring back to some global sound-generating object (though technically a sampler block does refer back to the sample it is using, rather than storing a copy of the sample data).

The current idea to solve the issue is to introduce the idea of block references:

  • At the moment the operation to copy a block is named "clone" in the context menu. I will likely be changing the name of this operation from "clone" to "copy".
  • The "clone" operation will be kept, but instead of copying the block it would create a reference to the same block.
  • All references to the same block will be magically connected together, so if you edit it in one place then the changes will be automatically reflected across all other instances.
  • There will be a quick way to "disconnect" a block from its reference group, which would be the equivalent of replacing it with a "copy" of itself
  • All blocks will technically be reference blocks, even if they are "unique" (i.e. in a group of one). But there will be some visual distinction when a block is in a group of 2 or more references so it is clear when edits will be reflected elsewhere.
  • Through the use of manipulator blocks (once I implement them), it will still be possible to create variations of the sound without having to disconnect a block reference from its associated group.

I started thinking a lot about this while working on the new block list and hit a bit of a dilemma when I realised that this would all have to interact with the block management interface quite closely. The way the block list implementation works so far is you can right-click a block in the workspace and click "save". This creates a copy of the block in memory which is stored in an internal block manager and it is displayed in the block list. However I am not sure this is the correct model to proceed with when considering block references.

What I am considering currently is the following system:

  • Any time a unique block is created, it is automatically added to the block list
  • References (described above) to the same block can be created in the workspace. They will all refer back to the same block (viewable in the block list)
  • If a block appears anywhere in the workspace, it will always have a corresponding list item somewhere in the block list.
  • When the last reference to a block is deleted from the workspace, the block is automatically removed from the block list
  • The user can "save" a block, either from the block's context menu in the workspace or from the list interface.
  • Saved blocks will be visually separated from the rest in the block list (perhaps "pinned" to the top of the list?).
  • When a block is "saved", all that actually means is that it won't be automatically removed from the block list when the last reference to it is deleted.
  • Blocks (not block references) can be named
  • In a typical project with lots of unique blocks, the block list would quickly become massive since every unique block is automatically added to the list, but this should actually be fine. The list of all blocks is just there as a master reference, and the blocks that the user actually cares about (the ones they have saved) will be visually separated from the rest.

As with most Blockhead concepts I think this idea might seem more complicated than it is when you write it down like this. Hopefully in practice it would be intuitive and something that you don't really have to think about.

At the moment I am midway through implementing the block management system based on my original design but I am not sure I want to proceed now that I have thought things through more. I am probably in a good position to switch track and start implementing this new plan though this will involve working on the block reference system in tandem so it will likely take a lot longer for the next "new features" release!

Files

2021 07 22 11 39 11

Comments

Anonymous

That all sounds great! Blender the 3d program has a similar paradigm where you can "duplicate" or "duplicate linked" (the latter being the reference version) - to me it all makes sense, but in blender at least, it's not massively clear to me whether an object is linked to others or not. You did mention that you would try to visually distinguish blocks that have a reference - maybe a simple one is to show the selected block as highlighted, and have a sort of ghost highlight for any linked blocks the user can see - idk if that would be too obtrusive or not obvious enough but it sounds good

colugomusic

In the Godot editor most resources are copied by reference by default (makes sense for a game engine), with the option to "make unique". It has the same problem you describe where it can be unclear whether an object is unique or part of a group of references. My current thought is that blocks on the workspace will have a number in the corner indicating how many references belong to the same group, and probably some other visual distinctions around the edges. I could also highlight related blocks on the workspace when hovering

Anonymous

yeah could be nice! one thought is that its difficult to imagine how easy to understand it would be to someone who's not familiar with c++ smart pointers and reference counting - maybe it's still really obvious. If every block in the workspace had a little number it it, it might become a bit cluttered for the sake of letting people know how many instances there are - e.g. a row of kick drums. Maybe they just need some simple signifier, like a chain link icon or even simpler like an italicised or underlined name. Just thinking of whatever would be the least visual clutter/cognitive load for the amount of information a user needs

colugomusic

Yea There might be a bit of a learning curve. I'm thinking the "most default" behavior should be to always copy rather than clone. i.e. on Windows CTRL+C to copy and CTRL+SHIFT+C to clone. So if someone tries the usual "copy" keyboard shortcut then it won't do anything too surprising and the "clone" operation might be something they find out about through documentation or tutorial videos. My hope is that as soon as a user makes an edit in one block and sees the changes automatically reflected in another, the visual feedback of that would help the concept click even if they are not familiar with the concept of references. Though this would only happen if they are editing a parameter which affects the waveform, or one that is currently visible in the other block. I think we are on the same wavelength wrt visual clutter. The block header/footer controls already automatically hide things when there's not enough room which is sort of nice because if a user is manipulating a particular block they will usually zoom in on it anyway. Probably what i will do for non-unique blocks is add a chain-link icon/button in the header with its own context menu with all the reference-management related operations and info for that block, similar to what I did for the sample channel selector.