1/*
2 * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.media.sound;
27
28import java.io.IOException;
29import java.io.InputStream;
30import java.util.HashSet;
31import java.util.Iterator;
32import java.util.Map.Entry;
33import java.util.Set;
34import java.util.TreeMap;
35
36import javax.sound.midi.MidiMessage;
37import javax.sound.midi.Patch;
38import javax.sound.midi.ShortMessage;
39import javax.sound.sampled.AudioInputStream;
40import javax.sound.sampled.AudioSystem;
41
42/**
43 * Software synthesizer main audio mixer.
44 *
45 * @author Karl Helgason
46 */
47public final class SoftMainMixer {
48
49    // A private class thats contains a ModelChannelMixer and it's private buffers.
50    // This becomes necessary when we want to have separate delay buffers for each channel mixer.
51    private class SoftChannelMixerContainer
52    {
53        ModelChannelMixer mixer;
54        SoftAudioBuffer[] buffers;
55    }
56
57    public static final int CHANNEL_LEFT = 0;
58    public static final int CHANNEL_RIGHT = 1;
59    public static final int CHANNEL_MONO = 2;
60    public static final int CHANNEL_DELAY_LEFT = 3;
61    public static final int CHANNEL_DELAY_RIGHT = 4;
62    public static final int CHANNEL_DELAY_MONO = 5;
63    public static final int CHANNEL_EFFECT1 = 6;
64    public static final int CHANNEL_EFFECT2 = 7;
65    public static final int CHANNEL_DELAY_EFFECT1 = 8;
66    public static final int CHANNEL_DELAY_EFFECT2 = 9;
67    public static final int CHANNEL_LEFT_DRY = 10;
68    public static final int CHANNEL_RIGHT_DRY = 11;
69    public static final int CHANNEL_SCRATCH1 = 12;
70    public static final int CHANNEL_SCRATCH2 = 13;
71    boolean active_sensing_on = false;
72    private long msec_last_activity = -1;
73    private boolean pusher_silent = false;
74    private int pusher_silent_count = 0;
75    private long sample_pos = 0;
76    boolean readfully = true;
77    private final Object control_mutex;
78    private final SoftSynthesizer synth;
79    private float samplerate = 44100;
80    private int nrofchannels = 2;
81    private SoftVoice[] voicestatus = null;
82    private final SoftAudioBuffer[] buffers;
83    private final SoftReverb reverb;
84    private final SoftAudioProcessor chorus;
85    private final SoftAudioProcessor agc;
86    private long msec_buffer_len = 0;
87    private int buffer_len = 0;
88    TreeMap<Long, Object> midimessages = new TreeMap<>();
89    private int delay_midievent = 0;
90    private int max_delay_midievent = 0;
91    double last_volume_left = 1.0;
92    double last_volume_right = 1.0;
93    private final double[] co_master_balance = new double[1];
94    private final double[] co_master_volume = new double[1];
95    private final double[] co_master_coarse_tuning = new double[1];
96    private final double[] co_master_fine_tuning = new double[1];
97    private final AudioInputStream ais;
98    private Set<SoftChannelMixerContainer> registeredMixers = null;
99    private Set<ModelChannelMixer> stoppedMixers = null;
100    private SoftChannelMixerContainer[] cur_registeredMixers = null;
101    SoftControl co_master = new SoftControl() {
102
103        double[] balance = co_master_balance;
104        double[] volume = co_master_volume;
105        double[] coarse_tuning = co_master_coarse_tuning;
106        double[] fine_tuning = co_master_fine_tuning;
107
108        @Override
109        public double[] get(int instance, String name) {
110            if (name == null)
111                return null;
112            if (name.equals("balance"))
113                return balance;
114            if (name.equals("volume"))
115                return volume;
116            if (name.equals("coarse_tuning"))
117                return coarse_tuning;
118            if (name.equals("fine_tuning"))
119                return fine_tuning;
120            return null;
121        }
122    };
123
124    private void processSystemExclusiveMessage(byte[] data) {
125        synchronized (synth.control_mutex) {
126            activity();
127
128            // Universal Non-Real-Time SysEx
129            if ((data[1] & 0xFF) == 0x7E) {
130                int deviceID = data[2] & 0xFF;
131                if (deviceID == 0x7F || deviceID == synth.getDeviceID()) {
132                    int subid1 = data[3] & 0xFF;
133                    int subid2;
134                    switch (subid1) {
135                    case 0x08:  // MIDI Tuning Standard
136                        subid2 = data[4] & 0xFF;
137                        switch (subid2) {
138                        case 0x01:  // BULK TUNING DUMP
139                        {
140                            // http://www.midi.org/about-midi/tuning.shtml
141                            SoftTuning tuning = synth.getTuning(new Patch(0,
142                                    data[5] & 0xFF));
143                            tuning.load(data);
144                            break;
145                        }
146                        case 0x04:  // KEY-BASED TUNING DUMP
147                        case 0x05:  // SCALE/OCTAVE TUNING DUMP, 1 byte format
148                        case 0x06:  // SCALE/OCTAVE TUNING DUMP, 2 byte format
149                        case 0x07:  // SINGLE NOTE TUNING CHANGE (NON REAL-TIME)
150                                    // (BANK)
151                        {
152                            // http://www.midi.org/about-midi/tuning_extens.shtml
153                            SoftTuning tuning = synth.getTuning(new Patch(
154                                    data[5] & 0xFF, data[6] & 0xFF));
155                            tuning.load(data);
156                            break;
157                        }
158                        case 0x08:  // scale/octave tuning 1-byte form (Non
159                                    // Real-Time)
160                        case 0x09:  // scale/octave tuning 2-byte form (Non
161                                    // Real-Time)
162                        {
163                            // http://www.midi.org/about-midi/tuning-scale.shtml
164                            SoftTuning tuning = new SoftTuning(data);
165                            int channelmask = (data[5] & 0xFF) * 16384
166                                    + (data[6] & 0xFF) * 128 + (data[7] & 0xFF);
167                            SoftChannel[] channels = synth.channels;
168                            for (int i = 0; i < channels.length; i++)
169                                if ((channelmask & (1 << i)) != 0)
170                                    channels[i].tuning = tuning;
171                            break;
172                        }
173                        default:
174                            break;
175                        }
176                        break;
177                    case 0x09:  // General Midi Message
178                        subid2 = data[4] & 0xFF;
179                        switch (subid2) {
180                        case 0x01:  // General Midi 1 On
181                            synth.setGeneralMidiMode(1);
182                            reset();
183                            break;
184                        case 0x02:  // General Midi Off
185                            synth.setGeneralMidiMode(0);
186                            reset();
187                            break;
188                        case 0x03:  // General MidI Level 2 On
189                            synth.setGeneralMidiMode(2);
190                            reset();
191                            break;
192                        default:
193                            break;
194                        }
195                        break;
196                    case 0x0A: // DLS Message
197                        subid2 = data[4] & 0xFF;
198                        switch (subid2) {
199                        case 0x01:  // DLS On
200                            if (synth.getGeneralMidiMode() == 0)
201                                synth.setGeneralMidiMode(1);
202                            synth.voice_allocation_mode = 1;
203                            reset();
204                            break;
205                        case 0x02:  // DLS Off
206                            synth.setGeneralMidiMode(0);
207                            synth.voice_allocation_mode = 0;
208                            reset();
209                            break;
210                        case 0x03:  // DLS Static Voice Allocation Off
211                            synth.voice_allocation_mode = 0;
212                            break;
213                        case 0x04:  // DLS Static Voice Allocation On
214                            synth.voice_allocation_mode = 1;
215                            break;
216                        default:
217                            break;
218                        }
219                        break;
220
221                    default:
222                        break;
223                    }
224                }
225            }
226
227            // Universal Real-Time SysEx
228            if ((data[1] & 0xFF) == 0x7F) {
229                int deviceID = data[2] & 0xFF;
230                if (deviceID == 0x7F || deviceID == synth.getDeviceID()) {
231                    int subid1 = data[3] & 0xFF;
232                    int subid2;
233                    switch (subid1) {
234                    case 0x04: // Device Control
235
236                        subid2 = data[4] & 0xFF;
237                        switch (subid2) {
238                        case 0x01: // Master Volume
239                        case 0x02: // Master Balane
240                        case 0x03: // Master fine tuning
241                        case 0x04: // Master coarse tuning
242                            int val = (data[5] & 0x7F)
243                                    + ((data[6] & 0x7F) * 128);
244                            if (subid2 == 0x01)
245                                setVolume(val);
246                            else if (subid2 == 0x02)
247                                setBalance(val);
248                            else if (subid2 == 0x03)
249                                setFineTuning(val);
250                            else if (subid2 == 0x04)
251                                setCoarseTuning(val);
252                            break;
253                        case 0x05: // Global Parameter Control
254                            int ix = 5;
255                            int slotPathLen = (data[ix++] & 0xFF);
256                            int paramWidth = (data[ix++] & 0xFF);
257                            int valueWidth = (data[ix++] & 0xFF);
258                            int[] slotPath = new int[slotPathLen];
259                            for (int i = 0; i < slotPathLen; i++) {
260                                int msb = (data[ix++] & 0xFF);
261                                int lsb = (data[ix++] & 0xFF);
262                                slotPath[i] = msb * 128 + lsb;
263                            }
264                            int paramCount = (data.length - 1 - ix)
265                                    / (paramWidth + valueWidth);
266                            long[] params = new long[paramCount];
267                            long[] values = new long[paramCount];
268                            for (int i = 0; i < paramCount; i++) {
269                                values[i] = 0;
270                                for (int j = 0; j < paramWidth; j++)
271                                    params[i] = params[i] * 128
272                                            + (data[ix++] & 0xFF);
273                                for (int j = 0; j < valueWidth; j++)
274                                    values[i] = values[i] * 128
275                                            + (data[ix++] & 0xFF);
276
277                            }
278                            globalParameterControlChange(slotPath, params, values);
279                            break;
280                        default:
281                            break;
282                        }
283                        break;
284
285                    case 0x08:  // MIDI Tuning Standard
286                        subid2 = data[4] & 0xFF;
287                        switch (subid2) {
288                        case 0x02:  // SINGLE NOTE TUNING CHANGE (REAL-TIME)
289                        {
290                            // http://www.midi.org/about-midi/tuning.shtml
291                            SoftTuning tuning = synth.getTuning(new Patch(0,
292                                    data[5] & 0xFF));
293                            tuning.load(data);
294                            SoftVoice[] voices = synth.getVoices();
295                            for (int i = 0; i < voices.length; i++)
296                                if (voices[i].active)
297                                    if (voices[i].tuning == tuning)
298                                        voices[i].updateTuning(tuning);
299                            break;
300                        }
301                        case 0x07:  // SINGLE NOTE TUNING CHANGE (REAL-TIME)
302                                    // (BANK)
303                        {
304                            // http://www.midi.org/about-midi/tuning_extens.shtml
305                            SoftTuning tuning = synth.getTuning(new Patch(
306                                    data[5] & 0xFF, data[6] & 0xFF));
307                            tuning.load(data);
308                            SoftVoice[] voices = synth.getVoices();
309                            for (int i = 0; i < voices.length; i++)
310                                if (voices[i].active)
311                                    if (voices[i].tuning == tuning)
312                                        voices[i].updateTuning(tuning);
313                            break;
314                        }
315                        case 0x08:  // scale/octave tuning 1-byte form
316                                    //(Real-Time)
317                        case 0x09:  // scale/octave tuning 2-byte form
318                                    // (Real-Time)
319                        {
320                            // http://www.midi.org/about-midi/tuning-scale.shtml
321                            SoftTuning tuning = new SoftTuning(data);
322                            int channelmask = (data[5] & 0xFF) * 16384
323                                    + (data[6] & 0xFF) * 128 + (data[7] & 0xFF);
324                            SoftChannel[] channels = synth.channels;
325                            for (int i = 0; i < channels.length; i++)
326                                if ((channelmask & (1 << i)) != 0)
327                                    channels[i].tuning = tuning;
328                            SoftVoice[] voices = synth.getVoices();
329                            for (int i = 0; i < voices.length; i++)
330                                if (voices[i].active)
331                                    if ((channelmask & (1 << (voices[i].channel))) != 0)
332                                        voices[i].updateTuning(tuning);
333                            break;
334                        }
335                        default:
336                            break;
337                        }
338                        break;
339                    case 0x09:  // Control Destination Settings
340                        subid2 = data[4] & 0xFF;
341                        switch (subid2) {
342                        case 0x01: // Channel Pressure
343                        {
344                            int[] destinations = new int[(data.length - 7) / 2];
345                            int[] ranges = new int[(data.length - 7) / 2];
346                            int ix = 0;
347                            for (int j = 6; j < data.length - 1; j += 2) {
348                                destinations[ix] = data[j] & 0xFF;
349                                ranges[ix] = data[j + 1] & 0xFF;
350                                ix++;
351                            }
352                            int channel = data[5] & 0xFF;
353                            SoftChannel softchannel = synth.channels[channel];
354                            softchannel.mapChannelPressureToDestination(
355                                    destinations, ranges);
356                            break;
357                        }
358                        case 0x02: // Poly Pressure
359                        {
360                            int[] destinations = new int[(data.length - 7) / 2];
361                            int[] ranges = new int[(data.length - 7) / 2];
362                            int ix = 0;
363                            for (int j = 6; j < data.length - 1; j += 2) {
364                                destinations[ix] = data[j] & 0xFF;
365                                ranges[ix] = data[j + 1] & 0xFF;
366                                ix++;
367                            }
368                            int channel = data[5] & 0xFF;
369                            SoftChannel softchannel = synth.channels[channel];
370                            softchannel.mapPolyPressureToDestination(
371                                    destinations, ranges);
372                            break;
373                        }
374                        case 0x03: // Control Change
375                        {
376                            int[] destinations = new int[(data.length - 7) / 2];
377                            int[] ranges = new int[(data.length - 7) / 2];
378                            int ix = 0;
379                            for (int j = 7; j < data.length - 1; j += 2) {
380                                destinations[ix] = data[j] & 0xFF;
381                                ranges[ix] = data[j + 1] & 0xFF;
382                                ix++;
383                            }
384                            int channel = data[5] & 0xFF;
385                            SoftChannel softchannel = synth.channels[channel];
386                            int control = data[6] & 0xFF;
387                            softchannel.mapControlToDestination(control,
388                                    destinations, ranges);
389                            break;
390                        }
391                        default:
392                            break;
393                        }
394                        break;
395
396                    case 0x0A:  // Key Based Instrument Control
397                    {
398                        subid2 = data[4] & 0xFF;
399                        switch (subid2) {
400                        case 0x01: // Basic Message
401                            int channel = data[5] & 0xFF;
402                            int keynumber = data[6] & 0xFF;
403                            SoftChannel softchannel = synth.channels[channel];
404                            for (int j = 7; j < data.length - 1; j += 2) {
405                                int controlnumber = data[j] & 0xFF;
406                                int controlvalue = data[j + 1] & 0xFF;
407                                softchannel.controlChangePerNote(keynumber,
408                                        controlnumber, controlvalue);
409                            }
410                            break;
411                        default:
412                            break;
413                        }
414                        break;
415                    }
416                    default:
417                        break;
418                    }
419                }
420            }
421
422        }
423    }
424
425    private void processMessages(long timeStamp) {
426        Iterator<Entry<Long, Object>> iter = midimessages.entrySet().iterator();
427        while (iter.hasNext()) {
428            Entry<Long, Object> entry = iter.next();
429            if (entry.getKey() >= (timeStamp + msec_buffer_len))
430                return;
431            long msec_delay = entry.getKey() - timeStamp;
432            delay_midievent = (int)(msec_delay * (samplerate / 1000000.0) + 0.5);
433            if(delay_midievent > max_delay_midievent)
434                delay_midievent = max_delay_midievent;
435            if(delay_midievent < 0)
436                delay_midievent = 0;
437            processMessage(entry.getValue());
438            iter.remove();
439        }
440        delay_midievent = 0;
441    }
442
443    void processAudioBuffers() {
444
445        if(synth.weakstream != null && synth.weakstream.silent_samples != 0)
446        {
447            sample_pos += synth.weakstream.silent_samples;
448            synth.weakstream.silent_samples = 0;
449        }
450
451        for (int i = 0; i < buffers.length; i++) {
452            if(i != CHANNEL_DELAY_LEFT &&
453                    i != CHANNEL_DELAY_RIGHT &&
454                    i != CHANNEL_DELAY_MONO &&
455                    i != CHANNEL_DELAY_EFFECT1 &&
456                    i != CHANNEL_DELAY_EFFECT2)
457                buffers[i].clear();
458        }
459
460        if(!buffers[CHANNEL_DELAY_LEFT].isSilent())
461        {
462            buffers[CHANNEL_LEFT].swap(buffers[CHANNEL_DELAY_LEFT]);
463        }
464        if(!buffers[CHANNEL_DELAY_RIGHT].isSilent())
465        {
466            buffers[CHANNEL_RIGHT].swap(buffers[CHANNEL_DELAY_RIGHT]);
467        }
468        if(!buffers[CHANNEL_DELAY_MONO].isSilent())
469        {
470            buffers[CHANNEL_MONO].swap(buffers[CHANNEL_DELAY_MONO]);
471        }
472        if(!buffers[CHANNEL_DELAY_EFFECT1].isSilent())
473        {
474            buffers[CHANNEL_EFFECT1].swap(buffers[CHANNEL_DELAY_EFFECT1]);
475        }
476        if(!buffers[CHANNEL_DELAY_EFFECT2].isSilent())
477        {
478            buffers[CHANNEL_EFFECT2].swap(buffers[CHANNEL_DELAY_EFFECT2]);
479        }
480
481        double volume_left;
482        double volume_right;
483
484        SoftChannelMixerContainer[] act_registeredMixers;
485
486        // perform control logic
487        synchronized (control_mutex) {
488
489            long msec_pos = (long)(sample_pos * (1000000.0 / samplerate));
490
491            processMessages(msec_pos);
492
493            if (active_sensing_on) {
494                // Active Sensing
495                // if no message occurs for max 1000 ms
496                // then do AllSoundOff on all channels
497                if ((msec_pos - msec_last_activity) > 1000000) {
498                    active_sensing_on = false;
499                    for (SoftChannel c : synth.channels)
500                        c.allSoundOff();
501                }
502
503            }
504
505            for (int i = 0; i < voicestatus.length; i++)
506                if (voicestatus[i].active)
507                    voicestatus[i].processControlLogic();
508            sample_pos += buffer_len;
509
510            double volume = co_master_volume[0];
511            volume_left = volume;
512            volume_right = volume;
513
514            double balance = co_master_balance[0];
515            if (balance > 0.5)
516                volume_left *= (1 - balance) * 2;
517            else
518                volume_right *= balance * 2;
519
520            chorus.processControlLogic();
521            reverb.processControlLogic();
522            agc.processControlLogic();
523
524            if (cur_registeredMixers == null) {
525                if (registeredMixers != null) {
526                    cur_registeredMixers =
527                            new SoftChannelMixerContainer[registeredMixers.size()];
528                    registeredMixers.toArray(cur_registeredMixers);
529                }
530            }
531
532            act_registeredMixers = cur_registeredMixers;
533            if (act_registeredMixers != null)
534                if (act_registeredMixers.length == 0)
535                    act_registeredMixers = null;
536
537        }
538
539        if (act_registeredMixers != null) {
540
541            // Make backup of left,right,mono channels
542            SoftAudioBuffer leftbak = buffers[CHANNEL_LEFT];
543            SoftAudioBuffer rightbak = buffers[CHANNEL_RIGHT];
544            SoftAudioBuffer monobak = buffers[CHANNEL_MONO];
545            SoftAudioBuffer delayleftbak = buffers[CHANNEL_DELAY_LEFT];
546            SoftAudioBuffer delayrightbak = buffers[CHANNEL_DELAY_RIGHT];
547            SoftAudioBuffer delaymonobak = buffers[CHANNEL_DELAY_MONO];
548
549            int bufferlen = buffers[CHANNEL_LEFT].getSize();
550
551            float[][] cbuffer = new float[nrofchannels][];
552            float[][] obuffer = new float[nrofchannels][];
553            obuffer[0] = leftbak.array();
554            if (nrofchannels != 1)
555                obuffer[1] = rightbak.array();
556
557            for (SoftChannelMixerContainer cmixer : act_registeredMixers) {
558
559                // Reroute default left,right output
560                // to channelmixer left,right input/output
561                buffers[CHANNEL_LEFT] =  cmixer.buffers[CHANNEL_LEFT];
562                buffers[CHANNEL_RIGHT] = cmixer.buffers[CHANNEL_RIGHT];
563                buffers[CHANNEL_MONO] = cmixer.buffers[CHANNEL_MONO];
564                buffers[CHANNEL_DELAY_LEFT] = cmixer.buffers[CHANNEL_DELAY_LEFT];
565                buffers[CHANNEL_DELAY_RIGHT] = cmixer.buffers[CHANNEL_DELAY_RIGHT];
566                buffers[CHANNEL_DELAY_MONO] = cmixer.buffers[CHANNEL_DELAY_MONO];
567
568                buffers[CHANNEL_LEFT].clear();
569                buffers[CHANNEL_RIGHT].clear();
570                buffers[CHANNEL_MONO].clear();
571
572                if(!buffers[CHANNEL_DELAY_LEFT].isSilent())
573                {
574                    buffers[CHANNEL_LEFT].swap(buffers[CHANNEL_DELAY_LEFT]);
575                }
576                if(!buffers[CHANNEL_DELAY_RIGHT].isSilent())
577                {
578                    buffers[CHANNEL_RIGHT].swap(buffers[CHANNEL_DELAY_RIGHT]);
579                }
580                if(!buffers[CHANNEL_DELAY_MONO].isSilent())
581                {
582                    buffers[CHANNEL_MONO].swap(buffers[CHANNEL_DELAY_MONO]);
583                }
584
585                cbuffer[0] = buffers[CHANNEL_LEFT].array();
586                if (nrofchannels != 1)
587                    cbuffer[1] = buffers[CHANNEL_RIGHT].array();
588
589                boolean hasactivevoices = false;
590                for (int i = 0; i < voicestatus.length; i++)
591                    if (voicestatus[i].active)
592                        if (voicestatus[i].channelmixer == cmixer.mixer) {
593                            voicestatus[i].processAudioLogic(buffers);
594                            hasactivevoices = true;
595                        }
596
597                if(!buffers[CHANNEL_MONO].isSilent())
598                {
599                    float[] mono = buffers[CHANNEL_MONO].array();
600                    float[] left = buffers[CHANNEL_LEFT].array();
601                    if (nrofchannels != 1) {
602                        float[] right = buffers[CHANNEL_RIGHT].array();
603                        for (int i = 0; i < bufferlen; i++) {
604                            float v = mono[i];
605                            left[i] += v;
606                            right[i] += v;
607                        }
608                    }
609                    else
610                    {
611                        for (int i = 0; i < bufferlen; i++) {
612                            left[i] += mono[i];
613                        }
614                    }
615                }
616
617                if (!cmixer.mixer.process(cbuffer, 0, bufferlen)) {
618                    synchronized (control_mutex) {
619                        registeredMixers.remove(cmixer);
620                        cur_registeredMixers = null;
621                    }
622                }
623
624                for (int i = 0; i < cbuffer.length; i++) {
625                    float[] cbuff = cbuffer[i];
626                    float[] obuff = obuffer[i];
627                    for (int j = 0; j < bufferlen; j++)
628                        obuff[j] += cbuff[j];
629                }
630
631                if (!hasactivevoices) {
632                    synchronized (control_mutex) {
633                        if (stoppedMixers != null) {
634                            if (stoppedMixers.contains(cmixer)) {
635                                stoppedMixers.remove(cmixer);
636                                cmixer.mixer.stop();
637                            }
638                        }
639                    }
640                }
641
642            }
643
644            buffers[CHANNEL_LEFT] = leftbak;
645            buffers[CHANNEL_RIGHT] = rightbak;
646            buffers[CHANNEL_MONO] = monobak;
647            buffers[CHANNEL_DELAY_LEFT] = delayleftbak;
648            buffers[CHANNEL_DELAY_RIGHT] = delayrightbak;
649            buffers[CHANNEL_DELAY_MONO] = delaymonobak;
650
651        }
652
653        for (int i = 0; i < voicestatus.length; i++)
654            if (voicestatus[i].active)
655                if (voicestatus[i].channelmixer == null)
656                    voicestatus[i].processAudioLogic(buffers);
657
658        if(!buffers[CHANNEL_MONO].isSilent())
659        {
660            float[] mono = buffers[CHANNEL_MONO].array();
661            float[] left = buffers[CHANNEL_LEFT].array();
662            int bufferlen = buffers[CHANNEL_LEFT].getSize();
663            if (nrofchannels != 1) {
664                float[] right = buffers[CHANNEL_RIGHT].array();
665                for (int i = 0; i < bufferlen; i++) {
666                    float v = mono[i];
667                    left[i] += v;
668                    right[i] += v;
669                }
670            }
671            else
672            {
673                for (int i = 0; i < bufferlen; i++) {
674                    left[i] += mono[i];
675                }
676            }
677        }
678
679        // Run effects
680        if (synth.chorus_on)
681            chorus.processAudio();
682
683        if (synth.reverb_on)
684            reverb.processAudio();
685
686        if (nrofchannels == 1)
687            volume_left = (volume_left + volume_right) / 2;
688
689        // Set Volume / Balance
690        if (last_volume_left != volume_left || last_volume_right != volume_right) {
691            float[] left = buffers[CHANNEL_LEFT].array();
692            float[] right = buffers[CHANNEL_RIGHT].array();
693            int bufferlen = buffers[CHANNEL_LEFT].getSize();
694
695            float amp;
696            float amp_delta;
697            amp = (float)(last_volume_left * last_volume_left);
698            amp_delta = (float)((volume_left * volume_left - amp) / bufferlen);
699            for (int i = 0; i < bufferlen; i++) {
700                amp += amp_delta;
701                left[i] *= amp;
702            }
703            if (nrofchannels != 1) {
704                amp = (float)(last_volume_right * last_volume_right);
705                amp_delta = (float)((volume_right*volume_right - amp) / bufferlen);
706                for (int i = 0; i < bufferlen; i++) {
707                    amp += amp_delta;
708                    right[i] *= volume_right;
709                }
710            }
711            last_volume_left = volume_left;
712            last_volume_right = volume_right;
713
714        } else {
715            if (volume_left != 1.0 || volume_right != 1.0) {
716                float[] left = buffers[CHANNEL_LEFT].array();
717                float[] right = buffers[CHANNEL_RIGHT].array();
718                int bufferlen = buffers[CHANNEL_LEFT].getSize();
719                float amp;
720                amp = (float) (volume_left * volume_left);
721                for (int i = 0; i < bufferlen; i++)
722                    left[i] *= amp;
723                if (nrofchannels != 1) {
724                    amp = (float)(volume_right * volume_right);
725                    for (int i = 0; i < bufferlen; i++)
726                        right[i] *= amp;
727                }
728
729            }
730        }
731
732        if(buffers[CHANNEL_LEFT].isSilent()
733            && buffers[CHANNEL_RIGHT].isSilent())
734        {
735
736            int midimessages_size;
737            synchronized (control_mutex) {
738                midimessages_size = midimessages.size();
739            }
740
741            if(midimessages_size == 0)
742            {
743                pusher_silent_count++;
744                if(pusher_silent_count > 5)
745                {
746                    pusher_silent_count = 0;
747                    synchronized (control_mutex) {
748                        pusher_silent = true;
749                        if(synth.weakstream != null)
750                            synth.weakstream.setInputStream(null);
751                    }
752                }
753            }
754        }
755        else
756            pusher_silent_count = 0;
757
758        if (synth.agc_on)
759            agc.processAudio();
760
761    }
762
763    // Must only we called within control_mutex synchronization
764    public void activity()
765    {
766        long silent_samples = 0;
767        if(pusher_silent)
768        {
769            pusher_silent = false;
770            if(synth.weakstream != null)
771            {
772                synth.weakstream.setInputStream(ais);
773                silent_samples = synth.weakstream.silent_samples;
774            }
775        }
776        msec_last_activity = (long)((sample_pos + silent_samples)
777                * (1000000.0 / samplerate));
778    }
779
780    public void stopMixer(ModelChannelMixer mixer) {
781        if (stoppedMixers == null)
782            stoppedMixers = new HashSet<>();
783        stoppedMixers.add(mixer);
784    }
785
786    public void registerMixer(ModelChannelMixer mixer) {
787        if (registeredMixers == null)
788            registeredMixers = new HashSet<>();
789        SoftChannelMixerContainer mixercontainer = new SoftChannelMixerContainer();
790        mixercontainer.buffers = new SoftAudioBuffer[6];
791        for (int i = 0; i < mixercontainer.buffers.length; i++) {
792            mixercontainer.buffers[i] =
793                new SoftAudioBuffer(buffer_len, synth.getFormat());
794        }
795        mixercontainer.mixer = mixer;
796        registeredMixers.add(mixercontainer);
797        cur_registeredMixers = null;
798    }
799
800    public SoftMainMixer(SoftSynthesizer synth) {
801        this.synth = synth;
802
803        sample_pos = 0;
804
805        co_master_balance[0] = 0.5;
806        co_master_volume[0] = 1;
807        co_master_coarse_tuning[0] = 0.5;
808        co_master_fine_tuning[0] = 0.5;
809
810        msec_buffer_len = (long) (1000000.0 / synth.getControlRate());
811        samplerate = synth.getFormat().getSampleRate();
812        nrofchannels = synth.getFormat().getChannels();
813
814        int buffersize = (int) (synth.getFormat().getSampleRate()
815                                / synth.getControlRate());
816
817        buffer_len = buffersize;
818
819        max_delay_midievent = buffersize;
820
821        control_mutex = synth.control_mutex;
822        buffers = new SoftAudioBuffer[14];
823        for (int i = 0; i < buffers.length; i++) {
824            buffers[i] = new SoftAudioBuffer(buffersize, synth.getFormat());
825        }
826        voicestatus = synth.getVoices();
827
828        reverb = new SoftReverb();
829        chorus = new SoftChorus();
830        agc = new SoftLimiter();
831
832        float samplerate = synth.getFormat().getSampleRate();
833        float controlrate = synth.getControlRate();
834        reverb.init(samplerate, controlrate);
835        chorus.init(samplerate, controlrate);
836        agc.init(samplerate, controlrate);
837
838        reverb.setLightMode(synth.reverb_light);
839
840        reverb.setMixMode(true);
841        chorus.setMixMode(true);
842        agc.setMixMode(false);
843
844        chorus.setInput(0, buffers[CHANNEL_EFFECT2]);
845        chorus.setOutput(0, buffers[CHANNEL_LEFT]);
846        if (nrofchannels != 1)
847            chorus.setOutput(1, buffers[CHANNEL_RIGHT]);
848        chorus.setOutput(2, buffers[CHANNEL_EFFECT1]);
849
850        reverb.setInput(0, buffers[CHANNEL_EFFECT1]);
851        reverb.setOutput(0, buffers[CHANNEL_LEFT]);
852        if (nrofchannels != 1)
853            reverb.setOutput(1, buffers[CHANNEL_RIGHT]);
854
855        agc.setInput(0, buffers[CHANNEL_LEFT]);
856        if (nrofchannels != 1)
857            agc.setInput(1, buffers[CHANNEL_RIGHT]);
858        agc.setOutput(0, buffers[CHANNEL_LEFT]);
859        if (nrofchannels != 1)
860            agc.setOutput(1, buffers[CHANNEL_RIGHT]);
861
862        InputStream in = new InputStream() {
863
864            private final SoftAudioBuffer[] buffers = SoftMainMixer.this.buffers;
865            private final int nrofchannels
866                    = SoftMainMixer.this.synth.getFormat().getChannels();
867            private final int buffersize = buffers[0].getSize();
868            private final byte[] bbuffer = new byte[buffersize
869                    * (SoftMainMixer.this.synth.getFormat()
870                        .getSampleSizeInBits() / 8)
871                    * nrofchannels];
872            private int bbuffer_pos = 0;
873            private final byte[] single = new byte[1];
874
875            public void fillBuffer() {
876                /*
877                boolean pusher_silent2;
878                synchronized (control_mutex) {
879                    pusher_silent2 = pusher_silent;
880                }
881                if(!pusher_silent2)*/
882                processAudioBuffers();
883                for (int i = 0; i < nrofchannels; i++)
884                    buffers[i].get(bbuffer, i);
885                bbuffer_pos = 0;
886            }
887
888            @Override
889            public int read(byte[] b, int off, int len) {
890                int bbuffer_len = bbuffer.length;
891                int offlen = off + len;
892                int orgoff = off;
893                byte[] bbuffer = this.bbuffer;
894                while (off < offlen) {
895                    if (available() == 0)
896                        fillBuffer();
897                    else {
898                        int bbuffer_pos = this.bbuffer_pos;
899                        while (off < offlen && bbuffer_pos < bbuffer_len)
900                            b[off++] = bbuffer[bbuffer_pos++];
901                        this.bbuffer_pos = bbuffer_pos;
902                        if (!readfully)
903                            return off - orgoff;
904                    }
905                }
906                return len;
907            }
908
909            @Override
910            public int read() throws IOException {
911                int ret = read(single);
912                if (ret == -1)
913                    return -1;
914                return single[0] & 0xFF;
915            }
916
917            @Override
918            public int available() {
919                return bbuffer.length - bbuffer_pos;
920            }
921
922            @Override
923            public void close() {
924                SoftMainMixer.this.synth.close();
925            }
926        };
927
928        ais = new AudioInputStream(in, synth.getFormat(), AudioSystem.NOT_SPECIFIED);
929
930    }
931
932    public AudioInputStream getInputStream() {
933        return ais;
934    }
935
936    public void reset() {
937
938        SoftChannel[] channels = synth.channels;
939        for (int i = 0; i < channels.length; i++) {
940            channels[i].allSoundOff();
941            channels[i].resetAllControllers(true);
942
943            if (synth.getGeneralMidiMode() == 2) {
944                if (i == 9)
945                    channels[i].programChange(0, 0x78 * 128);
946                else
947                    channels[i].programChange(0, 0x79 * 128);
948            } else
949                channels[i].programChange(0, 0);
950        }
951        setVolume(0x7F * 128 + 0x7F);
952        setBalance(0x40 * 128 + 0x00);
953        setCoarseTuning(0x40 * 128 + 0x00);
954        setFineTuning(0x40 * 128 + 0x00);
955        // Reset Reverb
956        globalParameterControlChange(
957                new int[]{0x01 * 128 + 0x01}, new long[]{0}, new long[]{4});
958        // Reset Chorus
959        globalParameterControlChange(
960                new int[]{0x01 * 128 + 0x02}, new long[]{0}, new long[]{2});
961    }
962
963    public void setVolume(int value) {
964        synchronized (control_mutex) {
965            co_master_volume[0] = value / 16384.0;
966        }
967    }
968
969    public void setBalance(int value) {
970        synchronized (control_mutex) {
971            co_master_balance[0] = value / 16384.0;
972        }
973    }
974
975    public void setFineTuning(int value) {
976        synchronized (control_mutex) {
977            co_master_fine_tuning[0] = value / 16384.0;
978        }
979    }
980
981    public void setCoarseTuning(int value) {
982        synchronized (control_mutex) {
983            co_master_coarse_tuning[0] = value / 16384.0;
984        }
985    }
986
987    public int getVolume() {
988        synchronized (control_mutex) {
989            return (int) (co_master_volume[0] * 16384.0);
990        }
991    }
992
993    public int getBalance() {
994        synchronized (control_mutex) {
995            return (int) (co_master_balance[0] * 16384.0);
996        }
997    }
998
999    public int getFineTuning() {
1000        synchronized (control_mutex) {
1001            return (int) (co_master_fine_tuning[0] * 16384.0);
1002        }
1003    }
1004
1005    public int getCoarseTuning() {
1006        synchronized (control_mutex) {
1007            return (int) (co_master_coarse_tuning[0] * 16384.0);
1008        }
1009    }
1010
1011    public void globalParameterControlChange(int[] slothpath, long[] params,
1012            long[] paramsvalue) {
1013        if (slothpath.length == 0)
1014            return;
1015
1016        synchronized (control_mutex) {
1017
1018            // slothpath: 01xx are reserved only for GM2
1019
1020            if (slothpath[0] == 0x01 * 128 + 0x01) {
1021                for (int i = 0; i < paramsvalue.length; i++) {
1022                    reverb.globalParameterControlChange(slothpath, params[i],
1023                            paramsvalue[i]);
1024                }
1025            }
1026            if (slothpath[0] == 0x01 * 128 + 0x02) {
1027                for (int i = 0; i < paramsvalue.length; i++) {
1028                    chorus.globalParameterControlChange(slothpath, params[i],
1029                            paramsvalue[i]);
1030                }
1031
1032            }
1033
1034        }
1035    }
1036
1037    public void processMessage(Object object) {
1038        if (object instanceof byte[])
1039            processMessage((byte[]) object);
1040        if (object instanceof MidiMessage)
1041            processMessage((MidiMessage)object);
1042    }
1043
1044    public void processMessage(MidiMessage message) {
1045        if (message instanceof ShortMessage) {
1046            ShortMessage sms = (ShortMessage)message;
1047            processMessage(sms.getChannel(), sms.getCommand(),
1048                    sms.getData1(), sms.getData2());
1049            return;
1050        }
1051        processMessage(message.getMessage());
1052    }
1053
1054    public void processMessage(byte[] data) {
1055        int status = 0;
1056        if (data.length > 0)
1057            status = data[0] & 0xFF;
1058
1059        if (status == 0xF0) {
1060            processSystemExclusiveMessage(data);
1061            return;
1062        }
1063
1064        int cmd = (status & 0xF0);
1065        int ch = (status & 0x0F);
1066
1067        int data1;
1068        int data2;
1069        if (data.length > 1)
1070            data1 = data[1] & 0xFF;
1071        else
1072            data1 = 0;
1073        if (data.length > 2)
1074            data2 = data[2] & 0xFF;
1075        else
1076            data2 = 0;
1077
1078        processMessage(ch, cmd, data1, data2);
1079
1080    }
1081
1082    public void processMessage(int ch, int cmd, int data1, int data2) {
1083        synchronized (synth.control_mutex) {
1084            activity();
1085        }
1086
1087        if (cmd == 0xF0) {
1088            int status = cmd | ch;
1089            switch (status) {
1090            case ShortMessage.ACTIVE_SENSING:
1091                synchronized (synth.control_mutex) {
1092                    active_sensing_on = true;
1093                }
1094                break;
1095            default:
1096                break;
1097            }
1098            return;
1099        }
1100
1101        SoftChannel[] channels = synth.channels;
1102        if (ch >= channels.length)
1103            return;
1104        SoftChannel softchannel = channels[ch];
1105
1106        switch (cmd) {
1107        case ShortMessage.NOTE_ON:
1108            if(delay_midievent != 0)
1109                softchannel.noteOn(data1, data2, delay_midievent);
1110            else
1111                softchannel.noteOn(data1, data2);
1112            break;
1113        case ShortMessage.NOTE_OFF:
1114            softchannel.noteOff(data1, data2);
1115            break;
1116        case ShortMessage.POLY_PRESSURE:
1117            softchannel.setPolyPressure(data1, data2);
1118            break;
1119        case ShortMessage.CONTROL_CHANGE:
1120            softchannel.controlChange(data1, data2);
1121            break;
1122        case ShortMessage.PROGRAM_CHANGE:
1123            softchannel.programChange(data1);
1124            break;
1125        case ShortMessage.CHANNEL_PRESSURE:
1126            softchannel.setChannelPressure(data1);
1127            break;
1128        case ShortMessage.PITCH_BEND:
1129            softchannel.setPitchBend(data1 + data2 * 128);
1130            break;
1131        default:
1132            break;
1133        }
1134
1135    }
1136
1137    public long getMicrosecondPosition() {
1138        if(pusher_silent)
1139        {
1140            if(synth.weakstream != null)
1141            {
1142                return (long)((sample_pos  + synth.weakstream.silent_samples)
1143                        * (1000000.0 / samplerate));
1144            }
1145        }
1146        return (long)(sample_pos * (1000000.0 / samplerate));
1147    }
1148
1149    public void close() {
1150    }
1151}
1152