audioUtil.js 2.38 KB
/**
 * 音频处理工具类
 * 用于语音对讲功能的 PCM 格式转换与编码
 */

// 【修改】降采样并转换函数:Float32(44.1k/48k) -> Int16(8k)
export function resampleTo8kInt16(audioData, sampleRate) {
  const targetSampleRate = 8000; // 目标采样率
  const ratio = sampleRate / targetSampleRate;
  const newLength = Math.round(audioData.length / ratio);
  const result = new Int16Array(newLength);

  for (let i = 0; i < newLength; i++) {
    // 简单的线性插值或直接抽取
    const index = Math.floor(i * ratio);
    let s = audioData[index];

    // 限幅处理,防止爆音
    s = Math.max(-1, Math.min(1, s));

    // 转换到 Int16 范围: s < 0 ? s * 0x8000 : s * 0x7FFF
    result[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
  }
  return result;
}

/**
 * 将 Web Audio API 的 Float32Array (采样率 44.1k/48k/8k) 转换为 PCM Int16
 * @param {Float32Array} float32Array - 原始音频数据
 * @returns {Int16Array} - 转换后的 16位 PCM 数据
 */
export function floatTo16BitPCM(float32Array) {
  var l = float32Array.length
  var buffer = new ArrayBuffer(l * 2)
  var view = new DataView(buffer)
  for (var i = 0; i < l; i++) {
    // 限制范围在 -1 到 1 之间
    var s = Math.max(-1, Math.min(1, float32Array[i]))
    // 转换公式:负数 * 0x8000,正数 * 0x7FFF,并使用小端序 (little-endian)
    view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true)
  }
  return new Int16Array(buffer)
}

/**
 * 将 Uint8Array 二进制数据转换为 Base64 字符串
 * @param {Uint8Array} u8 - 二进制数据
 * @returns {string} - Base64 字符串
 */
export function uint8ArrayToBase64(u8) {
  var CHUNK_SIZE = 0x8000 // 32768
  var index = 0
  var length = u8.length
  var result = ''
  var slice
  // 分块处理防止栈溢出
  while (index < length) {
    slice = u8.subarray(index, Math.min(index + CHUNK_SIZE, length))
    result += String.fromCharCode.apply(null, slice)
    index += CHUNK_SIZE
  }
  return btoa(result)
}

/**
 * 快捷组合函数:直接将 Float32Array 音频数据转为 Base64 字符串
 * (常用于语音对讲发送)
 * @param {Float32Array} float32Array
 * @returns {string}
 */
export function pcmToG711Base64(float32Array) {
  const pcm16 = floatTo16BitPCM(float32Array)
  const u8 = new Uint8Array(pcm16.buffer)
  return uint8ArrayToBase64(u8)
}

export default {
  floatTo16BitPCM,
  uint8ArrayToBase64,
  pcmToG711Base64
}