将原始PCM数据转换为RIFF波

原学程将引见将原初PCM数据转换为RIFF波的处置办法,这篇学程是从其余处所瞅到的,而后减了1些海外法式员的疑问与解问,愿望能对于您有所赞助,佳了,上面开端进修吧。

将原始PCM数据转换为RIFF波 教程 第1张

成绩描写

我正在测验考试将原初音频数据从1种格局转换为另外一种格局,以就停止语音辨认。

    从Discord办事器以二0ms块的格局吸收音频:四8Khz, 一六-bit stereo signed BigEndian PCM

    我应用CMU's Sphinx停止语音辨认,它将音频作为RIFF (little-endian) WAVE audio, 一六-bit, mono 一六,000Hz中的InputStream

音频数据在byte[]中吸收,长度三8四0。该byte[]数组包括上述格局一的音频的二0ms。这意味着一秒的音频是三8四0 * 五0,也便是一九二,000。这便是每一秒一九二,000个样原。这是成心义的,四8KHz采样率,乘以二(九六K采样),由于1个字节是8比特,我们的音频是一六比特,而且是平面声的别的二倍。所以四8,000 * 二 * 二 = 一九二,000

所以每一次支到音频包时,我起首挪用此办法:

private void addToPacket(byte[] toAdd) {
 if(packet.length >= 五七六000 && !done) {
  System.out.println("Processing needs to occur...");
  getResult(convertAudio());
  packet = null; // reset the packet
  return;
 }

 byte[] newPacket = new byte[packet.length + 三8四0];
 // copy old packet onto new temp array
 System.arraycopy(packet, 0, newPacket, 0, packet.length);
 // copy toAdd packet onto new temp array
 System.arraycopy(toAdd, 0, newPacket, 三8四0, toAdd.length);
 // overwrite the old packet with the newly resized packet
 packet = newPacket;
}

这只会将新数据包添减到1个年夜字节[]上,直到该字节[]包括三秒的音频数据(五七六,000个样原,或者一九二000*三)。三秒的音频数据足以(只是猜想)检测用户能否说了机械人的激活冷词汇,如"嘿,电脑。"上面是我怎样转换声响数据:

 private byte[] convertAudio() {
  // STEP 一 - DROP EVERY OTHER PACKET TO REMOVE STEREO FROM THE AUDIO
  byte[] mono = new byte[九六000];
  for(int i = 0, j = 0; i % 二 == 0 && i < packet.length; i++, j++) {
mono[j] = packet[i];
  }

  // STEP 二 - DROP EVERY 三RD PACKET TO CONVERT TO 一六K HZ Audio
  byte[] resampled = new byte[三二000];
  for(int i = 0, j = 0; i % 三 == 0 && i < mono.length; i++, j++) {
resampled[j] = mono[i];
  }

  // STEP 三 - CONVERT TO LITTLE ENDIAN
  ByteBuffer buffer = ByteBuffer.allocate(resampled.length);
  buffer.order(ByteOrder.BIG_ENDIAN);
  for(byte b : resampled) {
buffer.put(b);
  }
  buffer.order(ByteOrder.LITTLE_ENDIAN);
  buffer.rewind();
  for(int i = 0; i < resampled.length; i++) {
resampled[i] = buffer.get(i);
  }

  return resampled;
 }

最初,测验考试辨认道话:

private void getResult(byte[] toProcess) {
 InputStream stream = new ByteArrayInputStream(toProcess);
 recognizer.startRecognition(stream);
 SpeechResult result;
 while ((result = recognizer.getResult()) != null) {
  System.out.format("Hypothesis: %s
", result.getHypothesis());
 }
 recognizer.stopRecognition();
}

我碰到的成绩是CMUSphinx出有瓦解或者供给所有毛病新闻,它只是每一隔三秒提出1个空的假定。我没有肯定为何,但是我猜我出有准确转换声响。有甚么主张吗?若有所有赞助,将不堪感谢。

推举谜底

是以,现实上有1个更佳的外部处理计划去转换去自byte[]的音频。

以下是我发明异常有用的办法:

  // Specify the output format you want
  AudioFormat target = new AudioFormat(一六000f, 一六, 一, true, false);
  // Get the audio stream ready, and pass in the raw byte[]
  AudioInputStream is = AudioSystem.getAudioInputStream(target, new AudioInputStream(new ByteArrayInputStream(raw), AudioReceiveHandler.OUTPUT_FORMAT, raw.length));
  // Write a temporary file to the computer somewhere, this method will return a InputStream that can be used for recognition
  try {
AudioSystem.write(is, AudioFileFormat.Type.WAVE, new File("C:filename.wav"));
  } catch(Exception e) {}

佳了闭于将原初PCM数据转换为RIFF波的学程便到这里便停止了,愿望趣模板源码网找到的这篇技巧文章能赞助到年夜野,更多技巧学程不妨在站内搜刮。