I’ve always wanted to make software that did something with music. That led me to play with JS libraries out there that can handle music theory, playback, and notation. Slowly, I started to think of ways to tie this all together to build an automatic music composer.
I had a few features in mind when building this:
- generating melodies based on a given chord progression
- playing back those generated melodies to users
- downloading the melody (and accompaniment) as a MIDI file, for future playback or tinkering
Maybe it’d be a useful tool for exploring different ways to move through a chord progression. Or for brainstorming when writing a musical composition.
- ReactJS as the main front-end framework.
- Browserify for bundling the HTML/JS
- Mocha for unit testing.
- ESDoc for generating documentation
Stylus for CSS processing.
Thankfully, I was at a point where I could do something with my coding skills and music theory knowledge. I started to see music theory can be seen as a set of design patterns or best practices followed by musicians and composers for the last few centuries. As those musicians kept encountering musical problems, they developed techniques to solve them, and passed those techniques down to their apprentices.
The way I saw it, I could embed those musical rules into a piece of software, and it should produce sounds that weren’t too horrible. For this version of the AutoComposer, I modelled the following musical concepts in code:
1. Chords and Notes
Musical chords are commonly defined as a set of notes being played together. There are many types of chords out there, and each one specifies the notes that musicians will choose in order to play a chord. For example, G major consists of the notes G, B, and D. There are other principles which determine the exact order and range to be played. But generally, when a musician wants to play a G major chord, the audience will hear the notes G, B, and D.
In most musical situations, melodies are rarely played on their own. Even when an instrument takes a solo, the band continues playing. Now, as a melody rises and falls in pitch, the exact notes in the melody usually harmonize with the chord that’s currently being played by the band. So if the band is playing G major chord and our melody is playing a G, B, or D, those two sides are in harmony.
3. Melody Generation
The easiest way to create a smooth melody that sounds good when played with chords is to simply choose from the chord tones of each chord. For the initial stage of melody generation, the AutoComposer simply chooses which chord tones are available for each chord, and connects them together. Then it filters them out by a few criteria.
UPDATE: I ended up building the mecha-muse as the successor to this project.
Back to Code.