Javascript — API веб-аудио — ввод типа диапазона не является динамическим в Firefox, но является динамическим в Chrome — добавлен репрекс

  • Контроллер усиления работает динамически в хроме, а в фаерфоксе нет. Мне нужно воспроизвести аудиофайл, чтобы браузер распознал новое входное значение диапазона ввода для Firefox. Я не мог понять, почему.
  • Кстати, вам нужно поместить mp3-файл в часть «example.mp3».
  • Я новичок здесь. Пробовал репрекс. Извините, если не так, как должно быть

[HTML + Javascript]

<!DOCTYPE html>
<html lang = "en">
  <head>
    <meta charset = "UTF-8" />
    <meta http-equiv = "X-UA-Compatible" content = "IE=edge" />
    <meta name = "viewport" content = "width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel = "stylesheet" href = "style.css" />
  </head>
  <body>
    <div>
      <button class = "button">click</button>
      <input
        class = "input"
        type = "range"
        step = "0.01"
        min = "0"
        max = "1.20"
        value = "0.60"
      />
    </div>
  </body>
  <script src = "script.js" type = "text/javascript"></script>
</html>
<script type = "text/javascript">
  loopify("example.mp3", function (err, loop) {
    // If something went wrong, `err` is supplied
    document.querySelector(".button").dataset.playing = "false";
    if (err) {
      return console.err(err);
    }

    document.querySelector(".button").addEventListener("click", function () {
      if (this.dataset.playing === "false") {
        loop.play();

        this.dataset.playing = "true";
      } else if (this.dataset.playing === "true") {
        setTimeout(loop.stop, 250);
        this.dataset.playing = "false";
      }
    });
  });
</script>

[Яваскрипт]

(function () {
  function loopify(uri, cb) {
    var context = new (window.AudioContext || window.webkitAudioContext)(),
      request = new XMLHttpRequest();
    const gainNode = context.createGain();

    request.responseType = "arraybuffer";
    request.open("GET", uri, true);

    // XHR failed
    request.onerror = function () {
      cb(new Error("Couldn't load audio from " + uri));
    };

    // XHR complete
    request.onload = function () {
      context.decodeAudioData(request.response, success, function (err) {
        // Audio was bad
        cb(new Error("Couldn't decode audio from " + uri));
      });
    };

    request.send();

    function success(buffer) {
      var source;

      // fade-out
      document.querySelector(".button").onclick = function () {
        if (this.dataset.playing === "true") {
          gainNode.gain.setTargetAtTime(0, context.currentTime, 0.25);
        }
      };
      function play() {
        // Stop if it's already playing
        stop();

        // Create a new source (can't replay an existing source)
        source = context.createBufferSource();
        source.connect(gainNode).connect(context.destination);
        // fade-in
        gainNode.gain.value = 0.1;
        gainNode.gain.setTargetAtTime(
          document.querySelector(".input").value,
          context.currentTime,
          0.25
        );
        //gain input assignment
        document.querySelector(".input").addEventListener(
          "input",
          function () {
            gainNode.gain.value = this.value;
          },
          false
        );

        // Set the buffer
        source.buffer = buffer;
        source.loop = true;

        // Play it

        source.start(0);
      }

      function stop() {
        // Stop and clear if it's playing
        if (source) {
          source.stop();
          source = null;
        }
      }

      cb(null, {
        play: play,
        stop: stop,
      });
    }
  }

  loopify.version = "0.1";

  if (typeof define === "function" && define.amd) {
    define(function () {
      return loopify;
    });
  } else if (typeof module === "object" && module.exports) {
    module.exports = loopify;
  } else {
    this.loopify = loopify;
  }
})();

[CSS]

div {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

Что означает динамично в этом контексте? И можете ли вы создать минимальный воспроизводимый пример для отладки вашей проблемы?

Emiel Zuurbier 08.05.2022 20:44

Спасибо за ваш комментарий, я не смог добавить его в тот день, поэтому это заняло некоторое время, но я отредактировал первый пост с репрексом.

Clarity 15.05.2022 00:01

Этот вопрос остался без ответа, потому что до сих пор неясно, о чем спрашивают. Что подразумевается под «ввод типа диапазона не является динамическим»? Похоже, вход используется как регулятор громкости. И код, похоже, основан на этом устаревшем ЖКТ, который специально предназначен для зацикливания звука. Есть ли требование для «бесперебойного» цикла или обычный аудиоэлемент тоже подойдет? Код действительно довольно беспорядочный и может быть сильно рефакторинг.

Yogi 15.05.2022 02:17

@Yogi, извините за беспорядок. разработчик-стажер здесь. Да, моя ситуация связана с зацикливанием без пропусков, и я искал эталонное репо, чтобы начать с веб-аудио API, и нашел его (veltman-loopify). Сейчас он работает великолепно, так как Эмиэль Зуурбир дал мне решение. Но вы сказали, что это устарело. Есть ли более выгодный способ сделать бесконечную звуковую петлю?

Clarity 15.05.2022 18:40

Да, @EmielZuurbier провел для вас отличное исследование и устранил неполадки. Что касается библиотек без пробелов, та, которую вы используете, не обновлялась 7 лет и действительно написана не очень хорошо. Я не специалист по аудио, но на GitHub есть более новые и популярные библиотеки. Например, вот тот, который был недавно обновлен и кажется намного проще в использовании: Без зазоров 5

Yogi 15.05.2022 19:41
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
37
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

После некоторых экспериментов и попыток воспроизвести ваш код я наткнулся на кое-что любопытное.

Всякий раз, когда мы используем gainNode.gain.setTargetAtTime, мы не можем обновить значение усиления с помощью установщика gainNode.gain.value. Я не смог найти в документации setTargetAtTime или value никаких объяснений, почему это происходит.

К счастью, есть исправление без нарушение постепенного появления, которое обеспечивает setTargetAtTime.
Решение заключается в установке значения усиления с помощью setValueAtTime вместо сеттера.

const input = document.querySelector(".input");

gainNode.gain.value = 0.1;
gainNode.gain.setTargetAtTime(
  input.value,
  context.currentTime,
  0.25
);

input.addEventListener(
  "input",
  function () {
    gainNode.gain.setValueAtTime(
      this.value,
      context.currentTime
    )
  },
  false
);

Большое спасибо за вашу попытку. Это работало великолепно, я не знал, что есть альтернатива setTargetAtTime, так как я новичок в разработке. И из-за того, что я был новичком в вещах, мой репрекс был большим беспорядком, но вы все равно потратили свое время, так что ценю, сэр.

Clarity 15.05.2022 17:06

Другие вопросы по теме