| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
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.AudioFileFormat.Type;  | 
 | 
import javax.sound.sampled.AudioFormat;  | 
 | 
import javax.sound.sampled.AudioInputStream;  | 
 | 
import javax.sound.sampled.UnsupportedAudioFileException;  | 
 | 
import javax.sound.sampled.spi.AudioFileReader;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
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();  | 
 | 
                        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;  | 
 | 
    }  | 
 | 
 | 
 | 
    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);  | 
 | 
    }  | 
 | 
}  |