protected void processAudioLogic(SoftAudioBuffer[] buffer) {
    if (!audiostarted) return;

    int bufferlen = buffer[0].getSize();

    try {
      osc_buff[0] = buffer[SoftMainMixer.CHANNEL_LEFT_DRY].array();
      if (nrofchannels != 1) osc_buff[1] = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY].array();
      int ret = osc_stream.read(osc_buff, 0, bufferlen);
      if (ret == -1) {
        stopping = true;
        return;
      }
      if (ret != bufferlen) {
        Arrays.fill(osc_buff[0], ret, bufferlen, 0f);
        if (nrofchannels != 1) Arrays.fill(osc_buff[1], ret, bufferlen, 0f);
      }

    } catch (IOException e) {
      // e.printStackTrace();
    }

    SoftAudioBuffer left = buffer[SoftMainMixer.CHANNEL_LEFT];
    SoftAudioBuffer right = buffer[SoftMainMixer.CHANNEL_RIGHT];
    SoftAudioBuffer eff1 = buffer[SoftMainMixer.CHANNEL_EFFECT1];
    SoftAudioBuffer eff2 = buffer[SoftMainMixer.CHANNEL_EFFECT2];
    SoftAudioBuffer leftdry = buffer[SoftMainMixer.CHANNEL_LEFT_DRY];
    SoftAudioBuffer rightdry = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY];

    if (osc_stream_nrofchannels == 1) rightdry = null;

    if (!Double.isInfinite(co_filter_freq[0])) {
      filter_left.processAudio(leftdry);
      if (rightdry != null) filter_right.processAudio(rightdry);
    }

    if (nrofchannels == 1) {
      out_mixer_left = (out_mixer_left + out_mixer_right) / 2;
      mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left);
      if (rightdry != null) mixAudioStream(rightdry, left, last_out_mixer_left, out_mixer_left);
    } else {
      mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left);
      if (rightdry != null) mixAudioStream(rightdry, right, last_out_mixer_right, out_mixer_right);
      else mixAudioStream(leftdry, right, last_out_mixer_right, out_mixer_right);
    }

    if (rightdry == null) {
      mixAudioStream(leftdry, eff1, last_out_mixer_effect1, out_mixer_effect1);
      mixAudioStream(leftdry, eff2, last_out_mixer_effect2, out_mixer_effect2);
    } else {
      mixAudioStream(leftdry, eff1, last_out_mixer_effect1 * 0.5f, out_mixer_effect1 * 0.5f);
      mixAudioStream(leftdry, eff2, last_out_mixer_effect2 * 0.5f, out_mixer_effect2 * 0.5f);
      mixAudioStream(rightdry, eff1, last_out_mixer_effect1 * 0.5f, out_mixer_effect1 * 0.5f);
      mixAudioStream(rightdry, eff2, last_out_mixer_effect2 * 0.5f, out_mixer_effect2 * 0.5f);
    }

    last_out_mixer_left = out_mixer_left;
    last_out_mixer_right = out_mixer_right;
    last_out_mixer_effect1 = out_mixer_effect1;
    last_out_mixer_effect2 = out_mixer_effect2;

    if (out_mixer_end) {
      stopping = true;
    }
  }
  protected void processControlLogic() {
    if (stopping) {
      active = false;
      stopping = false;
      audiostarted = false;
      if (osc_stream != null)
        try {
          osc_stream.close();
        } catch (IOException e) {
          // e.printStackTrace();
        }

      if (stealer_channel != null) {
        stealer_channel.initVoice(
            this,
            stealer_performer,
            stealer_voiceID,
            stealer_noteNumber,
            stealer_velocity,
            stealer_extendedConnectionBlocks,
            stealer_channelmixer,
            stealer_releaseTriggered);
        stealer_releaseTriggered = false;
        stealer_channel = null;
        stealer_performer = null;
        stealer_voiceID = -1;
        stealer_noteNumber = 0;
        stealer_velocity = 0;
        stealer_extendedConnectionBlocks = null;
        stealer_channelmixer = null;
      }
    }
    if (started) {
      audiostarted = true;

      ModelOscillator osc = performer.oscillators[0];

      osc_stream_off_transmitted = false;
      if (osc instanceof ModelWavetable) {
        try {
          resampler.open((ModelWavetable) osc, synthesizer.getFormat().getSampleRate());
          osc_stream = resampler;
        } catch (IOException e) {
          // e.printStackTrace();
        }
      } else {
        osc_stream = osc.open(synthesizer.getFormat().getSampleRate());
      }
      osc_attenuation = osc.getAttenuation();
      osc_stream_nrofchannels = osc.getChannels();
      if (osc_buff == null || osc_buff.length < osc_stream_nrofchannels)
        osc_buff = new float[osc_stream_nrofchannels][];

      if (osc_stream != null)
        osc_stream.noteOn(softchannel, this, noteOn_noteNumber, noteOn_velocity);
    }
    if (audiostarted) {
      if (portamento) {
        double note_delta = tunedKey - (co_noteon_keynumber[0] * 128);
        double note_delta_a = Math.abs(note_delta);
        if (note_delta_a < 0.0000000001) {
          co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0);
          portamento = false;
        } else {
          if (note_delta_a > softchannel.portamento_time)
            note_delta = Math.signum(note_delta) * softchannel.portamento_time;
          co_noteon_keynumber[0] += note_delta * (1.0 / 128.0);
        }

        int[] c = performer.midi_connections[4];
        if (c == null) return;
        for (int i = 0; i < c.length; i++) processConnection(c[i]);
      }

      eg.processControlLogic();
      lfo.processControlLogic();

      for (int i = 0; i < performer.ctrl_connections.length; i++)
        processConnection(performer.ctrl_connections[i]);

      osc_stream.setPitch((float) co_osc_pitch[0]);

      int filter_type = (int) co_filter_type[0];
      double filter_freq;

      if (co_filter_freq[0] == 13500.0) filter_freq = 19912.126958213175;
      else
        filter_freq = 440.0 * Math.exp(((co_filter_freq[0]) - 6900.0) * (Math.log(2.0) / 1200.0));
      /*
      filter_freq = 440.0 * Math.pow(2.0,
      ((co_filter_freq[0]) - 6900.0) / 1200.0);*/
      /*
       * double velocity = co_noteon_velocity[0]; if(velocity < 0.5)
       * filter_freq *= ((velocity * 2)*0.75 + 0.25);
       */

      double q = co_filter_q[0] / 10.0;
      filter_left.setFilterType(filter_type);
      filter_left.setFrequency(filter_freq);
      filter_left.setResonance(q);
      filter_right.setFilterType(filter_type);
      filter_right.setFrequency(filter_freq);
      filter_right.setResonance(q);
      /*
      float gain = (float) Math.pow(10,
      (-osc_attenuation + co_mixer_gain[0]) / 200.0);
       */
      float gain = (float) Math.exp((-osc_attenuation + co_mixer_gain[0]) * (Math.log(10) / 200.0));

      if (co_mixer_gain[0] <= -960) gain = 0;

      if (soundoff) {
        stopping = true;
        gain = 0;
        /*
         * if(co_mixer_gain[0] > -960)
         *   co_mixer_gain[0] -= 960;
         */
      }

      volume = (int) (Math.sqrt(gain) * 128);

      // gain *= 0.2;

      double pan = co_mixer_pan[0] * (1.0 / 1000.0);
      // System.out.println("pan = " + pan);
      if (pan < 0) pan = 0;
      else if (pan > 1) pan = 1;

      if (pan == 0.5) {
        out_mixer_left = gain * 0.7071067811865476f;
        out_mixer_right = out_mixer_left;
      } else {
        out_mixer_left = gain * (float) Math.cos(pan * Math.PI * 0.5);
        out_mixer_right = gain * (float) Math.sin(pan * Math.PI * 0.5);
      }

      double balance = co_mixer_balance[0] * (1.0 / 1000.0);
      if (balance != 0.5) {
        if (balance > 0.5) out_mixer_left *= (1 - balance) * 2;
        else out_mixer_right *= balance * 2;
      }

      if (synthesizer.reverb_on) {
        out_mixer_effect1 = (float) (co_mixer_reverb[0] * (1.0 / 1000.0));
        out_mixer_effect1 *= gain;
      } else out_mixer_effect1 = 0;
      if (synthesizer.chorus_on) {
        out_mixer_effect2 = (float) (co_mixer_chorus[0] * (1.0 / 1000.0));
        out_mixer_effect2 *= gain;
      } else out_mixer_effect2 = 0;
      out_mixer_end = co_mixer_active[0] < 0.5;

      if (!on)
        if (!osc_stream_off_transmitted) {
          osc_stream_off_transmitted = true;
          if (osc_stream != null) osc_stream.noteOff(noteOff_velocity);
        }
    }
    if (started) {
      last_out_mixer_left = out_mixer_left;
      last_out_mixer_right = out_mixer_right;
      last_out_mixer_effect1 = out_mixer_effect1;
      last_out_mixer_effect2 = out_mixer_effect2;
      started = false;
    }
  }