Search in sources :

Example 1 with MidiEvent

use of javax.sound.midi.MidiEvent 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;
}
Also used : MidiUnavailableException(javax.sound.midi.MidiUnavailableException) MidiMessage(javax.sound.midi.MidiMessage) Receiver(javax.sound.midi.Receiver) MidiEvent(javax.sound.midi.MidiEvent) IOException(java.io.IOException) AudioInputStream(javax.sound.sampled.AudioInputStream) UnsupportedAudioFileException(javax.sound.sampled.UnsupportedAudioFileException) MetaMessage(javax.sound.midi.MetaMessage) Track(javax.sound.midi.Track)

Example 2 with MidiEvent

use of javax.sound.midi.MidiEvent 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");
    }
}
Also used : InvalidMidiDataException(javax.sound.midi.InvalidMidiDataException) MidiMessage(javax.sound.midi.MidiMessage) MidiEvent(javax.sound.midi.MidiEvent) IOException(java.io.IOException) SysexMessage(javax.sound.midi.SysexMessage) EOFException(java.io.EOFException) MetaMessage(javax.sound.midi.MetaMessage)

Example 3 with MidiEvent

use of javax.sound.midi.MidiEvent 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;
}
Also used : InvalidMidiDataException(javax.sound.midi.InvalidMidiDataException) DataOutputStream(java.io.DataOutputStream) MidiEvent(javax.sound.midi.MidiEvent) PipedOutputStream(java.io.PipedOutputStream) PipedInputStream(java.io.PipedInputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) SequenceInputStream(java.io.SequenceInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) ShortMessage(javax.sound.midi.ShortMessage) SysexMessage(javax.sound.midi.SysexMessage) MetaMessage(javax.sound.midi.MetaMessage)

Aggregations

MetaMessage (javax.sound.midi.MetaMessage)3 MidiEvent (javax.sound.midi.MidiEvent)3 IOException (java.io.IOException)2 InvalidMidiDataException (javax.sound.midi.InvalidMidiDataException)2 MidiMessage (javax.sound.midi.MidiMessage)2 SysexMessage (javax.sound.midi.SysexMessage)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 DataOutputStream (java.io.DataOutputStream)1 EOFException (java.io.EOFException)1 PipedInputStream (java.io.PipedInputStream)1 PipedOutputStream (java.io.PipedOutputStream)1 SequenceInputStream (java.io.SequenceInputStream)1 MidiUnavailableException (javax.sound.midi.MidiUnavailableException)1 Receiver (javax.sound.midi.Receiver)1 ShortMessage (javax.sound.midi.ShortMessage)1 Track (javax.sound.midi.Track)1 AudioInputStream (javax.sound.sampled.AudioInputStream)1 UnsupportedAudioFileException (javax.sound.sampled.UnsupportedAudioFileException)1