115 lines
2.7 KiB
Text
115 lines
2.7 KiB
Text
-- Lesson 27: Music And MIDI. The finished script, exactly as the lesson ends.
|
|
local NOTE_NAMES = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }
|
|
local MIDI_NOTE_ON = 0x90
|
|
local LOWEST = 60
|
|
local HIGHEST = 71
|
|
local HOLD_MS = 400
|
|
local VOLUME_STEP = 8
|
|
|
|
local theme = musicLoad("Singe/menuIntro.flac")
|
|
local volume = 64
|
|
|
|
local target = LOWEST
|
|
local heard = "nothing yet"
|
|
local score = 0
|
|
local inPort = "none"
|
|
local outPort = "none"
|
|
|
|
|
|
function noteName(key)
|
|
return NOTE_NAMES[(key % 12) + 1] .. (math.floor(key / 12) - 1)
|
|
end
|
|
|
|
|
|
function pickTarget()
|
|
target = math.random(LOWEST, HIGHEST)
|
|
end
|
|
|
|
|
|
function playTarget()
|
|
if not midiIsOutputOpen() then
|
|
return
|
|
end
|
|
local key = target
|
|
midiNoteOn(1, key, 100)
|
|
timerAfter(HOLD_MS, function()
|
|
midiNoteOff(1, key)
|
|
end)
|
|
end
|
|
|
|
|
|
function setVolume(level)
|
|
volume = math.min(128, math.max(0, level))
|
|
musicSetVolume(volume)
|
|
end
|
|
|
|
|
|
function onInputPressed(what)
|
|
if what == SWITCH_BUTTON1 then
|
|
playTarget()
|
|
elseif what == SWITCH_BUTTON2 then
|
|
if musicIsPlaying(theme) then
|
|
musicPause(theme)
|
|
else
|
|
musicResume(theme)
|
|
end
|
|
elseif what == SWITCH_BUTTON3 then
|
|
if musicIsPlaying(theme) then
|
|
musicStop(theme, 2000)
|
|
else
|
|
musicPlay(theme, -1)
|
|
end
|
|
elseif what == SWITCH_UP then
|
|
setVolume(volume + VOLUME_STEP)
|
|
elseif what == SWITCH_DOWN then
|
|
setVolume(volume - VOLUME_STEP)
|
|
end
|
|
end
|
|
|
|
|
|
function onMidiMessage(status, data1, data2, bytes)
|
|
if (status & 0xF0) ~= MIDI_NOTE_ON or data2 == 0 then
|
|
return
|
|
end
|
|
heard = noteName(data1)
|
|
if data1 == target then
|
|
score = score + 1
|
|
pickTarget()
|
|
playTarget()
|
|
end
|
|
end
|
|
|
|
|
|
function onOverlayUpdate()
|
|
overlayClear()
|
|
overlayPrint(2, 2, "Music: " .. (musicIsPlaying(theme) and "playing" or "stopped"))
|
|
overlayPrint(2, 3, "Volume: " .. volume .. " of 128")
|
|
overlayPrint(2, 5, "MIDI in: " .. inPort)
|
|
overlayPrint(2, 6, "MIDI out: " .. outPort)
|
|
overlayPrint(2, 8, "Play this note: " .. noteName(target))
|
|
overlayPrint(2, 9, "Last note heard: " .. heard)
|
|
overlayPrint(2, 10, "Score: " .. score)
|
|
overlayPrint(2, 12, "Up and down change the volume.")
|
|
overlayPrint(2, 13, "Space sends the note out, Alt pauses, Shift fades out.")
|
|
return OVERLAY_UPDATED
|
|
end
|
|
|
|
|
|
function onShutdown()
|
|
midiCloseInput()
|
|
midiCloseOutput()
|
|
musicUnload(theme)
|
|
end
|
|
|
|
|
|
setVolume(volume)
|
|
musicPlay(theme, -1)
|
|
|
|
if midiInputCount() > 0 and midiOpenInput(0) then
|
|
inPort = midiInputName(0)
|
|
end
|
|
if midiOutputCount() > 0 and midiOpenOutput(0) then
|
|
outPort = midiOutputName(0)
|
|
end
|
|
|
|
pickTarget()
|