Code analysis of JAVA PCM Voice audio change processing

  • 2020-12-20 03:38:44
  • OfStack

In this project, PCM voice audio data needs to be processed with sound variation. After struggling for a week, I finally found a set of frameworks for pure Java implementation, TarsosDSP. Very powerful! Real-time audio processing! Of course, I only use the file processing. The logic is actually 1

TarsosDSP GitHub address: https: / / github com JorenSix/TarsosDSP integrating it to their own projects.

Specific Java tool class code:


  /**
   *  voice 
   * @param rawPcmInputStream  The original PCM Data input stream 
   * @param speedFactor  Variable rate  (0,2)  Is greater than 1 In order to speed up the speech, is less than 1 To slow down 
   * @param rateFactor  Rate of tone change  (0,2)  Is greater than 1 To lower the pitch (deep), less than 1 For ascending tones (sharp) 
   * @return  After breaking PCM Data input stream 
   */
  public static InputStream speechPitchShift(final InputStream rawPcmInputStream,double speedFactor,double rateFactor) {
    TarsosDSPAudioFormat format = new TarsosDSPAudioFormat(16000,16,1,true,false);
    AudioInputStream inputStream = new AudioInputStream(rawPcmInputStream, JVMAudioInputStream.toAudioFormat(format),AudioSystem.NOT_SPECIFIED);
    JVMAudioInputStream stream = new JVMAudioInputStream(inputStream);
    WaveformSimilarityBasedOverlapAdd w = new WaveformSimilarityBasedOverlapAdd(WaveformSimilarityBasedOverlapAdd.Parameters.speechDefaults(speedFactor, 16000));
    int inputBufferSize = w.getInputBufferSize();
    int overlap = w.getOverlap();
    AudioDispatcher dispatcher = new AudioDispatcher(stream, inputBufferSize ,overlap);
    w.setDispatcher(dispatcher);
    AudioOutputToByteArray out = new AudioOutputToByteArray();
    dispatcher.addAudioProcessor(w);
    dispatcher.addAudioProcessor(new RateTransposer(rateFactor));
    dispatcher.addAudioProcessor(out);
    dispatcher.run();
    return new ByteArrayInputStream(out.getData());
  }

The data transcriber (AudioOutputToByteArray) code is as follows:


public class AudioOutputToByteArray implements AudioProcessor {
  private boolean isDone = false;
  private byte[] out = null;
  private ByteArrayOutputStream bos;
  public AudioOutputToByteArray() {
    bos = new ByteArrayOutputStream();
  }
  public byte[] getData() {
    while (!isDone && out == null) {
      try {
        Thread.sleep(10);
      } catch (InterruptedException ignored) {}
    }
    return out;
  }
  @Override
  public boolean process(AudioEvent audioEvent) {
    bos.write(audioEvent.getByteBuffer(),0,audioEvent.getByteBuffer().length);
    return true;
  }
  @Override
  public void processingFinished() {
    out = bos.toByteArray().clone();
    bos = null;
    isDone = true;
  }
}

Audio can be played through this tool method:


  /**
   *  play PCM
   *
   *  Do not call in a non-desktop environment... Who knows what might happen 
   * @param rawPcmInputStream  The original PCM Data input stream 
   * @throws LineUnavailableException
   */
  public static void play(final InputStream rawPcmInputStream) throws LineUnavailableException {
    TarsosDSPAudioFormat format = new TarsosDSPAudioFormat(16000,16,1,true,false);
    AudioInputStream inputStream = new AudioInputStream(rawPcmInputStream, JVMAudioInputStream.toAudioFormat(format),AudioSystem.NOT_SPECIFIED);
    JVMAudioInputStream stream = new JVMAudioInputStream(inputStream);
    AudioDispatcher dispatcher = new AudioDispatcher(stream, 1024 ,0);
    dispatcher.addAudioProcessor(new AudioPlayer(format,1024));
    dispatcher.run();
  }


Related articles: