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