/*
  * stop() ferma e rilascia le audiotrack
  * Inoltre ferma il service e toglie la notifica
  */
 private void stop() {
   isPlaying = false;
   initialized = false;
   try {
     if (audioX.getState() == AudioTrack.STATE_INITIALIZED
         && audioY.getState() == AudioTrack.STATE_INITIALIZED
         && audioZ.getState() == AudioTrack.STATE_INITIALIZED) {
       audioX.stop();
       audioY.stop();
       audioZ.stop();
       audioX.release();
       audioY.release();
       audioZ.release();
       audioX.flush();
       audioY.flush();
       audioZ.flush();
     }
     if (audioXe.getState() == AudioTrack.STATE_INITIALIZED
         && audioYe.getState() == AudioTrack.STATE_INITIALIZED
         && audioZe.getState() == AudioTrack.STATE_INITIALIZED) {
       audioXe.stop();
       audioYe.stop();
       audioZe.stop();
       audioXe.release();
       audioYe.release();
       audioZe.release();
       audioXe.flush();
       audioYe.flush();
       audioZe.flush();
       echo.release();
     }
     if (audioXd.getState() == AudioTrack.STATE_INITIALIZED
         && audioYd.getState() == AudioTrack.STATE_INITIALIZED
         && audioZd.getState() == AudioTrack.STATE_INITIALIZED) {
       audioXd.stop();
       audioYd.stop();
       audioZd.stop();
       audioXd.release();
       audioYd.release();
       audioZd.release();
       audioXd.flush();
       audioYd.flush();
       audioZd.flush();
       delay.release();
     }
   } // Fine try
   catch (NullPointerException e) {
     Log.d("AudioTrack", "Audiotrack not initialized");
     return;
   }
   stopForeground(true);
 }
  /*
   * delay() crea 3 audiotrack cloni di quelle "principali"
   * e ci applica un effetto creato con la classe EnvironmentalReverb
   * Un thread (timer) gestisce l'avvio posticipato dell'effetto
   * Se al double tap è già attivo(isDelaying==true), le audiotrack
   * e l'effetto ad esse applicato vengono rilasciati
   */
  synchronized void delay() {
    if (isPlaying == true) {
      if (isDelaying == false) {
        isDelaying = true;
        showToast("Delay on");

        // Creo effetto audio per le tracce ritardate che vado a sovrapporre
        delay = new EnvironmentalReverb(1, 0);
        delay.setReverbLevel((short) 1000);
        delay.setRoomLevel((short) -10);
        delay.setRoomHFLevel((short) -10);
        delay.setReverbDelay(100);
        delay.setEnabled(true);

        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        final int delaytime = preferences.getInt("rdelay", 10);
        final float idelay = preferences.getInt("idelay", 10) / 10;

        timer =
            new Thread() {
              @Override
              public void run() {
                try {
                  audioXd = playSound(genArrayX); // Genero le audiotrack basate sullo stesso
                  audioYd = playSound(genArrayY); // array "sonoro" delle audiotrack "principali"
                  audioZd = playSound(genArrayZ);
                  audioXd.setPlaybackHeadPosition(
                      audioX
                          .getPlaybackHeadPosition()); // Imposto posizione uguale a quella della
                                                       // traccia
                  audioYd.setPlaybackHeadPosition(
                      audioY.getPlaybackHeadPosition()); // in riproduzione
                  audioZd.setPlaybackHeadPosition(audioZ.getPlaybackHeadPosition());
                  audioXd.attachAuxEffect(delay.getId());
                  audioXd.setAuxEffectSendLevel(idelay);
                  audioYd.attachAuxEffect(delay.getId());
                  audioYd.setAuxEffectSendLevel(idelay);
                  audioZd.attachAuxEffect(delay.getId());
                  audioZd.setAuxEffectSendLevel(idelay); // Aggiungo effetto alle audiotrack
                  audioXd.play();
                  audioYd.play();
                  audioZd.play();
                  audioXd.pause();
                  audioYd.pause();
                  audioZd.pause(); // Necessario per inizializzare le audiotrack
                  sleep(delaytime); // Tempo in millisecondi di ritardo tra la traccia principale
                  // e quella ritardata (settabile tramite seekbar)
                } catch (InterruptedException e) {
                  e.printStackTrace();
                } finally {
                  if (isPlaying) {
                    audioXd.play();
                    audioYd.play();
                    audioZd.play();
                  }
                  timer.interrupt();
                }

                super.run();
              }
            };
        timer.start();
      } // Fine isdelaying == false
      else {
        isDelaying = false;
        showToast("Delay off");
        audioXd.release();
        audioYd.release();
        audioZd.release();
        delay.release();
      }
    } // Fine isplaying
  } // Fine delay
  /*
   * echo() crea 3 audiotrack cloni di quelle "principali"
   * e ci applica un effetto creato con la classe EnvironmentalReverb
   * Due thread (timer1 e timer2) gestiscono l'avvio posticipato e l'interruzione dell'effetto
   */
  synchronized void echo() {
    if (isPlaying == true) {
      showToast("Echo on");
      if (echo != null) {
        echo.release();
      }

      // Creo effetto audio per le tracce ritardate che vado a sovrapporre
      echo = new EnvironmentalReverb(1, 0);
      echo.setDecayHFRatio((short) 1000);
      echo.setDecayTime(2000);
      echo.setDensity((short) 500);
      echo.setDiffusion((short) 700);
      echo.setReflectionsLevel((short) 1000);
      echo.setReverbLevel((short) 2000);
      echo.setReflectionsDelay(100);
      echo.setRoomLevel((short) -10);
      echo.setEnabled(true);

      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
      final int echotime = 1000 + preferences.getInt("recho", 10);
      final float iecho = preferences.getInt("iecho", 10) / 10;

      timer1 =
          new Thread() {
            @Override
            public void run() {
              try {
                audioXe = playSound(genArrayX);
                audioYe = playSound(genArrayY);
                audioZe = playSound(genArrayZ);
                audioXe.setPlaybackHeadPosition(audioX.getPlaybackHeadPosition());
                audioYe.setPlaybackHeadPosition(audioY.getPlaybackHeadPosition());
                audioZe.setPlaybackHeadPosition(audioZ.getPlaybackHeadPosition());
                audioXe.attachAuxEffect(echo.getId());
                audioXe.setAuxEffectSendLevel(iecho);
                audioYe.attachAuxEffect(echo.getId());
                audioYe.setAuxEffectSendLevel(iecho);
                audioZe.attachAuxEffect(echo.getId());
                audioZe.setAuxEffectSendLevel(iecho);
                audioXe.play();
                audioYe.play();
                audioZe.play();
                audioXe.pause();
                audioYe.pause();
                audioZe.pause();
                sleep(500); // Tempo in millisecondi di ritardo delle tracce
                // per creare l'effetto echo
              } catch (InterruptedException e) {
                e.printStackTrace();
              } finally {
                audioXe.play(); // Trascorso il tempo mando le tracce in riproduzi
                audioYe.play(); // (sovrapposte alle tracce audio "principali")
                audioZe.play();
                timer1.interrupt();
              }
              super.run();
            }
          };
      timer1.start();
      timer2 =
          new Thread() {
            @Override
            public void run() {

              try {
                sleep(
                    echotime); // Tempo in millisecondi a cui fermare l'echo (settabile tramite
                               // seekbar)
              } catch (InterruptedException e) {
                e.printStackTrace();
              } finally {
                if (audioXe.getState() == AudioTrack.STATE_INITIALIZED
                    && audioYe.getState() == AudioTrack.STATE_INITIALIZED
                    && audioZe.getState() == AudioTrack.STATE_INITIALIZED) {

                  audioXe.stop();
                  audioYe.stop();
                  audioZe.stop();

                  audioXe.release();
                  audioYe.release();
                  audioZe.release();
                  echo.release();
                  timer2.interrupt();
                }
              }
              super.run();
            }
          };
      timer2.start();
    }
  }