Skip to content

Commit

Permalink
Midi -> MIDI
Browse files Browse the repository at this point in the history
  • Loading branch information
fhunleth committed Aug 5, 2020
1 parent 5446188 commit 6ee0497
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 41 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# MidiSynth
# MIDISynth

Play music in Elixir.

Expand Down Expand Up @@ -35,24 +35,24 @@ place to start, but can be changed later on.
Start IEx by running `iex -S mix` from a shell prompt.
`MidiSynth` is a `GenServer` and must be started first. The library comes with
`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.
```elixir
iex> {:ok, synth} = MidiSynth.start_link([])
iex> {:ok, synth} = MIDISynth.start_link([])
{:ok, #PID<0.226.0>}
iex> MidiSynth.Keyboard.play(synth, 60, 100)
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.
```elixir
iex> MidiSynth.Keyboard.play(synth, 60, 100, 80)
iex> MIDISynth.Keyboard.play(synth, 60, 100, 80)
```
If you don't like the piano, try switching the instrument to something else. For
Expand All @@ -61,8 +61,8 @@ instrument](https://www.midi.org/specifications-old/item/gm-level-1-sound-set)
57) are nice:
```elixir
iex> MidiSynth.Keyboard.change_program(synth, 57)
iex> MidiSynth.Keyboard.play(synth, 60, 500)
iex> MIDISynth.Keyboard.change_program(synth, 57)
iex> MIDISynth.Keyboard.play(synth, 60, 500)
```
The real value of this library is the ability to send raw MIDI messages to the
Expand All @@ -72,11 +72,11 @@ commands](https://www.midi.org/specifications/item/table-1-summary-of-midi-messa
try this out:
```elixir
iex> MidiSynth.midi(<<0x90, 60, 127>>)
iex> MidiSynth.midi(<<0x80, 60, 127>>)
iex> MIDISynth.midi(<<0x90, 60, 127>>)
iex> MIDISynth.midi(<<0x80, 60, 127>>)
```
See `MidiSynth.Command` for help with encoding messages, and please feel free to
See `MIDISynth.Command` for help with encoding messages, and please feel free to
add more.
## License
Expand Down
10 changes: 5 additions & 5 deletions lib/midi_synth.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule MidiSynth do
defmodule MIDISynth do
use GenServer

@moduledoc """
Expand All @@ -21,13 +21,13 @@ defmodule MidiSynth do
@doc """
Send a raw MIDI command to the synthesizer
See `MidiSynth.Command` for encoding MIDI commands and `MidiSynth.Keyboard`
See `MIDISynth.Command` for encoding MIDI commands and `MIDISynth.Keyboard`
for playing simple songs.
## Examples
iex> {:ok, synth} = MidiSynth.start_link([])
iex> MidiSynth.midi(synth, <<0x90, 60, 127>>)
iex> {:ok, synth} = MIDISynth.start_link([])
iex> MIDISynth.midi(synth, <<0x90, 60, 127>>)
:ok
"""
Expand Down Expand Up @@ -72,7 +72,7 @@ defmodule MidiSynth do
Keyword.put(args, :soundfont, soundfont_path)
else
raise ArgumentError,
"Could not find '#{soundfont_path}'.\nCheck the `:soundfont` option to MidiSynth.start_link/2."
"Could not find '#{soundfont_path}'.\nCheck the `:soundfont` option to MIDISynth.start_link/2."
end
end
end
2 changes: 1 addition & 1 deletion lib/midi_synth/command.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule MidiSynth.Command do
defmodule MIDISynth.Command do
@moduledoc """
Convert MIDI commands to raw bytes
"""
Expand Down
24 changes: 12 additions & 12 deletions lib/midi_synth/keyboard.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule MidiSynth.Keyboard do
alias MidiSynth.Command
defmodule MIDISynth.Keyboard do
alias MIDISynth.Command

@moduledoc """
Simple keyboard functions for sending MIDI commands to the synthesizer
Expand All @@ -13,23 +13,23 @@ defmodule MidiSynth.Keyboard do
## Example
iex> {:ok, synth} = MidiSynth.start_link([])
iex> MidiSynth.Keyboard.play(synth, 60, 100)
iex> {:ok, synth} = MIDISynth.start_link([])
iex> MIDISynth.Keyboard.play(synth, 60, 100)
:ok
iex> MidiSynth.Keyboard.play(synth, 60, 100, 80)
iex> MIDISynth.Keyboard.play(synth, 60, 100, 80)
:ok
"""
@spec play(GenServer.server(), Command.note(), Command.duration(), Command.velocity()) :: :ok
def play(server, note, duration, velocity \\ 127) do
MidiSynth.midi(server, Command.note_on(note, velocity))
MIDISynth.midi(server, Command.note_on(note, velocity))
Process.sleep(duration)
MidiSynth.midi(server, Command.note_off(note))
MIDISynth.midi(server, Command.note_off(note))
end

@doc """
Change the current program (e.g., the current instrument)
The soundfont that's supplied to `MidiSynth.start_link/2` determines the
The soundfont that's supplied to `MIDISynth.start_link/2` determines the
mapping from program numbers to instruments. The default is to use a general
MIDI soundfont, and instrument mappings for those can be found by looking at
the [General MIDI
Expand All @@ -40,14 +40,14 @@ defmodule MidiSynth.Keyboard do
## Example
# Play a violin
iex> {:ok, synth} = MidiSynth.start_link([])
iex> MidiSynth.Keyboard.change_program(synth, 41)
iex> {:ok, synth} = MIDISynth.start_link([])
iex> MIDISynth.Keyboard.change_program(synth, 41)
:ok
iex> MidiSynth.Keyboard.play(synth, 60, 100)
iex> MIDISynth.Keyboard.play(synth, 60, 100)
:ok
"""
@spec change_program(GenServer.server(), Command.program()) :: :ok
def change_program(server, prog) do
MidiSynth.midi(server, Command.change_program(prog))
MIDISynth.midi(server, Command.change_program(prog))
end
end
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule MidiSynth.MixProject do
defmodule MIDISynth.MixProject do
use Mix.Project

@version "0.2.0"
Expand Down
4 changes: 2 additions & 2 deletions test/midi_synth/command_test.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule MidiSynth.CommandTest do
defmodule MIDISynth.CommandTest do
use ExUnit.Case

alias MidiSynth.Command
alias MIDISynth.Command
doctest Command

test "note on" do
Expand Down
6 changes: 3 additions & 3 deletions test/midi_synth/keyboard_test.exs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
defmodule MidiSynth.KeyboardTest do
defmodule MIDISynth.KeyboardTest do
use ExUnit.Case

alias MidiSynth.Keyboard
alias MIDISynth.Keyboard
doctest Keyboard

test "playing notes" do
synth = start_supervised!(MidiSynth)
synth = start_supervised!(MIDISynth)
Keyboard.change_program(synth, 57)
Keyboard.play(synth, 60, 250)
Keyboard.play(synth, 67, 250)
Expand Down
14 changes: 7 additions & 7 deletions test/midi_synth_test.exs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
defmodule MidiSynthTest do
defmodule MIDISynthTest do
use ExUnit.Case

import ExUnit.CaptureLog
doctest MidiSynth
doctest MIDISynth

test "playing raw midi strings" do
synth = start_supervised!(MidiSynth)
MidiSynth.midi(synth, <<0x90, 60, 127>>)
synth = start_supervised!(MIDISynth)
MIDISynth.midi(synth, <<0x90, 60, 127>>)
Process.sleep(250)
MidiSynth.midi(synth, <<0x80, 60, 127>>)
MIDISynth.midi(synth, <<0x80, 60, 127>>)
end

@tag :requires_working_audio
test "MidiSynth exits when port crashes" do
test "MIDISynth exits when port crashes" do
Process.flag(:trap_exit, true)

capture_log(fn ->
{:ok, synth} = MidiSynth.start_link([])
{:ok, synth} = MIDISynth.start_link([])
System.cmd("killall", ["midi_synth"])

assert_receive {:EXIT, ^synth, message}
Expand Down

0 comments on commit 6ee0497

Please sign in to comment.