package tk.amberide.engine.al; import tk.amberide.ide.gui.misc.ErrorHandler; import java.io.InputStream; import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.MetaEventListener; import javax.sound.midi.MetaMessage; import javax.sound.midi.MidiChannel; import javax.sound.midi.MidiDevice; import javax.sound.midi.MidiSystem; import javax.sound.midi.MidiUnavailableException; import javax.sound.midi.Sequence; import javax.sound.midi.Sequencer; import javax.sound.midi.Synthesizer; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFileFormat.Type; import javax.sound.sampled.AudioFormat; /** * * @author Tudor */ public class MidiAudio implements Audio { private Sequencer sequencer; private Sequence sequence; private boolean loop; private float volume; private AudioFormat format; MidiAudio(InputStream data) throws MidiUnavailableException { getSequencer(); setSequence(data); sequencer.addMetaEventListener(new MetaEventListener() { public void meta(MetaMessage msg) { if (msg.getType() == 47) { try { sequencer.setSequence(sequence); } catch (InvalidMidiDataException e) { ErrorHandler.alert(e); } sequencer.setTickPosition(0); if (loop) { // End of track sequencer.start(); } } } }); AudioFormat base = new AudioFormat(44100, 16, 2, true, false); format = new AudioFileFormat(new Type("MIDI", "mid"), base, (int) (base.getFrameRate() * (sequence.getMicrosecondLength() / 1000000 + 4))).getFormat(); } public void start() { sequencer.start(); } public void pause() { sequencer.stop(); } public void stop() { sequencer.stop(); sequencer.setTickPosition(0); } public State getState() { return sequencer.isRunning() ? State.PLAYING : (sequencer.getMicrosecondPosition() == 0 ? State.STOPPED : State.PAUSED); } public void setVolume(float volume) { try { this.volume = volume; Synthesizer synthesizer = MidiSystem.getSynthesizer(); synthesizer.open(); MidiChannel[] channels = synthesizer.getChannels(); for (MidiChannel channel : channels) { if (channel != null) { channel.controlChange(7, (int) volume); } } } catch (Exception ex) { } } public float getVolume() { return volume; } public void setLooping(boolean flag) { loop = flag; } public boolean isLooping() { return loop; } public void setMillisecondPosition(long position) { sequencer.setMicrosecondPosition(position * 1000); } public long getMillisecondPosition() { return sequencer.getMicrosecondPosition() / 1000; } public long getMillisecondLength() { return sequencer.getMicrosecondLength() / 1000; } private void getSequencer() throws MidiUnavailableException { try { sequencer = MidiSystem.getSequencer(); if (sequencer != null) { try { sequencer.getTransmitter(); } catch (MidiUnavailableException mue) { } sequencer.open(); } } catch (MidiUnavailableException mue) { sequencer = null; } catch (Exception e) { if (e instanceof InterruptedException) { sequencer = null; } try { sequencer = MidiSystem.getSequencer(); if (sequencer != null) { try { sequencer.getTransmitter(); } catch (MidiUnavailableException mue) { } sequencer.open(); } } catch (MidiUnavailableException mue) { sequencer = null; } catch (Exception e2) { sequencer = null; } } if (sequencer == null) { sequencer = openSequencer("Real Time Sequencer"); } if (sequencer == null) { sequencer = openSequencer("Java Sound Sequencer"); } if (sequencer == null) { throw new MidiUnavailableException("unable to find MIDI-capable device"); } } private Sequencer openSequencer(String containsString) { Sequencer s; s = (Sequencer) openMidiDevice(containsString); if (s == null) { return null; } try { s.getTransmitter(); } catch (MidiUnavailableException mue) { return null; } return s; } private MidiDevice openMidiDevice(String containsString) { MidiDevice device; MidiDevice.Info[] midiDevices = MidiSystem.getMidiDeviceInfo(); for (int i = 0; i < midiDevices.length; i++) { try { device = MidiSystem.getMidiDevice(midiDevices[i]); } catch (MidiUnavailableException e) { device = null; } if (device != null && midiDevices[i].getName().contains(containsString)) { try { device.open(); } catch (MidiUnavailableException mue) { device = null; } return device; } } return null; } private void setSequence(InputStream midiSource) { if (sequencer == null || midiSource == null) { return; } try { sequence = MidiSystem.getSequence(midiSource); } catch (Exception e) { ErrorHandler.alert(e); return; } if (sequence != null) { try { sequencer.setSequence(sequence); } catch (Exception e) { ErrorHandler.alert(e); } } } public AudioFormat getFormat() { return format; } }