What is it?
This code is a simple example of how you can auto-compose songs using Python and generate the audio for those songs using FluidSynth.
- Download MIDIUtil from here. From within the downloaded folder, run in a terminal:
python setup.py install.
- Download and install FluidSynth. Follow instructions for your OS here.
- Download the JSB2 code. From within the downloaded folder, run in a terminal:
python run_JSB2.py. You just made your first computer-generated song! You'll hear it playing.
What's happening under the hood?
Python code randomly generates notes (within the constraints of some musical structure) that get translated to a midi file. The Python code also generates a file that assigns instrument samples to different channels in the midi file (we'll call this the channel mapping script). The midi file and the channel mapping script are used by FluidSynth to generate an audio file.
How can you interact with the code?
- Generate a random song using default parameters.
- Generate a random song using user-defined parameters like tempo and song structure.
- Play the song.
- Save a .raw file of the song (which can be converted to .wav automatically. See 'Generating .wav files').
You can do all of the above by (un)commenting lines in the very short
How can you modify the code to generate different songs?
The code has lots of comments and has an object-oriented structure, which makes it easy to modify and expand.
Some things you can do to start playing with it:
- Download a .sf2 audio sample file from the web (there are lots of free resources). Put it in the
samplesfolder and replace the filename in the
JSB2.pywith the new filename.
- Remove some of the chords in the
chordslist in the
- Replace the logic in the for loop of the
JSB2.pywith your own.
This code is really only meant to serve as an example of how easy it is to auto-generate songs. You could work within the (rather loose) structure I used, or create your own. The hope is that by knowing how these tools (MIDIUtil and FluidSynth) work together, people can start thinking about the algorithms behind auto-generated music and easily implement their ideas in Python.
samplesfolder contains .sf2 audio samples.
output_filesfolder is where all generated files (.mid, .txt, .raw) are saved.
JSB2.pyhas the class implementations.
run_JSB2.pyis used to interact with the classes and functions.
Generating .wav files
Using SoX, you can convert the .raw files generated by FluidSynth into .wav files. Just
brew install sox and uncomment the call to
run_JSB2. Make sure you call the
write_raw_audio() function before the
How does MIDIUtil generate midi files from Python code?
MIDIUtil writes notes to a midi file like this:
midi_obj.addNote(channel_num,note_pitch,time,note_duration,note_volume). That's it; you can just use Python code to generate those variables. Notes with the same
channel_num will be played using the same instrument sample. Notes with the same
time will be played at the same time in the song.
What's the algorithm used in JSB2 to generate songs?
It's pretty simple:
- At the start of every bar of music, randomly pick a chord from the set of possible chords.
- Play a bass note that corresponds to that chord at the start of every bar.
- Play a rhythm chord at the start of every bar made up of notes from the chord for that bar.
- At every timestep in the song, randomly play one, none, or some combination of a bass drum, a rim shot, and a high hat.
- At every timestep in the song, randomly pick the next note higher, the next note lower, or the same note as the previous melody note. Limit the selection of notes to those on the Pentatonic scale. Also, randomly play no note sometimes.
- With the default settings, four bars makes up a part (verse or chorus) of the song. The order in which these parts are played is specified (default is
['verse', 'verse', 'chorus', 'chorus','verse','verse','chorus','chorus','verse','verse','chorus','chorus']). The same one bar of drums is repeated throughout the song.
- Notes, chords, keys, and tempo are all randomly picked as the program runs, so every song is different.
You can listen to some songs it made here.
JSB2.py makes use of the
subprocess Python module. For your own peace of mind, check out the lines of code that use that module.