1351 lines · 48.5 KB · Java
RawDownload
/* * 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.