NinSheetMusic Forums

Music => Music => Topic started by: Zunawe on April 28, 2016, 07:08:07 PM

Title: Procedurally Generated Music
Post by: Zunawe on April 28, 2016, 07:08:07 PM
https://github.com/Zunawe/markov-chain-music-generator

So, spring semester 2016 I took a linear algebra class, and our project for the year was to find a paper on linear algebra and write a mini-paper on the applications of the ideas presented in that paper. And that was about it for guidelines. After a while of trying to come up with something interesting, I realized Markov chains (http://setosa.io/ev/markov-chains/) could easily be applied to matrices. Turns out that's been a thing for a long time. So I started trying to think up fun things to do with Markov chains (http://kingjamesprogramming.tumblr.com/). And eventually I realized that music might be possible. I'm certainly not the first to do this, and I certainly haven't figured out the best way, but it was kinda cool to try, and it made the project fun.

The paper I used (http://www.sciencedirect.com/science/article/pii/S0024379507002169) discusses higher-order multivariate chains. Basically, if a regular Markov chain uses the previous "state" to determine the next one in a single list, a higher-order uses the previous n states, and a multivariate uses s lists. In terms of music, that means you can design the program so that the next note the right hand of a piano plays depends on the previous 32 notes that both the right and left hand have played, or something along those lines.

These probabilities have to be determined somehow because a Markov chain basically predicts what's going to happen next based on what it knows has already happened. In my case, I used some of Beethoven's piano sonatas as reference. So, the program essentially tries to mimic the style of Beethoven's piano sonatas. If I had fed it Pokémon music from this site, it might have sounded vaguely more Pokémon-ish.

In order to keep things simple and reasonable, I had to limit myself a lot, and it had an impact on the results, but the point was just to prove that it might work, not to make one that does work. For one, I only considered pieces written in 4/4 and the key of C major. Each "state" was the space of an 8th note, so sometimes I had to kinda lie to the program. (I was trying to tell something that only knows what an eighth note is what notes were in a triplet or a set of sixteenth notes occasionally.) I looked 16 8th notes back, and used only the most "important" note being played at the time. I also only used the left and right hand of the piano as sequences. So basically the simplest I could get it so I wouldn't have to deal with unnecessary things.

So, now that everything's been explained, here are some literal random notes thrown on a page:
Random 1: [PDF] (#post_) [MIDI] (#post_)
Random 2: [PDF] (#post_) [MIDI] (#post_)
(Example outputs can be found in the GitHub repository)

Those are for comparison, because what my program generated certainly isn't good. But I would say it's markedly better than a random set of notes, and that's with all the limitations I put on the program. Here are four generated 8-measure pieces:
Test 1: [PDF] (#post_) [MIDI] (#post_)
Test 2: [PDF] (#post_) [MIDI] (#post_)
Test 3: [PDF] (#post_) [MIDI] (#post_)
Test 4: [PDF] (#post_) [MIDI] (#post_)
(Example outputs can be found in the GitHub repository)

By the way, ignore notation and spelling in those. The note itself was a state, not the spelling, so that's not the important part.

If I do make any major changes, I'll add more tests and explain the updates I make. For now, I'll just kinda explain some ideas I had that could build off this model:

For the most part, those aren't realistic for me to do without some major driving force. But it's an interesting thing to consider.

All the code has been posted on GitHub (link at the top). Feel free to ask questions, but it has been a while since I wrote this.

Thanks for reading all that. And if you didn't, thanks for reading the thank you message at the end.
Title: Re: Procedurally Generated Music
Post by: mikey on April 28, 2016, 07:14:28 PM
If you really believe you're onto something here (and hey, computers writing music is a paying idea imo) then I wouldn't put the code anywhere near the internet
Title: Re: Procedurally Generated Music
Post by: Zunawe on April 28, 2016, 07:27:57 PM
The thing is, I'd have to learn a lot more music theory to even consider making this into something viable. And I currently don't have the time for that.
Title: Re: Procedurally Generated Music
Post by: mikey on April 28, 2016, 07:36:31 PM
you can always shelve it away until life gets a little more stable, too.  I mean this is actually something you could do, you know?
Title: Re: Procedurally Generated Music
Post by: Zeila on April 28, 2016, 08:20:38 PM
I agree. Although looking at an open source would be cool and all, this has potential and I think it's really cool. Nice work!

Edit: wait, so does your program just generate the notes and you write it down? Or does it recognize a musical program and write it out itself? I mean the former is more likely, but the second one is even more impressive
Title: Re: Procedurally Generated Music
Post by: Zunawe on April 28, 2016, 08:57:27 PM
No, I didn't have the time or energy to output midis or music xmls, so each note is actually just a number, and then I translated those numbers into notes by hand.

EDIT: This is what the output looks like:
Bigish
{
 {{13, 11, 6, 4, 3, 13, 9, 4, 6, 11, 8, 12, 5, 3, 13, 8, 12, 13, 1, 4,
    11, 13, 4, 6, 11, 8, 13, 13, 3, 13, 1, 4, 13, 3, 9, 8, 13, 8, 3,
   4, 3, 13, 1, 4, 13, 7, 4, 10, 9, 9, 11, 11, 12, 13, 6, 8, 9, 11,
   11, 3, 13, 2, 11, 10}},
 {{9, 8, 7, 4, 11, 13, 8, 8, 11, 7, 11, 6, 8, 1, 1, 12, 1, 13, 13, 12,
    13, 13, 13, 10, 3, 11, 9, 9, 1, 7, 11, 8, 7, 11, 13, 6, 7, 13, 11,
    12, 11, 6, 9, 11, 13, 8, 9, 13, 11, 13, 13, 11, 8, 6, 13, 11, 9,
   4, 4, 4, 13, 13, 5, 11}}
}
[close]
Title: Re: Procedurally Generated Music
Post by: InsigTurtle on May 01, 2016, 03:15:03 AM
Hmm, I was thinking actually thinking of writing code to write procedurally generated music, but in a completely different manner, mostly based on the harmony instead of individual notes. So it would end up playing a 'random' harmonic sequence each time. I was planning on doing this for a four-part chorale, but then I'd have to code in stuff that'd prevent parallel octaves and fifths, ensure proper doubling, etc. etc... So I just gave up on the idea. I don't know if you want to do someone similar with your code, but there's an idea if you want to take it a bit further.
Title: Re: Procedurally Generated Music
Post by: Zunawe on May 01, 2016, 12:30:44 PM
That's the other side to "procedural generation" where the computer is given a list of rules to follow and randomly picks sequences that follow these rules. The problem I saw with that is that either your rules aren't very strict and you end up with weird mixings of styles in music theory world, or your rules are too strict and you get an uninteresting result. By using Markov chains, the computer doesn't ever really need to care because it's only imitating another composer or music style where all those rules were already used. A really good version of my program would have few problems with straying away from the style it's fed because it's all based on something that has actually happened before.

So your idea is cool, but it kinda fundamentally strays from the basis of this project.
Title: Re: Procedurally Generated Music
Post by: InsigTurtle on May 01, 2016, 01:15:51 PM
I was going to actually use Markov Chains for it, but I gave up since I honestly didn't know what I was doing at that point :P
Title: Re: Procedurally Generated Music
Post by: Zunawe on May 01, 2016, 01:19:35 PM
That would be something like a pseudo-Markov chain. Which could work with a lot of testing.
Title: Re: Procedurally Generated Music
Post by: Zunawe on February 02, 2017, 02:37:16 AM
Code posted to GitHub. Link in OP. That's all.
Title: Re: Procedurally Generated Music
Post by: mikey on February 02, 2017, 02:43:42 AM
awesome!  Are you gonna keep building on it or just drop it?
Title: Re: Procedurally Generated Music
Post by: Zunawe on February 02, 2017, 09:23:58 AM
Maybe if I run out of other projects, but really it was just a cool idea that I proved is doable with a lot more sophistication. So it probably will only exist as the paper I wrote (also in the repo).
Title: Re: Procedurally Generated Music
Post by: mikey on February 20, 2017, 08:21:46 PM
could you get the program to ignore certain intervals?  For example, never play note "1" and note "7" at the same time?
Title: Re: Procedurally Generated Music
Post by: Zunawe on February 21, 2017, 08:52:35 AM
Yeah. At every tick, if the generation creates that interval, you just rerun that tick. It'll work as long as the probability that the interval is created isn't 1.
Title: Re: Procedurally Generated Music
Post by: BlueStone on February 21, 2017, 07:56:35 PM
You might be interested in Google's WaveNet text-to-speech engine that uses neural networks to generate sound. Scroll to the bottom of this (https://deepmind.com/blog/wavenet-generative-model-raw-audio/) article to see the results of it generate classical sounding piano music.
Title: Re: Procedurally Generated Music
Post by: Zunawe on February 22, 2017, 12:14:58 AM
Yeah, neural networks are cool stuff. Also, holy crap that's a lot of data.

I like how the generator just goes insane with the music as soon as it starts playing faster notes.