/** * 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(); } }
@Override public void send(MidiMessage message, long timeStamp) { try { if (sound) { midiPlugin.sound(message); } MidiMessageEvent<?> event; if (message instanceof ShortMessage) { event = MidiUtils.createShortMessageEvent(midiPlugin, (ShortMessage) message, timeStamp); } else if (message instanceof SysexMessage) { event = new MidiSysexMessageEvent(midiPlugin.getMidiSysexMessageEventName(), midiPlugin.getEngine().getDefaultParameters().getEventClonePolicy(), (SysexMessage) message, timeStamp); } else if (message instanceof MetaMessage) { event = new MidiMetaMessageEvent(midiPlugin.getMidiMetaMessageEventName(), midiPlugin.getEngine().getDefaultParameters().getEventClonePolicy(), (MetaMessage) message, timeStamp); } else { throw new SpongeException("Unknown MIDI message type: " + message.getClass()); } midiPlugin.getEngine().getOperations().event(event).send(); } catch (Exception e) { logger.error("send", e); } }
/** parses this message for a META tempo message and returns * the tempo in MPQ, or -1 if this isn't a tempo message */ public static int getTempoMPQ(MidiMessage midiMsg) { // first check if it is a META message at all if (midiMsg.getLength() != 6 || midiMsg.getStatus() != MetaMessage.META) { return -1; } byte[] msg = midiMsg.getMessage(); if (((msg[1] & 0xFF) != META_TEMPO_TYPE) || (msg[2] != 3)) { return -1; } int tempo = (msg[5] & 0xFF) | ((msg[4] & 0xFF) << 8) | ((msg[3] & 0xFF) << 16); return tempo; }
private static void checkClone(MetaMessage msg) throws Exception { System.out.print("Original: "); byte[] msgData=msg.getData(); printMsg(msg, msgData); MetaMessage msg2=(MetaMessage) msg.clone(); byte[] msg2Data=msg2.getData(); System.out.print("Clone: "); printMsg(msg2, msg2Data); if (msg2.getLength()!=msg.getLength() || msg.getType()!=msg2.getType() || msgData.length!=msg2Data.length) { throw new Exception("cloned MetaMessage is not equal."); } int max=Math.min(msgData.length, 10); for (int i=0; i<max; i++) { if (msgData[i]!=msg2Data[i]) { throw new Exception("Cloned MetaMessage data is not equal."); } } }
public static void main(String[] args) throws Exception { // let's create some MetaMessages and check them MetaMessage msg=new MetaMessage(); String text="a textmarker"; msg.setMessage(1, text.getBytes(), text.length()); checkClone(msg); msg.setMessage(0x2E, new byte[0], 0); checkClone(msg); byte[] data=new byte[17000]; for (int i=0; i<30; data[i]=(byte) (i++ & 0xFF)); msg.setMessage(0x02, data, 80); checkClone(msg); msg.setMessage(0x02, data, 160); checkClone(msg); msg.setMessage(0x02, data, 400); checkClone(msg); msg.setMessage(0x02, data, 1000); checkClone(msg); msg.setMessage(0x02, data, 10000); checkClone(msg); msg.setMessage(0x02, data, 17000); checkClone(msg); }
/** * 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)); }
/** * 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; }
@Override public void meta(MetaMessage event) { // we are only worried about the end of track meta message if (event.getType() == MidiAudioPlayer.END_OF_TRACK_MESSAGE) { // make sure the audio should loop if (this.configuration.isLoopEnabled()) { this.loop(); // log that the audio is being looped LOGGER.debug("Looping"); } else { this.stop(); } // set the volume again this.setVolume(this.configuration.getVolume()); // set the mute control this.setMuted(this.configuration.isAudioMuted()); } }
/** * 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"); }
/** 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; }
public TimeSignature(MetaMessage midiMessage) { byte[] data = midiMessage.getData(); if (midiMessage.getType() != META_TIME_SIGNATURE || data.length < 4) { throw new IllegalArgumentException("Midi message is not a time signature event"); } if ((1 << data[1]) > MAX_DENOMINATOR) { this.numerator = 4; this.denominator = 4; this.metronome = 24; this.thirtySecondNotes = 8; } else { this.numerator = data[0]; this.denominator = 1 << data[1]; this.metronome = data[2]; this.thirtySecondNotes = data[3]; } }
public MetaMessage toMidiMessage() { MetaMessage midiMessage = new MetaMessage(); byte[] data = new byte[4]; data[0] = (byte) numerator; data[1] = floorLog2(denominator); data[2] = metronome; data[3] = thirtySecondNotes; try { midiMessage.setMessage(META_TIME_SIGNATURE, data, data.length); } catch (InvalidMidiDataException e) { throw new RuntimeException(e); } return midiMessage; }
/** * @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); } }
public MetaMessage toMidiMessage() { try { MetaMessage midiMessage = new MetaMessage(); byte[] data = new byte[2]; data[0] = sharpsFlats; data[1] = (byte) (mode == KeyMode.MINOR ? 1 : 0); midiMessage.setMessage(META_KEY_SIGNATURE, data, data.length); return midiMessage; } catch (InvalidMidiDataException e) { throw new RuntimeException(e); } }
/** * Delegator method that calls specific parsers depending on the * type of MidiMessage passed in. * @param message the message to parse * @param timestamp the time at which the message was encountered in this track */ public void parse(MidiMessage message, long timestamp) { if (message instanceof ShortMessage) { parseShortMessage((ShortMessage)message, timestamp); } else if (message instanceof SysexMessage) { parseSysexMessage((SysexMessage)message, timestamp); } else if (message instanceof MetaMessage) { parseMetaMessage((MetaMessage)message, timestamp); } }
/** * Test method getType() of class MetaMessage * */ public void test_getType() throws Exception { MetaMessage meta = new MetaMessage(); assertEquals(0, meta.getType()); byte[] bt = new byte[] { 9, -4, 34, 18 }; MetaMessage1 meta2 = new MetaMessage1(bt); assertEquals(252, meta2.getType()); bt[1] = 5; /** * value change */ assertEquals(5, meta2.getType()); meta.setMessage(10, new byte[] { 1, 2, 3, 4 }, 4); assertEquals(10, meta.getType()); meta.setMessage(27, null, 0); assertEquals(27, meta.getType()); }
/** * Test method getType() of class MetaMessage * */ public void test_getType() throws Exception { MetaMessage meta = new MetaMessage(); assertEquals(meta.getType(), 0); byte[] bt = new byte[] { 9, -4, 34, 18 }; MetaMessage1 meta2 = new MetaMessage1(bt); assertEquals(meta2.getType(), 252); bt[1] = 5; /** * value change */ assertEquals(5, meta2.getType()); meta.setMessage(10, new byte[] { 1, 2, 3, 4 }, 4); assertEquals(meta.getType(), 10); meta.setMessage(27, null, 0); assertEquals(meta.getType(), 27); }
/** * Fluidsynth async mid ievent. * * @param msg the msg */ private void fluidsynthAsyncMIDIevent(MetaMessage msg) { byte[] metaData = msg.getData(); String strData = new String(metaData); //logger.debug("*FS* META message: text= " + strData); if ("fsbOnLow".equals(strData)) fluidSynth.send(9, ShortMessage.NOTE_ON, 77, 100); else if ("fsbOnHi".equals(strData)) fluidSynth.send(9, ShortMessage.NOTE_ON, 76, 100); else if ("fsbOff".equals(strData)) fluidSynth.send(9, ShortMessage.NOTE_OFF, 77, 0); else if ("fsnOn".equals(strData.substring(0, 5))) { lastNote = Integer.parseInt(strData.substring(5)); fluidSynth.send(0, ShortMessage.NOTE_ON, lastNote, 100); } else if ("fsnOff".equals(strData.substring(0, 6))) { fluidSynth.send(0, ShortMessage.NOTE_OFF, Integer.parseInt(strData.substring(6)), 0); lastNote = -1; } }
/** Creates a MIDI tempo change event if this Sound element specifies tempo. * @return a MetaMessage or null, if no tempo attribute was found */ public MetaMessage getTempoMessage() { if (element.hasAttribute("tempo")) { final float tempo = Float.parseFloat(element.getAttribute("tempo")); int midiTempo = Math.round((float)60000.0 / tempo * 1000); final MetaMessage message = new MetaMessage(); byte[] bytes = new byte[3]; bytes[0] = (byte) (midiTempo / 0X10000); midiTempo %= 0X10000; bytes[1] = (byte) (midiTempo / 0X100); midiTempo %= 0X100; bytes[2] = (byte) midiTempo; try { message.setMessage(0X51, bytes, bytes.length); return message; } catch (InvalidMidiDataException e) {} } return null; }
MidiAudio(InputStream data) throws MidiUnavailableException { getSequencer(); setSequence(data); sequencer.addMetaEventListener(new MetaEventListener() { public void meta(MetaMessage msg) { if (msg.getType() == 47) { try { sequencer.setSequence(sequence); } catch (InvalidMidiDataException e) { ErrorHandler.alert(e); } sequencer.setTickPosition(0); if (loop) { // End of track sequencer.start(); } } } }); AudioFormat base = new AudioFormat(44100, 16, 2, true, false); format = new AudioFileFormat(new Type("MIDI", "mid"), base, (int) (base.getFrameRate() * (sequence.getMicrosecondLength() / 1000000 + 4))).getFormat(); }
public synchronized void meta( MetaMessage message ) { if (DEBUG || Printer.debug)Printer.debug("META EVENT RECEIVED!!!!! "); if( message.getType() == 47 ) { if (sequencerloop){ //notifyAll(); sequencer.setMicrosecondPosition(0); loop(); } else { stop(); } } }
@Override public synchronized void meta(MetaMessage message) { if (DEBUG || Printer.debug)Printer.debug("META EVENT RECEIVED!!!!! "); if( message.getType() == 47 ) { if (sequencerloop){ //notifyAll(); sequencer.setMicrosecondPosition(0); loop(); } else { stop(); } } }
/** return true if the passed message is Meta End Of Track */ public static boolean isMetaEndOfTrack(MidiMessage midiMsg) { // first check if it is a META message at all if (midiMsg.getLength() != 3 || midiMsg.getStatus() != MetaMessage.META) { return false; } // now get message and check for end of track byte[] msg = midiMsg.getMessage(); return ((msg[1] & 0xFF) == META_END_OF_TRACK_TYPE) && (msg[2] == 0); }
/** return if the given message is a meta tempo message */ public static boolean isMetaTempo(MidiMessage midiMsg) { // first check if it is a META message at all if (midiMsg.getLength() != 6 || midiMsg.getStatus() != MetaMessage.META) { return false; } // now get message and check for tempo byte[] msg = midiMsg.getMessage(); // meta type must be 0x51, and data length must be 3 return ((msg[1] & 0xFF) == META_TEMPO_TYPE) && (msg[2] == 3); }
public void meta(MetaMessage m) { System.out.print(" Got MetaMessage: "); if (m.getType() == 47) { stopTime = System.currentTimeMillis(); System.out.println(" End Of Track -- OK"); } else { System.out.println(" unknown. Ignored."); } }
public void meta(MetaMessage p1) { if(p1.getType() ==47) { return; } System.out.println("getTickPosition:\t"+theSequencer.getTickPosition() +"\t Sequencer.getTickLength:\t"+theSequencer.getTickLength() +"\tReal Length:\t"+lastTick +"\t Sequence.getTickLength:\t"+theSequence.getTickLength() //(theSequencer.getTickLength()/64)); ); }
MetaCallback() throws Exception { sequencer=MidiSystem.getSequencer(); sequence=new Sequence(Sequence.PPQ,240); track=sequence.createTrack(); sequencer.addMetaEventListener(this); byte[] data = new byte[1]; track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,100),0)); track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,0),0 + 240)); int c; for(c=0; c < TOTAL_COUNT; c++) { data[0]=(byte)(c+1); MetaMessage meta = new MetaMessage(); meta.setMessage(1, data, 1); // type, data, length track.add(new MidiEvent(meta,c*20)); } track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,100),c*20)); track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,0),c*20 + 10)); sequencer.setSlaveSyncMode(Sequencer.SyncMode.INTERNAL_CLOCK); sequencer.setMasterSyncMode(Sequencer.SyncMode.INTERNAL_CLOCK); sequencer.open(); sequencer.setSequence(sequence); sequencer.setTempoInBPM(100); System.out.println("Starting playback..."); this.start(); while (!finished && sequencer.getTickPosition() < sequencer.getTickLength()) { System.out.println("Tick "+sequencer.getTickPosition()+"..."); Thread.sleep(1000); } System.out.println("Stopping playback..."); this.stop(); if (metaCount != TOTAL_COUNT) { throw new Exception("Expected "+TOTAL_COUNT+" callbacks, but got "+metaCount+"!"); } }
public void meta(MetaMessage msg) { System.out.println(""+metaCount+": got "+msg); if (msg.getType() == 0x2F) { finished = true; } else if (msg.getData().length > 0 && msg.getType() == 1) { metaCount++; } }
/** * create a key signature event * @param date * @param accids * @return */ public static MidiEvent createKeySignature(long date, int accids) { try { return new MidiEvent(new MetaMessage(META_Key_Signature, new byte[] {(byte)accids, 0}, 2), date); } catch (InvalidMidiDataException e) { e.printStackTrace(); return null; } }
/** * create a time signature event * @param date * @param numerator * @param denominator * @return */ public static MidiEvent createTimeSignature(long date, int numerator, int denominator) { int p = 1; for (; Math.pow(2, p) < denominator; ++p) ; try { return new MidiEvent(new MetaMessage(META_Time_Signature, new byte[] {(byte)numerator, (byte)p, 24, 8}, 4), date); } catch (InvalidMidiDataException e) { e.printStackTrace(); return null; } }
/** * create tempo event * @param date * @param bpm * @param beatlength length of one beat in floating point format (e.g. quarter=0.25, whole=1; eight=0.125) * @return */ public static MidiEvent createTempo(long date, double bpm, double beatlength) { int mpq = (int)(60000000 / (bpm * beatlength * 4)); // compute microseconds per quarter note from bpm byte[] tempo = intToByteArray(mpq, false); // generate byte array (little endian) from mpq try { return new MidiEvent(new MetaMessage(META_Set_Tempo, new byte[] {tempo[1], tempo[2], tempo[3]}, 3), date); // create the event; only the 2nd, 3rd and 4th byte of the tempo byte array are needed, as the first byte is then filled with the number of bytes (3) } catch (InvalidMidiDataException e1) { e1.printStackTrace(); return null; } }
/** * create a track name event * @param date * @param name * @return */ public static MidiEvent createInstrumentName(long date, String name) { byte[] text = name.getBytes(); try { return new MidiEvent(new MetaMessage(META_Instrument_Name, text, text.length), date); } catch (InvalidMidiDataException e) { e.printStackTrace(); return null; } }
/** * create a marker event * @param date * @param markerText * @return */ public static MidiEvent createMarker(long date, String markerText) { byte[] text = markerText.getBytes(); try { return new MidiEvent(new MetaMessage(META_Marker, text, text.length), date); } catch (InvalidMidiDataException e) { e.printStackTrace(); return null; } }