Safari - Невозможно создать Осциллятор после первых нескольких - PullRequest
0 голосов
/ 01 апреля 2020

Я пытаюсь работать с API WebAudio, но у меня возникают проблемы с его корректной работой с Safari. Мой эксперимент работает правильно с Firefox и Chrome.

Я написал функцию Promisified для воспроизведения одной ноты, а затем попытался воспроизвести серию нот с помощью этой функции.

Только в Safari происходит сбой после первых четырех заметок со следующим сообщением:

Отклонение необработанного обещания: TypeError: null не является объектом (оценивает context.createOscillator)

ОК, я не обработал ошибку, но почему я ее получаю? Он предполагает ограничение в четыре генератора.

function tone(frequency,duration) {
	return new Promise(function (resolve,reject) {
		var audioContext = window.AudioContext || window.webkitAudioContext;
		var context=new audioContext;
		var oscillator = context.createOscillator();
		oscillator.frequency.value = frequency;
		oscillator.connect(context.destination);
		oscillator.type='sawtooth';
		oscillator.start(context.currentTime);
		oscillator.stop(context.currentTime+duration);
		oscillator.onended=resolve;
	});
}
document.querySelector('button#play-test').onclick=function(event) {
	tone(130.81,1)
	.then(()=>tone(146.83,1))
	.then(()=>tone(164.81,1))
	.then(()=>tone(174.61,1))
	.then(()=>tone(196.00,1))
	;
};
<button id="play-test">Play</button>

1 Ответ

2 голосов
/ 01 апреля 2020

Ограничение на количество AudioContexts, которое вы можете запускать одновременно.

У некоторых браузеров есть такое ограничение, потому что AudioContext требует ресурсов от Аппаратного обеспечения (звуковая карта) и что это Аппаратное обеспечение имеет ограничения.

Проведите рефакторинг вашего кода, чтобы он не создавал новый AudioContext каждый раз:

// create a single audio context
var context = new (window.AudioContext || window.webkitAudioContext)();

function tone(frequency, duration) {
  return new Promise(function(resolve, reject) {
    var oscillator = context.createOscillator();
    oscillator.frequency.value = frequency;
    oscillator.connect(context.destination);
    oscillator.type = 'sawtooth';
    oscillator.start(context.currentTime);
    oscillator.stop(context.currentTime + duration);
    oscillator.onended = resolve;
  });
}
document.querySelector('button#play-test').onclick = function(event) {
  tone(130.81, 1)
    .then(() => tone(146.83, 1))
    .then(() => tone(164.81, 1))
    .then(() => tone(174.61, 1))
    .then(() => tone(196.00, 1))
    .catch(console.error);
};
<button id="play-test">Play</button>
...