/** * Write the given tempo out to {@link #sequence} at the given tick. * * @param tempo The tempo to write. * @param tick The tick at which to write it. * * @throws InvalidMidiDataException If the tempo contained invalid Midi data. */ private void writeTempo(Tempo tempo, long tick) throws InvalidMidiDataException { MetaMessage mm = new MetaMessage(); int mspq = tempo.getMicroSecondsPerQuarter(); byte[] data = { (byte) ((mspq & 0xff000000) >> 24), (byte) ((mspq & 0x00ff0000) >> 16), (byte) ((mspq & 0x0000ff00) >> 8), (byte) (mspq & 0x000000ff)}; // Clear leading 0's int i; for (i = 0; i < data.length - 1 && data[i] == 0; i++); if (i != 0) { data = Arrays.copyOfRange(data, i, data.length); } mm.setMessage(EventParser.TEMPO, data, data.length); sequence.getTracks()[0].add(new MidiEvent(mm, tick)); }
protected void setUp() throws Exception { super.setUp(); seq = new Sequence(Sequence.PPQ, resolution,1); int mpq = (int)(60000000 / tempo); try { MetaMessage tempoMsg = new MetaMessage(); tempoMsg.setMessage(0x51,new byte[] { (byte)(mpq>>16 & 0xff), (byte)(mpq>>8 & 0xff), (byte)(mpq & 0xff) },3); MidiEvent tempoEvent = new MidiEvent(tempoMsg,0); seq.getTracks()[0].add(tempoEvent); } catch (Exception e) { e.printStackTrace(); } }
/** * Compute the length of a track as it will be written to the * output stream. * * @param track the track to measure * @param dos a MidiDataOutputStream used for helper method * @return the length of the track */ private int computeTrackLength(Track track, MidiDataOutputStream dos) { int count = 0, length = 0, i = 0, eventCount = track.size(); long ptick = 0; while (i < eventCount) { MidiEvent me = track.get(i); long tick = me.getTick(); length += dos.variableLengthIntLength((int) (tick - ptick)); ptick = tick; length += me.getMessage().getLength(); i++; } return length; }
/** * Write the given time signature out to {@link #sequence} at the given tick. * * @param timeSignature The time signature to write. * @param tick The tick at which to write it. * @throws InvalidMidiDataException If the time signature contained invalid Midi data. */ private void writeTimeSignature(TimeSignature timeSignature, long tick) throws InvalidMidiDataException { MetaMessage mm = new MetaMessage(); int denominator = timeSignature.getDenominator(); // Base 2 log calculator for whole numbers int i = 0; while (denominator != 1) { denominator /= 2; i++; } byte[] data = { (byte) timeSignature.getNumerator(), (byte) i, (byte) timeSignature.getMetronomeTicksPerBeat(), (byte) timeSignature.getNotes32PerQuarter()}; mm.setMessage(EventParser.TIME_SIGNATURE, data, data.length); sequence.getTracks()[0].add(new MidiEvent(mm, tick)); }
/** * Add the given MidiNote into the {@link #sequence}. * * @param note The note to add. * * @throws InvalidMidiDataException If the MidiNote contains invalid Midi data. */ public void addMidiNote(MidiNote note) throws InvalidMidiDataException { int correctVoice = note.getCorrectVoice(); // Pad with enough tracks while (sequence.getTracks().length <= correctVoice) { sequence.createTrack(); } // Get the correct track Track track = sequence.getTracks()[correctVoice]; ShortMessage noteOn = new ShortMessage(); noteOn.setMessage(ShortMessage.NOTE_ON | correctVoice, note.getPitch(), note.getVelocity()); MidiEvent noteOnEvent = new MidiEvent(noteOn, note.getOnsetTick()); ShortMessage noteOff = new ShortMessage(); noteOff.setMessage(ShortMessage.NOTE_OFF | correctVoice, note.getPitch(), 0); MidiEvent noteOffEvent = new MidiEvent(noteOff, note.getOffsetTick()); track.add(noteOnEvent); track.add(noteOffEvent); }
/** * Gets the number of microseconds per quarter note for a sequence, used to * determine its BPM. * * @param sequence * @return */ private static int getMicrosecondsPerQuarterNote(Sequence sequence) { // Check all MIDI tracks for MIDI_SET_TEMPO message for (Track track : sequence.getTracks()) { for (int i = 0; i < track.size(); i++) { MidiEvent event = track.get(i); MidiMessage message = event.getMessage(); if (message instanceof MetaMessage) { MetaMessage m = (MetaMessage) message; byte[] data = m.getData(); int type = m.getType(); if (type == MIDI_SET_TEMPO) { return ((data[0] & 0xff) << 16) | ((data[1] & 0xff) << 8) | (data[2] & 0xff); } } } } return 0; }
/** * Find the first tempo meta message and return the tempo value * @return */ public static float findFirstTempo(Sequence sequence) throws Exception { for(Track track : sequence.getTracks()) { for(int n=0;n<track.size();n++) { MidiEvent event = track.get(n); if(event.getMessage() instanceof MetaMessage && ((MetaMessage)event.getMessage()).getType()==0x51) { float tempo = new TempoMessage((MetaMessage)event.getMessage()).getBpm(); System.out.println("Found tempomessage "+tempo+" bpm"); return tempo; } } } throw new Exception("No tempo message found"); }
private static void quantizeOnTheFly(Vector<MidiEvent> eventsToBeQuantized, Quantization q, QuantizeBuffer quantizeBuffer) { for (MidiEvent event : eventsToBeQuantized) { event = q.quantize(event); long tick = event.getTick(); long d = tick - quantizeBuffer.startTick; if (d < 0) { d = 0; // cannot do better } else { d %= quantizeBuffer.data.length; // if the data is cached at // the beginning of the // buffer (thus reaches over // the end of the current // buffer), this part of the // buffer that has already // been played and will be // reused later, "rotating" } Vector<MidiEvent> v = quantizeBuffer.data[(int) d]; if (v == null) { v = new Vector<MidiEvent>(); quantizeBuffer.data[(int) d] = v; } v.add(event); } }
@SuppressWarnings("deprecation") @Override public void commitAddImpl() { // Jens, renamed to be able to handle notification of CommitListeners in MultiEvent, see MultiEvent.commitXxx() // System. out.println(" COMMIT ADD PROG "); try { metaEvent = new MidiEvent(getMessage(), startTick); getTrack().add(metaEvent); } catch (InvalidMidiDataException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
@SuppressWarnings("deprecation") @Override public void commitAddImpl() { // Jens, renamed to be able to handle notification of CommitListeners in MultiEvent, see MultiEvent.commitXxx() try { ShortMessage shm = new ShortMessage(); shm.setMessage(ShortMessage.PITCH_BEND,channel,value & 0x3f,(value >> 7)); midiEvent = new MidiEvent(shm,startTick); getTrack().add(midiEvent); } catch(InvalidMidiDataException e) { e.printStackTrace(); } zombie=false; }
@SuppressWarnings("deprecation") @Override public void commitAddImpl() { // Jens, renamed to be able to handle notification of CommitListeners in MultiEvent, see MultiEvent.commitXxx() try { ShortMessage shm = new ShortMessage(); shm.setMessage(ShortMessage.CONTROL_CHANGE,channel,controlNumber,value); midiEvent = new MidiEvent(shm,startTick); getTrack().add(midiEvent); } catch(InvalidMidiDataException e) { e.printStackTrace(); } zombie=false; }
protected MidiEvent[] parseMacro(String macro) throws InvalidMidiDataException { if ((macro == null) || (macro.trim().length() == 0)) { return new MidiEvent[0]; } SysexMacro m = AbstractSysexMacro.findMacro(macro); if (m == null) { throw new InvalidMidiDataException("Cannot find macro '"+Toolbox.firstWord(macro)+"'."); } MidiMessage[] mm = null; mm = m.parseMessages(macro); if (mm == null) { throw new InvalidMidiDataException("Parsing of '"+macro+"' failed."); } MidiEvent[] me = new MidiEvent[mm.length]; for (int i = 0; i < mm.length; i++) { me[i] = new MidiEvent(mm[i], getStartTick()); } return me; }
/** * Returns a clone of this sequence suitable for Midi file export. What it does is to map the FTW channel setting to all the midi events * for the corresponding tracks * @return * @throws InvalidMidiDataException */ public Sequence export() throws InvalidMidiDataException { Sequence newSeq = new Sequence(getDivisionType(),getResolution()); for(FrinikaTrackWrapper ftw : frinikaTrackWrappers) { Track track = newSeq.createTrack(); for(int n=0;n<ftw.size();n++) { MidiEvent sourceMidiEvent = ftw.get(n); MidiMessage msg = sourceMidiEvent.getMessage(); if(msg instanceof ShortMessage) { ShortMessage shm = (ShortMessage)msg; ShortMessage nshm = new ShortMessage(); nshm.setMessage(shm.getCommand(),ftw.getMidiChannel(),shm.getData1(),shm.getData2()); msg = nshm; } MidiEvent newEvent = new MidiEvent(msg,sourceMidiEvent.getTick()); track.add(newEvent); } } return newSeq; }
/** * Render a bar of notes as MIDI to the specified Track from the * specified start tick with the specified ticks per bar. * @param notes the notes to render * @param track the MIDI Track to render to * @param startTick the tick at the start of the bar * @param ticksPerBar the number of ticks per bar */ public void renderBar(int[] notes, Track track, long startTick, int ppqn) throws InvalidMidiDataException { final int channel = getInstrument().getChannel(); MidiMessage msg; for ( int i = 0; i < notes.length; i++) { int note = notes[i]; float timeOn = swing(Note.getTime(note)); int pitch = Note.getPitch(note); int level = Note.getLevel(note); long onTick = ticks2MidiTicks(timeOn, ppqn); msg = ChannelMsg.createChannel( ChannelMsg.NOTE_ON, channel, pitch, level); track.add(new MidiEvent(msg, startTick + onTick)); // note off msg = ChannelMsg.createChannel( ChannelMsg.NOTE_OFF, channel, pitch, 0); float timeOff = swing(Note.getTime(note)+Note.getDuration(note)); long offTick = ticks2MidiTicks(timeOff, ppqn); track.add(new MidiEvent(msg, startTick + offTick)); } }
/** Create a sequence from an InputStream. * This is the counterpart of {@link MidiSystem#getSequence(InputStream)} * for MUS format. * * @param is MUS data (this method does not try to auto-detect the format.) */ public static Sequence getSequence(InputStream is) throws IOException, InvalidMidiDataException { DataInputStream dis = new DataInputStream(is); dis.skip(6); int rus = dis.readUnsignedShort(); short scoreStart = Swap.SHORT((char) rus); dis.skip(scoreStart - 8); Sequence sequence = new Sequence(Sequence.SMPTE_30, 14, 1); Track track = sequence.getTracks()[0]; int[] chanVelocity = new int[16]; Arrays.fill(chanVelocity, 100); EventGroup eg; long tick = 0; while ((eg = nextEventGroup(dis, chanVelocity)) != null) { tick = eg.appendTo(track, tick); } MetaMessage endOfSequence = new MetaMessage(); endOfSequence.setMessage(47, new byte[] {0}, 1); track.add(new MidiEvent(endOfSequence, tick)); return sequence; }
/** * �������ף�����MIDI�¼�,����2 */ public void makeMidiMusic(){ canvas.genPlayingNoteSequence(); List<MeasurePart> meaPartList = canvas.getScore().toMeaPartList(); //С����ʱ�����ʱ�����С��Ϊ��λУ����ÿ��ʼһ���µ�С���飬����С���������� //С�ڵ�ʱ�������ͳһ���Է�ֹ�������ȷ��������ʱ���������ۻ��� int time = 0; Set<Integer> metaSet = new HashSet<Integer>(); for(int i = 0, n = meaPartList.size(); i < n; i++){ MeasurePart measurePart = meaPartList.get(i); for(int j = 0, jn = measurePart.getMeasureNum(); j < jn; j++){ Measure measure = measurePart.getMeasure(j); List<MidiEvent> list = midiEvents.get(j); makeMeasureMidi(measure, list, time, metaSet); } time += MusicMath.getMeasureDuration(measurePart.getMeasure(0)); } }
/** * ��ijһ�������������MIDI�����¼� * * @param events ����ӵ�MIDI�¼����У�����һ������ * @param duration ����ʱ�� * @param pitch �����������MIDI�����ֵ * @param time �¼���ʱ��� */ public void setNoteEvent(List<MidiEvent> events, int duration, int pitch, int time){ ShortMessage message = new ShortMessage(); ShortMessage messageOff = new ShortMessage(); try{ message.setMessage(ShortMessage.NOTE_ON, 0, pitch, volume); messageOff.setMessage(ShortMessage.NOTE_OFF, 0, pitch, volume); } catch (InvalidMidiDataException e) { e.printStackTrace(); } events.add(new MidiEvent(message, time)); time += duration; events.add(new MidiEvent(messageOff, time)); }
public long calcLastNoteTick() { long lastNoteTick = 0; for (Track t : sequence.getTracks()) { for (int j = t.size() - 1; j >= 0; j--) { MidiEvent evt = t.get(j); MidiMessage msg = evt.getMessage(); if (msg instanceof ShortMessage) { ShortMessage m = (ShortMessage) msg; if (m.getCommand() == ShortMessage.NOTE_OFF) { if (evt.getTick() > lastNoteTick) { lastNoteTick = evt.getTick(); } break; } } } } return lastNoteTick; }
/** * @param mpqn Microseconds per quarter note */ public static MidiEvent createTempoEvent(int mpqn, long ticks) { try { byte[] data = new byte[3]; data[0] = (byte) ((mpqn >>> 16) & 0xFF); data[1] = (byte) ((mpqn >>> 8) & 0xFF); data[2] = (byte) (mpqn & 0xFF); MetaMessage msg = new MetaMessage(); msg.setMessage(META_TEMPO, data, data.length); return new MidiEvent(msg, ticks); } catch (InvalidMidiDataException e) { throw new RuntimeException(e); } }
private void turnOffInactiveNotes() { if (receiver == null) return; for (int c = 0; c < CHANNEL_COUNT; c++) { BitSet set = notesOn[c]; if (set == null) continue; for (int noteId = set.nextSetBit(0); noteId >= 0; noteId = set.nextSetBit(noteId + 1)) { if (!isNoteActive(noteId)) { set.clear(noteId); MidiEvent evt = MidiFactory.createNoteOffEvent(noteId, c, -1); receiver.send(evt.getMessage(), evt.getTick()); } } } }
/** * Adds a ShortMessage.NOTE_ON event to the current track, using attack and * decay velocity values. Also adds a ShortMessage.NOTE_OFF command for * the note, using the duration parameter to space the NOTE_OFF command properly. * * Both the NOTE_ON and NOTE_OFF events can be suppressed. This is useful * when notes are tied to other notes. * * @param data1 the first data byte, which contains the note value * @param data2 the second data byte for the NOTE_ON event, which contains the attack velocity * @param data3 the second data byte for the NOTE_OFF event, which contains the decay velocity * @param duration the duration of the note * @param addNoteOn whether a ShortMessage.NOTE_ON event should be created for for this event. For the end of a tied note, this should be false; otherwise it should be true. * @param addNoteOff whether a ShortMessage.NOTE_OFF event should be created for for this event. For the start of a tied note, this should be false; otherwise it should be true. */ public void addNoteEvent(int data1, int data2, int data3, long duration, boolean addNoteOn, boolean addNoteOff) { try { if (addNoteOn) { ShortMessage message = new ShortMessage(); message.setMessage(ShortMessage.NOTE_ON, currentTrack, data1, data2); MidiEvent event = new MidiEvent(message, getTrackTimer()); track[currentTrack].add(event); } advanceTrackTimer(duration); if (addNoteOff) { ShortMessage message2 = new ShortMessage(); message2.setMessage(ShortMessage.NOTE_OFF, currentTrack, data1, data3); MidiEvent event2 = new MidiEvent(message2, getTrackTimer()); track[currentTrack].add(event2); } } catch (InvalidMidiDataException e) { // We've kept a good eye on the data. This exception won't happen. e.printStackTrace(); } }
/** * Returns the events from this sequence in temporal order. This is * done in a two step process: * 1. mapSequence() populates timeMap. Each timestamp key in timeMap is mapped to * a List of events that take place at that time * 2. A list of all events from all timestamps is created and returned * @return The events from the sequence, in temporal order */ public static final List<MidiEvent> getAllEventsSortedByTimestamp(Sequence sequence) { Map<Long, List<MidiEvent>> timeMap = new HashMap<Long, List<MidiEvent>>(); long longestTime = sortSequenceByTimestamp(sequence, timeMap); List<MidiEvent> totalList = new ArrayList<MidiEvent>(); for (long l=0; l < longestTime; l++) { Long key = new Long(l); if (timeMap.containsKey(key)) { List<MidiEvent> list = (List<MidiEvent>)timeMap.get(key); totalList.addAll(list); } } return totalList; }
/** * test method getPatchList() * */ public void test_getPatchList() throws Exception { //TODO /* * I don't understand how this method works */ Sequence seq = new Sequence(Sequence.PPQ, 987, 2); Track tr = seq.createTrack(); MidiEvent event1 = new MidiEvent(new MidiMessage1(new byte[] {1, 2, 3, 34, -98, -27}), -10L); MidiEvent event2 = new MidiEvent(new MidiMessage1(new byte[] {23, -16, 4, 78, -12, 5}), 3L); MidiEvent event3 = new MidiEvent(new MidiMessage1(new byte[] {3, -67, -1, 87, 9, 8, -2}), 6L); tr.add(event1); tr.add(event3); Track tr1 = seq.createTrack(); tr1.add(event2); assertEquals(0, seq.getPatchList().length); }
/** * test method getTickLength() * */ public void test_getTickLength() throws Exception { Sequence seq = new Sequence(Sequence.SMPTE_24, 67, 9); Track tr = seq.createTrack(); MidiEvent event1 = new MidiEvent(new MidiMessage1(new byte[] {1, 2, 3}), -10L); MidiEvent event2 = new MidiEvent(new MidiMessage1(new byte[] {23, -16, 4}), 2L); MidiEvent event3 = new MidiEvent(new MidiMessage1(new byte[] {3, -67, -1}), 6L); tr.add(event1); tr.add(event2); assertEquals(2, seq.getTickLength()); Track tr1 = seq.createTrack(); tr1.add(event1); tr1.add(event2); tr1.add(event3); assertEquals(6, seq.getTickLength()); seq.deleteTrack(tr1); assertEquals(2, seq.getTickLength()); seq.deleteTrack(tr); assertEquals(0, seq.getTickLength()); }
public MidiTune(int ticksPerQuarter) { try { sequence = new Sequence(Sequence.PPQ, ticksPerQuarter); mainTrack = sequence.createTrack(); mainTrack.add(new MidiEvent(new ShortMessage(ShortMessage.PROGRAM_CHANGE, MELODY_TRACK, 111, 0), 0)); mainTrack.add(new MidiEvent(new ShortMessage(ShortMessage.PROGRAM_CHANGE, TENOR_TRACK, 111, 0), 0)); mainTrack.add(new MidiEvent(new ShortMessage(ShortMessage.PROGRAM_CHANGE, BASS_TRACK, 111, 0), 0)); // Controller 73 = Attack Time mainTrack.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, MELODY_TRACK, 73, 0), 0)); mainTrack.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, TENOR_TRACK, 73, 0), 0)); mainTrack.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, BASS_TRACK, 73, 0), 0)); // Controller 75 = Decay Time mainTrack.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, MELODY_TRACK, 75, 0), 0)); mainTrack.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, TENOR_TRACK, 75, 0), 0)); mainTrack.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, BASS_TRACK, 75, 0), 0)); } catch (InvalidMidiDataException imde) { } }
/** * Compute the length of a track as it will be written to the * output stream. * * @param track the track to measure * @param dos a MidiDataOutputStream used for helper method * @return the length of the track */ private int computeTrackLength(Track track, MidiDataOutputStream dos) { int length = 0, i = 0, eventCount = track.size(); long ptick = 0; while (i < eventCount) { MidiEvent me = track.get(i); long tick = me.getTick(); length += dos.variableLengthIntLength((int) (tick - ptick)); ptick = tick; length += me.getMessage().getLength(); i++; } return length; }
private static void sort(List events){ Collections.sort(events, new Comparator() { public int compare(Object o1, Object o2) { if( o1 instanceof MidiEvent && o2 instanceof MidiEvent ){ MidiEvent e1 = (MidiEvent)o1; MidiEvent e2 = (MidiEvent)o2; if(e1.getTick() > e2.getTick()){ return 1; } else if(e1.getTick() < e2.getTick()){ return -1; } } return 0; } }); }
/** * Creates the note event. * * @param nCommand the n command * @param nKey the n key * @param nVelocity the n velocity * @param lTick the l tick * @return the midi event */ private static MidiEvent createNoteEvent(int nCommand, int nKey, int nVelocity, long lTick) { ShortMessage message=new ShortMessage(); try { message.setMessage(nCommand, 0, // always on channel 1 nKey, nVelocity); } catch (InvalidMidiDataException e) { e.printStackTrace(); System.exit(1); } return new MidiEvent(message, lTick); }
public MidiEvent[] getMidiEventsFor(Note note, KeySignature key, long elapsedTime) throws InvalidMidiDataException { long noteLength = (long)getNoteLengthInTicks(note);//, defaultLength); MidiEvent[] events = null; if (!note.isRest()) { events = new MidiEvent[2]; ShortMessage myNoteOn = new ShortMessage(); myNoteOn.setMessage(ShortMessage.NOTE_ON, getMidiNoteNumber(note, key), 50); events[0] = new MidiEvent(myNoteOn,elapsedTime); //events[1] = new MidiEvent(new NotationMarkerMessage((PositionableNote)note), elapsedTime); ShortMessage myNoteOff = new ShortMessage(); myNoteOff.setMessage(ShortMessage.NOTE_OFF , getMidiNoteNumber(note, key), 50); events[1] = new MidiEvent(myNoteOff,elapsedTime+noteLength); } return events; }
public static MidiEvent getNextEvent() { ArrayList<MidiEvent> nextEvent = new ArrayList<MidiEvent>(); ArrayList<Integer> trackOfNextEvent = new ArrayList<Integer>(); for (int track = 0; track < seq.getTracks().length; track ++) { if (seq.getTracks()[track].size()-1 > (nextMessageOf.get(track))) { nextEvent.add(seq.getTracks()[track].get(nextMessageOf.get(track))); trackOfNextEvent.add(track); } } if (nextEvent.size() == 0) return null; int closestMessage = 0; int smallestTick = (int)nextEvent.get(0).getTick(); for (int trialMessage = 1; trialMessage < nextEvent.size(); trialMessage ++) { if ((int)nextEvent.get(trialMessage).getTick() < smallestTick) { smallestTick = (int)nextEvent.get(trialMessage).getTick(); closestMessage = trialMessage; } } currentTrack = trackOfNextEvent.get(closestMessage); nextMessageOf.set(currentTrack,(nextMessageOf.get(currentTrack)+1)); return nextEvent.get(closestMessage); }
/** * Loads and adds the effects to the given midi track * * @param track The track to write to * @param channel The channel to write to */ @Override public void writeToTrack(Track track, int channel) { long lastEnd = 0; for (String name : effects.keySet()) { Sequence sequence = FileUtils.LoadMidiFile("effects/" + name + ".mid"); if (sequence != null) { int start =// Position effect in track (int) (QUARTER * tempo.averageBpm / 60.0 * //beats per second 15 * //because 15 seconds effects.get(name) //i-th word in text ); if (start < lastEnd) start = (int) lastEnd; if (sequence.getMicrosecondLength() / 1000000.0 + TicksInSecs(start, tempo.resolution) > 15.0) { start -= SecsInTicks(TicksInSecs(start, tempo.resolution) + sequence.getMicrosecondLength() / 1000000.0 - 15, tempo.resolution); } float scale = tempo.resolution / (float) sequence.getResolution(); // Make the tempo fit for (Track t : sequence.getTracks()) { for (int i = 0; i < t.size(); i++) { MidiEvent event = t.get(i); byte[] data = event.getMessage().getMessage();//(command & 0xF0) | (channel & 0x0F) data[0] += 2; // Keep channel 1 and 2 free long tick = (long) (event.getTick() * scale) + start; MidiEvent ev = new MidiEvent(new MidiMessage(data) { @Override public Object clone() { return null; } }, tick); track.add(ev); if (tick > lastEnd) lastEnd = tick; } } } } }
public static void main(String argv[]) throws Exception { Sequence seq = new Sequence(Sequence.PPQ, 240); Track t = seq.createTrack(); log("add 10 events in random order"); t.add(createEvent(10, 5)); t.add(createEvent(0, 0)); t.add(createEvent(10, 6)); t.add(createEvent(11, 8)); t.add(createEvent(10, 7)); t.add(createEvent(0, 1)); t.add(createEvent(0, 2)); t.add(createEvent(15, 9)); t.add(createEvent(0, 3)); t.add(createEvent(1, 4)); // now compare the events. // The note param will tell us the // the expected position long lastTick = 0; for (int i = 0; i < t.size(); i++) { MidiEvent ev = t.get(i); if (ev.getMessage() instanceof ShortMessage) { ShortMessage msg = (ShortMessage) ev.getMessage(); log(""+i+": ShortMessage at tick "+ev.getTick() +" with expected position "+msg.getData1()); if (ev.getTick() < lastTick) { log(" FAILED: last tick is larger than this event's tick!"); failed = true; } if (i != msg.getData1()) { log(" FAILED: Track did not order correctly."); failed = true; } } } if (failed) throw new Exception("Test FAILED!"); log("Test passed."); }
public static MidiEvent createEvent(long tick, int expectedPos) throws Exception { ShortMessage msg = new ShortMessage(); msg.setMessage(0x90, (int) expectedPos, 00); MidiEvent ev = new MidiEvent(msg, tick); return ev; }
public static void printEvent(MidiEvent event) { MidiMessage message = event.getMessage(); long tick = event.getTick(); byte[] data = message.getMessage(); StringBuffer sb = new StringBuffer((data.length * 3) - 1); for (int i = 0; i < data.length; i++) { sb.append(toHexByteString(data[i])); if (i < data.length - 1) sb.append(' '); } System.out.printf("%5d: %s%n", tick, sb); }