|
@@ -11,20 +11,22 @@
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
package com.jinmingyunle.midiplaylib.midifile;
|
|
package com.jinmingyunle.midiplaylib.midifile;
|
|
|
|
|
|
|
|
+import android.util.Log;
|
|
|
|
+
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
|
|
|
|
|
|
|
-/** @class MidiTrack
|
|
|
|
|
|
+/**
|
|
|
|
+ * @class MidiTrack
|
|
* MidiTrack将曲目的原始middievents作为输入,并获取:
|
|
* MidiTrack将曲目的原始middievents作为输入,并获取:
|
|
* The MidiTrack takes as input the raw MidiEvents for the track, and gets:
|
|
* The MidiTrack takes as input the raw MidiEvents for the track, and gets:
|
|
* * -曲目中midi音符的列表。
|
|
* * -曲目中midi音符的列表。
|
|
* - The list of midi notes in the track.
|
|
* - The list of midi notes in the track.
|
|
* * -在轨道上使用的第一个乐器。
|
|
* * -在轨道上使用的第一个乐器。
|
|
* - The first instrument used in the track.
|
|
* - The first instrument used in the track.
|
|
- *对于midi文件中的每个NoteOn事件,都会创建一个新的MidiNote
|
|
|
|
|
|
+ * 对于midi文件中的每个NoteOn事件,都会创建一个新的MidiNote
|
|
* For each NoteOn event in the midi file, a new MidiNote is created
|
|
* For each NoteOn event in the midi file, a new MidiNote is created
|
|
* 和添加到轨道,使用AddNote()方法。
|
|
* 和添加到轨道,使用AddNote()方法。
|
|
* and added to the track, using the AddNote() method.
|
|
* and added to the track, using the AddNote() method.
|
|
@@ -32,60 +34,74 @@ import java.util.ArrayList;
|
|
* The NoteOff() method is called when a NoteOff event is encountered,
|
|
* The NoteOff() method is called when a NoteOff event is encountered,
|
|
* 以更新MidiNote的持续时间
|
|
* 以更新MidiNote的持续时间
|
|
* in order to update the duration of the MidiNote.
|
|
* in order to update the duration of the MidiNote.
|
|
- */
|
|
|
|
-public class MidiTrack {
|
|
|
|
- private int tracknum; /** The track number 音轨数量*/
|
|
|
|
- private ArrayList<MidiNote> notes; /** List of Midi notes 音符集合*/
|
|
|
|
- private int instrument; /** Instrument for this track 乐器 音轨*/
|
|
|
|
- private String trackName; /** 声道名称 */
|
|
|
|
- private ArrayList<MidiEvent> lyrics; /** The lyrics歌词 in this track */
|
|
|
|
|
|
+ */
|
|
|
|
+public class MidiTrack implements Comparable<MidiTrack> {
|
|
|
|
+ private int tracknum;
|
|
|
|
+ /**
|
|
|
|
+ * The track number 音轨数量
|
|
|
|
+ */
|
|
|
|
+ private ArrayList<MidiNote> notes;
|
|
|
|
+ /**
|
|
|
|
+ * List of Midi notes 音符集合
|
|
|
|
+ */
|
|
|
|
+ private int instrument;
|
|
|
|
+ /**
|
|
|
|
+ * Instrument for this track 乐器 音轨
|
|
|
|
+ */
|
|
|
|
+ private String trackName;
|
|
|
|
+ /**
|
|
|
|
+ * 声道名称
|
|
|
|
+ */
|
|
|
|
+ private ArrayList<MidiEvent> lyrics;
|
|
|
|
+ /**
|
|
|
|
+ * The lyrics歌词 in this track
|
|
|
|
+ */
|
|
private int time = 0;
|
|
private int time = 0;
|
|
|
|
|
|
- /** Create an empty MidiTrack. Used by the Clone method */
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Create an empty MidiTrack. Used by the Clone method
|
|
|
|
+ */
|
|
public MidiTrack(int tracknum) {
|
|
public MidiTrack(int tracknum) {
|
|
this.tracknum = tracknum;
|
|
this.tracknum = tracknum;
|
|
notes = new ArrayList<MidiNote>(20);
|
|
notes = new ArrayList<MidiNote>(20);
|
|
instrument = 0;
|
|
instrument = 0;
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- /** Create a MidiTrack based on the Midi events. Extract the NoteOn/NoteOff
|
|
|
|
- * events to gather the list of MidiNotes. 基于Midi事件创建MidiTrack。 提取NoteOn件/ NoteOff
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Create a MidiTrack based on the Midi events. Extract the NoteOn/NoteOff
|
|
|
|
+ * events to gather the list of MidiNotes. 基于Midi事件创建MidiTrack。 提取NoteOn件/ NoteOff
|
|
* *事件收集MidiNotes列表
|
|
* *事件收集MidiNotes列表
|
|
*/
|
|
*/
|
|
public MidiTrack(ArrayList<MidiEvent> events, int tracknum) {
|
|
public MidiTrack(ArrayList<MidiEvent> events, int tracknum) {
|
|
this.tracknum = tracknum;
|
|
this.tracknum = tracknum;
|
|
notes = new ArrayList<MidiNote>(events.size());
|
|
notes = new ArrayList<MidiNote>(events.size());
|
|
- instrument = 0;
|
|
|
|
|
|
+ instrument = -1;
|
|
time = 0;
|
|
time = 0;
|
|
- time = events.get(events.size() - 1).StartTime+events.get(events.size() - 1).DeltaTime;
|
|
|
|
-
|
|
|
|
|
|
+ time = events.get(events.size() - 1).StartTime + events.get(events.size() - 1).DeltaTime;
|
|
|
|
+
|
|
for (MidiEvent mevent : events) {
|
|
for (MidiEvent mevent : events) {
|
|
if (mevent.EventFlag == MidiFile.EventNoteOn && mevent.Velocity > 0) {
|
|
if (mevent.EventFlag == MidiFile.EventNoteOn && mevent.Velocity > 0) {
|
|
MidiNote note = new MidiNote(mevent.StartTime, mevent.Channel, mevent.Notenumber, 0);
|
|
MidiNote note = new MidiNote(mevent.StartTime, mevent.Channel, mevent.Notenumber, 0);
|
|
AddNote(note);
|
|
AddNote(note);
|
|
- }
|
|
|
|
- else if (mevent.EventFlag == MidiFile.EventNoteOn && mevent.Velocity == 0) {
|
|
|
|
|
|
+ } else if (mevent.EventFlag == MidiFile.EventNoteOn && mevent.Velocity == 0) {
|
|
NoteOff(mevent.Channel, mevent.Notenumber, mevent.StartTime);
|
|
NoteOff(mevent.Channel, mevent.Notenumber, mevent.StartTime);
|
|
- }
|
|
|
|
- else if (mevent.EventFlag == MidiFile.EventNoteOff) {
|
|
|
|
|
|
+ } else if (mevent.EventFlag == MidiFile.EventNoteOff) {
|
|
NoteOff(mevent.Channel, mevent.Notenumber, mevent.StartTime);
|
|
NoteOff(mevent.Channel, mevent.Notenumber, mevent.StartTime);
|
|
- }
|
|
|
|
- else if (mevent.EventFlag == MidiFile.EventProgramChange) {
|
|
|
|
|
|
+ } else if (mevent.EventFlag == MidiFile.EventProgramChange) {
|
|
instrument = mevent.Instrument;
|
|
instrument = mevent.Instrument;
|
|
- }
|
|
|
|
- else if (mevent.Metaevent == MidiFile.MetaEventLyric) {
|
|
|
|
|
|
+ } else if (mevent.Metaevent == MidiFile.MetaEventLyric) {
|
|
AddLyric(mevent);
|
|
AddLyric(mevent);
|
|
if (lyrics == null) {
|
|
if (lyrics == null) {
|
|
lyrics = new ArrayList<MidiEvent>();
|
|
lyrics = new ArrayList<MidiEvent>();
|
|
}
|
|
}
|
|
lyrics.add(mevent);
|
|
lyrics.add(mevent);
|
|
- } else if(mevent.Metaevent == MidiFile.MetaEventSequenceName) {
|
|
|
|
|
|
+ } else if (mevent.Metaevent == MidiFile.MetaEventSequenceName) {
|
|
trackName = new String(mevent.Value);
|
|
trackName = new String(mevent.Value);
|
|
- } else if(mevent.Metaevent == MidiFile.MetaEventInstrument) {
|
|
|
|
|
|
+ } else if (mevent.Metaevent == MidiFile.MetaEventInstrument) {
|
|
// trackName = new String(mevent.Value);
|
|
// trackName = new String(mevent.Value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if (notes.size() > 0 && notes.get(0).getChannel() == 9) {
|
|
|
|
|
|
+ if (notes.size() > 0 && notes.get(0).getChannel() == 9) {
|
|
instrument = 128; /* Percussion */
|
|
instrument = 128; /* Percussion */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -106,56 +122,78 @@ public class MidiTrack {
|
|
this.trackName = trackName;
|
|
this.trackName = trackName;
|
|
}
|
|
}
|
|
|
|
|
|
- public int trackNumber() { return tracknum; }
|
|
|
|
|
|
+ public int trackNumber() {
|
|
|
|
+ return tracknum;
|
|
|
|
+ }
|
|
|
|
|
|
- public ArrayList<MidiNote> getNotes() { return notes; }
|
|
|
|
|
|
+ public ArrayList<MidiNote> getNotes() {
|
|
|
|
+ return notes;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public int getInstrument() {
|
|
|
|
+ return instrument;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void setInstrument(int value) {
|
|
|
|
+ instrument = value;
|
|
|
|
+ }
|
|
|
|
|
|
- public int getInstrument() { return instrument; }
|
|
|
|
- public void setInstrument(int value) { instrument = value; }
|
|
|
|
|
|
+ public ArrayList<MidiEvent> getLyrics() {
|
|
|
|
+ return lyrics;
|
|
|
|
+ }
|
|
|
|
|
|
- public ArrayList<MidiEvent> getLyrics() { return lyrics; }
|
|
|
|
- public void setLyrics(ArrayList<MidiEvent> value) { lyrics = value; }
|
|
|
|
|
|
+ public void setLyrics(ArrayList<MidiEvent> value) {
|
|
|
|
+ lyrics = value;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
- public String getInstrumentName() { if (instrument >= 0 && instrument <= 128)
|
|
|
|
- return MidiFile.Instruments[instrument];
|
|
|
|
- else
|
|
|
|
- return "";
|
|
|
|
- }
|
|
|
|
|
|
+ public String getInstrumentName() {
|
|
|
|
+ if (instrument >= 0 && instrument <= 128)
|
|
|
|
+ return MidiFile.Instruments[instrument];
|
|
|
|
+ else
|
|
|
|
+ return "";
|
|
|
|
+ }
|
|
|
|
|
|
- /** Add a MidiNote to this track. This is called for each NoteOn event */
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Add a MidiNote to this track. This is called for each NoteOn event
|
|
|
|
+ */
|
|
public void AddNote(MidiNote m) {
|
|
public void AddNote(MidiNote m) {
|
|
notes.add(m);
|
|
notes.add(m);
|
|
}
|
|
}
|
|
|
|
|
|
- /** A NoteOff event occured. Find the MidiNote of the corresponding
|
|
|
|
|
|
+ /**
|
|
|
|
+ * A NoteOff event occured. Find the MidiNote of the corresponding
|
|
* NoteOn event, and update the duration of the MidiNote.
|
|
* NoteOn event, and update the duration of the MidiNote.
|
|
*/
|
|
*/
|
|
public void NoteOff(int channel, int notenumber, int endtime) {
|
|
public void NoteOff(int channel, int notenumber, int endtime) {
|
|
- for (int i = notes.size()-1; i >= 0; i--) {
|
|
|
|
|
|
+ for (int i = notes.size() - 1; i >= 0; i--) {
|
|
MidiNote note = notes.get(i);
|
|
MidiNote note = notes.get(i);
|
|
if (note.getChannel() == channel && note.getNumber() == notenumber &&
|
|
if (note.getChannel() == channel && note.getNumber() == notenumber &&
|
|
- note.getDuration() == 0) {
|
|
|
|
|
|
+ note.getDuration() == 0) {
|
|
note.NoteOff(endtime);
|
|
note.NoteOff(endtime);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /** Add a lyric event to this track */
|
|
|
|
- public void AddLyric(MidiEvent mevent) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Add a lyric event to this track
|
|
|
|
+ */
|
|
|
|
+ public void AddLyric(MidiEvent mevent) {
|
|
if (lyrics == null) {
|
|
if (lyrics == null) {
|
|
lyrics = new ArrayList<MidiEvent>();
|
|
lyrics = new ArrayList<MidiEvent>();
|
|
}
|
|
}
|
|
lyrics.add(mevent);
|
|
lyrics.add(mevent);
|
|
}
|
|
}
|
|
|
|
|
|
- /** Return a deep copy clone of this MidiTrack. */
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Return a deep copy clone of this MidiTrack.
|
|
|
|
+ */
|
|
public MidiTrack Clone() {
|
|
public MidiTrack Clone() {
|
|
MidiTrack track = new MidiTrack(trackNumber());
|
|
MidiTrack track = new MidiTrack(trackNumber());
|
|
track.instrument = instrument;
|
|
track.instrument = instrument;
|
|
for (MidiNote note : notes) {
|
|
for (MidiNote note : notes) {
|
|
- track.notes.add( note.Clone() );
|
|
|
|
|
|
+ track.notes.add(note.Clone());
|
|
}
|
|
}
|
|
if (lyrics != null) {
|
|
if (lyrics != null) {
|
|
track.lyrics = new ArrayList<MidiEvent>();
|
|
track.lyrics = new ArrayList<MidiEvent>();
|
|
@@ -170,11 +208,24 @@ public class MidiTrack {
|
|
public String toString() {
|
|
public String toString() {
|
|
String result = "Track number=" + tracknum + " instrument=" + instrument + "\n";
|
|
String result = "Track number=" + tracknum + " instrument=" + instrument + "\n";
|
|
for (MidiNote n : notes) {
|
|
for (MidiNote n : notes) {
|
|
- result = result + n + "\n";
|
|
|
|
|
|
+ result = result + n + "\n";
|
|
}
|
|
}
|
|
result += "End Track\n";
|
|
result += "End Track\n";
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public int compareTo(MidiTrack o) {
|
|
|
|
+ int original = getInstrument();
|
|
|
|
+ int target = o.getInstrument();
|
|
|
|
+ if (original > target) {
|
|
|
|
+ return 1;
|
|
|
|
+ } else if (original < target) {
|
|
|
|
+ return -1;
|
|
|
|
+ } else {
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|