gpt4 book ai didi

java - 将原始 PCM 数据转换为 RIFF WAV

转载 作者:太空宇宙 更新时间:2023-11-04 10:50:54 25 4
gpt4 key购买 nike

我正在尝试将原始音频数据从一种格式转换为另一种格式,以便进行语音识别。

  • 音频是从 Discord 接收的服务器以20ms block 的格式:48Khz,16位立体声签名BigEndian PCM
  • 我正在使用CMU's Sphinx用于语音识别,它将音频作为 RIFF(little-endian)WAVE 音频、16 位、单声道 16,000Hz 中的 InputStream

音频数据以 byte[] 形式接收,长度为 3840。此 byte[] 数组包含上述格式 1 的 20ms 音频。这意味着该音频的 1 秒为 3840 * 50,即 192,000。也就是说每秒 192,000 个样本。这是有道理的,48KHz 采样率乘以 2(96K 样本),因为一个字节是 8 位,而我们的音频是 16 位,再乘以 2 即可获得立体声。所以48,000 * 2 * 2 = 192,000

因此,每次收到音频数据包时,我都会首先调用此方法:

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

byte[] newPacket = new byte[packet.length + 3840];
// 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, 3840, toAdd.length);
// overwrite the old packet with the newly resized packet
packet = newPacket;
}

这只会将新数据包添加到一个大字节 [] 上,直到该字节 [] 包含 3 秒的音频数据(576,000 个样本,或 192000 * 3)。 3 秒的音频数据足以(只是猜测)来检测用户是否说出了机器人的激活热词,例如“嘿计算机”。以下是我转换声音数据的方法:

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

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

// STEP 3 - 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\n", result.getHypothesis());
}
recognizer.stopRecognition();
}

我遇到的问题是 CMUSphinx 不会崩溃或提供任何错误消息,它只是每 3 秒提出一个空假设。我不太清楚为什么,但我的猜测是我没有正确转换声音。有任何想法吗?任何帮助将不胜感激。

最佳答案

因此,实际上有一个更好的内部解决方案用于从 byte[] 转换音频。

以下是我发现效果非常好的方法:

        // Specify the output format you want
AudioFormat target = new AudioFormat(16000f, 16, 1, 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) {}

关于java - 将原始 PCM 数据转换为 RIFF WAV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47879925/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com