Comments 12
Впечатляет
Атрибут dropzone
не нужен.
// добавляем подсказкуПодсказку в консоль? Не очень хорошая идея, лучше текстом или при наведении на иконку.
console.log(
" Use Keyboard: \n Space to Play/Pause \n Enter to Stop \n Arrows to Change \n Time and Volume"
);
$ = C.getContext(«2d»)Имя переменной по-моему неудачное. Можно подумать, что используется jQuery.
Но в целом материал очень полезный. Странно, что такие статьи не выходят на главную.
Давайте попробуем разобраться что происходит тут:
необходимость использования try/catch обусловлена странным поведением Chrome, связанным с вычислением громкости звука. Попробуйте убрать try/catch и выводить в консоль громкость звука (console.log(audio.volume)) после каждого изменения при приближении к 0 и 1 (согласно спецификации значение громкости звука варьируется от 0.1 до 1) получаем странные значения, которые нивелируют проверки типа if(audio.volume>0 && audio.volume<1). Использование в проверках «неточных» значений вроде 0.1 и 0.9 решает проблему исключений, но приводит к некорректному изменению громкости звука. Исключения работе плеера не мешают, но раздражаютМне стало интересно, я попробовал воспроизвести и не совсем понял в чем заключается «странное поведение»: у меня в Chrome
console.log(audio.volume)
выдает предсказуемые значения в диапазоне (0;1]. А такое решение у вас работает или тоже падает/ведет себя странно?согласно спецификации значение громкости звука варьируется от 0.1 до 1Нет, от 0 до 1.
Смотрите, без try/catch и вашей функции (clampNumber) это выглядит так (уменьшаем громкость):
C вашей функцией так:
Проблема исключений решается, странные значения остаются. Результат такой же, как при использовании try/catch, но пришлось написать целую функцию (которая иногда приводит к громкости = 79, 89 и т.д.). С диапазоном согласен.
document.addEventListener("keydown", e => {
if (e.keyCode == 32) {
audio.paused ? audio.play() : audio.pause();
} else if (e.keyCode == 13) {
audio.load();
} else if (e.keyCode == 39) {
audio.currentTime += 10;
} else if (e.keyCode == 37) {
audio.currentTime -= 10;
} else if (e.keyCode == 40) {
audio.volume -= 0.1;
console.log(audio.volume)
} else if (e.keyCode == 38) {
audio.volume += 0.1;
console.log(audio.volume)
}
});
C вашей функцией так:
document.addEventListener("keydown", e => {
if (e.keyCode == 32) {
audio.paused ? audio.play() : audio.pause();
} else if (e.keyCode == 13) {
audio.load();
} else if (e.keyCode == 39) {
audio.currentTime += 10;
} else if (e.keyCode == 37) {
audio.currentTime -= 10;
} else if (e.keyCode == 40) {
audio.volume = clampNumber(audio.volume - 0.1);
} else if (e.keyCode == 38) {
audio.volume = clampNumber(audio.volume + 0.1);
}
});
Проблема исключений решается, странные значения остаются. Результат такой же, как при использовании try/catch, но пришлось написать целую функцию (которая иногда приводит к громкости = 79, 89 и т.д.). С диапазоном согласен.
Ага, кажется понял о чем вы. «Странные» некруглые значения громкости — это всего лишь артефакт того, что значение храниться во float.
В нормальных (ирония) языках вроде C, где есть отдельно целочисленные и плавающие типы, такое поведение — обычное дело. Там никого не удивишь, что 0.0001 + 0.0002 != 0.0003. А в javascript число представлено одним универсальным типом IEEE 754 binary64. Что позволяет однозначно закодировать (в том числе и) диапазон целых чисел от
А в нашем случае вообще происходит итеративное сложение, которое за каждую операцию накапливает в себе ошибку. Так что это поведение абсолютно нормально. Чтобы видеть красивые ровные проценты в UI — отображаемое значение необходимо округлить. Это стандартная практика.
В нормальных (ирония) языках вроде C, где есть отдельно целочисленные и плавающие типы, такое поведение — обычное дело. Там никого не удивишь, что 0.0001 + 0.0002 != 0.0003. А в javascript число представлено одним универсальным типом IEEE 754 binary64. Что позволяет однозначно закодировать (в том числе и) диапазон целых чисел от
Number.MIN_SAFE_INTEGER
до Number.MAX_SAFE_INTEGER
и как будто бы ожидать от number поведение, свойственное для integer в других языках: 123 + 456 == 579
строго. И это ослабляет бдительность. Ведь по-прежнему 0.1 + 0.2 == 0.30000000000000004
А в нашем случае вообще происходит итеративное сложение, которое за каждую операцию накапливает в себе ошибку. Так что это поведение абсолютно нормально. Чтобы видеть красивые ровные проценты в UI — отображаемое значение необходимо округлить. Это стандартная практика.
И ещё один момент по поводу:
Дело в том, что
это антипаттерн, которого рекомендуют всячески избегать. Ведь вы никогда не узнаете, если что-то другое неожиданно сломается внутри try блока.
Считается, что допустимо использовать try/catch при выполнении трех условий:
Но всё это совершенно не оправдано в нашем случае. И не красиво.
А вот функция
Результат такой же, как при использовании try/catch, но пришлось написать целую функцию
Дело в том, что
catch(everyErrorIDontCare) { return; }
это антипаттерн, которого рекомендуют всячески избегать. Ведь вы никогда не узнаете, если что-то другое неожиданно сломается внутри try блока.
Считается, что допустимо использовать try/catch при выполнении трех условий:
- без ошибок никак иначе не обойтись
- минимально необходимое тело try
- выброс необработанной ошибки наружу
try {
audio.volume = 1.1;
} catch (err) {
if (err instanceof DOMException && err.name === 'IndexSizeError') {
return;
} else {
throw err; // pass any other unhandled error
}
}
Но всё это совершенно не оправдано в нашем случае. И не красиво.
А вот функция
clampNumber()
— вполне self-explaining code. Ведь вам сам API как бы говорит: «программист, позаботься о том, чтобы громкость была в интервале от 0 до 1, иначе я ломаюсь».Когда занимался подобным проектом, попалась интересная библиотека по определению ритма музыки (BPM): web-audio-beat-detector
Работает с применением Web-воркеров
Работает с применением Web-воркеров
А можно такое же, но для бесконечного радиопотока? :)
Sign up to leave a comment.
Работаем с аудио: прогресс и визуализация данных