発生状況
iOS 14.4 のブラウザ(Safari, Chrome で確認)で、
サンプルレート 8000Hz 以上 22050Hz 未満の音声素材を再生しようとすると、
vorbisdecoder.js
が
RangeError: Range consisting of offset and length are out of bounds
を吐いて死ぬ。
原因考察
算出された総サンプル数以上の音声データをバッファに入れようとして死んでる?
concatenate() {
for (let i = 0; i < this.channels; i++) {
this.data = new Float32Array(this.totalSamples);
let offset = 0;
for (const array of this.arrays) {
this.data.set(array, offset); // <- ここでエラる
offset += array.length;
}
}
}
どうもこの if 文によって、8000 ~ 22049Hz のサンプルレートが指定されたら、
sampleScale を変更するようになってるっぽい。
this.sampleRate = Module.getValue(this.v + 0, "i32");
this.sampleScale = 1;
if (this.sampleRate >= 8e3 && this.sampleRate < 22050) { // <-
this.sampleScale = Math.ceil(22050 / this.sampleRate); // <- なにこれ
} // <-
this.totalSamples = 0;
この計算式が、なんかおかしいのかも。
応急処置
こうしたら一応出なくなった。
this.sampleRate = Module.getValue(this.v + 0, "i32");
this.sampleScale = 1;
if (this.sampleRate >= 8e3 && this.sampleRate < 22050) {
- this.sampleScale = Math.ceil(22050 / this.sampleRate);
+ this.sampleScale = Math.floor(22050 / this.sampleRate);
}
this.totalSamples = 0;
これでも一応動いた。
this.sampleRate = Module.getValue(this.v + 0, "i32");
this.sampleScale = 1;
- if (this.sampleRate >= 8e3 && this.sampleRate < 22050) {
- this.sampleScale = Math.ceil(22050 / this.sampleRate);
- }
this.totalSamples = 0;
ただ、この対処法では何か問題があるかもしれないので、様子見したい。
追伸
公式に報告した
あと、このデバッグにあたり Windows 上で iPhone デバッグをしたので、そのやり方も記事にした。