INDIVIDUAL NOTE REMOVAL: a new feature for the open-source project The Amanuensis: Automated Songwriting and Recording

in #utopian-io6 years ago (edited)

Repository

https://github.com/to-the-sun/amanuensis

The Amanuensis is an automated songwriting and recording system aimed at ridding the process of anything left-brained, so one need never leave a creative, spontaneous and improvisational state of mind, from the inception of the song until its final master. The program will construct a cohesive song structure, using the best of what you give it, looping around you and growing in real-time as you play. All you have to do is jam and fully written songs will flow out behind you wherever you go.

If you're interested in trying it out, please get a hold of me! Playtesters wanted!

New Features

  • What feature(s) did you add?

A new hotkey-triggered command has been added that allows for the deletion of portions of the recorded and looping audio on a note-by-note basis.

Although deliberate editing is not the goal of The Amanuensis, it can occur that an otherwise great recording is flawed by a single note. So far, the way to deal with such a situation has been to just keep playing and hope the errant note gets recorded over. In general this is still the recommended strategy as the song will tend towards improvement over time, however sometimes long (and therefore highly-scoring in the system's eyes) spans can be difficult to overwrite.

The use of this function is not meant to take place during the actual writing and recording of the song (although it can be), but perhaps in a separate session after having a particularly successful jam, in order to refine the chosen recording with the intent of coming back to it again. I imagine adhering to a regimen of this cycle could create a feedback loop that would really start churning out high quality songs. It's the sort of thing that ideally might one day be embodied automatically in the process itself, and already is to some extent: the continual removal of some lesser portion making room for new and potentially better material, an ever-moving process of evolution.

In a future update perhaps The Amanuensis will specifically select deviant notes on its own to get rid of, but in the meantime manual action will suffice. The idea is simply to streamline the process as much as possible, so it doesn't become a tedious chore. With the implementation of a hotkey, one can simply listen to the music they've created and tap a button really quick anytime they hear something they don't like. The last note that's been heard on the track will be removed and the next day when they load up that song, it will be freshened and ready for more writing.

The hotkey in question is BACKSPACE. MIDI notes with pitch 5 will execute this function as well.

  • How did you implement it/them?

If you're not familiar, Max is a visual language and textual representations like those shown for each commit on Github aren't particularly comprehensible to humans. You won't find any of the commenting there either. Therefore, I will do my best to present the work done in images instead. Read the comments there to get an idea of how the code works. I'll try to keep my description here about the process of writing that code.

These are the primary commits involved:

The notes in an Amanuensis recording are played individually with a simple attack/release envelope opening and closing for each at the correct place in the larger buffer of recorded audio. These envelope triggers are known as "cues". The first task was in identifying which cue has just been played at any given moment.

They are stored in coll latest_cue_by_trackso they may be queried later. It was realized that the actual cues themselves should not be looked for, as they only signal the beginning of the envelope and it's actually the peak of it when the note is heard by the user. Therefore, in commit #8 the functionality was moved to polyplaybars~.maxpat, the poly~ patch where the notes are actually played, so the peaks could be identified correctly in real-time.


polyplaybars~.maxpat was augmented with latest_envelope_peak; ---raw_playbackcomes from where the patch was originally placed, in p transmitterof organism.maxpat

These four commits all pertain to the creation of (and subsequent refinements upon testing of) the subpatcher remove_latest_cue. Unfortunately I came to the conclusion that there was no way to implement this functionality without dumping the seq~ that stores all of the cues, a potentially expensive operation if there are hundreds or even thousands of notes already recorded in a song.


remove_latest_cuefound in p midipaletteof organism.maxpat

Another complication of the dumpand of seq~ in general arose in that the object cannot be edited before it is finished with the dumpwithout creating a feedback loop. So it became necessary to introduce the dreaded deferlowin order to separate the action into two events.

The gist of what's going on in this patch is that the cue slated for removal has its span split on either side of it to create two new spans. These new spans will be shorter and therefore more vulnerable to being replaced by future recorded segments. This is the idea with this entire update, to shake things up a bit so no span gets locked into the recording too easily unless it really deserves to be.

At first I thought it would be easy enough to just add new renumbered cues, edit the spans they're associated with and then let the old cues be filtered out automatically since at that point they would lack a containing span. But again complications arose owing to the seq~ object. It seems that if you add an entry to it with the same exact timestamp as an already existing one, when it comes time to play it only one will emerge and the other will get "stuck" and then get played late. So it became necessary to immediately delete cues before re-adding them.

While p remove_latest_cuehandles the necessary modifications to the cues themselves, its subpatcher split_spanhandles those to the spans in question. These three commits pertain to the creation of p split_span.


split_spanand its subpatcher first_half

I began with the intention of removing the span in question and creating two spans in its place, one on either side of the removed cue. It became apparent that it would be more advantageous however to retain the original span, modifying it to be only the length of its first half, and then create only one new span. You can see that the first half is handled differently (in p first_half) than the second.

Although it would have been easier to split the span directly at the position of the removed cue, empty space on the ends of a span is misleading (especially when the quality of the span is judged by its length), so it became necessary to send all of the cues in the span through and identify the positions of the ones directly before and after the one removed. Contingencies were also considered for if the cue to be deleted happened to be the first or last in its span. In the case of the latter, the new span will simply not be placed.

Commit #4 and Commit #10

These two commits implemented the keyboard and MIDI hotkeys themselves, respectively.

Commit #9

There was one other debacle worth mentioning in this update and it was finally resolved in this commit. It involved the new span ID created when the span is split. I was at first using topIDto find it, but existing code was already relying on this variable in determining whether an imported song actually had anything added to it when it came time to export it again or not. Modifying this variable when creating spans caused export to fail, so it became necessary to introduce two new variables ---spanIDand createdID (see p split_spanabove).


p document_span_start, the only place where spans should have been being created, now communicating with the cue removal process through these two variables

Commit #11

Cleanup and commenting

GitHub Account

https://github.com/to-the-sun

Sort:  

Thanks for the contribution, @to-the-sun!

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

Hey @to-the-sun
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Coin Marketplace

STEEM 0.16
TRX 0.15
JST 0.028
BTC 60231.53
ETH 2321.91
USDT 1.00
SBD 2.51