You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将PCM字节数组转换为小端序单声道格式适配Vosk语音识别API

代码问题修正

原有实现的错误点

  • 单声道转换逻辑错误:你的输入是PCM_SIGNED 48000.0 Hz, 16 bit, stereo, 4 bytes/frame, big-endian格式,每帧4个字节对应左右两个声道各2字节的采样,原有代码将所有2字节块都读取为独立采样,最终输出仍是双声道采样序列,没有合并为单声道。
  • 端序转换逻辑冗余:不需要通过ByteBuffer写入再读取的方式转换端序,可在采样处理环节一次性完成,性能更高。

修正后的实现代码

转换逻辑为:拆分左右声道采样 -> 合并为单声道(取左右声道平均值)-> 转小端序输出

byte[] audioData = userAudio.getAudioData(1);
// 立体声每帧4字节,单声道采样总数为总字节数 / 4
int monoSampleCount = audioData.length / 4;
short[] convertedAudio = new short[monoSampleCount];

for (int i = 0; i < audioData.length; i += 4) {
    // 读取大端序左声道采样
    short left = (short) ((audioData[i] & 0xFF) << 8 | (audioData[i+1] & 0xFF));
    // 读取大端序右声道采样
    short right = (short) ((audioData[i+2] & 0xFF) << 8 | (audioData[i+3] & 0xFF));
    // 合并为单声道:先转int计算避免溢出,取平均值
    short monoSample = (short) ((left + right) / 2);
    // 转换为小端序
    convertedAudio[i/4] = Short.reverseBytes(monoSample);
}

queue.add(convertedAudio);

可选优化:如果确认有效音频仅在左/右其中一个声道,可以直接取对应声道的采样,无需计算平均值,减少计算开销。

可选:直接输出小端单声道字节数组

如果Vosk接口要求输入字节数组格式的PCM数据,可以直接生成目标字节数组,省略中间short数组转换步骤,性能更高:

byte[] audioData = userAudio.getAudioData(1);
int monoSampleCount = audioData.length / 4;
byte[] monoLittleEndianPcm = new byte[monoSampleCount * 2];
int writeIndex = 0;
for (int i = 0; i < audioData.length; i += 4) {
    short left = (short) ((audioData[i] & 0xFF) << 8 | (audioData[i+1] & 0xFF));
    short right = (short) ((audioData[i+2] & 0xFF) << 8 | (audioData[i+3] & 0xFF));
    short monoSample = (short) ((left + right) / 2);
    // 直接写入小端字节:先写低8位,再写高8位
    monoLittleEndianPcm[writeIndex++] = (byte) (monoSample & 0xFF);
    monoLittleEndianPcm[writeIndex++] = (byte) ((monoSample >> 8) & 0xFF);
}

queue.add(monoLittleEndianPcm);

内容的提问来源于stack exchange,提问作者moeux

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 09:24:04