Как воспроизвести аудио-байтовый массив wav через javascript/html5?
Я использую следующий метод для воспроизведения байтового массива, содержащего данные WAV. Функция вызывается из проекта GWT.
Эта функция воспроизводит звук, но звучит как какой-то адский монстр. Частота дискретизации определенно правильная (звук генерируется Neospeech), и я попробовал все виды значений для numberOfSamples, которые, кажется, просто представляют, как долго аудио данные.
Значение больше 30000 для numberOfSamples будет воспроизводить полную длину аудиофайла, но оно искажено и ужасно.
Итак, что я делаю не так?
function playByteArray(byteArray, numberOfSamples) {
sampleRate = 8000;
if (!window.AudioContext) {
if (!window.webkitAudioContext) {
alert("Your browser does not support any AudioContext and cannot play back this audio.");
return;
}
window.AudioContext = window.webkitAudioContext;
}
var audioContext = new AudioContext();
var buffer = audioContext.createBuffer(1, numberOfSamples, sampleRate);
var buf = buffer.getChannelData(0);
for (i = 0; i < byteArray.length; ++i) {
buf[i] = byteArray[i];
}
var source = audioContext.createBufferSource();
source.buffer = buffer;
source.connect(audioContext.destination);
source.start(0);
}
2 ответа
Я понял, как сделать то, что я описал в своем вопросе, и подумал, что я должен опубликовать это для блага других. Код ниже. Я вызываю playByteArray и передаю ему байтовый массив, содержащий wav-данные pcm.
window.onload = init;
var context; // Audio context
var buf; // Audio buffer
function init() {
if (!window.AudioContext) {
if (!window.webkitAudioContext) {
alert("Your browser does not support any AudioContext and cannot play back this audio.");
return;
}
window.AudioContext = window.webkitAudioContext;
}
context = new AudioContext();
}
function playByteArray(byteArray) {
var arrayBuffer = new ArrayBuffer(byteArray.length);
var bufferView = new Uint8Array(arrayBuffer);
for (i = 0; i < byteArray.length; i++) {
bufferView[i] = byteArray[i];
}
context.decodeAudioData(arrayBuffer, function(buffer) {
buf = buffer;
play();
});
}
// Play the loaded file
function play() {
// Create a source node from the buffer
var source = context.createBufferSource();
source.buffer = buf;
// Connect to the final output node (the speakers)
source.connect(context.destination);
// Play immediately
source.start(0);
}
Очистить предложение:
function playByteArray( bytes ) {
var buffer = new Uint8Array( bytes.length );
buffer.set( new Uint8Array(bytes), 0 );
context.decodeAudioData(buffer.buffer, play);
}
function play( audioBuffer ) {
var source = context.createBufferSource();
source.buffer = audioBuffer;
source.connect( context.destination );
source.start(0);
}
Этот подход будет работать с последним сафари iOS по сравнению с AudioContext. Аудиообъект должен быть создан при событии касания / щелчка (взаимодействия с пользователем), поэтому не делайте этого в обратных вызовах запроса.
const audio = new Audio()
fetch(url, options) // set content header to array buffer
.then((response) => {
var blob = new Blob([response.value], { type: 'audio/mp3' })
var url = window.URL.createObjectURL(blob)
audio.src = url
audio.play()
})
фрагмент отсюда