/* * Copyright (c) 2007, 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.IOException;import java.io.InputStream;import java.util.HashSet;import java.util.Iterator;import java.util.Set;import java.util.TreeMap;import java.util.Map.Entry; import javax.sound.midi.MidiMessage;import javax.sound.midi.Patch;import javax.sound.midi.ShortMessage;import javax.sound.sampled.AudioInputStream;import javax.sound.sampled.AudioSystem; /** * Software synthesizer main audio mixer. * * @author Karl Helgason */public class SoftMainMixer { // A private class thats contains a ModelChannelMixer and it's private buffers. // This becomes necessary when we want to have separate delay buffers for each channel mixer. private class SoftChannelMixerContainer { ModelChannelMixer mixer; SoftAudioBuffer[] buffers; } public final static int CHANNEL_LEFT = 0; public final static int CHANNEL_RIGHT = 1; public final static int CHANNEL_MONO = 2; public final static int CHANNEL_DELAY_LEFT = 3; public final static int CHANNEL_DELAY_RIGHT = 4; public final static int CHANNEL_DELAY_MONO = 5; public final static int CHANNEL_EFFECT1 = 6; public final static int CHANNEL_EFFECT2 = 7; public final static int CHANNEL_DELAY_EFFECT1 = 8; public final static int CHANNEL_DELAY_EFFECT2 = 9; public final static int CHANNEL_LEFT_DRY = 10; public final static int CHANNEL_RIGHT_DRY = 11; public final static int CHANNEL_SCRATCH1 = 12; public final static int CHANNEL_SCRATCH2 = 13; protected boolean active_sensing_on = false; private long msec_last_activity = -1; private boolean pusher_silent = false; private int pusher_silent_count = 0; private long sample_pos = 0; protected boolean readfully = true; private Object control_mutex; private SoftSynthesizer synth; private float samplerate = 44100; private int nrofchannels = 2; private SoftVoice[] voicestatus = null; private SoftAudioBuffer[] buffers; private SoftReverb reverb; private SoftAudioProcessor chorus; private SoftAudioProcessor agc; private long msec_buffer_len = 0; private int buffer_len = 0; protected TreeMap<Long, Object> midimessages = new TreeMap<Long, Object>(); private int delay_midievent = 0; private int max_delay_midievent = 0; double last_volume_left = 1.0; double last_volume_right = 1.0; private double[] co_master_balance = new double[1]; private double[] co_master_volume = new double[1]; private double[] co_master_coarse_tuning = new double[1]; private double[] co_master_fine_tuning = new double[1]; private AudioInputStream ais; private Set<SoftChannelMixerContainer> registeredMixers = null; private Set<ModelChannelMixer> stoppedMixers = null; private SoftChannelMixerContainer[] cur_registeredMixers = null; protected SoftControl co_master = new SoftControl() { double[] balance = co_master_balance; double[] volume = co_master_volume; double[] coarse_tuning = co_master_coarse_tuning; double[] fine_tuning = co_master_fine_tuning; public double[] get(int instance, String name) { if (name == null) return null; if (name.equals("balance")) return balance; if (name.equals("volume")) return volume; if (name.equals("coarse_tuning")) return coarse_tuning; if (name.equals("fine_tuning")) return fine_tuning; return null; } }; private void processSystemExclusiveMessage(byte[] data) { synchronized (synth.control_mutex) { activity(); // Universal Non-Real-Time SysEx if ((data[1] & 0xFF) == 0x7E) { int deviceID = data[2] & 0xFF; if (deviceID == 0x7F || deviceID == synth.getDeviceID()) { int subid1 = data[3] & 0xFF; int subid2; switch (subid1) { case 0x08: // MIDI Tuning Standard subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // BULK TUNING DUMP { // http://www.midi.org/about-midi/tuning.shtml SoftTuning tuning = synth.getTuning(new Patch(0, data[5] & 0xFF)); tuning.load(data); break; } case 0x04: // KEY-BASED TUNING DUMP case 0x05: // SCALE/OCTAVE TUNING DUMP, 1 byte format case 0x06: // SCALE/OCTAVE TUNING DUMP, 2 byte format case 0x07: // SINGLE NOTE TUNING CHANGE (NON REAL-TIME) // (BANK) { // http://www.midi.org/about-midi/tuning_extens.shtml SoftTuning tuning = synth.getTuning(new Patch( data[5] & 0xFF, data[6] & 0xFF)); tuning.load(data); break; } case 0x08: // scale/octave tuning 1-byte form (Non // Real-Time) case 0x09: // scale/octave tuning 2-byte form (Non // Real-Time) { // http://www.midi.org/about-midi/tuning-scale.shtml SoftTuning tuning = new SoftTuning(data); int channelmask = (data[5] & 0xFF) * 16384 + (data[6] & 0xFF) * 128 + (data[7] & 0xFF); SoftChannel[] channels = synth.channels; for (int i = 0; i < channels.length; i++) if ((channelmask & (1 << i)) != 0) channels[i].tuning = tuning; break; } default: break; } break; case 0x09: // General Midi Message subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // General Midi 1 On synth.setGeneralMidiMode(1); reset(); break; case 0x02: // General Midi Off synth.setGeneralMidiMode(0); reset(); break; case 0x03: // General MidI Level 2 On synth.setGeneralMidiMode(2); reset(); break; default: break; } break; case 0x0A: // DLS Message subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // DLS On if (synth.getGeneralMidiMode() == 0) synth.setGeneralMidiMode(1); synth.voice_allocation_mode = 1; reset(); break; case 0x02: // DLS Off synth.setGeneralMidiMode(0); synth.voice_allocation_mode = 0; reset(); break; case 0x03: // DLS Static Voice Allocation Off synth.voice_allocation_mode = 0; break; case 0x04: // DLS Static Voice Allocation On synth.voice_allocation_mode = 1; break; default: break; } break; default: break; } } } // Universal Real-Time SysEx if ((data[1] & 0xFF) == 0x7F) { int deviceID = data[2] & 0xFF; if (deviceID == 0x7F || deviceID == synth.getDeviceID()) { int subid1 = data[3] & 0xFF; int subid2; switch (subid1) { case 0x04: // Device Control subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // Master Volume case 0x02: // Master Balane case 0x03: // Master fine tuning case 0x04: // Master coarse tuning int val = (data[5] & 0x7F) + ((data[6] & 0x7F) * 128); if (subid2 == 0x01) setVolume(val); else if (subid2 == 0x02) setBalance(val); else if (subid2 == 0x03) setFineTuning(val); else if (subid2 == 0x04) setCoarseTuning(val); break; case 0x05: // Global Parameter Control int ix = 5; int slotPathLen = (data[ix++] & 0xFF); int paramWidth = (data[ix++] & 0xFF); int valueWidth = (data[ix++] & 0xFF); int[] slotPath = new int[slotPathLen]; for (int i = 0; i < slotPathLen; i++) { int msb = (data[ix++] & 0xFF); int lsb = (data[ix++] & 0xFF); slotPath[i] = msb * 128 + lsb; } int paramCount = (data.length - 1 - ix) / (paramWidth + valueWidth); long[] params = new long[paramCount]; long[] values = new long[paramCount]; for (int i = 0; i < paramCount; i++) { values[i] = 0; for (int j = 0; j < paramWidth; j++) params[i] = params[i] * 128 + (data[ix++] & 0xFF); for (int j = 0; j < valueWidth; j++) values[i] = values[i] * 128 + (data[ix++] & 0xFF); } globalParameterControlChange(slotPath, params, values); break; default: break; } break; case 0x08: // MIDI Tuning Standard subid2 = data[4] & 0xFF; switch (subid2) { case 0x02: // SINGLE NOTE TUNING CHANGE (REAL-TIME) { // http://www.midi.org/about-midi/tuning.shtml SoftTuning tuning = synth.getTuning(new Patch(0, data[5] & 0xFF)); tuning.load(data); SoftVoice[] voices = synth.getVoices(); for (int i = 0; i < voices.length; i++) if (voices[i].active) if (voices[i].tuning == tuning) voices[i].updateTuning(tuning); break; } case 0x07: // SINGLE NOTE TUNING CHANGE (REAL-TIME) // (BANK) { // http://www.midi.org/about-midi/tuning_extens.shtml SoftTuning tuning = synth.getTuning(new Patch( data[5] & 0xFF, data[6] & 0xFF)); tuning.load(data); SoftVoice[] voices = synth.getVoices(); for (int i = 0; i < voices.length; i++) if (voices[i].active) if (voices[i].tuning == tuning) voices[i].updateTuning(tuning); break; } case 0x08: // scale/octave tuning 1-byte form //(Real-Time) case 0x09: // scale/octave tuning 2-byte form // (Real-Time) { // http://www.midi.org/about-midi/tuning-scale.shtml SoftTuning tuning = new SoftTuning(data); int channelmask = (data[5] & 0xFF) * 16384 + (data[6] & 0xFF) * 128 + (data[7] & 0xFF); SoftChannel[] channels = synth.channels; for (int i = 0; i < channels.length; i++) if ((channelmask & (1 << i)) != 0) channels[i].tuning = tuning; SoftVoice[] voices = synth.getVoices(); for (int i = 0; i < voices.length; i++) if (voices[i].active) if ((channelmask & (1 << (voices[i].channel))) != 0) voices[i].updateTuning(tuning); break; } default: break; } break; case 0x09: // Control Destination Settings subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // Channel Pressure { int[] destinations = new int[(data.length - 7) / 2]; int[] ranges = new int[(data.length - 7) / 2]; int ix = 0; for (int j = 6; j < data.length - 1; j += 2) { destinations[ix] = data[j] & 0xFF; ranges[ix] = data[j + 1] & 0xFF; ix++; } int channel = data[5] & 0xFF; SoftChannel softchannel = synth.channels[channel]; softchannel.mapChannelPressureToDestination( destinations, ranges); break; } case 0x02: // Poly Pressure { int[] destinations = new int[(data.length - 7) / 2]; int[] ranges = new int[(data.length - 7) / 2]; int ix = 0; for (int j = 6; j < data.length - 1; j += 2) { destinations[ix] = data[j] & 0xFF; ranges[ix] = data[j + 1] & 0xFF; ix++; } int channel = data[5] & 0xFF; SoftChannel softchannel = synth.channels[channel]; softchannel.mapPolyPressureToDestination( destinations, ranges); break; } case 0x03: // Control Change { int[] destinations = new int[(data.length - 7) / 2]; int[] ranges = new int[(data.length - 7) / 2]; int ix = 0; for (int j = 7; j < data.length - 1; j += 2) { destinations[ix] = data[j] & 0xFF; ranges[ix] = data[j + 1] & 0xFF; ix++; } int channel = data[5] & 0xFF; SoftChannel softchannel = synth.channels[channel]; int control = data[6] & 0xFF; softchannel.mapControlToDestination(control, destinations, ranges); break; } default: break; } break; case 0x0A: // Key Based Instrument Control { subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // Basic Message int channel = data[5] & 0xFF; int keynumber = data[6] & 0xFF; SoftChannel softchannel = synth.channels[channel]; for (int j = 7; j < data.length - 1; j += 2) { int controlnumber = data[j] & 0xFF; int controlvalue = data[j + 1] & 0xFF; softchannel.controlChangePerNote(keynumber, controlnumber, controlvalue); } break; default: break; } break; } default: break; } } } } } private void processMessages(long timeStamp) { Iterator<Entry<Long, Object>> iter = midimessages.entrySet().iterator(); while (iter.hasNext()) { Entry<Long, Object> entry = iter.next(); if (entry.getKey() >= (timeStamp + msec_buffer_len)) return; long msec_delay = entry.getKey() - timeStamp; delay_midievent = (int)(msec_delay * (samplerate / 1000000.0) + 0.5); if(delay_midievent > max_delay_midievent) delay_midievent = max_delay_midievent; if(delay_midievent < 0) delay_midievent = 0; processMessage(entry.getValue()); iter.remove(); } delay_midievent = 0; } protected void processAudioBuffers() { if(synth.weakstream != null && synth.weakstream.silent_samples != 0) { sample_pos += synth.weakstream.silent_samples; synth.weakstream.silent_samples = 0; } for (int i = 0; i < buffers.length; i++) { if(i != CHANNEL_DELAY_LEFT && i != CHANNEL_DELAY_RIGHT && i != CHANNEL_DELAY_MONO && i != CHANNEL_DELAY_EFFECT1 && i != CHANNEL_DELAY_EFFECT2) buffers[i].clear(); } if(!buffers[CHANNEL_DELAY_LEFT].isSilent()) { buffers[CHANNEL_LEFT].swap(buffers[CHANNEL_DELAY_LEFT]); } if(!buffers[CHANNEL_DELAY_RIGHT].isSilent()) { buffers[CHANNEL_RIGHT].swap(buffers[CHANNEL_DELAY_RIGHT]); } if(!buffers[CHANNEL_DELAY_MONO].isSilent()) { buffers[CHANNEL_MONO].swap(buffers[CHANNEL_DELAY_MONO]); } if(!buffers[CHANNEL_DELAY_EFFECT1].isSilent()) { buffers[CHANNEL_EFFECT1].swap(buffers[CHANNEL_DELAY_EFFECT1]); } if(!buffers[CHANNEL_DELAY_EFFECT2].isSilent()) { buffers[CHANNEL_EFFECT2].swap(buffers[CHANNEL_DELAY_EFFECT2]); } double volume_left; double volume_right; SoftChannelMixerContainer[] act_registeredMixers; // perform control logic synchronized (control_mutex) { long msec_pos = (long)(sample_pos * (1000000.0 / samplerate)); processMessages(msec_pos); if (active_sensing_on) { // Active Sensing // if no message occurs for max 1000 ms // then do AllSoundOff on all channels if ((msec_pos - msec_last_activity) > 1000000) { active_sensing_on = false; for (SoftChannel c : synth.channels) c.allSoundOff(); } Lines 1–500 of 1145. Load more
/* * Copyright (c) 2007, 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.IOException; import java.io.InputStream; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.TreeMap; import java.util.Map.Entry; import javax.sound.midi.MidiMessage; import javax.sound.midi.Patch; import javax.sound.midi.ShortMessage; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; /** * Software synthesizer main audio mixer. * * @author Karl Helgason */ public class SoftMainMixer { // A private class thats contains a ModelChannelMixer and it's private buffers. // This becomes necessary when we want to have separate delay buffers for each channel mixer. private class SoftChannelMixerContainer { ModelChannelMixer mixer; SoftAudioBuffer[] buffers; } public final static int CHANNEL_LEFT = 0; public final static int CHANNEL_RIGHT = 1; public final static int CHANNEL_MONO = 2; public final static int CHANNEL_DELAY_LEFT = 3; public final static int CHANNEL_DELAY_RIGHT = 4; public final static int CHANNEL_DELAY_MONO = 5; public final static int CHANNEL_EFFECT1 = 6; public final static int CHANNEL_EFFECT2 = 7; public final static int CHANNEL_DELAY_EFFECT1 = 8; public final static int CHANNEL_DELAY_EFFECT2 = 9; public final static int CHANNEL_LEFT_DRY = 10; public final static int CHANNEL_RIGHT_DRY = 11; public final static int CHANNEL_SCRATCH1 = 12; public final static int CHANNEL_SCRATCH2 = 13; protected boolean active_sensing_on = false; private long msec_last_activity = -1; private boolean pusher_silent = false; private int pusher_silent_count = 0; private long sample_pos = 0; protected boolean readfully = true; private Object control_mutex; private SoftSynthesizer synth; private float samplerate = 44100; private int nrofchannels = 2; private SoftVoice[] voicestatus = null; private SoftAudioBuffer[] buffers; private SoftReverb reverb; private SoftAudioProcessor chorus; private SoftAudioProcessor agc; private long msec_buffer_len = 0; private int buffer_len = 0; protected TreeMap<Long, Object> midimessages = new TreeMap<Long, Object>(); private int delay_midievent = 0; private int max_delay_midievent = 0; double last_volume_left = 1.0; double last_volume_right = 1.0; private double[] co_master_balance = new double[1]; private double[] co_master_volume = new double[1]; private double[] co_master_coarse_tuning = new double[1]; private double[] co_master_fine_tuning = new double[1]; private AudioInputStream ais; private Set<SoftChannelMixerContainer> registeredMixers = null; private Set<ModelChannelMixer> stoppedMixers = null; private SoftChannelMixerContainer[] cur_registeredMixers = null; protected SoftControl co_master = new SoftControl() { double[] balance = co_master_balance; double[] volume = co_master_volume; double[] coarse_tuning = co_master_coarse_tuning; double[] fine_tuning = co_master_fine_tuning; public double[] get(int instance, String name) { if (name == null) return null; if (name.equals("balance")) return balance; if (name.equals("volume")) return volume; if (name.equals("coarse_tuning")) return coarse_tuning; if (name.equals("fine_tuning")) return fine_tuning; return null; } }; private void processSystemExclusiveMessage(byte[] data) { synchronized (synth.control_mutex) { activity(); // Universal Non-Real-Time SysEx if ((data[1] & 0xFF) == 0x7E) { int deviceID = data[2] & 0xFF; if (deviceID == 0x7F || deviceID == synth.getDeviceID()) { int subid1 = data[3] & 0xFF; int subid2; switch (subid1) { case 0x08: // MIDI Tuning Standard subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // BULK TUNING DUMP { // http://www.midi.org/about-midi/tuning.shtml SoftTuning tuning = synth.getTuning(new Patch(0, data[5] & 0xFF)); tuning.load(data); break; } case 0x04: // KEY-BASED TUNING DUMP case 0x05: // SCALE/OCTAVE TUNING DUMP, 1 byte format case 0x06: // SCALE/OCTAVE TUNING DUMP, 2 byte format case 0x07: // SINGLE NOTE TUNING CHANGE (NON REAL-TIME) // (BANK) { // http://www.midi.org/about-midi/tuning_extens.shtml SoftTuning tuning = synth.getTuning(new Patch( data[5] & 0xFF, data[6] & 0xFF)); tuning.load(data); break; } case 0x08: // scale/octave tuning 1-byte form (Non // Real-Time) case 0x09: // scale/octave tuning 2-byte form (Non // Real-Time) { // http://www.midi.org/about-midi/tuning-scale.shtml SoftTuning tuning = new SoftTuning(data); int channelmask = (data[5] & 0xFF) * 16384 + (data[6] & 0xFF) * 128 + (data[7] & 0xFF); SoftChannel[] channels = synth.channels; for (int i = 0; i < channels.length; i++) if ((channelmask & (1 << i)) != 0) channels[i].tuning = tuning; break; } default: break; } break; case 0x09: // General Midi Message subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // General Midi 1 On synth.setGeneralMidiMode(1); reset(); break; case 0x02: // General Midi Off synth.setGeneralMidiMode(0); reset(); break; case 0x03: // General MidI Level 2 On synth.setGeneralMidiMode(2); reset(); break; default: break; } break; case 0x0A: // DLS Message subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // DLS On if (synth.getGeneralMidiMode() == 0) synth.setGeneralMidiMode(1); synth.voice_allocation_mode = 1; reset(); break; case 0x02: // DLS Off synth.setGeneralMidiMode(0); synth.voice_allocation_mode = 0; reset(); break; case 0x03: // DLS Static Voice Allocation Off synth.voice_allocation_mode = 0; break; case 0x04: // DLS Static Voice Allocation On synth.voice_allocation_mode = 1; break; default: break; } break; default: break; } } } // Universal Real-Time SysEx if ((data[1] & 0xFF) == 0x7F) { int deviceID = data[2] & 0xFF; if (deviceID == 0x7F || deviceID == synth.getDeviceID()) { int subid1 = data[3] & 0xFF; int subid2; switch (subid1) { case 0x04: // Device Control subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // Master Volume case 0x02: // Master Balane case 0x03: // Master fine tuning case 0x04: // Master coarse tuning int val = (data[5] & 0x7F) + ((data[6] & 0x7F) * 128); if (subid2 == 0x01) setVolume(val); else if (subid2 == 0x02) setBalance(val); else if (subid2 == 0x03) setFineTuning(val); else if (subid2 == 0x04) setCoarseTuning(val); break; case 0x05: // Global Parameter Control int ix = 5; int slotPathLen = (data[ix++] & 0xFF); int paramWidth = (data[ix++] & 0xFF); int valueWidth = (data[ix++] & 0xFF); int[] slotPath = new int[slotPathLen]; for (int i = 0; i < slotPathLen; i++) { int msb = (data[ix++] & 0xFF); int lsb = (data[ix++] & 0xFF); slotPath[i] = msb * 128 + lsb; } int paramCount = (data.length - 1 - ix) / (paramWidth + valueWidth); long[] params = new long[paramCount]; long[] values = new long[paramCount]; for (int i = 0; i < paramCount; i++) { values[i] = 0; for (int j = 0; j < paramWidth; j++) params[i] = params[i] * 128 + (data[ix++] & 0xFF); for (int j = 0; j < valueWidth; j++) values[i] = values[i] * 128 + (data[ix++] & 0xFF); } globalParameterControlChange(slotPath, params, values); break; default: break; } break; case 0x08: // MIDI Tuning Standard subid2 = data[4] & 0xFF; switch (subid2) { case 0x02: // SINGLE NOTE TUNING CHANGE (REAL-TIME) { // http://www.midi.org/about-midi/tuning.shtml SoftTuning tuning = synth.getTuning(new Patch(0, data[5] & 0xFF)); tuning.load(data); SoftVoice[] voices = synth.getVoices(); for (int i = 0; i < voices.length; i++) if (voices[i].active) if (voices[i].tuning == tuning) voices[i].updateTuning(tuning); break; } case 0x07: // SINGLE NOTE TUNING CHANGE (REAL-TIME) // (BANK) { // http://www.midi.org/about-midi/tuning_extens.shtml SoftTuning tuning = synth.getTuning(new Patch( data[5] & 0xFF, data[6] & 0xFF)); tuning.load(data); SoftVoice[] voices = synth.getVoices(); for (int i = 0; i < voices.length; i++) if (voices[i].active) if (voices[i].tuning == tuning) voices[i].updateTuning(tuning); break; } case 0x08: // scale/octave tuning 1-byte form //(Real-Time) case 0x09: // scale/octave tuning 2-byte form // (Real-Time) { // http://www.midi.org/about-midi/tuning-scale.shtml SoftTuning tuning = new SoftTuning(data); int channelmask = (data[5] & 0xFF) * 16384 + (data[6] & 0xFF) * 128 + (data[7] & 0xFF); SoftChannel[] channels = synth.channels; for (int i = 0; i < channels.length; i++) if ((channelmask & (1 << i)) != 0) channels[i].tuning = tuning; SoftVoice[] voices = synth.getVoices(); for (int i = 0; i < voices.length; i++) if (voices[i].active) if ((channelmask & (1 << (voices[i].channel))) != 0) voices[i].updateTuning(tuning); break; } default: break; } break; case 0x09: // Control Destination Settings subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // Channel Pressure { int[] destinations = new int[(data.length - 7) / 2]; int[] ranges = new int[(data.length - 7) / 2]; int ix = 0; for (int j = 6; j < data.length - 1; j += 2) { destinations[ix] = data[j] & 0xFF; ranges[ix] = data[j + 1] & 0xFF; ix++; } int channel = data[5] & 0xFF; SoftChannel softchannel = synth.channels[channel]; softchannel.mapChannelPressureToDestination( destinations, ranges); break; } case 0x02: // Poly Pressure { int[] destinations = new int[(data.length - 7) / 2]; int[] ranges = new int[(data.length - 7) / 2]; int ix = 0; for (int j = 6; j < data.length - 1; j += 2) { destinations[ix] = data[j] & 0xFF; ranges[ix] = data[j + 1] & 0xFF; ix++; } int channel = data[5] & 0xFF; SoftChannel softchannel = synth.channels[channel]; softchannel.mapPolyPressureToDestination( destinations, ranges); break; } case 0x03: // Control Change { int[] destinations = new int[(data.length - 7) / 2]; int[] ranges = new int[(data.length - 7) / 2]; int ix = 0; for (int j = 7; j < data.length - 1; j += 2) { destinations[ix] = data[j] & 0xFF; ranges[ix] = data[j + 1] & 0xFF; ix++; } int channel = data[5] & 0xFF; SoftChannel softchannel = synth.channels[channel]; int control = data[6] & 0xFF; softchannel.mapControlToDestination(control, destinations, ranges); break; } default: break; } break; case 0x0A: // Key Based Instrument Control { subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // Basic Message int channel = data[5] & 0xFF; int keynumber = data[6] & 0xFF; SoftChannel softchannel = synth.channels[channel]; for (int j = 7; j < data.length - 1; j += 2) { int controlnumber = data[j] & 0xFF; int controlvalue = data[j + 1] & 0xFF; softchannel.controlChangePerNote(keynumber, controlnumber, controlvalue); } break; default: break; } break; } default: break; } } } } } private void processMessages(long timeStamp) { Iterator<Entry<Long, Object>> iter = midimessages.entrySet().iterator(); while (iter.hasNext()) { Entry<Long, Object> entry = iter.next(); if (entry.getKey() >= (timeStamp + msec_buffer_len)) return; long msec_delay = entry.getKey() - timeStamp; delay_midievent = (int)(msec_delay * (samplerate / 1000000.0) + 0.5); if(delay_midievent > max_delay_midievent) delay_midievent = max_delay_midievent; if(delay_midievent < 0) delay_midievent = 0; processMessage(entry.getValue()); iter.remove(); } delay_midievent = 0; } protected void processAudioBuffers() { if(synth.weakstream != null && synth.weakstream.silent_samples != 0) { sample_pos += synth.weakstream.silent_samples; synth.weakstream.silent_samples = 0; } for (int i = 0; i < buffers.length; i++) { if(i != CHANNEL_DELAY_LEFT && i != CHANNEL_DELAY_RIGHT && i != CHANNEL_DELAY_MONO && i != CHANNEL_DELAY_EFFECT1 && i != CHANNEL_DELAY_EFFECT2) buffers[i].clear(); } if(!buffers[CHANNEL_DELAY_LEFT].isSilent()) { buffers[CHANNEL_LEFT].swap(buffers[CHANNEL_DELAY_LEFT]); } if(!buffers[CHANNEL_DELAY_RIGHT].isSilent()) { buffers[CHANNEL_RIGHT].swap(buffers[CHANNEL_DELAY_RIGHT]); } if(!buffers[CHANNEL_DELAY_MONO].isSilent()) { buffers[CHANNEL_MONO].swap(buffers[CHANNEL_DELAY_MONO]); } if(!buffers[CHANNEL_DELAY_EFFECT1].isSilent()) { buffers[CHANNEL_EFFECT1].swap(buffers[CHANNEL_DELAY_EFFECT1]); } if(!buffers[CHANNEL_DELAY_EFFECT2].isSilent()) { buffers[CHANNEL_EFFECT2].swap(buffers[CHANNEL_DELAY_EFFECT2]); } double volume_left; double volume_right; SoftChannelMixerContainer[] act_registeredMixers; // perform control logic synchronized (control_mutex) { long msec_pos = (long)(sample_pos * (1000000.0 / samplerate)); processMessages(msec_pos); if (active_sensing_on) { // Active Sensing // if no message occurs for max 1000 ms // then do AllSoundOff on all channels if ((msec_pos - msec_last_activity) > 1000000) { active_sensing_on = false; for (SoftChannel c : synth.channels) c.allSoundOff(); }