static private void ReadTrack() { MIDITrack track = new MIDITrack(); track.events = new List <MIDIEvent>(); string trackChunkType = ReadString(4); if (!trackChunkType.Equals("MTrk")) { throw new System.FormatException("No track chunk type has been found."); } int trackChunkLength = ReadInt32(); uint trackChunkEnd = m_index + (uint)trackChunkLength; int accumulatedDeltaTicks = 0; m_prevStatus = 0; while (m_index < trackChunkEnd) { int deltaTicks = ReadVariableLengthInt(); accumulatedDeltaTicks += deltaTicks; m_status = ReadByte(); MIDIEvent midiEvent = ReadEvent(accumulatedDeltaTicks); if (midiEvent != null) { track.events.Add(midiEvent); accumulatedDeltaTicks = 0; } } m_song.tracks.Add(track); }
/// <summary> /// MIDIデータに歌詞を追加します。 /// </summary> private void MakeLyric(MIDITrack midiTrack, List <MeasureAndTextBox> measures) { RemoveLyric(midiTrack); foreach (MeasureAndTextBox measure in measures) { StringBuilder stringBuilder = new StringBuilder(measure.Lyric); for (int i = 0; i < measure.MidiEvent.Length; i++) { if (stringBuilder.Length <= 0) { break; } string lyricChar = stringBuilder[0].ToString(); //先頭の文字を取得 stringBuilder.Remove(0, 1); //先頭の文字を削除 //次の文字が小文字の場合、一緒に歌詞に含める。 if (IsFirstCharacterLowerCase(stringBuilder.ToString())) { lyricChar += stringBuilder[0].ToString(); //先頭の文字を追加 stringBuilder.Remove(0, 1); //先頭の文字を削除 } MIDIEvent targetEvent = measure.MidiEvent[i]; MIDIEvent lyricEvent = MIDIEvent.CreateLyric(targetEvent.Time, lyricChar); midiTrack.InsertEventAfter(lyricEvent, targetEvent); } } }
static void AnalyzeTrack(MIDITrack track) { foreach (IMIDIEvent lEvent in track.Events) { switch (lEvent.Type) { case MIDIEventType.NoteOn: MIDIChannelEvent cEvent = (MIDIChannelEvent)lEvent; Console.WriteLine($"Note on: {cEvent.Data1}"); break; case MIDIEventType.Meta: MIDIMetaEvent mEvent = (MIDIMetaEvent)lEvent; if (mEvent.MetaType == 3) { Console.WriteLine($"Track name: {Encoding.ASCII.GetString(mEvent.Data)}"); } if (mEvent.MetaType == 4) { Console.WriteLine($"Instrument: {Encoding.ASCII.GetString(mEvent.Data)}"); } break; } } }
public void TestRead() { midi.Read(TestUtils.GetResourceStream("Bass_sample.mid")); Assert.AreEqual(2, midi.TrackCount); int i = 0; List <MIDIEvent> events = new List <MIDIEvent>(); MIDITrack track0 = midi.Tracks[0]; Assert.AreEqual(4, track0.EventCount); events.Clear(); events.AddRange(track0.GetAllEvents()); Assert.AreEqual(0, events[0].Time); Assert.AreEqual(MIDIMessageType.TimeSignature, events[0].Data.Type); Assert.AreEqual(4, (events[0].Data as MIDITimeSignatureMessage).Numerator); Assert.AreEqual(4, (events[0].Data as MIDITimeSignatureMessage).Denominator); Assert.AreEqual(24, (events[0].Data as MIDITimeSignatureMessage).MetronomeClocks); Assert.AreEqual(8, (events[0].Data as MIDITimeSignatureMessage).NotatedQuarterTicks); Assert.AreEqual(0, events[1].Time); Assert.AreEqual(MIDIMessageType.SetTempo, events[1].Data.Type); Assert.AreEqual(500000, (events[1].Data as MIDITempoMessage).Tempo); Assert.That((events[1].Data as MIDITempoMessage).BeatsPerMinute, Is.EqualTo(120).Within(0.001)); MIDITrack track1 = midi.Tracks[1]; Assert.AreEqual(31, track1.EventCount); events.Clear(); events.AddRange(track1.GetAllEvents()); Assert.AreEqual(0, events[0].Time); Assert.AreEqual(MIDIMessageType.ProgramChange, events[0].Data.Type); Assert.AreEqual(0x21, (events[0].Data as MIDIProgramChangeMessage).Program); Assert.AreEqual(0, events[1].Time); Assert.AreEqual(MIDIMessageType.ControlChange, events[1].Data.Type); Assert.AreEqual(MIDIControl.ChannelVolumeMSB, (events[1].Data as MIDIControlChangeMessage).Controller); Assert.AreEqual(0, events[2].Time); Assert.AreEqual(129, events[3].Time); Assert.AreEqual(360, events[4].Time); Assert.AreEqual(480, events[5].Time); Assert.AreEqual(483, events[6].Time); Assert.AreEqual(600, events[7].Time); Assert.AreEqual(3450, events[29].Time); Assert.AreEqual(MIDIMessageType.NoteOn, events[2].Data.Type); Assert.AreEqual(MIDIMessageType.NoteOff, events[3].Data.Type); Assert.AreEqual(MIDIMessageType.NoteOff, events[29].Data.Type); Assert.AreEqual(0, (events[2].Data as MIDINoteMessage).Channel); Assert.AreEqual(0x2D, (events[2].Data as MIDINoteMessage).Key); Assert.AreEqual(0x2D, (events[3].Data as MIDINoteMessage).Key); Assert.AreEqual(0x32, (events[22].Data as MIDINoteMessage).Key); }
public void ReadMIDIFile(string path) { Debug.Log(path); this.midiFile = File.OpenRead(path); this.header = ParseHeader(midiFile); this.tracks = new List <MIDITrack>(); this.currentNotes = new Dictionary <uint, MIDINote>(); for (int i = 0; i < header.number_of_tracks; i++) { MIDITrack track = ParseTrack(midiFile); this.tracks.Add(track); } }
/// <summary> /// MIDIデータから歌詞を削除します。 /// </summary> public void RemoveLyric(MIDITrack midiTrack) { List <MIDIEvent> lyricEvents = new List <MIDIEvent>(); //ループ中にイベントを除外又は削除してはならない。イベントの消滅により次のイベントが探索できなくなるからだ。 foreach (MIDIEvent midiEvent in midiTrack) { if (midiEvent.IsLyric) { lyricEvents.Add(midiEvent); } } foreach (MIDIEvent midiEvent in lyricEvents) { midiTrack.RemoveEvent(midiEvent); } }
private void Reset() { if (m_song == null) { return; } m_elapsedTime = -m_song.firstMeasureDuration; m_score = 0; m_totalNoteCount = 0; m_correctNoteCount = 0; m_hitStreak = 0; m_multiplier = 1.0f; m_leftHandSongNoteIndex = 0; m_rightHandSongNoteIndex = 0; m_leftHandSongNotes.Clear(); m_rightHandSongNotes.Clear(); for (int i = 0; i < m_song.tracks.Count; i++) { MIDITrack track = m_song.tracks[i]; foreach (MIDIEvent midiEvent in track.events) { if (midiEvent.GetType() == typeof(MIDINoteEvent)) { MIDINoteEvent noteEvent = midiEvent as MIDINoteEvent; if (noteEvent.isNoteOn) { if (i == 1) { m_leftHandSongNotes.Add(noteEvent); } else if (i == 0) { m_rightHandSongNotes.Add(noteEvent); } } } } } m_deviceNoteTimestamps.Clear(); }
static private void ForwardMinNextEvent(MIDIEvent minNextEvent, List <MIDIEvent> nextEventList) { for (int i = 0; i < m_song.tracks.Count; i++) { MIDITrack track = m_song.tracks[i]; int nextEventIndex = track.events.IndexOf(minNextEvent); if (nextEventIndex == -1) { continue; } nextEventList[i] = null; nextEventIndex++; if (nextEventIndex < track.events.Count) { nextEventList[i] = track.events[nextEventIndex]; } } }
// Use this for initialization void Start() { midi = GetComponent <MIDI>(); midi.ReadMIDIFile(midiFilePath); int trackCount = midi.tracks.Count; if (generateOnlyFromFirstTrack) { trackCount = 1; } for (int i = 0; i < trackCount; i++) { MIDITrack track = midi.tracks[i]; foreach (MIDIEvent e in track.events) { Debug.Log("type of event" + e.GetType().ToString()); if (e.GetType() != typeof(MIDINote)) { continue; } MIDINote note = (MIDINote)e; GameObject platform; if (this.platforms.Length > 0) { int idx = Random.Range(0, this.platforms.Length); platform = GameObject.Instantiate(this.platforms[idx]) as GameObject; } else { platform = GameObject.CreatePrimitive(PrimitiveType.Cube); } Vector3 pos = new Vector3(note.absoluteStartTime, (float)note.note, 0.0f); platform.transform.position = pos; } } }
private void PrepareNextEventIndexList() { for (int i = 0; i < m_song.tracks.Count; i++) { MIDITrack track = m_song.tracks[i]; for (int j = 0; j < track.events.Count; j++) { if (track.events[j].timestamp >= m_elapsedTime - 0.001f) { m_nextEventIndexList[i] = j; break; } else { m_nextEventIndexList[i] = track.events.Count; } } } }
void OnGUI() { if (GUI.Button(new Rect(10, 70, 120, 30), "Play")) { AudioSource audioSrc = GetComponent <AudioSource>(); MIDITrack track = midi.tracks[0]; foreach (MIDIEvent e in track.events) { Debug.Log("type of event" + e.GetType().ToString()); if (e.GetType() != typeof(MIDINote)) { continue; } MIDINote note = (MIDINote)e; Debug.Log("note:" + note.note); audioSrc.clip = sampler.samples[note.note]; audioSrc.PlayScheduled((double)note.absoluteStartTime); } } }
public void Update(float deltaTime) { if (m_isPlaying && !m_isSleeping) { deltaTime = deltaTime * m_speedFactor; NotifyUpdate(deltaTime); m_elapsedTime += deltaTime; CalcCurrentMeasure(); for (int i = 0; i < m_song.tracks.Count; i++) { MIDITrack track = m_song.tracks[i]; bool processedAllEventsWithCurrentTimestamp = false; while (!processedAllEventsWithCurrentTimestamp) { int nextEventIndex = m_nextEventIndexList[i]; if (nextEventIndex >= track.events.Count) { break; } MIDIEvent nextEvent = track.events[nextEventIndex]; if (nextEvent.timestamp <= m_elapsedTime) { NotifyEvent(nextEvent, i); m_nextEventIndexList[i]++; } else { processedAllEventsWithCurrentTimestamp = true; } } } } }
public void TestRead() { midi.ReadHMP(TestUtils.GetResourceStream("vgame20.hmp")); Assert.AreEqual(13, midi.TrackCount); Assert.AreEqual(HMPValidDevice.Default, midi.Tracks[0].HMPDevices); for (int i = 1; i < midi.TrackCount; ++i) { Assert.AreEqual(HMPValidDevice.All, midi.Tracks[i].HMPDevices); } foreach (MIDITrack track in midi.Tracks) { Assert.AreEqual(0, track.HMPBranchPoints.Count); } List <MIDIEvent> events = new List <MIDIEvent>(); MIDITrack track1 = midi.Tracks[1]; Assert.AreEqual(2952, track1.EventCount); events.Clear(); events.AddRange(track1.GetAllEvents()); Assert.AreEqual(0, events[2].Time); Assert.AreEqual(5743, events[120].Time); Assert.AreEqual(5977, events[300].Time); }
MIDITrack ParseTrack(FileStream inFile) { MIDITrack track = new MIDITrack(); // MThd { byte[] _mtrk = new byte[4]; inFile.Read(_mtrk, 0, 4); Array.Reverse(_mtrk); track.MTrk = BitConverter.ToUInt32(_mtrk, 0); if(track.MTrk != (UInt32)MIDI_EVENT_TYPES.TRACK_CHUNK_ID){ throw new Exception("wrong track header"); } } // track length { byte[] _len = new byte[4]; inFile.Read(_len, 0, 4); Array.Reverse(_len); track.track_length = BitConverter.ToUInt32(_len, 0); } // start reading events long pos = inFile.Position; this.timeOffset = 0; while(inFile.Position < pos + track.track_length){ int deltaTime = ParseVarLen(inFile); this.timeOffset += deltaTime; MIDIEvent midi_event = new MIDIEvent(); midi_event.delta_time = deltaTime; midi_event.event_type = inFile.ReadByte(); switch(midi_event.event_type){ case (int)MIDI_EVENT_TYPES.META_EVENT: ParseMetaEvent(inFile, midi_event); // Debug.Log("Meta event"); break; case (int)MIDI_EVENT_TYPES.SYSEX_EVENT: case (int)MIDI_EVENT_TYPES.SYSEX_CHUNK: ParseSysexEvent(inFile, midi_event); // Debug.Log("Sysex event"); break; default: midi_event = ParseChannelEvent(inFile, midi_event); // Debug.Log("channel event"); break; } Debug.Log(midi_event); track.events.Add(midi_event); } return track; }
public byte[] ProcessMessage(MIDITrack track, int messageIndex) { return(track.MidiEvents[messageIndex].MidiMessage); }
private void ShowNotesInVisibleRegion(float startTimeOfVisibleRegion, float endTimeOfVisibleRegion) { for (int i = 0; i < m_noteObjectsRingBuffer.GetSize(); i++) { GameObject noteObject = m_noteObjectsRingBuffer.GetCurrentElement(); m_noteObjectsRingBuffer.Advance(); noteObject.transform.localPosition = new Vector3(0.0f, 0.0f, -10.0f); noteObject.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); } List <MIDINoteEvent> pressedNoteEvents = new List <MIDINoteEvent>(); for (int i = 0; i < m_song.tracks.Count; i++) { if (!m_isRightHandEnabled && i == 0) { continue; } if (!m_isLeftHandEnabled && i == 1) { continue; } MIDITrack track = m_song.tracks[i]; foreach (MIDIEvent midiEvent in track.events) { if (midiEvent.GetType() == typeof(MIDINoteEvent)) { MIDINoteEvent noteEvent = midiEvent as MIDINoteEvent; if (noteEvent.isNoteOn && noteEvent.timestamp >= startTimeOfVisibleRegion - 5.0f && noteEvent.timestamp <= endTimeOfVisibleRegion + 5.0f) { pressedNoteEvents.Add(noteEvent); } else if (!noteEvent.isNoteOn && noteEvent.timestamp >= startTimeOfVisibleRegion - 5.0f && noteEvent.timestamp <= endTimeOfVisibleRegion + 5.0f) { MIDINoteEvent releasedNoteEvent = noteEvent; foreach (MIDINoteEvent pressedNoteEvent in pressedNoteEvents) { if (pressedNoteEvent.note == releasedNoteEvent.note) { if (releasedNoteEvent.timestamp < pressedNoteEvent.timestamp) { break; } pressedNoteEvents.Remove(pressedNoteEvent); GameObject noteObject = m_noteObjectsRingBuffer.GetCurrentElement(); m_noteObjectsRingBuffer.Advance(); float startX, startY, startZ, endX, endY, endZ; startZ = (pressedNoteEvent.timestamp - startTimeOfVisibleRegion) * m_defaultSpeed; endZ = (releasedNoteEvent.timestamp - startTimeOfVisibleRegion) * m_defaultSpeed; float offset = GetNoteOffset(noteEvent.note, m_octavePitch); if (IsBlackNote(noteEvent.note)) { startX = offset * m_noteWidth + 0.0015f; endX = (offset + 0.5f) * m_noteWidth - 0.0015f; startY = 0.0f - 0.059f; endY = 0.0121f - 0.059f; } else { startX = offset * m_noteWidth; endX = (offset + 1.0f) * m_noteWidth; startY = 0.0f - 0.059f; endY = m_noteHeight - 0.059f; } noteObject.transform.localPosition = new Vector3((startX + endX) * 0.5f, (startY + endY) * 0.5f, (startZ + endZ) * 0.5f); noteObject.transform.localScale = new Vector3(Mathf.Abs(endX - startX), Mathf.Abs(endY - startY), Mathf.Abs(endZ - startZ)); // determine vertex colors Color color = Color.HSVToRGB((float)i / (float)m_song.tracks.Count, 1.0f, 1.0f); if (IsBlackNote(noteEvent.note)) { color *= 0.5f; } Mesh mesh = noteObject.GetComponent <MeshFilter>().mesh; Vector3[] vertPositions = mesh.vertices; Color[] vertColors = new Color[vertPositions.Length]; for (int j = 0; j < vertPositions.Length; j++) { float t = vertPositions[j].z + 0.5f; vertColors[j] = Color.Lerp(color, color * 0.5f, t); } mesh.colors = vertColors; break; } } } } } } }
MIDITrack ParseTrack(FileStream inFile) { MIDITrack track = new MIDITrack(); // MThd { byte[] _mtrk = new byte[4]; inFile.Read(_mtrk, 0, 4); Array.Reverse(_mtrk); track.MTrk = BitConverter.ToUInt32(_mtrk, 0); if (track.MTrk != (UInt32)MIDI_EVENT_TYPES.TRACK_CHUNK_ID) { throw new Exception("wrong track header"); } } // track length { byte[] _len = new byte[4]; inFile.Read(_len, 0, 4); Array.Reverse(_len); track.track_length = BitConverter.ToUInt32(_len, 0); } // start reading events long pos = inFile.Position; this.timeOffset = 0; while (inFile.Position < pos + track.track_length) { int deltaTime = ParseVarLen(inFile); this.timeOffset += deltaTime; MIDIEvent midi_event = new MIDIEvent(); midi_event.delta_time = deltaTime; midi_event.event_type = inFile.ReadByte(); switch (midi_event.event_type) { case (int)MIDI_EVENT_TYPES.META_EVENT: ParseMetaEvent(inFile, midi_event); // Debug.Log("Meta event"); break; case (int)MIDI_EVENT_TYPES.SYSEX_EVENT: case (int)MIDI_EVENT_TYPES.SYSEX_CHUNK: ParseSysexEvent(inFile, midi_event); // Debug.Log("Sysex event"); break; default: midi_event = ParseChannelEvent(inFile, midi_event); // Debug.Log("channel event"); break; } Debug.Log(midi_event); track.events.Add(midi_event); } return(track); }
private void ExecuteButton_Click(object sender, RoutedEventArgs e) { OutputStackPanel.Children.Clear(); Measures.Clear(); if (!File.Exists(MidiFileName)) { return; } try { MidiData = new MIDIData(MidiFileName); } catch (Exception ex) { MessageBox.Show(ex.Message); return; } if (MidiData.TimeMode != MIDIData.TimeModes.TPQN) { MessageBox.Show("TPQN以外の形式には対応していません。", "エラー", MessageBoxButton.OK, MessageBoxImage.Error); return; } MIDITrack track = TargetTrack; if (track == null) { MessageBox.Show("未対応のフォーマットです。\n対応フォーマットは「Format0」と「Format1」です。", "エラー", MessageBoxButton.OK, MessageBoxImage.Error); return; } //結合できるイベントを結合 foreach (MIDIEvent midiEvent in track) { if (midiEvent.IsNoteOn) //ノートONで { if (!midiEvent.IsCombined) //結合されていない場合 { midiEvent.Combine(); } } } int currentMeasure = -1; List <MIDIEvent> events = new List <MIDIEvent>(); //一小節分のノートイベントを保管する。 //ノートのある小節の個数分、テキストボックス追加 foreach (MIDIEvent midiEvent in track) { if (midiEvent.IsNoteOn) { int measure = MidiData.BreakTime(midiEvent.Time).Measure; //このノートの所属している小節取得 if (measure > currentMeasure) //次の小節に行ったら { if (events.Count != 0) //小節へイベントの追加、その後クリア { Measures.Last().MidiEvent = events.ToArray(); events.Clear(); } TextBox textBox = AddTextBox(measure); //ここで作成しないと、小節番号がわからない。 Measures.Add(new MeasureAndTextBox(textBox)); events.Add(midiEvent); currentMeasure = measure; } else { events.Add(midiEvent); } } } //最後のイベント追加 if (events.Count != 0) { Measures.Last().MidiEvent = events.ToArray(); events.Clear(); } SaveButton.IsEnabled = true; }