-- 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()