8

私はしばらくの間、音声認識のデモに取り組んできましたが、API は8000または16000のサンプル レートで .wav ファイルを渡す必要があるため、ダウンサンプリングする必要があります。次のように2つのアルゴリズムを試しました。私が望むように問題を解決するものはありませんが、結果にはいくつかの違いがあり、それがより明確になることを願っています.

これは私の最初の試みであり、sampleRate % outputSampleRate = 0の場合は正常に動作しますが、outputSampleRate = 8000 または 1600の場合、結果のオーディオ ファイルは無音になります (出力配列のすべての要素の値が 0 であることを意味します)。

function interleave(inputL){
  var compression = sampleRate / outputSampleRate;
  var length = inputL.length / compression;
  var result = new Float32Array(length);

  var index = 0,
  inputIndex = 0;

  while (index < length){
    result[index++] = inputL[inputIndex];
    inputIndex += compression;
  }
  return result;
}

これが巨大企業からの 2 回目の試みで、うまくいきませんでした。さらに、sampleRate % outputSampleRate = 0を設定すると、サイレントファイルが出力されます。

function interleave(e){
  var t = e.length;
  var n = new Float32Array(t),
    r = 0,
    i;
  for (i = 0; i < e.length; i++){
    n[r] = e[i];
    r += e[i].length;
  }
  sampleRate += 0.0;
  outputSampleRate += 0.0;
  var s = 0,
  o = sampleRate / outputSampleRate,
  u = Math.ceil(t * outputSampleRate / sampleRate),
  a = new Float32Array(u);
  for (i = 0; i < u; i++) {
    a[i] = n[Math.floor(s)];
    s += o;
  }

  return a
}

設定が間違っていた場合のために、encodeWAV関数を次に示します。

function encodeWAV(samples){
  var sampleBits = 16;
  var dataLength = samples.length*(sampleBits/8);

  var buffer = new ArrayBuffer(44 + dataLength);
  var view = new DataView(buffer);

  var offset = 0;

  /* RIFF identifier */
  writeString(view, offset, 'RIFF'); offset += 4;
  /* file length */
  view.setUint32(offset, 32 + dataLength, true); offset += 4;
  /* RIFF type */
  writeString(view, offset, 'WAVE'); offset += 4;
  /* format chunk identifier */
  writeString(view, offset, 'fmt '); offset += 4;
  /* format chunk length */
  view.setUint32(offset, 16, true); offset += 4;
  /* sample format (raw) */
  view.setUint16(offset, 1, true); offset += 2;
  /* channel count */
  view.setUint16(offset, outputChannels, true); offset += 2;
  /* sample rate */
  view.setUint32(offset, outputSampleRate, true); offset += 4;
  /* byte rate (sample rate * block align) */
  view.setUint32(offset, outputSampleRate*outputChannels*(sampleBits/8), true); offset += 4;
  /* block align (channel count * bytes per sample) */
  view.setUint16(offset, outputChannels*(sampleBits/8), true); offset += 2;
  /* bits per sample */
  view.setUint16(offset, sampleBits, true); offset += 2;
  /* data chunk identifier */
  writeString(view, offset, 'data'); offset += 4;
  /* data chunk length */
  view.setUint32(offset, dataLength, true); offset += 4;

  floatTo16BitPCM(view, offset, samples);

  return view;
}

非常に長い間私を混乱させてきました。私が見逃していたことを教えてください...

----------------------------- 解決後 ------------------ --------------

私はそれが今うまく動いていることをうれしく思います.これが関数interleave()の正しい版です:

    function interleave(e){
      var t = e.length;
      sampleRate += 0.0;
      outputSampleRate += 0.0;
      var s = 0,
      o = sampleRate / outputSampleRate,
      u = Math.ceil(t * outputSampleRate / sampleRate),
      a = new Float32Array(u);
      for (i = 0; i < u; i++) {
        a[i] = e[Math.floor(s)];
        s += o;
      }

      return a;
    }

だから、私が渡した変数が適切な型ではなかったことがわかります~そして、親愛なる@jaketと他の友人に再び感謝します~私は何とかmyslfを理解しましたが、彼らは私に元のものをよりよく知らせてくれました~~~ : )

4

3 に答える 3

0

問題は、浮動小数点数を使用して配列にアクセスしようとしていることです。アクセスinputL[5.5125]すると、 と同じです。つまり、配列データからのアイテムではなく、配列オブジェクトから名前がinput['5.5125']付けられたプロパティを読み取ろうとします。5.5125

最も近い整数インデックスが得られるように数値を丸めます。

function interleave(inputL){
  var compression = sampleRate / outputSampleRate;
  var length = inputL.length / compression;
  var result = new Float32Array(length);

  var index = 0,
  inputIndex = 0;

  while (index < length){
    result[index++] = inputL[Math.round(inputIndex)];
    inputIndex += compression;
  }
  return result;
}
于 2015-08-05T00:01:01.930 に答える