項目中須要用到對PCM人聲音頻數據進行變聲處理。苦苦掙扎了一週終於找到了純Java實現的一套框架——TarsosDSP。功能很是強大!能夠實時音頻處理!固然我只用到了對文件處理。實際上邏輯是同樣的java
TarsosDSP的GitHub地址:https://github.com/JorenSix/T...。將它整合至本身的項目工程。git
具體Java工具類代碼:github
/** * 變聲 * @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) { // 這裏根據本身PCM格式修改對應參數。咱們項目裏音頻格式是固定的,因此寫死 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; } }
能夠經過這個工具方法播放音頻:ide
/** * 播放PCM * * 不要在非桌面環境調用。。。鬼知道會發生什麼 * @param rawPcmInputStream 原始PCM數據輸入流 * @throws LineUnavailableException */ public static void play(final InputStream rawPcmInputStream) throws LineUnavailableException { // 這裏根據本身PCM格式修改對應參數。咱們項目裏音頻格式是固定的,因此寫死 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(); }