midi_player/lib/midi_tools/event.ex

74 lines
1.9 KiB
Elixir
Raw Normal View History

defmodule MIDITools.Event do
2020-10-11 11:40:12 +00:00
@moduledoc """
Several musical events which can be converted to MIDI commands.
All timings are in milliseconds.
"""
defmodule Note do
2020-10-11 11:40:12 +00:00
@moduledoc """
An event which plays the given tone for the given timespan.
"""
defstruct channel: 0, tone: 0, start_time: 0, end_time: 0, velocity: 0
2020-10-11 16:15:16 +00:00
@spec new(
MIDISynth.Command.channel(),
non_neg_integer(),
non_neg_integer(),
non_neg_integer(),
MIDISynth.Command.velocity()
) :: %Note{}
def new(channel, tone, start_time, end_time, velocity)
when start_time >= 0 and end_time > start_time do
%__MODULE__{
channel: channel,
tone: tone,
start_time: start_time,
end_time: end_time,
velocity: velocity
}
end
end
2020-10-11 10:27:49 +00:00
defmodule ChangeProgram do
2020-10-11 11:40:12 +00:00
@moduledoc """
An event which changes the current program of the given channel.
"""
2020-10-11 10:27:49 +00:00
defstruct channel: 0, time: 0, program: 0
2020-10-11 16:15:16 +00:00
@spec new(MIDISynth.Command.channel(), non_neg_integer(), non_neg_integer()) ::
%ChangeProgram{}
2020-10-11 10:27:49 +00:00
def new(channel, time, program) do
%__MODULE__{channel: channel, time: time, program: program}
end
end
2020-10-11 11:40:12 +00:00
@typedoc """
A musical event.
"""
@type t :: %Note{} | %ChangeProgram{}
@doc """
Converts the event to a list of MIDI commands.
"""
2020-10-11 14:04:56 +00:00
@spec convert(t()) :: [{non_neg_integer(), binary()}]
def convert(%Note{
channel: channel,
tone: tone,
start_time: start_time,
end_time: end_time,
velocity: velocity
}) do
note_on = MIDISynth.Command.note_on(channel, tone, velocity)
note_off = MIDISynth.Command.note_off(channel, tone)
[{start_time, note_on}, {end_time, note_off}]
end
2020-10-11 10:27:49 +00:00
def convert(%ChangeProgram{channel: channel, time: time, program: program}) do
change_program = MIDISynth.Command.change_program(channel, program)
[{time, change_program}]
end
end