07.12.2019, 23:54
|
Новичок на форуме
|
|
Регистрация: 07.12.2019
Сообщений: 1
|
|
Перевод из byte массива в звук
f (this.chatSocket) {
let context = new AudioContext();
let buf;
this.chatSocket.onmessage = function (e) {
let data = JSON.parse(e.data);
let message = data['message'];
let byteArray = Array();
for (let key in message) {
byteArray.push(message[key])
}
var arrayBuffer = new ArrayBuffer(byteArray.length);
var bufferView = new Uint8Array(arrayBuffer);
for (let i = 0; i < byteArray.length; i++) {
bufferView[i] = byteArray[i];
}
context.decodeAudioData(arrayBuffer, function (buffer) {
buf = buffer;
play()
});
};
function play() {
var source = context.createBufferSource();
source.buffer = buf;
// Connect to the final output node (the speakers)
source.connect(context.destination);
// Play immediately
source.start(0);
}
Здравствуйте. Пытаюсь перевести массив байтов в звук, но выдает ошибку Uncaught (in promise) DOMException: Unable to decode audio data
Подскажите как решить эту проблему
|
|
09.12.2019, 00:15
|
|
Аспирант
|
|
Регистрация: 10.09.2019
Сообщений: 35
|
|
А почему Вы пытаетесь декодировать массив байт, он как-то закодирован? Если нет, то его бы загнать напрямую в source.buffer без декодирования, только с определённым преобразованием. А decodeAudioData() предназначена для декодирования последовательности байт, которая представляет собой полное содержимое аудиофайла какого-то стандартного формата - MP3, OGG, WAV и т. п. У них есть заголовок со служебной информацией, сколько байт занимает один семпл, моно или стерео, и т. д., чтобы было известно, как его следует декодировать.
Последний раз редактировалось Опан1, 09.12.2019 в 00:22.
|
|
09.12.2019, 02:44
|
|
Аспирант
|
|
Регистрация: 10.09.2019
Сообщений: 35
|
|
Я же сказал - с преобразованиями. Если я правильно помню, перед воспроизведением все семплы должны быть в пределах от -1 до 1 с запятой.
Последний раз редактировалось Опан1, 09.12.2019 в 02:46.
|
|
09.12.2019, 23:54
|
|
Аспирант
|
|
Регистрация: 10.09.2019
Сообщений: 35
|
|
<button onclick="bytes_to_sound()"> Перевести из byte массива в звук </button>
<script>
var myarray = [], // тут будут байты для превращения в звук
a = b = 0,
c = 1;
for(i = 0; i < 44100; i ++){
myarray.push(Math.floor(a + b));
a += c; b += c * 0.75; c /= 1.000003;
if(a > 127) a = 0;
if(b > 127) b = 0;
} // байты готовы. ( звук сирены )
function bytes_to_sound(){
var context = new AudioContext();
var myBuffer = context.createBuffer(1, context.sampleRate, context.sampleRate);
var nowBuffering = myBuffer.getChannelData(0); // наверно, екземпляр, о котором Вы говорили
for (var i = 0; i < myBuffer.length; i ++) nowBuffering[i] = myarray[i] / 128 - 1; // преобразование, о котором я говорил
// другими словами, чтобы пределы значений от 0 до 255 превратились в пределы значений от -1 до 1
var source = context.createBufferSource();
source.buffer = myBuffer;
source.connect(context.destination);
source.start(0);
}
</script>
Это пример, показывающий, как можно массив байт перевести в звук. Ни decodeAudioData(), ни ArrayBuffer для этого не нужны. А в Вашем, symbians60v5, случае попробуйте так:
<button onclick="bytes_to_sound()"> Перевести из byte массива в звук </button>
if (this.chatSocket) {
this.chatSocket.onmessage = function (e) {
let data = JSON.parse(e.data);
let message = data['message'];
byteArray = new Array();
for (let key in message) {
byteArray.push(message[key]);
}
}
}
function bytes_to_sound(){
let context = new AudioContext();
var myBuffer = context.createBuffer(1, byteArray.length, context.sampleRate);
var nowBuffering = myBuffer.getChannelData(0);
for (var i = 0; i < myBuffer.length; i ++) nowBuffering[i] = byteArray[i] / 128 - 1;
var source = context.createBufferSource();
source.buffer = myBuffer;
source.connect(context.destination);
source.start(0);
}
Последний раз редактировалось Опан1, 10.12.2019 в 01:44.
|
|
10.12.2019, 22:39
|
|
Аспирант
|
|
Регистрация: 10.09.2019
Сообщений: 35
|
|
Самый первый аргумент указывает на количество каналов. В данном случае - 1. (моно) Второй аргумент - количество семплов. Тут выходит 44100. Третий - частота семплирования воспроизведения, которая тут определяется, как частота семплирования по умолчанию. У вас, видимо, 48000, наверно зависит от звуковой карты или драйвера звуковухи. Раньше у меня была материнка с картой AC-97 и там частота по умолчанию была 44100. Третьим аргументом может быть число, задающее частоту семплирования.
Последний раз редактировалось Опан1, 10.12.2019 в 22:49.
|
|
10.12.2019, 23:53
|
|
Аспирант
|
|
Регистрация: 10.09.2019
Сообщений: 35
|
|
Т. е., хотите сказать, что с помощью decodeAudioData() это можно определить? Каким образом?
К примеру, каждый семпл занимает байт Если в context.createBuffer() указать один канал, то каждый байт следует читать, как новый семпл, если указать 2 канала - то каждый первый байт будет для левого, а каждый второй для правого канала, и т. д. Если Каждый семпл занимает 2 байта, то первый из них следует читать, как младшую половину всего слова, второй - старшую. Если эти ещё и стерео, то на каждый семпл придётся соответственно 4 байта. Так и читать.
Да, как с помощью decodeAudioData() заставить массив байт играть с нужной частотой семплирования? Т. е., как это значение декодировать из массива байт?
Т. е., у аудиофайла стандартного формата есть заголовок - в таком-то байте находится количество каналов, в таком-то - количество байт на семпл, в таких-то байтах частота семплирования. Где эта информация в массиве байт?
Последний раз редактировалось Опан1, 11.12.2019 в 02:09.
|
|
12.12.2019, 00:49
|
|
Аспирант
|
|
Регистрация: 10.09.2019
Сообщений: 35
|
|
Я знаю, но перед этим Вы говорили, что без декодирования sampleRate будет неопределённым.
Последний раз редактировалось Опан1, 12.12.2019 в 00:52.
|
|
|
|