Lo-fi Music Generator

Procedurally generate and mix lo-fi jazz beats.

Published on: Wednesday, February 7th 2024, 01:11 am

Demo

Use headphones if you can!

Try it out: Github Release

Intro

"Relaxing lo-fi beats to study, relax, sleep, cry, etc. to" have gotten really popular in the last few years. I couldn't help but notice that these songs are generally pretty formulaic in their construction. A hip-hop drum pattern and a basic bassline backs standard jazz chords in a 2-8 bar loop. Add in a nice melody, some rain and vinyl noises, and you've got a standard lo-fi track.

I'm not trying to discount the artists here. One of the pioneers of this style - Nujabes - has amazing music that's always at the top of my Spotify wrapped. What I'm getting at is that it's quite possible to automatically generate this music.

How notes are generated

There's no AI or anything fancy here. Notes are all generated with automating music theory.

Chord progressions

On each generation, a jazzy chord progression is pulled from the chord bank. It is then transposed to a random key. This defines the chords for the rest of the instruments. The bass always plays the root, and the keys (rhodes) plays the chord in a random inversion.

A# 7 C m7 D m7 D m7
D m9 G 9sus4 A 9sus4 C# d7
...

Melody

Each sequential note is a function of the current chord, and the last played note. Each scale degree is assigned a weight, indicating how good it sounds against the current chord.

// Scale degrees:               x, 1, 2, 3, 4, 5, 6, 7
int[] degreeScores = new int[] {0, 8, 4, 9, 3, 9, 2, 6};

We can see that the root, 3rd, 5th have the highest weights, and the extensions progressively get lower: 7th, 9th(2), 11th(4), 13th(6). This is more or less an approximation of consonance.

Each interval is also assigned a weight.

// Distances (semitones):         0, 1, 2, 3, 4, 5, 6 
int[] distanceScores = new int[] {4, 8, 8, 7, 7, 6, 5};

We prioritize small distances vs large jumps.

Drums

Drums are pulled from a rhythm bank and loops. Fairly simple.

How sounds are made

Conclusion

This was a fun project and I'm pleased with the results! A next step could be to add some sort of "memory" to the melody generation so that it can repeat themes and licks. Hope you try it out :)