1579 lines · 60.4 KB · Java
RawDownload
/* * Copyright (c) 2007, 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.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map; import javax.sound.midi.MidiChannel;import javax.sound.midi.Patch; /** * Software Synthesizer MIDI channel class. * * @author Karl Helgason */public class SoftChannel implements MidiChannel, ModelDirectedPlayer {     private static boolean[] dontResetControls = new boolean[128];    static {        for (int i = 0; i < dontResetControls.length; i++)            dontResetControls[i] = false;         dontResetControls[0] = true;   // Bank Select (MSB)        dontResetControls[32] = true;  // Bank Select (LSB)        dontResetControls[7] = true;   // Channel Volume (MSB)        dontResetControls[8] = true;   // Balance (MSB)        dontResetControls[10] = true;  // Pan (MSB)        dontResetControls[11] = true;  // Expression (MSB)        dontResetControls[91] = true;  // Effects 1 Depth (default: Reverb Send)        dontResetControls[92] = true;  // Effects 2 Depth (default: Tremolo Depth)        dontResetControls[93] = true;  // Effects 3 Depth (default: Chorus Send)        dontResetControls[94] = true;  // Effects 4 Depth (default: Celeste [Detune] Depth)        dontResetControls[95] = true;  // Effects 5 Depth (default: Phaser Depth)        dontResetControls[70] = true;  // Sound Controller 1 (default: Sound Variation)        dontResetControls[71] = true;  // Sound Controller 2 (default: Timbre / Harmonic Quality)        dontResetControls[72] = true;  // Sound Controller 3 (default: Release Time)        dontResetControls[73] = true;  // Sound Controller 4 (default: Attack Time)        dontResetControls[74] = true;  // Sound Controller 5 (default: Brightness)        dontResetControls[75] = true;  // Sound Controller 6 (GM2 default: Decay Time)        dontResetControls[76] = true;  // Sound Controller 7 (GM2 default: Vibrato Rate)        dontResetControls[77] = true;  // Sound Controller 8 (GM2 default: Vibrato Depth)        dontResetControls[78] = true;  // Sound Controller 9 (GM2 default: Vibrato Delay)        dontResetControls[79] = true;  // Sound Controller 10 (GM2 default: Undefined)        dontResetControls[120] = true; // All Sound Off        dontResetControls[121] = true; // Reset All Controllers        dontResetControls[122] = true; // Local Control On/Off        dontResetControls[123] = true; // All Notes Off        dontResetControls[124] = true; // Omni Mode Off        dontResetControls[125] = true; // Omni Mode On        dontResetControls[126] = true; // Poly Mode Off        dontResetControls[127] = true; // Poly Mode On         dontResetControls[6] = true;   // Data Entry (MSB)        dontResetControls[38] = true;  // Data Entry (LSB)        dontResetControls[96] = true;  // Data Increment        dontResetControls[97] = true;  // Data Decrement        dontResetControls[98] = true;  // Non-Registered Parameter Number (LSB)        dontResetControls[99] = true;  // Non-Registered Parameter Number(MSB)        dontResetControls[100] = true; // RPN = Null        dontResetControls[101] = true; // RPN = Null     }     private static final int RPN_NULL_VALUE = (127 << 7) + 127;    private int rpn_control = RPN_NULL_VALUE;    private int nrpn_control = RPN_NULL_VALUE;    protected double portamento_time = 1; // keyschanges per control buffer time    protected int[] portamento_lastnote = new int[128];    protected int portamento_lastnote_ix = 0;    private boolean portamento = false;    private boolean mono = false;    private boolean mute = false;    private boolean solo = false;    private boolean solomute = false;    private Object control_mutex;    private int channel;    private SoftVoice[] voices;    private int bank;    private int program;    private SoftSynthesizer synthesizer;    private SoftMainMixer mainmixer;    private int[] polypressure = new int[128];    private int channelpressure = 0;    private int[] controller = new int[128];    private int pitchbend;    private double[] co_midi_pitch = new double[1];    private double[] co_midi_channel_pressure = new double[1];    protected SoftTuning tuning = new SoftTuning();    protected int tuning_bank = 0;    protected int tuning_program = 0;    protected SoftInstrument current_instrument = null;    protected ModelChannelMixer current_mixer = null;    protected ModelDirector current_director = null;     // Controller Destination Settings    protected int cds_control_number = -1;    protected ModelConnectionBlock[] cds_control_connections = null;    protected ModelConnectionBlock[] cds_channelpressure_connections = null;    protected ModelConnectionBlock[] cds_polypressure_connections = null;    protected boolean sustain = false;    protected boolean[][] keybasedcontroller_active = null;    protected double[][] keybasedcontroller_value = null;     private class MidiControlObject implements SoftControl {        double[] pitch = co_midi_pitch;        double[] channel_pressure = co_midi_channel_pressure;        double[] poly_pressure = new double[1];         public double[] get(int instance, String name) {            if (name == null)                return null;            if (name.equals("pitch"))                return pitch;            if (name.equals("channel_pressure"))                return channel_pressure;            if (name.equals("poly_pressure"))                return poly_pressure;            return null;        }    }     private SoftControl[] co_midi = new SoftControl[128];    {        for (int i = 0; i < co_midi.length; i++) {            co_midi[i] = new MidiControlObject();        }    }     private double[][] co_midi_cc_cc = new double[128][1];    private SoftControl co_midi_cc = new SoftControl() {        double[][] cc = co_midi_cc_cc;        public double[] get(int instance, String name) {            if (name == null)                return null;            return cc[Integer.parseInt(name)];        }    };    Map<Integer, int[]> co_midi_rpn_rpn_i = new HashMap<Integer, int[]>();    Map<Integer, double[]> co_midi_rpn_rpn = new HashMap<Integer, double[]>();    private SoftControl co_midi_rpn = new SoftControl() {        Map<Integer, double[]> rpn = co_midi_rpn_rpn;        public double[] get(int instance, String name) {            if (name == null)                return null;            int iname = Integer.parseInt(name);            double[] v = rpn.get(iname);            if (v == null) {                v = new double[1];                rpn.put(iname, v);            }            return v;        }    };    Map<Integer, int[]> co_midi_nrpn_nrpn_i = new HashMap<Integer, int[]>();    Map<Integer, double[]> co_midi_nrpn_nrpn = new HashMap<Integer, double[]>();    private SoftControl co_midi_nrpn = new SoftControl() {        Map<Integer, double[]> nrpn = co_midi_nrpn_nrpn;        public double[] get(int instance, String name) {            if (name == null)                return null;            int iname = Integer.parseInt(name);            double[] v = nrpn.get(iname);            if (v == null) {                v = new double[1];                nrpn.put(iname, v);            }            return v;        }    };     private static int restrict7Bit(int value)    {        if(value < 0) return 0;        if(value > 127) return 127;        return value;    }     private static int restrict14Bit(int value)    {        if(value < 0) return 0;        if(value > 16256) return 16256;        return value;    }     public SoftChannel(SoftSynthesizer synth, int channel) {        this.channel = channel;        this.voices = synth.getVoices();        this.synthesizer = synth;        this.mainmixer = synth.getMainMixer();        control_mutex = synth.control_mutex;        resetAllControllers(true);    }     private int findFreeVoice(int x) {        if(x == -1)        {            // x = -1 means that there where no available voice            // last time we called findFreeVoice            // and it hasn't changed because no audio has been            // rendered in the meantime.            // Therefore we have to return -1.            return -1;        }        for (int i = x; i < voices.length; i++)            if (!voices[i].active)                return i;         // No free voice was found, we must steal one         int vmode = synthesizer.getVoiceAllocationMode();        if (vmode == 1) {            // DLS Static Voice Allocation             //  * priority ( 10, 1-9, 11-16)            // Search for channel to steal from            int steal_channel = channel;            for (int j = 0; j < voices.length; j++) {                if (voices[j].stealer_channel == null) {                    if (steal_channel == 9) {                        steal_channel = voices[j].channel;                    } else {                        if (voices[j].channel != 9) {                            if (voices[j].channel > steal_channel)                                steal_channel = voices[j].channel;                        }                    }                }            }             int voiceNo = -1;             SoftVoice v = null;            // Search for oldest voice in off state on steal_channel            for (int j = 0; j < voices.length; j++) {                if (voices[j].channel == steal_channel) {                    if (voices[j].stealer_channel == null && !voices[j].on) {                        if (v == null) {                            v = voices[j];                            voiceNo = j;                        }                        if (voices[j].voiceID < v.voiceID) {                            v = voices[j];                            voiceNo = j;                        }                    }                }            }            // Search for oldest voice in on state on steal_channel            if (voiceNo == -1) {                for (int j = 0; j < voices.length; j++) {                    if (voices[j].channel == steal_channel) {                        if (voices[j].stealer_channel == null) {                            if (v == null) {                                v = voices[j];                                voiceNo = j;                            }                            if (voices[j].voiceID < v.voiceID) {                                v = voices[j];                                voiceNo = j;                            }                        }                    }                }            }             return voiceNo;         } else {            // Default Voice Allocation            //  * Find voice that is on            //    and Find voice which has lowest voiceID ( oldest voice)            //  * Or find voice that is off            //    and Find voice which has lowest voiceID ( oldest voice)             int voiceNo = -1;             SoftVoice v = null;            // Search for oldest voice in off state            for (int j = 0; j < voices.length; j++) {                if (voices[j].stealer_channel == null && !voices[j].on) {                    if (v == null) {                        v = voices[j];                        voiceNo = j;                    }                    if (voices[j].voiceID < v.voiceID) {                        v = voices[j];                        voiceNo = j;                    }                }            }            // Search for oldest voice in on state            if (voiceNo == -1) {                 for (int j = 0; j < voices.length; j++) {                    if (voices[j].stealer_channel == null) {                        if (v == null) {                            v = voices[j];                            voiceNo = j;                        }                        if (voices[j].voiceID < v.voiceID) {                            v = voices[j];                            voiceNo = j;                        }                    }                }            }             return voiceNo;        }     }     protected void initVoice(SoftVoice voice, SoftPerformer p, int voiceID,            int noteNumber, int velocity, int delay, ModelConnectionBlock[] connectionBlocks,            ModelChannelMixer channelmixer, boolean releaseTriggered) {        if (voice.active) {            // Voice is active , we must steal the voice            voice.stealer_channel = this;            voice.stealer_performer = p;            voice.stealer_voiceID = voiceID;            voice.stealer_noteNumber = noteNumber;            voice.stealer_velocity = velocity;            voice.stealer_extendedConnectionBlocks = connectionBlocks;            voice.stealer_channelmixer = channelmixer;            voice.stealer_releaseTriggered = releaseTriggered;            for (int i = 0; i < voices.length; i++)                if (voices[i].active && voices[i].voiceID == voice.voiceID)                    voices[i].soundOff();            return;        }         voice.extendedConnectionBlocks = connectionBlocks;        voice.channelmixer = channelmixer;        voice.releaseTriggered = releaseTriggered;        voice.voiceID = voiceID;        voice.tuning = tuning;        voice.exclusiveClass = p.exclusiveClass;        voice.softchannel = this;        voice.channel = channel;        voice.bank = bank;        voice.program = program;        voice.instrument = current_instrument;        voice.performer = p;        voice.objects.clear();        voice.objects.put("midi", co_midi[noteNumber]);        voice.objects.put("midi_cc", co_midi_cc);        voice.objects.put("midi_rpn", co_midi_rpn);        voice.objects.put("midi_nrpn", co_midi_nrpn);        voice.noteOn(noteNumber, velocity, delay);        voice.setMute(mute);        voice.setSoloMute(solomute);        if (releaseTriggered)            return;        if (controller[84] != 0) {            voice.co_noteon_keynumber[0]                    = (tuning.getTuning(controller[84]) / 100.0)                    * (1f / 128f);            voice.portamento = true;            controlChange(84, 0);        } else if (portamento) {            if (mono) {                if (portamento_lastnote[0] != -1) {                    voice.co_noteon_keynumber[0]                            = (tuning.getTuning(portamento_lastnote[0]) / 100.0)                            * (1f / 128f);                    voice.portamento = true;                    controlChange(84, 0);                }                portamento_lastnote[0] = noteNumber;            } else {                if (portamento_lastnote_ix != 0) {                    portamento_lastnote_ix--;                    voice.co_noteon_keynumber[0]                            = (tuning.getTuning(                                    portamento_lastnote[portamento_lastnote_ix])                                / 100.0)                            * (1f / 128f);                    voice.portamento = true;                }            }        }    }     public void noteOn(int noteNumber, int velocity) {        noteOn(noteNumber, velocity, 0);    }     /* A special noteOn with delay parameter, which is used to     * start note within control buffers.     */    protected void noteOn(int noteNumber, int velocity, int delay) {        noteNumber = restrict7Bit(noteNumber);        velocity = restrict7Bit(velocity);        noteOn_internal(noteNumber, velocity, delay);        if (current_mixer != null)            current_mixer.noteOn(noteNumber, velocity);    }     private void noteOn_internal(int noteNumber, int velocity, int delay) {         if (velocity == 0) {            noteOff_internal(noteNumber, 64);            return;        }         synchronized (control_mutex) {            if (sustain) {                sustain = false;                for (int i = 0; i < voices.length; i++) {                    if ((voices[i].sustain || voices[i].on)                            && voices[i].channel == channel && voices[i].active                            && voices[i].note == noteNumber) {                        voices[i].sustain = false;                        voices[i].on = true;                        voices[i].noteOff(0);                    }                }                sustain = true;            }             mainmixer.activity();             if (mono) {                if (portamento) {                    boolean n_found = false;                    for (int i = 0; i < voices.length; i++) {                        if (voices[i].on && voices[i].channel == channel                                && voices[i].active                                && voices[i].releaseTriggered == false) {                            voices[i].portamento = true;                            voices[i].setNote(noteNumber);                            n_found = true;                        }                    }                    if (n_found) {                        portamento_lastnote[0] = noteNumber;                        return;                    }                }                 if (controller[84] != 0) {                    boolean n_found = false;                    for (int i = 0; i < voices.length; i++) {                        if (voices[i].on && voices[i].channel == channel                                && voices[i].active                                && voices[i].note == controller[84]                                && voices[i].releaseTriggered == false) {                            voices[i].portamento = true;                            voices[i].setNote(noteNumber);                            n_found = true;                        }                    }                    controlChange(84, 0);                    if (n_found)                        return;                }            }             if (mono)                allNotesOff();             if (current_instrument == null) {                current_instrument                        = synthesizer.findInstrument(program, bank, channel);                if (current_instrument == null)                    return;                if (current_mixer != null)                    mainmixer.stopMixer(current_mixer);                current_mixer = current_instrument.getSourceInstrument()                        .getChannelMixer(this, synthesizer.getFormat());                if (current_mixer != null)                    mainmixer.registerMixer(current_mixer);                current_director = current_instrument.getDirector(this, this);                applyInstrumentCustomization();

Lines 1–500 of 1579.