• JavaScript web端录音测试噪声


    流程:

    1. 使用scriptprocessor记录前端音频流,转换成Float32Array
    2. 将Float32Array转换成16bit PCM
    3. 计算公式:引用:如何计算音频dB级别?

    代码:

      function floatTo16BitPCM(output: DataView, offset: number, input: Float32Array) {
        for (let i = 0; i < input.length; i++, offset += 2) {
          let s = Math.max(-1, Math.min(1, input[i]));
          output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);
        }
      }
    
      function onMediaSuccess(stream): Promise<Float32Array[]> {
        return new Promise(resolve => {
          const context = new AudioContext();
          const audioInput = context.createMediaStreamSource(stream);
          var inputData = [];
          const recorder = context.createScriptProcessor(4096, 1, 1);
          recorder.onaudioprocess = function(e) {
            var data = e.inputBuffer.getChannelData(0);
            inputData.push(new Float32Array(data));
          };
          audioInput.connect(recorder);
          recorder.connect(context.destination);
          setTimeout(() => {//噪声录音至少需要1s,数据才可用
            resolve(inputData);
            recorder.disconnect();
            audioInput.disconnect();
            if (stream) {
              stream.getAudioTracks().forEach(function(track) {
                track.stop();
              });
              stream = null;
            }
          }, 1000);
        });
      }
    
      //数据合并
      function compress(inputData: Float32Array[]) {
        let size = 0;
        for (let i = 0; i < inputData.length; i++) {
          size += inputData[i].length;
        }
        var data = new Float32Array(size);
        var offset = 0;
        for (var i = 0; i < inputData.length; i++) {
          data.set(inputData[i], offset);
          offset += inputData[i].length;
        }
        return data;
      }
      
      //record button click
      const onRecord = () => {
        navigator.mediaDevices.getUserMedia(mediaConstraints).then(async function computeNoise(stream) {
          const inputData = await onMediaSuccess(stream);
          const samples = compress(inputData);
          const db = getDB(samples);
          Recording(db);//正式录音
        });
      };
    
      //计算DB
      const getDB = (samples: Float32Array): number => {
        const bitDepth = 16;
        const bytesPerSample = bitDepth / 8;
        const offset = 0;
        let buffer = new ArrayBuffer(samples.length * bytesPerSample);
        let view = new DataView(buffer);
        floatTo16BitPCM(view, offset, samples);
    
        const int16Audio = new Int16Array(buffer);
    
        let avgEnergy = 0;
        int16Audio.forEach(fragment => {
          avgEnergy += fragment * fragment;
        });
    
        avgEnergy = Math.sqrt(avgEnergy / int16Audio.length);
        const db = 20 * Math.log10(avgEnergy / 32767);
        return Number(db.toFixed(3));
      };
    

    参考:js实现pcm数据编码

  • 相关阅读:
    给定一个十进制数M,以及需要转换的进制数N。 将十进制数M转化为N进制数
    java计算两条线段交点
    输入两个整数n和m,从数列1,2,3,……n中随意取几个数,使其和等于m 转载
    全排列 (递归求解+字典序) java 转载
    四大线程池详解(转载)
    生产者消费者简单实现(转载)
    进程 线程通信方式(转载)
    匿名对象和类名为数据类型(java)
    星星(java)
    杨辉三角(java)
  • 原文地址:https://www.cnblogs.com/xym4869/p/13638008.html
Copyright © 2020-2023  润新知