void Tick() { DateTime tickTime = DateTime.Now; if (toRelease != null && tickTime >= startTime + TimeSpan.FromMilliseconds(toRelease.MillisecondsElapsed)) { channel.Note = null; toRelease = null; } if (noMoreNotes && toRelease == null) { Stop(); return; } else if (noMoreNotes) { return; } while (tickTime >= startTime + TimeSpan.FromMilliseconds(millisecondsFromStart)) { MidiToken midiToken = null; int note = 0; while (midiToken == null || (midiToken.TokenType != MidiTokenType.Note && midiToken.TokenType != MidiTokenType.Rest)) { midiToken = DecodeNextToken(tune, ref index, out tokenIndex); switch (midiToken.TokenType) { case MidiTokenType.Null: noMoreNotes = true; return; case MidiTokenType.Octave: currentOctave = midiToken.Code.ToString()[0]; break; case MidiTokenType.Tempo: tempo = midiToken.Code; break; case MidiTokenType.Instrument: channel.Instrument = (SpeccyMIDIInstrument)midiToken.Code; break; case MidiTokenType.Volume: volume = midiToken.Code; break; case MidiTokenType.Rest: note = -1; break; case MidiTokenType.Note: note = midiToken.Code; break; case MidiTokenType.Duration: duration = midiToken.Value; break; default: throw new MidiParsingException(tokenIndex, "Expecting Tempo, Instrument, Volume, Note, Note Group, or Rest"); } } if (note != -1) { if (toRelease != null) { channel.Note = null; } channel.SetNote((SpeccyMIDINotes)note, volume); toRelease = new ReleaseInfo(note, millisecondsFromStart + 240000.0 * duration / tempo); } millisecondsFromStart += 240000.0 * duration / tempo; } }
MidiToken NewToken(List<MidiToken> tokens, int time, byte type) { var token = new MidiToken { Time = time, Type = type, OriginalIndex = tokens.Count }; tokens.Add(token); return token; }