use of javax.sound.midi.MetaMessage in project jdk8u_jdk by JetBrains.
the class EventDispatcher method processEvent.
/**
* Invoked when there is at least one event in the queue.
* Implement this as a callback to process one event.
*/
void processEvent(EventInfo eventInfo) {
int count = eventInfo.getListenerCount();
// process an LineEvent
if (eventInfo.getEvent() instanceof LineEvent) {
LineEvent event = (LineEvent) eventInfo.getEvent();
if (Printer.debug)
Printer.debug("Sending " + event + " to " + count + " listeners");
for (int i = 0; i < count; i++) {
try {
((LineListener) eventInfo.getListener(i)).update(event);
} catch (Throwable t) {
if (Printer.err)
t.printStackTrace();
}
}
return;
}
// process a MetaMessage
if (eventInfo.getEvent() instanceof MetaMessage) {
MetaMessage event = (MetaMessage) eventInfo.getEvent();
for (int i = 0; i < count; i++) {
try {
((MetaEventListener) eventInfo.getListener(i)).meta(event);
} catch (Throwable t) {
if (Printer.err)
t.printStackTrace();
}
}
return;
}
// process a Controller or Mode Event
if (eventInfo.getEvent() instanceof ShortMessage) {
ShortMessage event = (ShortMessage) eventInfo.getEvent();
int status = event.getStatus();
// c is the channel they are sent on.
if ((status & 0xF0) == 0xB0) {
for (int i = 0; i < count; i++) {
try {
((ControllerEventListener) eventInfo.getListener(i)).controlChange(event);
} catch (Throwable t) {
if (Printer.err)
t.printStackTrace();
}
}
}
return;
}
Printer.err("Unknown event type: " + eventInfo.getEvent());
}
use of javax.sound.midi.MetaMessage in project jdk8u_jdk by JetBrains.
the class SoftMidiAudioFileReader method getAudioInputStream.
public AudioInputStream getAudioInputStream(Sequence seq) throws UnsupportedAudioFileException, IOException {
AudioSynthesizer synth = (AudioSynthesizer) new SoftSynthesizer();
AudioInputStream stream;
Receiver recv;
try {
stream = synth.openStream(format, null);
recv = synth.getReceiver();
} catch (MidiUnavailableException e) {
throw new IOException(e.toString());
}
float divtype = seq.getDivisionType();
Track[] tracks = seq.getTracks();
int[] trackspos = new int[tracks.length];
int mpq = 500000;
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();
if (data.length < 3) {
throw new UnsupportedAudioFileException();
}
mpq = ((data[0] & 0xff) << 16) | ((data[1] & 0xff) << 8) | (data[2] & 0xff);
}
}
} else {
recv.send(msg, curtime);
}
}
long totallen = curtime / 1000000;
long len = (long) (stream.getFormat().getFrameRate() * (totallen + 4));
stream = new AudioInputStream(stream, stream.getFormat(), len);
return stream;
}
use of javax.sound.midi.MetaMessage in project tika by apache.
the class MidiParser method parse.
public void parse(InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
metadata.set(Metadata.CONTENT_TYPE, "audio/midi");
XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
xhtml.startDocument();
// MidiSystem expects the stream to support the mark feature
if (!stream.markSupported()) {
stream = new BufferedInputStream(stream);
}
try {
Sequence sequence = MidiSystem.getSequence(stream);
Track[] tracks = sequence.getTracks();
metadata.set("tracks", String.valueOf(tracks.length));
// TODO: Use XMPDM.TRACKS?
Patch[] patches = sequence.getPatchList();
metadata.set("patches", String.valueOf(patches.length));
float type = sequence.getDivisionType();
if (type == Sequence.PPQ) {
metadata.set("divisionType", "PPQ");
} else if (type == Sequence.SMPTE_24) {
metadata.set("divisionType", "SMPTE_24");
} else if (type == Sequence.SMPTE_25) {
metadata.set("divisionType", "SMPTE_25");
} else if (type == Sequence.SMPTE_30) {
metadata.set("divisionType", "SMPTE_30");
} else if (type == Sequence.SMPTE_30DROP) {
metadata.set("divisionType", "SMPTE_30DROP");
} else if (type == Sequence.SMPTE_24) {
metadata.set("divisionType", String.valueOf(type));
}
for (Track track : tracks) {
xhtml.startElement("p");
for (int i = 0; i < track.size(); i++) {
MidiMessage message = track.get(i).getMessage();
if (message instanceof MetaMessage) {
MetaMessage meta = (MetaMessage) message;
// Types 1-15 are reserved for text events
if (meta.getType() >= 1 && meta.getType() <= 15) {
// FIXME: What's the encoding?
xhtml.characters(new String(meta.getData(), ISO_8859_1));
}
}
}
xhtml.endElement("p");
}
} catch (InvalidMidiDataException ignore) {
// There is no way to know whether this exception was
// caused by the document being corrupted or by the format
// just being unsupported. So we do nothing.
}
xhtml.endDocument();
}
use of javax.sound.midi.MetaMessage in project jdk8u_jdk by JetBrains.
the class SMFParser method readTrack.
void readTrack(Track track) throws IOException, InvalidMidiDataException {
try {
// reset current tick to 0
long tick = 0;
// reset current status byte to 0 (invalid value).
// this should cause us to throw an InvalidMidiDataException if we don't
// get a valid status byte from the beginning of the track.
int status = 0;
boolean endOfTrackFound = false;
while (!trackFinished() && !endOfTrackFound) {
MidiMessage message;
// initialize to invalid value
int data1 = -1;
int data2 = 0;
// each event has a tick delay and then the event data.
// first read the delay (a variable-length int) and update our tick value
tick += readVarInt();
// check for new status
int byteValue = readUnsigned();
if (byteValue >= 0x80) {
status = byteValue;
} else {
data1 = byteValue;
}
switch(status & 0xF0) {
case 0x80:
case 0x90:
case 0xA0:
case 0xB0:
case 0xE0:
// two data bytes
if (data1 == -1) {
data1 = readUnsigned();
}
data2 = readUnsigned();
message = new FastShortMessage(status | (data1 << 8) | (data2 << 16));
break;
case 0xC0:
case 0xD0:
// one data byte
if (data1 == -1) {
data1 = readUnsigned();
}
message = new FastShortMessage(status | (data1 << 8));
break;
case 0xF0:
// sys-ex or meta
switch(status) {
case 0xF0:
case 0xF7:
// sys ex
int sysexLength = (int) readVarInt();
byte[] sysexData = new byte[sysexLength];
read(sysexData);
SysexMessage sysexMessage = new SysexMessage();
sysexMessage.setMessage(status, sysexData, sysexLength);
message = sysexMessage;
break;
case 0xFF:
// meta
int metaType = readUnsigned();
int metaLength = (int) readVarInt();
final byte[] metaData;
try {
metaData = new byte[metaLength];
} catch (final OutOfMemoryError oom) {
throw new IOException("Meta length too big", oom);
}
read(metaData);
MetaMessage metaMessage = new MetaMessage();
metaMessage.setMessage(metaType, metaData, metaLength);
message = metaMessage;
if (metaType == 0x2F) {
// end of track means it!
endOfTrackFound = true;
}
break;
default:
throw new InvalidMidiDataException("Invalid status byte: " + status);
}
// switch sys-ex or meta
break;
default:
throw new InvalidMidiDataException("Invalid status byte: " + status);
}
// switch
track.add(new MidiEvent(message, tick));
}
// while
} catch (ArrayIndexOutOfBoundsException e) {
if (DEBUG)
e.printStackTrace();
// fix for 4834374
throw new EOFException("invalid MIDI file");
}
}
use of javax.sound.midi.MetaMessage in project jdk8u_jdk by JetBrains.
the class StandardMidiFileWriter method writeTrack.
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;
// -----------------------------
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;
}
Aggregations