The Dissociated Mixes
Parry Gripp — Nom × 4
The short answer is by having a computer listen to the song, and having a short Python script automatically shuffle beats around according to what it understands about the song. I’ve actually given about a dozen answers in the past week, so I thought I would work on giving several complementary ones here. If you don’t follow a certain explanation, or are bored by it, skip down to the next section.
Is this your card?
The Dissociated Mixes shuffle the component beats of songs around so that the songs stay recognizable, but slightly-to-very unexpected.
Imagine a deck of cards. We have an order of suits — spades, hearts, diamonds, then clubs — that must always be followed. We start with a deck with the cards in numerical order, and then the cards in suit order within the same rank: ace of spades, ace of hearts, ace of diamonds, ace of clubs, then deuce of spades, and so on.
This represents the original song, with each of its beats in its original order. One bar of music is indicated by one rank — all threes would be the third bar in the song for example.
The original script for doing the original dissociated mixes worked analogously to this:
- Start with the first card in the first suit (ace of spades), and note it down on paper.
- Grab all of the cards of the next suit.
- Shuffle amongst the card of that suit.
- Choose one.
- Note the card and put it back in the deck.
- Repeat from #2, but for the next suit.
The result was a little too chaotic, so there were added constraints added for steps three and four:
- Order the cards in terms of the single suit in terms of how much they sound like the card that normally would have come after the last card you put down on paper. That is, take ones close to the card of the same rank, but of the next suit.
- Choose from one of the four top cards (including the one that you compared the other cards to).
This was instantly more pleasing to listen to than the first try, because not only was the local structure — the order of the suits — retained, but the numbers kept some degree of similarity, even if a bit scrambled. The remix could go on forever, because you’re just shuffling and re-ordering according to the last beat you heard. As a result, it becomes fairly tiresome after a while, because it had no sense of structure.
The ultimate version of the script changed just one thing: rather than shuffle the cards around for the entire song, it started the whole procedure anew, with a new ace of spades, for each section (such as a verse, chorus or bridge) of the song. As a result, you were dealing with fewer cards at the same time, and you were swapping places amongst cards that shared more properties than arbitrary ones in the whole song.
Beck — Zen Mixes Bids
I thought the sonic results were uncanny. The global structure was retained. The general picture of how the drumbeats and the riffs fit together also stayed. The little details of what happened from beat to beat, however, were strange. They were locally plausible, but they weren’t what was originally recorded. Obviously it suited some material better than others.
Again, but more musical
I have torturously avoided talk of beats as much as possible. If you have some musical background, you might be able to understand this more easily:
- The computer takes the first beat in a section.
- It listens to the next beat.
- It compares all of the beats that fall both in the same section and in the same part of the bar as that beat, and then chooses randomly from that next beat and the three that sound most like it.
- The computer finally saves the beat it chose, and repeats, comparing with the beat that would normally follow the beat just chosen.
It’s important to realize at this point that the new music is not a remix, but technically a re-edit. I do not have access to any of the component tracks of the song (such as what Parry Gripp has made available for other songs), only the original MP3 file that anyone can download. The computer doesn’t change the instrumentation or mix; it’s only shuffling whole beats around. (See where the card metaphor came from?)
How do you handle the sounds like part?
The script takes advantage of the timbre comparison from Analyze. It captures both the time and frequency qualities of a short slice of sound, how those interact with one another during that time, and reduces it to twelve numbers. The computer then compares those twelve timbre numbers with the twelve in the comparison beat.
Haven’t I seen this sort of thing before?
The name for the first batch of mixes is inspired by “Dissociated Press,” the infamous emacs command that makes nonsense and near-sense from normal text by probabilistically choosing words that are likely to follow.
Why choose among four beats?
Three was too few, and five was too many? It was an arbitrary choice, and it stuck as a default. Anyone running the script can change it, and choose from any of one to limitless candidates. Choosing from one candidate means you get the next beat, so you would hear the script run straight through the song. Choosing from lots and lots of the sorted candidates simply means that the sonic similarity is meaningless, and any beat that comes in the same part of the bar is fair game.
In fact, it was precisely that variation that was the key to the next set of mixes.
Again, but less annoying
It was annoying, but simple — simple enough that a computer could understand it well.
I plugged the song into my script, and it was rendered into something a little different, a little magical.
So the next series of mixes concentrated on the same song, and only varied by the “randomness” parameter from two up to nine. The results are instantly recognizable, but different, less relentless, less… annoying?
I received a comment from Parry Gripp after I emailed him:
Wow, that is really cool! How did you do that?
I particularly like X 4. Somehow, your randomizing process makes the song less annoying.
I was caught awkwardly trying to explain to the composer why his song was so annoying.
In any case, the remixes get less annoying for a while because the randomness disrupts the relentless repetition that’s going on. But the mixes are kept from being too random because the original uses few enough notes that any note following any other note makes for a plausible melody.
By the sixth remix, things get a little incoherent, but still relentlessly follow the same large-scale structure of the song, most obviously heard in the instrumentation. All but two of the remixes follow the algorithm above: keep the large scale structure of the song, but assume that beats are fairly interchangeable, and swap them around.
The final remix in the series follows an earlier script, the one before I started following the song’s original structure, when the next beat could be chosen from anywhere in the song. The ‘advantage’ to using this one was that it made things very scrambled, and could be given an arbitrary length — in this case, 200 bars.
Parry Gripp — Nom, etc.
The seventh remix (“Nom in 7”) was made using an old script, in which I retain the first three and a half beats in every bar (in their original order), and discard the final half-beat. This changes the meter from 4/4 to 7/8, making for some lopsided dancing or some breathless hamsters.
Parry Gripp — Nom in 7
Again, in code
That I was able to generate these so quickly and with very little code is because of the power of the Echo Nest Remix API. I’ve developed an overview of the API for those who want to learn more about it. For those so inclined, here’s a quick look at the Python code I wrote for the vast majority of the samples here. I have eliminated some of the error checking for the sake of brevity.
import random import echonest.audio as audio from echonest.sorting import * from echonest.selection import *
Start with the libraries.
def main(infile, outfile, choices=4): audiofile = audio.LocalAudioFile(infile) meter = audiofile.analysis.time_signature sections = audiofile.analysis.sections outchunks = audio.AudioQuantumList()
Initialize the audio file and analysis. Grab the number of beats in each measure, and the large, structural sections in the song. Initialize the list that will collect the beats for output.
for section in sections: beats = audiofile.analysis.beats.that(are_contained_by(section)) segments = audiofile.analysis.segments.that(overlap(section)) num_bars = len(section.children())
For each section, start the main loop. Grab all the beats and segments in the section, and count the bars in the section.
b =  segstarts =  for m in range(meter): b.append(beats.that(fall_on_the(m+1))) segstarts.append(segments.that(overlap_starts_of(b[m])))
Initialize the ‘suits’: get a list of beats that fall on the one, the two, the three, etc. Because the segments are the parts of the analysis that hold the real data detail, we capture those too. The segments that overlap the starts of the beats are the ones we will compare, so grab a group of those, for every suit/beat.
now = b
Begin with the ace of spades: the first beat in the section. Start a loop that lasts for the number of whole bars in the section:
for x in range(0, num_bars * meter): beat = x % meter next_beat = (x + 1) % meter
It’s helpful to keep track of the beats. Since they cycle from one to four (typically) and starting from one again, it’s easiest to model it with a modulus.
now_end_segment = segments.that(contain_point(now.end))
Select the precise segment that overlaps the end of the “now” beat. That is very likely the same as the beat that overlaps the start of the next beat, but I don’t assume it.
next_candidates = segstarts[next_beat].ordered_by( timbre_distance_from(now_end_segment))
The candidates for the next beat are collected from the set of segments overlapping the next beat, and are sorted by sonic similarity to the reference segment.
next_choice = next_candidates[random.randrange(choices)]
Choose one from the first choices (default four) amongst the candidates.
next = b[next_beat].that(start_during(next_choice)) outchunks.append(now)
Turn that candidate segment (which has an irregular length) back into a beat, and append it to the list of beats we’re collecting.
now = next
Start the loop again, but for the next beat.
out = audio.getpieces(audiofile, outchunks) out.encode(outfile)
Collect all of the beats we have collected into a sound, and write it out to an MP3 file.
If you want to compare, the full listing is available in the subversion repository.
If you enjoyed this, you might be interested in my broader overview of Remix, or you might like to delve right into downloading the libraries yourself. I have been collecting resources for Remix, including further documentation.
If you want to share with others, you can share the link to Infinite Noms <http://music.atl.me/nom/> or the Dissociated Mixes <http://music.atl.me/a/> (each page has downloadable MP3 links), or embed the mixes on your site: