title: Increase/decrease audio play speed of AudioInputStream with Java
body: <blockquote>
    <p>Getting into the complex world of audio using Java I am using <a href="https://github.com/goxr3plus/java-stream-player" rel="nofollow noreferrer">this
    library</a> , which basically I improved and published on Github.</p>
  </blockquote>
  
  <p>The main class of the library is <a href="https://github.com/goxr3plus/java-stream-player" rel="nofollow noreferrer">StreamPlayer</a> and the code has comments and is straightforward to understand.</p>
  
  <hr>
  
  <p>The problem is that it supports many functionalities <strong>except speed increase/decrease audio speed.</strong> Let's say like YouTube does when you change the video speed.</p>
  
  <p>I have no clue how I can implement such a functionality. I mean, what can I do when writing the audio to the sample rate of <code>targetFormat</code>? I have to restart the audio again and again every time....</p>
  
  <pre><code>AudioFormat targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, sourceFormat.getSampleRate()*2, nSampleSizeInBits, sourceFormat.getChannels(),
                  nSampleSizeInBits / 8 * sourceFormat.getChannels(), sourceFormat.getSampleRate(), false);
  </code></pre>
  
  <hr>
  
  <p>The code of playing the audio is:</p>
  
  <pre><code>/**
   * Main loop.
   *
   * Player Status == STOPPED || SEEKING = End of Thread + Freeing Audio Resources.&lt;br&gt;
   * Player Status == PLAYING = Audio stream data sent to Audio line.&lt;br&gt;
   * Player Status == PAUSED = Waiting for another status.
   */
  @Override
  public Void call() {
      //  int readBytes = 1
      //  byte[] abData = new byte[EXTERNAL_BUFFER_SIZE]
      int nBytesRead = 0;
      int audioDataLength = EXTERNAL_BUFFER_SIZE;
      ByteBuffer audioDataBuffer = ByteBuffer.allocate(audioDataLength);
      audioDataBuffer.order(ByteOrder.LITTLE_ENDIAN);
  
      // Lock stream while playing.
      synchronized (audioLock) {
          // Main play/pause loop.
          while ( ( nBytesRead != -1 ) &amp;&amp; status != Status.STOPPED &amp;&amp; status != Status.SEEKING &amp;&amp; status != Status.NOT_SPECIFIED) {
              try {
                  //Playing?
                  if (status == Status.PLAYING) {
  
                      // System.out.println("Inside Stream Player Run method")
                      int toRead = audioDataLength;
                      int totalRead = 0;
  
                      // Reads up a specified maximum number of bytes from audio stream   
                      //wtf i have written here xaxaxoaxoao omg //to fix! cause it is complicated
                      for (; toRead &gt; 0
                              &amp;&amp; ( nBytesRead = audioInputStream.read(audioDataBuffer.array(), totalRead, toRead) ) != -1; toRead -= nBytesRead, totalRead += nBytesRead)
  
                          // Check for under run
                          if (sourceDataLine.available() &gt;= sourceDataLine.getBufferSize())
                              logger.info(() -&gt; "Underrun&gt; Available=" + sourceDataLine.available() + " , SourceDataLineBuffer=" + sourceDataLine.getBufferSize());
  
                      //Check if anything has been read
                      if (totalRead &gt; 0) {
                          trimBuffer = audioDataBuffer.array();
                          if (totalRead &lt; trimBuffer.length) {
                              trimBuffer = new byte[totalRead];
                              //Copies an array from the specified source array, beginning at the specified position, to the specified position of the destination array
                              // The number of components copied is equal to the length argument. 
                              System.arraycopy(audioDataBuffer.array(), 0, trimBuffer, 0, totalRead);
                          }
  
                          //Writes audio data to the mixer via this source data line
                          sourceDataLine.write(trimBuffer, 0, totalRead);
  
                          // Compute position in bytes in encoded stream.
                          int nEncodedBytes = getEncodedStreamPosition();
  
                          // Notify all registered Listeners
                          listeners.forEach(listener -&gt; {
                              if (audioInputStream instanceof PropertiesContainer) {
                                  // Pass audio parameters such as instant
                                  // bit rate, ...
                                  listener.progress(nEncodedBytes, sourceDataLine.getMicrosecondPosition(), trimBuffer, ( (PropertiesContainer) audioInputStream ).properties());
                              } else
                                  // Pass audio parameters
                                  listener.progress(nEncodedBytes, sourceDataLine.getMicrosecondPosition(), trimBuffer, emptyMap);
                          });
  
                      }
  
                  } else if (status == Status.PAUSED) {
  
                      //Flush and stop the source data line 
                      if (sourceDataLine != null &amp;&amp; sourceDataLine.isRunning()) {
                          sourceDataLine.flush();
                          sourceDataLine.stop();
                      }
                      try {
                          while (status == Status.PAUSED) {
                              Thread.sleep(50);
                          }
                      } catch (InterruptedException ex) {
                          Thread.currentThread().interrupt();
                          logger.warning("Thread cannot sleep.\n" + ex);
                      }
                  }
              } catch (IOException ex) {
                  logger.log(Level.WARNING, "\"Decoder Exception: \" ", ex);
                  status = Status.STOPPED;
                  generateEvent(Status.STOPPED, getEncodedStreamPosition(), null);
              }
          }
  
          // Free audio resources.
          if (sourceDataLine != null) {
              sourceDataLine.drain();
              sourceDataLine.stop();
              sourceDataLine.close();
              sourceDataLine = null;
          }
  
          // Close stream.
          closeStream();
  
          // Notification of "End Of Media"
          if (nBytesRead == -1)
              generateEvent(Status.EOM, AudioSystem.NOT_SPECIFIED, null);
  
      }
      //Generate Event
      status = Status.STOPPED;
      generateEvent(Status.STOPPED, AudioSystem.NOT_SPECIFIED, null);
  
      //Log
      logger.info("Decoding thread completed");
  
      return null;
  }
  </code></pre>
  
  <p>Feel free to download and check out the library alone if you want. :) I need some help on this... <a href="https://github.com/goxr3plus/java-stream-player" rel="nofollow noreferrer">Library link</a>.</p>