This code is a simple example of how you can auto-compose songs using Python and generate the audio for those songs using FluidSynth.
- Linux or MacOS
- The Python library MIDIUtil
- The SoundFont synthesizer 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.
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.
You can:
- 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 run_JSB2.py
file.
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
samples
folder and replace the filename in theget_melody_sample
function inJSB2.py
with the new filename. - Remove some of the chords in the
chords
list in themusic_theory
class. - Replace the logic in the for loop of the
set_bass
function inJSB2.py
with 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.
- The
samples
folder contains .sf2 audio samples. - The
output_files
folder is where all generated files (.mid, .txt, .raw) are saved. JSB2.py
has the class implementations.run_JSB2.py
is used to interact with the classes and functions.
Using SoX, you can convert the .raw files generated by FluidSynth into .wav files. Just brew install sox
and uncomment the call to convert_raw_to_wav()
in run_JSB2
. Make sure you call the write_raw_audio()
function before the convert_raw_to_wav()
function.
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.
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.