It doesn't need to iterate over all of the notes, because it just checks each track in the currently playing sequence s and polls for the currently active notes with getNotesActive():
for i=1,#active do
Runs an iteration on i for each item in active
local track = s:getTrackAtIndex(i)
Uses i to get each track in s, one at a time, stored in track
local n = track:getNotesActive(active[i])
Pulls the active notes out of the current track. (I'm not sure what the active[i] argument does, since it doesn't seem to be described in the manual... maybe it's for a depreciated parameter)
For your second question, I'm not totally sure why your method for checking the current notes based on the current step doesn't work how you expected. But, I suspect that the MIDI sequence processing may be running in parallel with the playdate.update() callback, so you don't always see the same number of MIDI ticks between frames (if you did, then graphical framerate would affect playback). I'm guessing that getNotesActive() still works in update() because it is designed to do so, though I'm not really sure if this is the case.
EDIT: It just occurred to me that getNotes() probably only gives the notes STARTED at a given step, while getNotesActive() will return any notes that are currently playing, which is dependent on note length and start position, as well as the current step.
EDIT: robamcclellan points out below that getNotesActive() only returns the number of active notes, not the notes themselves.
Try one of these:
Use track:getNotesActive() instead, like in the example code (EDIT: only gives the number of notes, not the actual notes played)
Instead of checking only the current step, try checking for the notes played since the last update() by also storing the previous step value, and doing this:
local t = track:getNotes(prevStep, s:getCurrentStep())
If there are notes that are in quick succession, but not simultaneous, in a project with a fast song/slow framerate, I think you might sometimes get more than one set of notes from this method. Another option is to store the notes played in EACH step passed since the last update(), by iterating over each step between prevStep and s:getCurrentStep().
To address your last remark, the step is going to increment based on the Tempo of the MIDI file, not based on the framerate of the game, so I think it's expected that the step increases faster than the number of update() calls.