Vue 前端播放PCM(Websocket返回、base64转ArrayBuffer、下载ArrayBuffer、拼接ArrayBuffer、 ArrayBuffer转Float32Array)

以下是可能用到的函数

// base64 转 ArrayBuffer
function _base64ToArrayBuffer(base64) {
  var binary_string = window.atob(base64); //解码使用base64编码的字符串
  var len = binary_string.length; //获取长度
  var bytes = new Uint8Array(len);
  for (var i = 0; i < len; i++) {
    bytes[i] = binary_string.charCodeAt(i);
  }
  // console.log(bytes); //打印解析出来的byte
  // return bytes;
  return bytes.buffer;
}
// 下载 ArrayBuffer
function download(buff) {
  let url = window.URL.createObjectURL(
    new Blob([buff], { type: "arraybuffer" })
  );
  const link = document.createElement("a");
  link.style.display = "none";
  link.href = url;
  link.setAttribute("download", "out");
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}
// 拼接 ArrayBuffer
function mergeArrayBuffers(arrayBuffers) {
  // 计算新的ArrayBuffer的总长度
  let totalLength = 0;
  for (const buffer of arrayBuffers) {
    totalLength += buffer.byteLength;
  }

  // 创建一个新的ArrayBuffer
  const mergedBuffer = new ArrayBuffer(totalLength);

  // 创建一个Uint8Array以便操作新的ArrayBuffer
  const uint8Array = new Uint8Array(mergedBuffer);

  let offset = 0;
  // 逐个复制ArrayBuffer到新的ArrayBuffer中
  for (const buffer of arrayBuffers) {
    const sourceArray = new Uint8Array(buffer);
    uint8Array.set(sourceArray, offset);
    offset += sourceArray.length;
  }

  return mergedBuffer;
}
// ArrayBuffer 转 Float32Array
function convertArrayBufferToFloat32Array(arrayBuffer) {
  const dataView = new DataView(arrayBuffer);
  // const float32Array = new Float32Array(arrayBuffer.byteLength / Float32Array.BYTES_PER_ELEMENT);
  const float32Array = new Float32Array(arrayBuffer.byteLength / 2);
  for (let i = 0; i < float32Array.length; i++) {
    const pcmValue = dataView.getInt16(i * 2, true);
    float32Array[i] = pcmValue / 32768.0;
  }
  return float32Array;
}

其中PCM的数据 单声道 8000采样率

由于我这边返回的base64,所以需要把base64转换成ArrayBuffer,随后是 ArrayBuffer 转换成 Float32Array,再进行播放操作,另外,由于ws返回的数据太短了,所以这里对返回的数据进行拼接,拼接十段后再进行播放,使音频流畅起来,至于是否需要拼接可根据实际情况考虑,具体代码如下

	  var num = -1;
      var all_ArrayBuffer = [];
      // _this.wsList[index].wsObj.binaryType = "arraybuffer";
      const audioContext = new (window.AudioContext ||
        window.webkitAudioContext)();
      _this.wsList[index].wsObj.onmessage = async (event) => {
        var data = _base64ToArrayBuffer(event.data); // Uint8Array ArrayBuffer

        num++;
        if (num < 10) {
          all_ArrayBuffer.push(data);
        } else if (num == 10) {
          var arr = mergeArrayBuffers(all_ArrayBuffer);
           //   download(arr) // 下载到本地
          all_ArrayBuffer = [];
          num = 0;
          // 将 ArrayBuffer 格式的 PCM 数据转换为 Float32Array 格式
          const float32Array = convertArrayBufferToFloat32Array(arr);

          // 创建 AudioBufferSourceNode
          const audioBufferSource = audioContext.createBufferSource();

          // 创建 AudioBuffer
          const audioBuffer = audioContext.createBuffer(
            1,
            float32Array.length,
            8000
          );

          // 获取 AudioBuffer 的数据通道
          const channelData = audioBuffer.getChannelData(0);

          // 将 Float32Array 格式的 PCM 数据填充到 AudioBuffer 的数据通道
          channelData.set(float32Array);

          // 将 AudioBuffer 设置为 AudioBufferSourceNode 的音频数据
          audioBufferSource.buffer = audioBuffer;

          // 连接 AudioBufferSourceNode 到音频输出
          audioBufferSource.connect(audioContext.destination);

          // 播放音频
          audioBufferSource.start();
        }
      };
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值