【问题标题】:Record audio on web, preset: 16000Hz 16bit网络录音,预设:16000Hz 16bit
【发布时间】:2015-03-10 16:39:31
【问题描述】:
function floatTo16BitPCM(output, offset, input){
  for (var i = 0; i < input.length; i++, offset+=2){
    var s = Math.max(-1, Math.min(1, input[i]));
    output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
  }
}

function writeString(view, offset, string){
  for (var i = 0; i < string.length; i++){
    view.setUint8(offset + i, string.charCodeAt(i));
  }
}

function encodeWAV(samples){
  var buffer = new ArrayBuffer(44 + samples.length * 2);
  var view = new DataView(buffer);

  /* RIFF identifier */
  writeString(view, 0, 'RIFF');
  /* RIFF chunk length */
  view.setUint32(4, 36 + samples.length * 2, true);
  /* RIFF type */
  writeString(view, 8, 'WAVE');
  /* format chunk identifier */
  writeString(view, 12, 'fmt ');
  /* format chunk length */
  view.setUint32(16, 16, true);
  /* sample format (raw) */
  view.setUint16(20, 1, true);
  /* channel count */
  view.setUint16(22, 2, true);
  /* sample rate */
  view.setUint32(24, sampleRate, true);
  /* byte rate (sample rate * block align) */
  view.setUint32(28, sampleRate * 4, true);
  /* block align (channel count * bytes per sample) */
  view.setUint16(32, 4, true);
  /* bits per sample */
  view.setUint16(34, 16, true);
  /* data chunk identifier */
  writeString(view, 36, 'data');
  /* data chunk length */
  view.setUint32(40, samples.length * 2, true);

  floatTo16BitPCM(view, 44, samples);

  return view;
}

您好,我正在使用此源代码为我的学校考试录制音频。它以 44100Hz 和 16 位录制音频。我想更改录制设置以录制 16000Hz 和 16 位的音频。 我尝试将函数 encodeWAV 中的 44 修改为 16,但没有成功。

function encodeWAV(samples){
  var buffer = new ArrayBuffer(44 + samples.length * 2);
  var view = new DataView(buffer)

我也尝试过更改 floadRToBitPCM。我试图将 44 更改为 16,但它也没有工作。

floatTo16BitPCM(view, 44, samples);

你能帮我解决这个问题吗?我不知道如何修改这个源代码。

【问题讨论】:

  • 您的 sampleRate 变量在哪里设置?

标签: javascript audio record web-audio-api


【解决方案1】:

编辑:

另一种选择(IMO 更好)就是使用 HTML 的 MediaRecorder 并以 .ogg 格式记录,demo,它是 git repo


我假设您使用this 作为源,就像jaket 所说,floatTo16BitPCM(view, 44, samples); 行与采样率无关...

如果你想重新采样数据,你可以修改这个:

function exportWAV(type){
    var buffers = [];
    for (var channel = 0; channel < numChannels; channel++){
        buffers.push(mergeBuffers(recBuffers[channel], recLength));
    }
    if (numChannels === 2){
        var interleaved = interleave(buffers[0], buffers[1]);
    } else {
        var interleaved = buffers[0];
    }
    var dataview = encodeWAV(interleaved);
    var audioBlob = new Blob([dataview], { type: type });
    this.postMessage(audioBlob);
}

进入这个:

function exportWAV(type, desiredSamplingRate){
    var buffers = [];
    for (var channel = 0; channel < numChannels; channel++){
        var buffer = mergeBuffers(recBuffers[channel], recLength);
        buffer = interpolateArray(buffer, desiredSamplingRate, sampleRate);
        buffers.push(buffer);
    }
    sampleRate = desiredSamplingRate;
    if (numChannels === 2){
        var interleaved = interleave(buffers[0], buffers[1]);
    } else {
        var interleaved = buffers[0];
    }
    var dataview = encodeWAV(interleaved);
    var audioBlob = new Blob([dataview], { type: type });
    this.postMessage(audioBlob);
}

重新采样数据的代码,

// for changing the sampling rate, data,
function interpolateArray(data, newSampleRate, oldSampleRate) {
    var fitCount = Math.round(data.length*(newSampleRate/oldSampleRate));
    var newData = new Array();
    var springFactor = new Number((data.length - 1) / (fitCount - 1));
    newData[0] = data[0]; // for new allocation
    for ( var i = 1; i < fitCount - 1; i++) {
    var tmp = i * springFactor;
    var before = new Number(Math.floor(tmp)).toFixed();
    var after = new Number(Math.ceil(tmp)).toFixed();
    var atPoint = tmp - before;
    newData[i] = this.linearInterpolate(data[before], data[after], atPoint);
    }
    newData[fitCount - 1] = data[data.length - 1]; // for new allocation
    return newData;
};
function linearInterpolate(before, after, atPoint) {
    return before + (after - before) * atPoint;
};

编辑:如果你不想改变太多,你可以硬编码为

function exportWAV(type){
    var buffers = [], desiredSamplingRate = 16000;

【讨论】:

  • 是的,你是对的,我使用这个来自 github.com 的源代码。正如您在上面写的那样,我已尝试根据您的说明修改代码。一切似乎都很好,但是当我将录制的声音下载到 PC 时,它无法打开。打开时出错,提示音频不支持格式。似乎音频已损坏或以 PC 不支持的格式录制。
  • 检查这段代码,github.com/Mido22/tmp1,对我来说,它适用于 linux 环境中的 firefoxchrome...
  • 请注意,在不使用 sinc 滤波器(“砖墙”低通滤波器)的情况下使用线性插值显着降低采样可能会导致高频内容出现一些严重的混叠问题。
  • @cwilso 我认为 OP 正在尝试为某个项目录制人声,所以我猜我们不需要担心高频位...
  • @mido22 我已经尝试实现您的源代码。它可以工作,所以它可以录制声音,我也可以将录制的声音下载到我的电脑上并播放。但是有一个问题:录制声音变慢了。录制的声音比应有的更慢,更深沉。录音已损坏。
【解决方案2】:

我不相信您可以使用 Web Audio API 控制采样率……它会采用在浏览器外部定义的系统默认采样率……当然,在录制之后,您可以以编程方式更改音频以重新采样到任何采样率...大多数音频播放器只能播放标准采样率的媒体...能够渲染 16 kHz 的非采样率可能比从 44.1 到 16 kHz 重新采样更具挑战性

【讨论】:

    【解决方案3】:

    您正在修改错误的字段。波形文件是一个标题,后面跟着数据。波头通常长 44 个字节。您在示例代码中看到的 44 的值与此相关,而不是与 44100 相关。

    在您尚未发布的代码中,sampleRate 被定义为 44100。您需要跟踪该定义并将其更改为 16000。根据您的其余代码和示例的来源,它可能不是不过就这么简单。例如,如果正在从设备记录样本,并且设备已配置为在 44100 记录,那么简单地将保存的波形标记为 16000 不会产生预期的效果。它只会让播放速度降低 2.75 倍,也就是 Barry White 效果。

    【讨论】:

      【解决方案4】:

      您可以像这样更改初始化函数,在这里您可以将默认浏览器采样率更改为 16000 以及指示单声道/立体声的通道,我们也可以更改该通道, 如果是单声道,则为 1 ,否则为 2 。

       function init(config) {
                  //sampleRate = config.sampleRate;
                  sampleRate = 16000;
                  debugger;
                  //numChannels = config.numChannels;
                  numChannels = 1;
                  initBuffers();
              }
      

      【讨论】:

        猜你喜欢
        • 2012-10-11
        • 1970-01-01
        • 1970-01-01
        • 2014-02-09
        • 1970-01-01
        • 1970-01-01
        • 2021-09-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多