Я некоторое время работал над демонстрацией распознавания звука, и API требует, чтобы я передал файл .wav с частотой дискретизации 8000 или 16000, поэтому я должны уменьшить его. Я пробовал 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;
}
Итак, вот моя вторая попытка от гигантской компании, и она тоже не работает. Более того, когда я устанавливаю sampleRate % outputSampleRate = 0, он по-прежнему выводит файл silent:
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 и других друзей~ Хотя я как-то сам это понял, они позволили мне лучше узнать исходные вещи~~~ : )