Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 07.12.2019, 23:54
Новичок на форуме
Отправить личное сообщение для symbians60v5 Посмотреть профиль Найти все сообщения от symbians60v5
 
Регистрация: 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
Подскажите как решить эту проблему
Ответить с цитированием
  #2 (permalink)  
Старый 08.12.2019, 12:45
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 4,662

А в message какое значение получается? Судя по дальнейшей логике, там должен быть массивоподобный объект чисел 0-255:
{ 0: 8, 1: 12, 2: 19, ... }

Последний раз редактировалось Rise, 08.12.2019 в 12:59.
Ответить с цитированием
  #3 (permalink)  
Старый 09.12.2019, 00:15
Аватар для Опан1
Аспирант
Отправить личное сообщение для Опан1 Посмотреть профиль Найти все сообщения от Опан1
 
Регистрация: 10.09.2019
Сообщений: 35

А почему Вы пытаетесь декодировать массив байт, он как-то закодирован? Если нет, то его бы загнать напрямую в source.buffer без декодирования, только с определённым преобразованием. А decodeAudioData() предназначена для декодирования последовательности байт, которая представляет собой полное содержимое аудиофайла какого-то стандартного формата - MP3, OGG, WAV и т. п. У них есть заголовок со служебной информацией, сколько байт занимает один семпл, моно или стерео, и т. д., чтобы было известно, как его следует декодировать.

Последний раз редактировалось Опан1, 09.12.2019 в 00:22.
Ответить с цитированием
  #4 (permalink)  
Старый 09.12.2019, 01:40
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 4,662

Опан1,
Массив байт нельзя загнать напрямую в source.buffer, потому что массив байт это ArrayBuffer, а source.buffer это AudioBuffer.
Ответить с цитированием
  #5 (permalink)  
Старый 09.12.2019, 02:44
Аватар для Опан1
Аспирант
Отправить личное сообщение для Опан1 Посмотреть профиль Найти все сообщения от Опан1
 
Регистрация: 10.09.2019
Сообщений: 35

Я же сказал - с преобразованиями. Если я правильно помню, перед воспроизведением все семплы должны быть в пределах от -1 до 1 с запятой.

Последний раз редактировалось Опан1, 09.12.2019 в 02:46.
Ответить с цитированием
  #6 (permalink)  
Старый 09.12.2019, 08:14
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 4,662

Опан1,
Есть всего два способа получить AudioBuffer это decodeAudioData() и createBuffer(), но для последнего аргументы неизвестны, потому что имеется только ArrayBuffer. Непонятно что тут преобразовывать... Массивы семплов тоже нельзя загнать напрямую в source.buffer, всё равно нужен экземпляр AudioBuffer.

Последний раз редактировалось Rise, 09.12.2019 в 08:22.
Ответить с цитированием
  #7 (permalink)  
Старый 09.12.2019, 23:54
Аватар для Опан1
Аспирант
Отправить личное сообщение для Опан1 Посмотреть профиль Найти все сообщения от Опан1
 
Регистрация: 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.
Ответить с цитированием
  #8 (permalink)  
Старый 10.12.2019, 13:17
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 4,662

Сообщение от Опан1
// наверно, екземпляр, о котором Вы говорили
// преобразование, о котором я говорил
nowBuffering это ArrayBuffer в виде Float32Array, а экземпляр AudioBuffer это myBuffer. Манипулировать ArrayBuffer напрямую нельзя, можно через так называемые view, типизированные массивы. У view есть свойство buffer, которое указывает на ArrayBuffer, который оно представляет (nowBuffering.buffer).
Сообщение от Опан1
context.createBuffer(1, byteArray.length, context.sampleRate)
А как узнать сколько каналов и какая частота, ведь помимо моно популярно и стерео, частота тоже разная бывает, у меня например 48000, а не 44100?

Последний раз редактировалось Rise, 10.12.2019 в 13:26.
Ответить с цитированием
  #9 (permalink)  
Старый 10.12.2019, 22:39
Аватар для Опан1
Аспирант
Отправить личное сообщение для Опан1 Посмотреть профиль Найти все сообщения от Опан1
 
Регистрация: 10.09.2019
Сообщений: 35

Самый первый аргумент указывает на количество каналов. В данном случае - 1. (моно) Второй аргумент - количество семплов. Тут выходит 44100. Третий - частота семплирования воспроизведения, которая тут определяется, как частота семплирования по умолчанию. У вас, видимо, 48000, наверно зависит от звуковой карты или драйвера звуковухи. Раньше у меня была материнка с картой AC-97 и там частота по умолчанию была 44100. Третьим аргументом может быть число, задающее частоту семплирования.

Последний раз редактировалось Опан1, 10.12.2019 в 22:49.
Ответить с цитированием
  #10 (permalink)  
Старый 10.12.2019, 23:02
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 4,662

Опан1,
Я понимаю что значат аргументы, вопрос не в этом, а в том что данные очевидно приходят от другого пользователя чата, невозможно знать какое аудио он отправит, это может быть 32 канала 98000 Гц или 10 каналов 8000 Гц, и тд. Это мы подошли к изначальному вопросу из поста 3 про зачем декодировать массив.

Последний раз редактировалось Rise, 10.12.2019 в 23:07.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Соединение массива Artur_Hopf Общие вопросы Javascript 4 07.06.2018 16:48
Обход многомерного массива с задержкой после каждого цикла Walk Общие вопросы Javascript 2 14.08.2017 16:17
Помогите к js коду, написать html код Modrih Элементы интерфейса 8 16.06.2015 18:08
Ввод диапазона значений массива с клавиатуры Воскобоенко Общие вопросы Javascript 11 06.06.2015 22:34
Как проиграть звук на сайте один раз за сеанс. tuchkovo-auto Общие вопросы Javascript 3 21.05.2014 11:13