/** * Play one bell sound immediately, bypassing Sequencer * * @param bell */ public void play(int bell) { MidiEvent evt; try { evt = createBellNote(bell, 0); fMidiOut.send(evt.getMessage(), -1); } catch (InvalidMidiDataException e) { System.out.println("Failed to play note; " + e); } }
private void loadNotes() { int program = 0; HashMap<Integer, Float> lastTimeNote = new HashMap<Integer, Float>(); HashMap<Float, Integer> secondsNotes = new HashMap<Float, Integer>(); this.notas = new ArrayList<MIDINote>(); for (Track track : sequencia.getTracks()) { for (int c = 0; c < track.size(); ++c) { MidiEvent event = track.get(c); MidiMessage msg = event.getMessage(); if (msg instanceof ShortMessage) { ShortMessage shortmsg = (ShortMessage) msg; if (shortmsg.getCommand() == ShortMessage.PROGRAM_CHANGE) { program = shortmsg.getData1(); } else { // }else if(program>=25 && program <= 40){ // else if(program== 30){ if (shortmsg.getCommand() == ShortMessage.NOTE_ON) { MIDINote midiNote = new MIDINote(event, sequencia, tempoProcessor, program); // tocador.start(); int noteChord = midiNote.getChord(); float noteSecond = midiNote.getSecond(); if (!lastTimeNote.containsKey(noteChord)) { lastTimeNote.put(noteChord, 0.0f); } if (noteSecond - lastTimeNote.get(noteChord).floatValue() <= this.interval) { continue; } lastTimeNote.put(noteChord, noteSecond); // System.out.println("Play chord "+noteChord+" in "+noteSecond+" seconds"); notas.add(midiNote); if (!secondsNotes.containsKey(noteSecond)) { secondsNotes.put(noteSecond, 1); } secondsNotes.put(noteSecond, secondsNotes.get(noteSecond).intValue() + 1); } } } } } // System.out.println("tamanho da pista "+notas.size()+" e track "+maxNote); for (float second : secondsNotes.keySet()) { int repeated = secondsNotes.get(second).intValue(); if (repeated > maxNote) { this.maxNote = repeated; } } this.notesLength = secondsNotes.size(); // GameEngine.getInstance().setFramesPerSecond((int)(((tocador.getMicrosecondLength()/1000000)/(notas.size()*1.0))*4000)); // System.out.println("(int)(("+sequencia.getMicrosecondLength()+"/1000000)/"+notas.size()+"="+(int)((sequencia.getMicrosecondLength()/1000000)/notas.size())) }
@Override public void run() { while (go) { try { MidiEvent event = (MidiEvent) waitNextEvent(); try { Log.i(MidiConstants.TAG, "Fire event " + event.data[0] + " at " + event.getTimestamp()); mDispatcher.send(event.data, 0, event.count, event.getTimestamp()); } catch (IOException e) { e.printStackTrace(); } // Put event back in the pool for future use. addEventToPool(event); } catch (InterruptedException e) { // OK, this is how we stop the thread. } } }
void callPlug(MidiInput _input, final MidiMessage msg) { try { if ((msg.getStatus() & 0xF0) != getStatus() && getStatus() != -1) return; if (msg instanceof ShortMessage) { ShortMessage smsg = (ShortMessage) msg; if (smsg.getChannel() != channel && channel != -1) return; } MidiEvent event = null; if (msg instanceof MidiEvent) { event = (MidiEvent) msg; } else { event = MidiEvent.create(msg); } if (event != null) { event.setInput(_input); if (paramClass.isInstance(event)) method.invoke(getObject(), new Object[] {event}); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Error on calling plug: " + methodName); } }
public static double send(Sequence seq, Receiver recv) { float divtype = seq.getDivisionType(); assert (seq.getDivisionType() == Sequence.PPQ); Track[] tracks = seq.getTracks(); int[] trackspos = new int[tracks.length]; int mpq = 60000000 / 100; int seqres = seq.getResolution(); long lasttick = 0; long curtime = 0; while (true) { MidiEvent selevent = null; int seltrack = -1; for (int i = 0; i < tracks.length; i++) { int trackpos = trackspos[i]; Track track = tracks[i]; if (trackpos < track.size()) { MidiEvent event = track.get(trackpos); if (selevent == null || event.getTick() < selevent.getTick()) { selevent = event; seltrack = i; } } } if (seltrack == -1) break; trackspos[seltrack]++; long tick = selevent.getTick(); if (divtype == Sequence.PPQ) curtime += ((tick - lasttick) * mpq) / seqres; else curtime = (long) ((tick * 1000000.0 * divtype) / seqres); lasttick = tick; MidiMessage msg = selevent.getMessage(); if (msg instanceof MetaMessage) { if (divtype == Sequence.PPQ) if (((MetaMessage) msg).getType() == 0x51) { byte[] data = ((MetaMessage) msg).getData(); mpq = ((data[0] & 0xff) << 16) | ((data[1] & 0xff) << 8) | (data[2] & 0xff); } } else { if (recv != null) recv.send(msg, curtime); } } return curtime / 1000000.0; }
/** * Obtains the duration of this sequence, expressed in microseconds. * * @return this sequence's duration in microseconds. */ public long getMicrosecondLength() { long ticks = getTickLength(); double seconds; // now convert ticks to time if (divisionType != PPQ) { seconds = ((double) getTickLength() / (double) (divisionType * resolution)); // $$fb 2002-10-30: fix for 4702328: Wrong time in sequence for SMPTE based types return (long) (1000000 * seconds); } else { Track tempos = new Track(); Track tmpTrack = null; MidiEvent tmpEvent = null; MidiMessage tmpMessage = null; MetaMessage tmpMeta = null; byte[] data; // find all tempo events synchronized (tracks) { for (int i = 0; i < tracks.size(); i++) { tmpTrack = (Track) tracks.elementAt(i); for (int j = 0; j < tmpTrack.size(); j++) { tmpEvent = (MidiEvent) tmpTrack.get(j); tmpMessage = tmpEvent.getMessage(); if (tmpMessage instanceof MetaMessage) { if (((MetaMessage) tmpMessage).getType() == 0x51) { tempos.add(tmpEvent); } } } } } // now add up chunks of time int tempo = (60 * 1000000) / 120; // default 120 bpm, converted to uSec/beat long microseconds = 0; long runningTick = 0; long tmpTick = 0; // loop through the tempo changes, but don't // include the last event, which is track end for (int i = 0; i < (tempos.size() - 1); i++) { tmpEvent = (MidiEvent) tempos.get(i); tmpTick = tmpEvent.getTick(); if (tmpTick >= runningTick) { microseconds += ((tmpTick - runningTick) * tempo / resolution); runningTick = tmpTick; data = ((MetaMessage) (tmpEvent.getMessage())).getMessage(); // data[0] => status, 0xFF // data[1] => type, 0x51 // data[2] => length, 0x03 // data[3] -> data[5] => tempo data tempo = (int) 0xff & data[5]; tempo = tempo | ((0xff & data[4]) << 8); tempo = tempo | ((0xff & data[3]) << 16); } } tmpTick = getTickLength(); if (tmpTick > runningTick) { microseconds += ((tmpTick - runningTick) * tempo / resolution); } // return in microseconds return (microseconds); } }
private InputStream writeTrack(Track track, int type) throws IOException, InvalidMidiDataException { int bytesWritten = 0; int lastBytesWritten = 0; int size = track.size(); PipedOutputStream thpos = new PipedOutputStream(); DataOutputStream thdos = new DataOutputStream(thpos); PipedInputStream thpis = new PipedInputStream(thpos); ByteArrayOutputStream tdbos = new ByteArrayOutputStream(); tddos = new DataOutputStream(tdbos); ByteArrayInputStream tdbis = null; SequenceInputStream fStream = null; long currentTick = 0; long deltaTick = 0; long eventTick = 0; int runningStatus = -1; // ----------------------------- // Write each event in the track // ----------------------------- for (int i = 0; i < size; i++) { MidiEvent event = track.get(i); int status; int eventtype; int metatype; int data1, data2; int length; byte data[] = null; ShortMessage shortMessage = null; MetaMessage metaMessage = null; SysexMessage sysexMessage = null; // get the tick // $$jb: this gets easier if we change all system-wide time to delta ticks eventTick = event.getTick(); deltaTick = event.getTick() - currentTick; currentTick = event.getTick(); // get the status byte status = event.getMessage().getStatus(); eventtype = getType(status); switch (eventtype) { case ONE_BYTE: shortMessage = (ShortMessage) event.getMessage(); data1 = shortMessage.getData1(); bytesWritten += writeVarInt(deltaTick); if (status != runningStatus) { runningStatus = status; tddos.writeByte(status); bytesWritten += 1; } tddos.writeByte(data1); bytesWritten += 1; break; case TWO_BYTE: shortMessage = (ShortMessage) event.getMessage(); data1 = shortMessage.getData1(); data2 = shortMessage.getData2(); bytesWritten += writeVarInt(deltaTick); if (status != runningStatus) { runningStatus = status; tddos.writeByte(status); bytesWritten += 1; } tddos.writeByte(data1); bytesWritten += 1; tddos.writeByte(data2); bytesWritten += 1; break; case SYSEX: sysexMessage = (SysexMessage) event.getMessage(); length = sysexMessage.getLength(); data = sysexMessage.getMessage(); bytesWritten += writeVarInt(deltaTick); // $$jb: 04.08.99: always write status for sysex runningStatus = status; tddos.writeByte(data[0]); bytesWritten += 1; // $$jb: 10.18.99: we don't maintain length in // the message data for SysEx (it is not transmitted // over the line), so write the calculated length // minus the status byte bytesWritten += writeVarInt((data.length - 1)); // $$jb: 10.18.99: now write the rest of the // message tddos.write(data, 1, (data.length - 1)); bytesWritten += (data.length - 1); break; case META: metaMessage = (MetaMessage) event.getMessage(); length = metaMessage.getLength(); data = metaMessage.getMessage(); bytesWritten += writeVarInt(deltaTick); // $$jb: 10.18.99: getMessage() returns the // entire valid midi message for a file, // including the status byte and the var-length-int // length value, so we can just write the data // here. note that we must _always_ write the // status byte, regardless of runningStatus. runningStatus = status; tddos.write(data, 0, data.length); bytesWritten += data.length; break; case IGNORE: // ignore this event break; case ERROR: // ignore this event break; default: throw new InvalidMidiDataException("internal file writer error"); } } // --------------------------------- // End write each event in the track // --------------------------------- // Build Track header now that we know length thdos.writeInt(MTrk_MAGIC); thdos.writeInt(bytesWritten); bytesWritten += 8; // Now sequence them tdbis = new ByteArrayInputStream(tdbos.toByteArray()); fStream = new SequenceInputStream(thpis, tdbis); thdos.close(); tddos.close(); return fStream; }
/** * Adds a new event to the track. However, if the event is already contained in the track, it is * not added again. The list of events is kept in time order, meaning that this event inserted at * the appropriate place in the list, not necessarily at the end. * * @param event the event to add * @return <code>true</code> if the event did not already exist in the track and was added, * otherwise <code>false</code> */ public boolean add(MidiEvent event) { if (event == null) { return false; } synchronized (eventsList) { if (!set.contains(event)) { int eventsCount = eventsList.size(); // get the last event MidiEvent lastEvent = null; if (eventsCount > 0) { lastEvent = (MidiEvent) eventsList.get(eventsCount - 1); } // sanity check that we have a correct end-of-track if (lastEvent != eotEvent) { // if there is no eot event, add our immutable instance again if (lastEvent != null) { // set eotEvent's tick to the last tick of the track eotEvent.setTick(lastEvent.getTick()); } else { // if the events list is empty, just set the tick to 0 eotEvent.setTick(0); } // we needn't check for a duplicate of eotEvent in "eventsList", // since then it would appear in the set. eventsList.add(eotEvent); set.add(eotEvent); eventsCount = eventsList.size(); } // first see if we are trying to add // and endoftrack event. if (MidiUtils.isMetaEndOfTrack(event.getMessage())) { // since end of track event is useful // for delays at the end of a track, we want to keep // the tick value requested here if it is greater // than the one on the eot we are maintaining. // Otherwise, we only want a single eot event, so ignore. if (event.getTick() > eotEvent.getTick()) { eotEvent.setTick(event.getTick()); } return true; } // prevent duplicates set.add(event); // insert event such that events is sorted in increasing // tick order int i = eventsCount; for (; i > 0; i--) { if (event.getTick() >= ((MidiEvent) eventsList.get(i - 1)).getTick()) { break; } } if (i == eventsCount) { // we're adding an event after the // tick value of our eot, so push the eot out. // Always add at the end for better performance: // this saves all the checks and arraycopy when inserting // overwrite eot with new event eventsList.set(eventsCount - 1, event); // set new time of eot, if necessary if (eotEvent.getTick() < event.getTick()) { eotEvent.setTick(event.getTick()); } // add eot again at the end eventsList.add(eotEvent); } else { eventsList.add(i, event); } return true; } } return false; }
public synchronized void addEvent(MidiEvent event) { this.midiEventPlayer.addEvent(event); this.midiTickPlayer.notifyTick(event.getTick()); }