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