jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java
changeset 25859 3317bb8137f4
parent 18215 b2afd66ce6db
child 26037 508779ce6619
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java	Sun Aug 17 15:54:13 2014 +0100
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.media.sound;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiMessage;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Track;
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.UnsupportedAudioFileException;
+import javax.sound.sampled.AudioFileFormat.Type;
+import javax.sound.sampled.spi.AudioFileReader;
+
+/**
+ * MIDI File Audio Renderer/Reader
+ *
+ * @author Karl Helgason
+ */
+public final class SoftMidiAudioFileReader extends AudioFileReader {
+
+    public static final Type MIDI = new Type("MIDI", "mid");
+    private static AudioFormat format = new AudioFormat(44100, 16, 2, true, false);
+
+    public AudioFileFormat getAudioFileFormat(Sequence seq)
+            throws UnsupportedAudioFileException, IOException {
+
+        long totallen = seq.getMicrosecondLength() / 1000000;
+        long len = (long) (format.getFrameRate() * (totallen + 4));
+        return new AudioFileFormat(MIDI, format, (int) len);
+    }
+
+    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();
+                        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;
+    }
+
+    public AudioInputStream getAudioInputStream(InputStream inputstream)
+            throws UnsupportedAudioFileException, IOException {
+
+        inputstream.mark(200);
+        Sequence seq;
+        try {
+            seq = MidiSystem.getSequence(inputstream);
+        } catch (InvalidMidiDataException e) {
+            inputstream.reset();
+            throw new UnsupportedAudioFileException();
+        } catch (IOException e) {
+            inputstream.reset();
+            throw new UnsupportedAudioFileException();
+        }
+        return getAudioInputStream(seq);
+    }
+
+    public AudioFileFormat getAudioFileFormat(URL url)
+            throws UnsupportedAudioFileException, IOException {
+        Sequence seq;
+        try {
+            seq = MidiSystem.getSequence(url);
+        } catch (InvalidMidiDataException e) {
+            throw new UnsupportedAudioFileException();
+        } catch (IOException e) {
+            throw new UnsupportedAudioFileException();
+        }
+        return getAudioFileFormat(seq);
+    }
+
+    public AudioFileFormat getAudioFileFormat(File file)
+            throws UnsupportedAudioFileException, IOException {
+        Sequence seq;
+        try {
+            seq = MidiSystem.getSequence(file);
+        } catch (InvalidMidiDataException e) {
+            throw new UnsupportedAudioFileException();
+        } catch (IOException e) {
+            throw new UnsupportedAudioFileException();
+        }
+        return getAudioFileFormat(seq);
+    }
+
+    public AudioInputStream getAudioInputStream(URL url)
+            throws UnsupportedAudioFileException, IOException {
+        Sequence seq;
+        try {
+            seq = MidiSystem.getSequence(url);
+        } catch (InvalidMidiDataException e) {
+            throw new UnsupportedAudioFileException();
+        } catch (IOException e) {
+            throw new UnsupportedAudioFileException();
+        }
+        return getAudioInputStream(seq);
+    }
+
+    public AudioInputStream getAudioInputStream(File file)
+            throws UnsupportedAudioFileException, IOException {
+        if (!file.getName().toLowerCase().endsWith(".mid"))
+            throw new UnsupportedAudioFileException();
+        Sequence seq;
+        try {
+            seq = MidiSystem.getSequence(file);
+        } catch (InvalidMidiDataException e) {
+            throw new UnsupportedAudioFileException();
+        } catch (IOException e) {
+            throw new UnsupportedAudioFileException();
+        }
+        return getAudioInputStream(seq);
+    }
+
+    public AudioFileFormat getAudioFileFormat(InputStream inputstream)
+            throws UnsupportedAudioFileException, IOException {
+
+        inputstream.mark(200);
+        Sequence seq;
+        try {
+            seq = MidiSystem.getSequence(inputstream);
+        } catch (InvalidMidiDataException e) {
+            inputstream.reset();
+            throw new UnsupportedAudioFileException();
+        } catch (IOException e) {
+            inputstream.reset();
+            throw new UnsupportedAudioFileException();
+        }
+        return getAudioFileFormat(seq);
+    }
+}