/* * Copyright (c) 2008, 2010, 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.BufferedInputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.lang.ref.WeakReference;import java.security.AccessController;import java.security.PrivilegedAction;import java.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Properties;import java.util.StringTokenizer;import java.util.prefs.BackingStoreException;import java.util.prefs.Preferences; import javax.sound.midi.Instrument;import javax.sound.midi.MidiChannel;import javax.sound.midi.MidiDevice;import javax.sound.midi.MidiSystem;import javax.sound.midi.MidiUnavailableException;import javax.sound.midi.Patch;import javax.sound.midi.Receiver;import javax.sound.midi.Soundbank;import javax.sound.midi.Transmitter;import javax.sound.midi.VoiceStatus;import javax.sound.sampled.AudioFormat;import javax.sound.sampled.AudioInputStream;import javax.sound.sampled.AudioSystem;import javax.sound.sampled.LineUnavailableException;import javax.sound.sampled.SourceDataLine; /** * The software synthesizer class. * * @author Karl Helgason */public class SoftSynthesizer implements AudioSynthesizer, ReferenceCountingDevice { protected static class WeakAudioStream extends InputStream { private volatile AudioInputStream stream; public SoftAudioPusher pusher = null; public AudioInputStream jitter_stream = null; public SourceDataLine sourceDataLine = null; public volatile long silent_samples = 0; private int framesize = 0; private WeakReference<AudioInputStream> weak_stream_link; private AudioFloatConverter converter; private float[] silentbuffer = null; private int samplesize; public void setInputStream(AudioInputStream stream) { this.stream = stream; } public int available() throws IOException { AudioInputStream local_stream = stream; if(local_stream != null) return local_stream.available(); return 0; } public int read() throws IOException { byte[] b = new byte[1]; if (read(b) == -1) return -1; return b[0] & 0xFF; } public int read(byte[] b, int off, int len) throws IOException { AudioInputStream local_stream = stream; if(local_stream != null) return local_stream.read(b, off, len); else { int flen = len / samplesize; if(silentbuffer == null || silentbuffer.length < flen) silentbuffer = new float[flen]; converter.toByteArray(silentbuffer, flen, b, off); silent_samples += (long)((len / framesize)); if(pusher != null) if(weak_stream_link.get() == null) { Runnable runnable = new Runnable() { SoftAudioPusher _pusher = pusher; AudioInputStream _jitter_stream = jitter_stream; SourceDataLine _sourceDataLine = sourceDataLine; public void run() { _pusher.stop(); if(_jitter_stream != null) try { _jitter_stream.close(); } catch (IOException e) { e.printStackTrace(); } if(_sourceDataLine != null) _sourceDataLine.close(); } }; pusher = null; jitter_stream = null; sourceDataLine = null; new Thread(runnable).start(); } return len; } } public WeakAudioStream(AudioInputStream stream) { this.stream = stream; weak_stream_link = new WeakReference<AudioInputStream>(stream); converter = AudioFloatConverter.getConverter(stream.getFormat()); samplesize = stream.getFormat().getFrameSize() / stream.getFormat().getChannels(); framesize = stream.getFormat().getFrameSize(); } public AudioInputStream getAudioInputStream() { return new AudioInputStream(this, stream.getFormat(), AudioSystem.NOT_SPECIFIED); } public void close() throws IOException { AudioInputStream astream = weak_stream_link.get(); if(astream != null) astream.close(); } } private static class Info extends MidiDevice.Info { public Info() { super(INFO_NAME, INFO_VENDOR, INFO_DESCRIPTION, INFO_VERSION); } } protected static final String INFO_NAME = "Gervill"; protected static final String INFO_VENDOR = "OpenJDK"; protected static final String INFO_DESCRIPTION = "Software MIDI Synthesizer"; protected static final String INFO_VERSION = "1.0"; protected final static MidiDevice.Info info = new Info(); private static SourceDataLine testline = null; private static Soundbank defaultSoundBank = null; protected WeakAudioStream weakstream = null; protected Object control_mutex = this; protected int voiceIDCounter = 0; // 0: default // 1: DLS Voice Allocation protected int voice_allocation_mode = 0; protected boolean load_default_soundbank = false; protected boolean reverb_light = true; protected boolean reverb_on = true; protected boolean chorus_on = true; protected boolean agc_on = true; protected SoftChannel[] channels; protected SoftChannelProxy[] external_channels = null; private boolean largemode = false; // 0: GM Mode off (default) // 1: GM Level 1 // 2: GM Level 2 private int gmmode = 0; private int deviceid = 0; private AudioFormat format = new AudioFormat(44100, 16, 2, true, false); private SourceDataLine sourceDataLine = null; private SoftAudioPusher pusher = null; private AudioInputStream pusher_stream = null; private float controlrate = 147f; private boolean open = false; private boolean implicitOpen = false; private String resamplerType = "linear"; private SoftResampler resampler = new SoftLinearResampler(); private int number_of_midi_channels = 16; private int maxpoly = 64; private long latency = 200000; // 200 msec private boolean jitter_correction = false; private SoftMainMixer mainmixer; private SoftVoice[] voices; private Map<String, SoftTuning> tunings = new HashMap<String, SoftTuning>(); private Map<String, SoftInstrument> inslist = new HashMap<String, SoftInstrument>(); private Map<String, ModelInstrument> loadedlist = new HashMap<String, ModelInstrument>(); private ArrayList<Receiver> recvslist = new ArrayList<Receiver>(); private void getBuffers(ModelInstrument instrument, List<ModelByteBuffer> buffers) { for (ModelPerformer performer : instrument.getPerformers()) { if (performer.getOscillators() != null) { for (ModelOscillator osc : performer.getOscillators()) { if (osc instanceof ModelByteBufferWavetable) { ModelByteBufferWavetable w = (ModelByteBufferWavetable)osc; ModelByteBuffer buff = w.getBuffer(); if (buff != null) buffers.add(buff); buff = w.get8BitExtensionBuffer(); if (buff != null) buffers.add(buff); } } } } } private boolean loadSamples(List<ModelInstrument> instruments) { if (largemode) return true; List<ModelByteBuffer> buffers = new ArrayList<ModelByteBuffer>(); for (ModelInstrument instrument : instruments) getBuffers(instrument, buffers); try { ModelByteBuffer.loadAll(buffers); } catch (IOException e) { return false; } return true; } private boolean loadInstruments(List<ModelInstrument> instruments) { if (!isOpen()) return false; if (!loadSamples(instruments)) return false; synchronized (control_mutex) { if (channels != null) for (SoftChannel c : channels) { c.current_instrument = null; c.current_director = null; } for (Instrument instrument : instruments) { String pat = patchToString(instrument.getPatch()); SoftInstrument softins = new SoftInstrument((ModelInstrument) instrument); inslist.put(pat, softins); loadedlist.put(pat, (ModelInstrument) instrument); } } return true; } private void processPropertyInfo(Map<String, Object> info) { AudioSynthesizerPropertyInfo[] items = getPropertyInfo(info); String resamplerType = (String)items[0].value; if (resamplerType.equalsIgnoreCase("point")) { this.resampler = new SoftPointResampler(); this.resamplerType = "point"; } else if (resamplerType.equalsIgnoreCase("linear")) { this.resampler = new SoftLinearResampler2(); this.resamplerType = "linear"; } else if (resamplerType.equalsIgnoreCase("linear1")) { this.resampler = new SoftLinearResampler(); this.resamplerType = "linear1"; } else if (resamplerType.equalsIgnoreCase("linear2")) { this.resampler = new SoftLinearResampler2(); this.resamplerType = "linear2"; } else if (resamplerType.equalsIgnoreCase("cubic")) { this.resampler = new SoftCubicResampler(); this.resamplerType = "cubic"; } else if (resamplerType.equalsIgnoreCase("lanczos")) { this.resampler = new SoftLanczosResampler(); this.resamplerType = "lanczos"; } else if (resamplerType.equalsIgnoreCase("sinc")) { this.resampler = new SoftSincResampler(); this.resamplerType = "sinc"; } setFormat((AudioFormat)items[2].value); controlrate = (Float)items[1].value; latency = (Long)items[3].value; deviceid = (Integer)items[4].value; maxpoly = (Integer)items[5].value; reverb_on = (Boolean)items[6].value; chorus_on = (Boolean)items[7].value; agc_on = (Boolean)items[8].value; largemode = (Boolean)items[9].value; number_of_midi_channels = (Integer)items[10].value; jitter_correction = (Boolean)items[11].value; reverb_light = (Boolean)items[12].value; load_default_soundbank = (Boolean)items[13].value; } private String patchToString(Patch patch) { if (patch instanceof ModelPatch && ((ModelPatch) patch).isPercussion()) return "p." + patch.getProgram() + "." + patch.getBank(); else return patch.getProgram() + "." + patch.getBank(); } private void setFormat(AudioFormat format) { if (format.getChannels() > 2) { throw new IllegalArgumentException( "Only mono and stereo audio supported."); } if (AudioFloatConverter.getConverter(format) == null) throw new IllegalArgumentException("Audio format not supported."); this.format = format; } protected void removeReceiver(Receiver recv) { boolean perform_close = false; synchronized (control_mutex) { if (recvslist.remove(recv)) { if (implicitOpen && recvslist.isEmpty()) perform_close = true; } } if (perform_close) close(); } protected SoftMainMixer getMainMixer() { if (!isOpen()) return null; return mainmixer; } protected SoftInstrument findInstrument(int program, int bank, int channel) { // Add support for GM2 banks 0x78 and 0x79 // as specified in DLS 2.2 in Section 1.4.6 // which allows using percussion and melodic instruments // on all channels if (bank >> 7 == 0x78 || bank >> 7 == 0x79) { SoftInstrument current_instrument = inslist.get(program + "." + bank); if (current_instrument != null) return current_instrument; String p_plaf; if (bank >> 7 == 0x78) p_plaf = "p."; else p_plaf = ""; // Instrument not found fallback to MSB:bank, LSB:0 current_instrument = inslist.get(p_plaf + program + "." + ((bank & 128) << 7)); if (current_instrument != null) return current_instrument; // Instrument not found fallback to MSB:0, LSB:bank current_instrument = inslist.get(p_plaf + program + "." + (bank & 128)); if (current_instrument != null) return current_instrument; // Instrument not found fallback to MSB:0, LSB:0 current_instrument = inslist.get(p_plaf + program + ".0"); if (current_instrument != null) return current_instrument; // Instrument not found fallback to MSB:0, LSB:0, program=0 current_instrument = inslist.get(p_plaf + program + "0.0"); if (current_instrument != null) return current_instrument; return null; } // Channel 10 uses percussion instruments String p_plaf; if (channel == 9) p_plaf = "p."; else p_plaf = ""; SoftInstrument current_instrument = inslist.get(p_plaf + program + "." + bank); if (current_instrument != null) return current_instrument; // Instrument not found fallback to MSB:0, LSB:0 current_instrument = inslist.get(p_plaf + program + ".0"); if (current_instrument != null) return current_instrument; // Instrument not found fallback to MSB:0, LSB:0, program=0 current_instrument = inslist.get(p_plaf + "0.0"); if (current_instrument != null) return current_instrument; return null; } protected int getVoiceAllocationMode() { return voice_allocation_mode; } protected int getGeneralMidiMode() { return gmmode; } protected void setGeneralMidiMode(int gmmode) { this.gmmode = gmmode; } protected int getDeviceID() { return deviceid; } protected float getControlRate() { return controlrate; } protected SoftVoice[] getVoices() { return voices; } protected SoftTuning getTuning(Patch patch) { String t_id = patchToString(patch); SoftTuning tuning = tunings.get(t_id); if (tuning == null) { tuning = new SoftTuning(patch); tunings.put(t_id, tuning); } return tuning; } public long getLatency() { synchronized (control_mutex) { return latency; } } public AudioFormat getFormat() { synchronized (control_mutex) { return format; } } public int getMaxPolyphony() { synchronized (control_mutex) {Lines 1–500 of 1351. Load more
/* * Copyright (c) 2008, 2010, 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.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.ref.WeakReference; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import javax.sound.midi.Instrument; import javax.sound.midi.MidiChannel; import javax.sound.midi.MidiDevice; import javax.sound.midi.MidiSystem; import javax.sound.midi.MidiUnavailableException; import javax.sound.midi.Patch; import javax.sound.midi.Receiver; import javax.sound.midi.Soundbank; import javax.sound.midi.Transmitter; import javax.sound.midi.VoiceStatus; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; /** * The software synthesizer class. * * @author Karl Helgason */ public class SoftSynthesizer implements AudioSynthesizer, ReferenceCountingDevice { protected static class WeakAudioStream extends InputStream { private volatile AudioInputStream stream; public SoftAudioPusher pusher = null; public AudioInputStream jitter_stream = null; public SourceDataLine sourceDataLine = null; public volatile long silent_samples = 0; private int framesize = 0; private WeakReference<AudioInputStream> weak_stream_link; private AudioFloatConverter converter; private float[] silentbuffer = null; private int samplesize; public void setInputStream(AudioInputStream stream) { this.stream = stream; } public int available() throws IOException { AudioInputStream local_stream = stream; if(local_stream != null) return local_stream.available(); return 0; } public int read() throws IOException { byte[] b = new byte[1]; if (read(b) == -1) return -1; return b[0] & 0xFF; } public int read(byte[] b, int off, int len) throws IOException { AudioInputStream local_stream = stream; if(local_stream != null) return local_stream.read(b, off, len); else { int flen = len / samplesize; if(silentbuffer == null || silentbuffer.length < flen) silentbuffer = new float[flen]; converter.toByteArray(silentbuffer, flen, b, off); silent_samples += (long)((len / framesize)); if(pusher != null) if(weak_stream_link.get() == null) { Runnable runnable = new Runnable() { SoftAudioPusher _pusher = pusher; AudioInputStream _jitter_stream = jitter_stream; SourceDataLine _sourceDataLine = sourceDataLine; public void run() { _pusher.stop(); if(_jitter_stream != null) try { _jitter_stream.close(); } catch (IOException e) { e.printStackTrace(); } if(_sourceDataLine != null) _sourceDataLine.close(); } }; pusher = null; jitter_stream = null; sourceDataLine = null; new Thread(runnable).start(); } return len; } } public WeakAudioStream(AudioInputStream stream) { this.stream = stream; weak_stream_link = new WeakReference<AudioInputStream>(stream); converter = AudioFloatConverter.getConverter(stream.getFormat()); samplesize = stream.getFormat().getFrameSize() / stream.getFormat().getChannels(); framesize = stream.getFormat().getFrameSize(); } public AudioInputStream getAudioInputStream() { return new AudioInputStream(this, stream.getFormat(), AudioSystem.NOT_SPECIFIED); } public void close() throws IOException { AudioInputStream astream = weak_stream_link.get(); if(astream != null) astream.close(); } } private static class Info extends MidiDevice.Info { public Info() { super(INFO_NAME, INFO_VENDOR, INFO_DESCRIPTION, INFO_VERSION); } } protected static final String INFO_NAME = "Gervill"; protected static final String INFO_VENDOR = "OpenJDK"; protected static final String INFO_DESCRIPTION = "Software MIDI Synthesizer"; protected static final String INFO_VERSION = "1.0"; protected final static MidiDevice.Info info = new Info(); private static SourceDataLine testline = null; private static Soundbank defaultSoundBank = null; protected WeakAudioStream weakstream = null; protected Object control_mutex = this; protected int voiceIDCounter = 0; // 0: default // 1: DLS Voice Allocation protected int voice_allocation_mode = 0; protected boolean load_default_soundbank = false; protected boolean reverb_light = true; protected boolean reverb_on = true; protected boolean chorus_on = true; protected boolean agc_on = true; protected SoftChannel[] channels; protected SoftChannelProxy[] external_channels = null; private boolean largemode = false; // 0: GM Mode off (default) // 1: GM Level 1 // 2: GM Level 2 private int gmmode = 0; private int deviceid = 0; private AudioFormat format = new AudioFormat(44100, 16, 2, true, false); private SourceDataLine sourceDataLine = null; private SoftAudioPusher pusher = null; private AudioInputStream pusher_stream = null; private float controlrate = 147f; private boolean open = false; private boolean implicitOpen = false; private String resamplerType = "linear"; private SoftResampler resampler = new SoftLinearResampler(); private int number_of_midi_channels = 16; private int maxpoly = 64; private long latency = 200000; // 200 msec private boolean jitter_correction = false; private SoftMainMixer mainmixer; private SoftVoice[] voices; private Map<String, SoftTuning> tunings = new HashMap<String, SoftTuning>(); private Map<String, SoftInstrument> inslist = new HashMap<String, SoftInstrument>(); private Map<String, ModelInstrument> loadedlist = new HashMap<String, ModelInstrument>(); private ArrayList<Receiver> recvslist = new ArrayList<Receiver>(); private void getBuffers(ModelInstrument instrument, List<ModelByteBuffer> buffers) { for (ModelPerformer performer : instrument.getPerformers()) { if (performer.getOscillators() != null) { for (ModelOscillator osc : performer.getOscillators()) { if (osc instanceof ModelByteBufferWavetable) { ModelByteBufferWavetable w = (ModelByteBufferWavetable)osc; ModelByteBuffer buff = w.getBuffer(); if (buff != null) buffers.add(buff); buff = w.get8BitExtensionBuffer(); if (buff != null) buffers.add(buff); } } } } } private boolean loadSamples(List<ModelInstrument> instruments) { if (largemode) return true; List<ModelByteBuffer> buffers = new ArrayList<ModelByteBuffer>(); for (ModelInstrument instrument : instruments) getBuffers(instrument, buffers); try { ModelByteBuffer.loadAll(buffers); } catch (IOException e) { return false; } return true; } private boolean loadInstruments(List<ModelInstrument> instruments) { if (!isOpen()) return false; if (!loadSamples(instruments)) return false; synchronized (control_mutex) { if (channels != null) for (SoftChannel c : channels) { c.current_instrument = null; c.current_director = null; } for (Instrument instrument : instruments) { String pat = patchToString(instrument.getPatch()); SoftInstrument softins = new SoftInstrument((ModelInstrument) instrument); inslist.put(pat, softins); loadedlist.put(pat, (ModelInstrument) instrument); } } return true; } private void processPropertyInfo(Map<String, Object> info) { AudioSynthesizerPropertyInfo[] items = getPropertyInfo(info); String resamplerType = (String)items[0].value; if (resamplerType.equalsIgnoreCase("point")) { this.resampler = new SoftPointResampler(); this.resamplerType = "point"; } else if (resamplerType.equalsIgnoreCase("linear")) { this.resampler = new SoftLinearResampler2(); this.resamplerType = "linear"; } else if (resamplerType.equalsIgnoreCase("linear1")) { this.resampler = new SoftLinearResampler(); this.resamplerType = "linear1"; } else if (resamplerType.equalsIgnoreCase("linear2")) { this.resampler = new SoftLinearResampler2(); this.resamplerType = "linear2"; } else if (resamplerType.equalsIgnoreCase("cubic")) { this.resampler = new SoftCubicResampler(); this.resamplerType = "cubic"; } else if (resamplerType.equalsIgnoreCase("lanczos")) { this.resampler = new SoftLanczosResampler(); this.resamplerType = "lanczos"; } else if (resamplerType.equalsIgnoreCase("sinc")) { this.resampler = new SoftSincResampler(); this.resamplerType = "sinc"; } setFormat((AudioFormat)items[2].value); controlrate = (Float)items[1].value; latency = (Long)items[3].value; deviceid = (Integer)items[4].value; maxpoly = (Integer)items[5].value; reverb_on = (Boolean)items[6].value; chorus_on = (Boolean)items[7].value; agc_on = (Boolean)items[8].value; largemode = (Boolean)items[9].value; number_of_midi_channels = (Integer)items[10].value; jitter_correction = (Boolean)items[11].value; reverb_light = (Boolean)items[12].value; load_default_soundbank = (Boolean)items[13].value; } private String patchToString(Patch patch) { if (patch instanceof ModelPatch && ((ModelPatch) patch).isPercussion()) return "p." + patch.getProgram() + "." + patch.getBank(); else return patch.getProgram() + "." + patch.getBank(); } private void setFormat(AudioFormat format) { if (format.getChannels() > 2) { throw new IllegalArgumentException( "Only mono and stereo audio supported."); } if (AudioFloatConverter.getConverter(format) == null) throw new IllegalArgumentException("Audio format not supported."); this.format = format; } protected void removeReceiver(Receiver recv) { boolean perform_close = false; synchronized (control_mutex) { if (recvslist.remove(recv)) { if (implicitOpen && recvslist.isEmpty()) perform_close = true; } } if (perform_close) close(); } protected SoftMainMixer getMainMixer() { if (!isOpen()) return null; return mainmixer; } protected SoftInstrument findInstrument(int program, int bank, int channel) { // Add support for GM2 banks 0x78 and 0x79 // as specified in DLS 2.2 in Section 1.4.6 // which allows using percussion and melodic instruments // on all channels if (bank >> 7 == 0x78 || bank >> 7 == 0x79) { SoftInstrument current_instrument = inslist.get(program + "." + bank); if (current_instrument != null) return current_instrument; String p_plaf; if (bank >> 7 == 0x78) p_plaf = "p."; else p_plaf = ""; // Instrument not found fallback to MSB:bank, LSB:0 current_instrument = inslist.get(p_plaf + program + "." + ((bank & 128) << 7)); if (current_instrument != null) return current_instrument; // Instrument not found fallback to MSB:0, LSB:bank current_instrument = inslist.get(p_plaf + program + "." + (bank & 128)); if (current_instrument != null) return current_instrument; // Instrument not found fallback to MSB:0, LSB:0 current_instrument = inslist.get(p_plaf + program + ".0"); if (current_instrument != null) return current_instrument; // Instrument not found fallback to MSB:0, LSB:0, program=0 current_instrument = inslist.get(p_plaf + program + "0.0"); if (current_instrument != null) return current_instrument; return null; } // Channel 10 uses percussion instruments String p_plaf; if (channel == 9) p_plaf = "p."; else p_plaf = ""; SoftInstrument current_instrument = inslist.get(p_plaf + program + "." + bank); if (current_instrument != null) return current_instrument; // Instrument not found fallback to MSB:0, LSB:0 current_instrument = inslist.get(p_plaf + program + ".0"); if (current_instrument != null) return current_instrument; // Instrument not found fallback to MSB:0, LSB:0, program=0 current_instrument = inslist.get(p_plaf + "0.0"); if (current_instrument != null) return current_instrument; return null; } protected int getVoiceAllocationMode() { return voice_allocation_mode; } protected int getGeneralMidiMode() { return gmmode; } protected void setGeneralMidiMode(int gmmode) { this.gmmode = gmmode; } protected int getDeviceID() { return deviceid; } protected float getControlRate() { return controlrate; } protected SoftVoice[] getVoices() { return voices; } protected SoftTuning getTuning(Patch patch) { String t_id = patchToString(patch); SoftTuning tuning = tunings.get(t_id); if (tuning == null) { tuning = new SoftTuning(patch); tunings.put(t_id, tuning); } return tuning; } public long getLatency() { synchronized (control_mutex) { return latency; } } public AudioFormat getFormat() { synchronized (control_mutex) { return format; } } public int getMaxPolyphony() { synchronized (control_mutex) {