欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

代码分析JAVA中PCM人声音频变声处理

程序员文章站 2023-12-12 13:54:34
项目中需要用到对pcm人声音频数据进行变声处理。苦苦挣扎了一周终于找到了纯java实现的一套框架——tarsosdsp。功能非常强大!可以实时音频处理!当然我只用到了对文件...

项目中需要用到对pcm人声音频数据进行变声处理。苦苦挣扎了一周终于找到了纯java实现的一套框架——tarsosdsp。功能非常强大!可以实时音频处理!当然我只用到了对文件处理。实际上逻辑是一样的

tarsosdsp的github地址:https://github.com/jorensix/tarsosdsp 将它整合至自己的项目工程。

具体java工具类代码:

  /**
   * 变声
   * @param rawpcminputstream 原始pcm数据输入流
   * @param speedfactor 变速率 (0,2) 大于1为加快语速,小于1为放慢语速
   * @param ratefactor 音调变化率 (0,2) 大于1为降低音调(深沉),小于1为提升音调(尖锐)
   * @return 变声后的pcm数据输入流
   */
  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());
  }

其中数据转录器(audiooutputtobytearray)代码如下:

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;
  }
}

可以通过这个工具方法播放音频:

  /**
   * 播放pcm
   *
   * 不要在非桌面环境调用。。。鬼知道会发生什么
   * @param rawpcminputstream 原始pcm数据输入流
   * @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();
  }

上一篇:

下一篇: