Play music in Elixir.
First, install FluidSynth.
On Linux:
sudo apt install libfluidsynth-dev
On MacOS:
brew install fluidsynth pkg-config
Next, either clone this library or pull it in as a dependency to your Elixir
project. The following is an example of the dependency for your mix.exs
:
{:midi_synth, "~> 0.4.0"}
Fetch dependencies and build as you normally would. The first build will
download the FluidR3_GM.sf2
soundfont file. This is a Creative
Commons-licensed data file that contains all of the
General MIDI instruments. It is a
good place to start, but can be changed later on.
IMPORTANT: If midi_synth
has a compiler error on MacOS, it is likely that it
is due to an error in a pkg-config file referred to by fluidsynth.pc
. To fix,
edit /opt/homebrew/lib/pkgconfig/fluidsynth.pc
and remove the word "readline".
Start IEx by running iex -S mix
from a shell prompt.
MIDISynth
is a GenServer
and must be started first. The library comes with
with helpers to make playing simple things easy. For more complicated uses,
you'll want to build on this library.
OK, let's play a note. Notes are numbered sequentially. Middle C is note 60. Here's how to play middle C for 100 ms.
iex> {:ok, synth} = MIDISynth.start_link([])
{:ok, #PID<0.226.0>}
iex> MIDISynth.Keyboard.play(synth, 60, 100)
You can play the same note with a different velocity. The velocities range from 1 to 127. Here's how to play middle C for 100 ms with velocity mezzo-forte: 80.
iex> MIDISynth.Keyboard.play(synth, 60, 100, 80)
If you don't like the piano, try switching the instrument to something else. For example, trumpets (General MIDI instrument 57) are nice:
iex> MIDISynth.Keyboard.change_program(synth, 57)
iex> MIDISynth.Keyboard.play(synth, 60, 500)
Percussion instruments can be played only through MIDI channel 9. For example, this is how to play a cowbell sound:
iex> MIDISynth.Keyboard.play(synth, 56, 0, 127, 9)
The real value of this library is the ability to send raw MIDI messages to the FluidSynth library. The Elixir code barely scratches the surface of what's possible. If you're comfortable with raw MIDI commands, try this out:
iex> MIDISynth.midi(synth, <<0x90, 60, 127>>)
iex> MIDISynth.midi(synth, <<0x80, 60, 127>>)
See MIDISynth.Command
for help with encoding messages, and please feel free to
add more.
The Elixir and C code are covered by the Apache 2 License.