1 /* 2 * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 package com.sun.media.sound; 26 27 import java.io.IOException; 28 import java.util.Arrays; 29 import java.util.HashMap; 30 import java.util.Map; 31 32 import javax.sound.midi.VoiceStatus; 33 34 /** 35 * Software synthesizer voice class. 36 * 37 * @author Karl Helgason 38 */ 39 public class SoftVoice extends VoiceStatus { 40 41 public int exclusiveClass = 0; 42 public boolean releaseTriggered = false; 43 private int noteOn_noteNumber = 0; 44 private int noteOn_velocity = 0; 45 private int noteOff_velocity = 0; 46 protected ModelChannelMixer channelmixer = null; 47 protected double tunedKey = 0; 48 protected SoftTuning tuning = null; 49 protected SoftChannel stealer_channel = null; 50 protected ModelConnectionBlock[] stealer_extendedConnectionBlocks = null; 51 protected SoftPerformer stealer_performer = null; 52 protected ModelChannelMixer stealer_channelmixer = null; 53 protected int stealer_voiceID = -1; 54 protected int stealer_noteNumber = 0; 55 protected int stealer_velocity = 0; 56 protected boolean stealer_releaseTriggered = false; 57 protected int voiceID = -1; 58 protected boolean sustain = false; 59 protected boolean sostenuto = false; 60 protected boolean portamento = false; 61 private SoftFilter filter_left; 62 private SoftFilter filter_right; 63 private SoftProcess eg = new SoftEnvelopeGenerator(); 64 private SoftProcess lfo = new SoftLowFrequencyOscillator(); 65 protected Map<String, SoftControl> objects = 66 new HashMap<String, SoftControl>(); 67 protected SoftSynthesizer synthesizer; 68 protected SoftInstrument instrument; 69 protected SoftPerformer performer; 70 protected SoftChannel softchannel = null; 71 protected boolean on = false; 72 private boolean audiostarted = false; 73 private boolean started = false; 74 private boolean stopping = false; 75 private float osc_attenuation = 0.0f; 76 private ModelOscillatorStream osc_stream; 77 private int osc_stream_nrofchannels; 78 private float[][] osc_buff = new float[2][]; 79 private boolean osc_stream_off_transmitted = false; 80 private boolean out_mixer_end = false; 81 private float out_mixer_left = 0; 82 private float out_mixer_right = 0; 83 private float out_mixer_effect1 = 0; 84 private float out_mixer_effect2 = 0; 85 private float last_out_mixer_left = 0; 86 private float last_out_mixer_right = 0; 87 private float last_out_mixer_effect1 = 0; 88 private float last_out_mixer_effect2 = 0; 89 protected ModelConnectionBlock[] extendedConnectionBlocks = null; 90 private ModelConnectionBlock[] connections; 91 // Last value added to destination 92 private double[] connections_last = new double[50]; 93 // Pointer to source value 94 private double[][][] connections_src = new double[50][3][]; 95 // Key-based override (if any) 96 private int[][] connections_src_kc = new int[50][3]; 97 // Pointer to destination value 98 private double[][] connections_dst = new double[50][]; 99 private boolean soundoff = false; 100 private float lastMuteValue = 0; 101 private float lastSoloMuteValue = 0; 102 protected double[] co_noteon_keynumber = new double[1]; 103 protected double[] co_noteon_velocity = new double[1]; 104 protected double[] co_noteon_on = new double[1]; 105 private SoftControl co_noteon = new SoftControl() { 106 double[] keynumber = co_noteon_keynumber; 107 double[] velocity = co_noteon_velocity; 108 double[] on = co_noteon_on; 109 public double[] get(int instance, String name) { 110 if (name == null) 111 return null; 112 if (name.equals("keynumber")) 113 return keynumber; 114 if (name.equals("velocity")) 115 return velocity; 116 if (name.equals("on")) 117 return on; 118 return null; 119 } 120 }; 121 private double[] co_mixer_active = new double[1]; 122 private double[] co_mixer_gain = new double[1]; 123 private double[] co_mixer_pan = new double[1]; 124 private double[] co_mixer_balance = new double[1]; 125 private double[] co_mixer_reverb = new double[1]; 126 private double[] co_mixer_chorus = new double[1]; 127 private SoftControl co_mixer = new SoftControl() { 128 double[] active = co_mixer_active; 129 double[] gain = co_mixer_gain; 130 double[] pan = co_mixer_pan; 131 double[] balance = co_mixer_balance; 132 double[] reverb = co_mixer_reverb; 133 double[] chorus = co_mixer_chorus; 134 public double[] get(int instance, String name) { 135 if (name == null) 136 return null; 137 if (name.equals("active")) 138 return active; 139 if (name.equals("gain")) 140 return gain; 141 if (name.equals("pan")) 142 return pan; 143 if (name.equals("balance")) 144 return balance; 145 if (name.equals("reverb")) 146 return reverb; 147 if (name.equals("chorus")) 148 return chorus; 149 return null; 150 } 151 }; 152 private double[] co_osc_pitch = new double[1]; 153 private SoftControl co_osc = new SoftControl() { 154 double[] pitch = co_osc_pitch; 155 public double[] get(int instance, String name) { 156 if (name == null) 157 return null; 158 if (name.equals("pitch")) 159 return pitch; 160 return null; 161 } 162 }; 163 private double[] co_filter_freq = new double[1]; 164 private double[] co_filter_type = new double[1]; 165 private double[] co_filter_q = new double[1]; 166 private SoftControl co_filter = new SoftControl() { 167 double[] freq = co_filter_freq; 168 double[] ftype = co_filter_type; 169 double[] q = co_filter_q; 170 public double[] get(int instance, String name) { 171 if (name == null) 172 return null; 173 if (name.equals("freq")) 174 return freq; 175 if (name.equals("type")) 176 return ftype; 177 if (name.equals("q")) 178 return q; 179 return null; 180 } 181 }; 182 protected SoftResamplerStreamer resampler; 183 private int nrofchannels; 184 SoftVoice(SoftSynthesizer synth)185 public SoftVoice(SoftSynthesizer synth) { 186 synthesizer = synth; 187 filter_left = new SoftFilter(synth.getFormat().getSampleRate()); 188 filter_right = new SoftFilter(synth.getFormat().getSampleRate()); 189 nrofchannels = synth.getFormat().getChannels(); 190 } 191 getValueKC(ModelIdentifier id)192 private int getValueKC(ModelIdentifier id) { 193 if (id.getObject().equals("midi_cc")) { 194 int ic = Integer.parseInt(id.getVariable()); 195 if (ic != 0 && ic != 32) { 196 if (ic < 120) 197 return ic; 198 } 199 } else if (id.getObject().equals("midi_rpn")) { 200 if (id.getVariable().equals("1")) 201 return 120; // Fine tuning 202 if (id.getVariable().equals("2")) 203 return 121; // Coarse tuning 204 } 205 return -1; 206 } 207 getValue(ModelIdentifier id)208 private double[] getValue(ModelIdentifier id) { 209 SoftControl o = objects.get(id.getObject()); 210 if (o == null) 211 return null; 212 return o.get(id.getInstance(), id.getVariable()); 213 } 214 transformValue(double value, ModelSource src)215 private double transformValue(double value, ModelSource src) { 216 if (src.getTransform() != null) 217 return src.getTransform().transform(value); 218 else 219 return value; 220 } 221 transformValue(double value, ModelDestination dst)222 private double transformValue(double value, ModelDestination dst) { 223 if (dst.getTransform() != null) 224 return dst.getTransform().transform(value); 225 else 226 return value; 227 } 228 processKeyBasedController(double value, int keycontrol)229 private double processKeyBasedController(double value, int keycontrol) { 230 if (keycontrol == -1) 231 return value; 232 if (softchannel.keybasedcontroller_active != null) 233 if (softchannel.keybasedcontroller_active[note] != null) 234 if (softchannel.keybasedcontroller_active[note][keycontrol]) { 235 double key_controlvalue = 236 softchannel.keybasedcontroller_value[note][keycontrol]; 237 if (keycontrol == 10 || keycontrol == 91 || keycontrol == 93) 238 return key_controlvalue; 239 value += key_controlvalue * 2.0 - 1.0; 240 if (value > 1) 241 value = 1; 242 else if (value < 0) 243 value = 0; 244 } 245 return value; 246 } 247 processConnection(int ix)248 private void processConnection(int ix) { 249 ModelConnectionBlock conn = connections[ix]; 250 double[][] src = connections_src[ix]; 251 double[] dst = connections_dst[ix]; 252 if (dst == null || Double.isInfinite(dst[0])) 253 return; 254 255 double value = conn.getScale(); 256 if (softchannel.keybasedcontroller_active == null) { 257 ModelSource[] srcs = conn.getSources(); 258 for (int i = 0; i < srcs.length; i++) { 259 value *= transformValue(src[i][0], srcs[i]); 260 if (value == 0) 261 break; 262 } 263 } else { 264 ModelSource[] srcs = conn.getSources(); 265 int[] src_kc = connections_src_kc[ix]; 266 for (int i = 0; i < srcs.length; i++) { 267 value *= transformValue(processKeyBasedController(src[i][0], 268 src_kc[i]), srcs[i]); 269 if (value == 0) 270 break; 271 } 272 } 273 274 value = transformValue(value, conn.getDestination()); 275 dst[0] = dst[0] - connections_last[ix] + value; 276 connections_last[ix] = value; 277 // co_mixer_gain[0] = 0; 278 } 279 updateTuning(SoftTuning newtuning)280 protected void updateTuning(SoftTuning newtuning) { 281 tunedKey = tuning.getTuning(note) / 100.0; 282 if (!portamento) { 283 co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0); 284 int[] c = performer.midi_connections[4]; 285 if (c == null) 286 return; 287 for (int i = 0; i < c.length; i++) 288 processConnection(c[i]); 289 } 290 } 291 setNote(int noteNumber)292 protected void setNote(int noteNumber) { 293 note = noteNumber; 294 tunedKey = tuning.getTuning(noteNumber) / 100.0; 295 } 296 noteOn(int noteNumber, int velocity)297 protected void noteOn(int noteNumber, int velocity) { 298 299 sustain = false; 300 sostenuto = false; 301 portamento = false; 302 303 soundoff = false; 304 on = true; 305 active = true; 306 started = true; 307 // volume = velocity; 308 309 noteOn_noteNumber = noteNumber; 310 noteOn_velocity = velocity; 311 312 lastMuteValue = 0; 313 lastSoloMuteValue = 0; 314 315 setNote(noteNumber); 316 317 if (performer.forcedKeynumber) 318 co_noteon_keynumber[0] = 0; 319 else 320 co_noteon_keynumber[0] = tunedKey * (1f / 128f); 321 if (performer.forcedVelocity) 322 co_noteon_velocity[0] = 0; 323 else 324 co_noteon_velocity[0] = velocity * (1f / 128f); 325 co_mixer_active[0] = 0; 326 co_mixer_gain[0] = 0; 327 co_mixer_pan[0] = 0; 328 co_mixer_balance[0] = 0; 329 co_mixer_reverb[0] = 0; 330 co_mixer_chorus[0] = 0; 331 co_osc_pitch[0] = 0; 332 co_filter_freq[0] = 0; 333 co_filter_q[0] = 0; 334 co_filter_type[0] = 0; 335 co_noteon_on[0] = 1; 336 337 eg.reset(); 338 lfo.reset(); 339 filter_left.reset(); 340 filter_right.reset(); 341 342 objects.put("master", synthesizer.getMainMixer().co_master); 343 objects.put("eg", eg); 344 objects.put("lfo", lfo); 345 objects.put("noteon", co_noteon); 346 objects.put("osc", co_osc); 347 objects.put("mixer", co_mixer); 348 objects.put("filter", co_filter); 349 350 connections = performer.connections; 351 352 if (connections_last == null 353 || connections_last.length < connections.length) { 354 connections_last = new double[connections.length]; 355 } 356 if (connections_src == null 357 || connections_src.length < connections.length) { 358 connections_src = new double[connections.length][][]; 359 connections_src_kc = new int[connections.length][]; 360 } 361 if (connections_dst == null 362 || connections_dst.length < connections.length) { 363 connections_dst = new double[connections.length][]; 364 } 365 for (int i = 0; i < connections.length; i++) { 366 ModelConnectionBlock conn = connections[i]; 367 connections_last[i] = 0; 368 if (conn.getSources() != null) { 369 ModelSource[] srcs = conn.getSources(); 370 if (connections_src[i] == null 371 || connections_src[i].length < srcs.length) { 372 connections_src[i] = new double[srcs.length][]; 373 connections_src_kc[i] = new int[srcs.length]; 374 } 375 double[][] src = connections_src[i]; 376 int[] src_kc = connections_src_kc[i]; 377 connections_src[i] = src; 378 for (int j = 0; j < srcs.length; j++) { 379 src_kc[j] = getValueKC(srcs[j].getIdentifier()); 380 src[j] = getValue(srcs[j].getIdentifier()); 381 } 382 } 383 384 if (conn.getDestination() != null) 385 connections_dst[i] = getValue(conn.getDestination() 386 .getIdentifier()); 387 else 388 connections_dst[i] = null; 389 } 390 391 for (int i = 0; i < connections.length; i++) 392 processConnection(i); 393 394 if (extendedConnectionBlocks != null) { 395 for (ModelConnectionBlock connection: extendedConnectionBlocks) { 396 double value = 0; 397 398 if (softchannel.keybasedcontroller_active == null) { 399 for (ModelSource src: connection.getSources()) { 400 double x = getValue(src.getIdentifier())[0]; 401 ModelTransform t = src.getTransform(); 402 if (t == null) 403 value += x; 404 else 405 value += t.transform(x); 406 } 407 } else { 408 for (ModelSource src: connection.getSources()) { 409 double x = getValue(src.getIdentifier())[0]; 410 x = processKeyBasedController(x, 411 getValueKC(src.getIdentifier())); 412 ModelTransform t = src.getTransform(); 413 if (t == null) 414 value += x; 415 else 416 value += t.transform(x); 417 } 418 } 419 420 ModelDestination dest = connection.getDestination(); 421 ModelTransform t = dest.getTransform(); 422 if (t != null) 423 value = t.transform(value); 424 getValue(dest.getIdentifier())[0] += value; 425 } 426 } 427 428 eg.init(synthesizer); 429 lfo.init(synthesizer); 430 431 } 432 setPolyPressure(int pressure)433 protected void setPolyPressure(int pressure) { 434 int[] c = performer.midi_connections[2]; 435 if (c == null) 436 return; 437 for (int i = 0; i < c.length; i++) 438 processConnection(c[i]); 439 } 440 setChannelPressure(int pressure)441 protected void setChannelPressure(int pressure) { 442 int[] c = performer.midi_connections[1]; 443 if (c == null) 444 return; 445 for (int i = 0; i < c.length; i++) 446 processConnection(c[i]); 447 } 448 controlChange(int controller, int value)449 protected void controlChange(int controller, int value) { 450 int[] c = performer.midi_ctrl_connections[controller]; 451 if (c == null) 452 return; 453 for (int i = 0; i < c.length; i++) 454 processConnection(c[i]); 455 } 456 nrpnChange(int controller, int value)457 protected void nrpnChange(int controller, int value) { 458 int[] c = performer.midi_nrpn_connections.get(controller); 459 if (c == null) 460 return; 461 for (int i = 0; i < c.length; i++) 462 processConnection(c[i]); 463 } 464 rpnChange(int controller, int value)465 protected void rpnChange(int controller, int value) { 466 int[] c = performer.midi_rpn_connections.get(controller); 467 if (c == null) 468 return; 469 for (int i = 0; i < c.length; i++) 470 processConnection(c[i]); 471 } 472 setPitchBend(int bend)473 protected void setPitchBend(int bend) { 474 int[] c = performer.midi_connections[0]; 475 if (c == null) 476 return; 477 for (int i = 0; i < c.length; i++) 478 processConnection(c[i]); 479 } 480 setMute(boolean mute)481 protected void setMute(boolean mute) { 482 co_mixer_gain[0] -= lastMuteValue; 483 lastMuteValue = mute ? -960 : 0; 484 co_mixer_gain[0] += lastMuteValue; 485 } 486 setSoloMute(boolean mute)487 protected void setSoloMute(boolean mute) { 488 co_mixer_gain[0] -= lastSoloMuteValue; 489 lastSoloMuteValue = mute ? -960 : 0; 490 co_mixer_gain[0] += lastSoloMuteValue; 491 } 492 shutdown()493 protected void shutdown() { 494 if (co_noteon_on[0] < -0.5) 495 return; 496 on = false; 497 498 co_noteon_on[0] = -1; 499 500 int[] c = performer.midi_connections[3]; 501 if (c == null) 502 return; 503 for (int i = 0; i < c.length; i++) 504 processConnection(c[i]); 505 } 506 soundOff()507 protected void soundOff() { 508 on = false; 509 soundoff = true; 510 } 511 noteOff(int velocity)512 protected void noteOff(int velocity) { 513 if (!on) 514 return; 515 on = false; 516 517 noteOff_velocity = velocity; 518 519 if (softchannel.sustain) { 520 sustain = true; 521 return; 522 } 523 if (sostenuto) 524 return; 525 526 co_noteon_on[0] = 0; 527 528 int[] c = performer.midi_connections[3]; 529 if (c == null) 530 return; 531 for (int i = 0; i < c.length; i++) 532 processConnection(c[i]); 533 } 534 redamp()535 protected void redamp() { 536 if (co_noteon_on[0] > 0.5) 537 return; 538 if (co_noteon_on[0] < -0.5) 539 return; // don't redamp notes in shutdown stage 540 541 sustain = true; 542 co_noteon_on[0] = 1; 543 544 int[] c = performer.midi_connections[3]; 545 if (c == null) 546 return; 547 for (int i = 0; i < c.length; i++) 548 processConnection(c[i]); 549 } 550 processControlLogic()551 protected void processControlLogic() { 552 if (stopping) { 553 active = false; 554 stopping = false; 555 audiostarted = false; 556 if (osc_stream != null) 557 try { 558 osc_stream.close(); 559 } catch (IOException e) { 560 //e.printStackTrace(); 561 } 562 563 if (stealer_channel != null) { 564 stealer_channel.initVoice(this, stealer_performer, 565 stealer_voiceID, stealer_noteNumber, stealer_velocity, 566 stealer_extendedConnectionBlocks, stealer_channelmixer, 567 stealer_releaseTriggered); 568 stealer_releaseTriggered = false; 569 stealer_channel = null; 570 stealer_performer = null; 571 stealer_voiceID = -1; 572 stealer_noteNumber = 0; 573 stealer_velocity = 0; 574 stealer_extendedConnectionBlocks = null; 575 stealer_channelmixer = null; 576 } 577 } 578 if (started) { 579 audiostarted = true; 580 581 ModelOscillator osc = performer.oscillators[0]; 582 583 osc_stream_off_transmitted = false; 584 if (osc instanceof ModelWavetable) { 585 try { 586 resampler.open((ModelWavetable)osc, 587 synthesizer.getFormat().getSampleRate()); 588 osc_stream = resampler; 589 } catch (IOException e) { 590 //e.printStackTrace(); 591 } 592 } else { 593 osc_stream = osc.open(synthesizer.getFormat().getSampleRate()); 594 } 595 osc_attenuation = osc.getAttenuation(); 596 osc_stream_nrofchannels = osc.getChannels(); 597 if (osc_buff == null || osc_buff.length < osc_stream_nrofchannels) 598 osc_buff = new float[osc_stream_nrofchannels][]; 599 600 if (osc_stream != null) 601 osc_stream.noteOn(softchannel, this, noteOn_noteNumber, 602 noteOn_velocity); 603 604 605 } 606 if (audiostarted) { 607 if (portamento) { 608 double note_delta = tunedKey - (co_noteon_keynumber[0] * 128); 609 double note_delta_a = Math.abs(note_delta); 610 if (note_delta_a < 0.0000000001) { 611 co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0); 612 portamento = false; 613 } else { 614 if (note_delta_a > softchannel.portamento_time) 615 note_delta = Math.signum(note_delta) 616 * softchannel.portamento_time; 617 co_noteon_keynumber[0] += note_delta * (1.0 / 128.0); 618 } 619 620 int[] c = performer.midi_connections[4]; 621 if (c == null) 622 return; 623 for (int i = 0; i < c.length; i++) 624 processConnection(c[i]); 625 } 626 627 eg.processControlLogic(); 628 lfo.processControlLogic(); 629 630 for (int i = 0; i < performer.ctrl_connections.length; i++) 631 processConnection(performer.ctrl_connections[i]); 632 633 osc_stream.setPitch((float)co_osc_pitch[0]); 634 635 int filter_type = (int)co_filter_type[0]; 636 double filter_freq; 637 638 if (co_filter_freq[0] == 13500.0) 639 filter_freq = 19912.126958213175; 640 else 641 filter_freq = 440.0 * Math.exp( 642 ((co_filter_freq[0]) - 6900.0) * 643 (Math.log(2.0) / 1200.0)); 644 /* 645 filter_freq = 440.0 * Math.pow(2.0, 646 ((co_filter_freq[0]) - 6900.0) / 1200.0);*/ 647 /* 648 * double velocity = co_noteon_velocity[0]; if(velocity < 0.5) 649 * filter_freq *= ((velocity * 2)*0.75 + 0.25); 650 */ 651 652 double q = co_filter_q[0] / 10.0; 653 filter_left.setFilterType(filter_type); 654 filter_left.setFrequency(filter_freq); 655 filter_left.setResonance(q); 656 filter_right.setFilterType(filter_type); 657 filter_right.setFrequency(filter_freq); 658 filter_right.setResonance(q); 659 /* 660 float gain = (float) Math.pow(10, 661 (-osc_attenuation + co_mixer_gain[0]) / 200.0); 662 */ 663 float gain = (float)Math.exp( 664 (-osc_attenuation + co_mixer_gain[0])*(Math.log(10) / 200.0)); 665 666 if (co_mixer_gain[0] <= -960) 667 gain = 0; 668 669 if (soundoff) { 670 stopping = true; 671 gain = 0; 672 /* 673 * if(co_mixer_gain[0] > -960) 674 * co_mixer_gain[0] -= 960; 675 */ 676 } 677 678 volume = (int)(Math.sqrt(gain) * 128); 679 680 // gain *= 0.2; 681 682 double pan = co_mixer_pan[0] * (1.0 / 1000.0); 683 // System.out.println("pan = " + pan); 684 if (pan < 0) 685 pan = 0; 686 else if (pan > 1) 687 pan = 1; 688 689 if (pan == 0.5) { 690 out_mixer_left = gain * 0.7071067811865476f; 691 out_mixer_right = out_mixer_left; 692 } else { 693 out_mixer_left = gain * (float)Math.cos(pan * Math.PI * 0.5); 694 out_mixer_right = gain * (float)Math.sin(pan * Math.PI * 0.5); 695 } 696 697 double balance = co_mixer_balance[0] * (1.0 / 1000.0); 698 if (balance != 0.5) { 699 if (balance > 0.5) 700 out_mixer_left *= (1 - balance) * 2; 701 else 702 out_mixer_right *= balance * 2; 703 } 704 705 if (synthesizer.reverb_on) { 706 out_mixer_effect1 = (float)(co_mixer_reverb[0] * (1.0 / 1000.0)); 707 out_mixer_effect1 *= gain; 708 } else 709 out_mixer_effect1 = 0; 710 if (synthesizer.chorus_on) { 711 out_mixer_effect2 = (float)(co_mixer_chorus[0] * (1.0 / 1000.0)); 712 out_mixer_effect2 *= gain; 713 } else 714 out_mixer_effect2 = 0; 715 out_mixer_end = co_mixer_active[0] < 0.5; 716 717 if (!on) 718 if (!osc_stream_off_transmitted) { 719 osc_stream_off_transmitted = true; 720 if (osc_stream != null) 721 osc_stream.noteOff(noteOff_velocity); 722 } 723 724 } 725 if (started) { 726 last_out_mixer_left = out_mixer_left; 727 last_out_mixer_right = out_mixer_right; 728 last_out_mixer_effect1 = out_mixer_effect1; 729 last_out_mixer_effect2 = out_mixer_effect2; 730 started = false; 731 } 732 733 } 734 735 protected void mixAudioStream(SoftAudioBuffer in, SoftAudioBuffer out, 736 float amp_from, float amp_to) { 737 int bufferlen = in.getSize(); 738 if (amp_from < 0.000000001 && amp_to < 0.000000001) 739 return; 740 if (amp_from == amp_to) { 741 float[] fout = out.array(); 742 float[] fin = in.array(); 743 for (int i = 0; i < bufferlen; i++) 744 fout[i] += fin[i] * amp_to; 745 } else { 746 float amp = amp_from; 747 float amp_delta = (amp_to - amp_from) / bufferlen; 748 float[] fout = out.array(); 749 float[] fin = in.array(); 750 for (int i = 0; i < bufferlen; i++) { 751 amp += amp_delta; 752 fout[i] += fin[i] * amp; 753 } 754 } 755 756 } 757 758 protected void processAudioLogic(SoftAudioBuffer[] buffer) { 759 if (!audiostarted) 760 return; 761 762 int bufferlen = buffer[0].getSize(); 763 764 try { 765 osc_buff[0] = buffer[SoftMainMixer.CHANNEL_LEFT_DRY].array(); 766 if (nrofchannels != 1) 767 osc_buff[1] = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY].array(); 768 int ret = osc_stream.read(osc_buff, 0, bufferlen); 769 if (ret == -1) { 770 stopping = true; 771 return; 772 } 773 if (ret != bufferlen) { 774 Arrays.fill(osc_buff[0], ret, bufferlen, 0f); 775 if (nrofchannels != 1) 776 Arrays.fill(osc_buff[1], ret, bufferlen, 0f); 777 } 778 779 } catch (IOException e) { 780 //e.printStackTrace(); 781 } 782 783 SoftAudioBuffer left = buffer[SoftMainMixer.CHANNEL_LEFT]; 784 SoftAudioBuffer right = buffer[SoftMainMixer.CHANNEL_RIGHT]; 785 SoftAudioBuffer eff1 = buffer[SoftMainMixer.CHANNEL_EFFECT1]; 786 SoftAudioBuffer eff2 = buffer[SoftMainMixer.CHANNEL_EFFECT2]; 787 SoftAudioBuffer leftdry = buffer[SoftMainMixer.CHANNEL_LEFT_DRY]; 788 SoftAudioBuffer rightdry = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY]; 789 790 if (osc_stream_nrofchannels == 1) 791 rightdry = null; 792 793 if (!Double.isInfinite(co_filter_freq[0])) { 794 filter_left.processAudio(leftdry); 795 if (rightdry != null) 796 filter_right.processAudio(rightdry); 797 } 798 799 if (nrofchannels == 1) { 800 out_mixer_left = (out_mixer_left + out_mixer_right) / 2; 801 mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left); 802 if (rightdry != null) 803 mixAudioStream(rightdry, left, last_out_mixer_left, 804 out_mixer_left); 805 } else { 806 mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left); 807 if (rightdry != null) 808 mixAudioStream(rightdry, right, last_out_mixer_right, 809 out_mixer_right); 810 else 811 mixAudioStream(leftdry, right, last_out_mixer_right, 812 out_mixer_right); 813 } 814 815 if (rightdry == null) { 816 mixAudioStream(leftdry, eff1, last_out_mixer_effect1, 817 out_mixer_effect1); 818 mixAudioStream(leftdry, eff2, last_out_mixer_effect2, 819 out_mixer_effect2); 820 } else { 821 mixAudioStream(leftdry, eff1, last_out_mixer_effect1 * 0.5f, 822 out_mixer_effect1 * 0.5f); 823 mixAudioStream(leftdry, eff2, last_out_mixer_effect2 * 0.5f, 824 out_mixer_effect2 * 0.5f); 825 mixAudioStream(rightdry, eff1, last_out_mixer_effect1 * 0.5f, 826 out_mixer_effect1 * 0.5f); 827 mixAudioStream(rightdry, eff2, last_out_mixer_effect2 * 0.5f, 828 out_mixer_effect2 * 0.5f); 829 } 830 831 last_out_mixer_left = out_mixer_left; 832 last_out_mixer_right = out_mixer_right; 833 last_out_mixer_effect1 = out_mixer_effect1; 834 last_out_mixer_effect2 = out_mixer_effect2; 835 836 if (out_mixer_end) { 837 stopping = true; 838 } 839 840 } 841 } 842