[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%);
}
Спасибо за ваш комментарий, я не смог добавить его в тот день, поэтому это заняло некоторое время, но я отредактировал первый пост с репрексом.
Этот вопрос остался без ответа, потому что до сих пор неясно, о чем спрашивают. Что подразумевается под «ввод типа диапазона не является динамическим»? Похоже, вход используется как регулятор громкости. И код, похоже, основан на этом устаревшем ЖКТ, который специально предназначен для зацикливания звука. Есть ли требование для «бесперебойного» цикла или обычный аудиоэлемент тоже подойдет? Код действительно довольно беспорядочный и может быть сильно рефакторинг.
@Yogi, извините за беспорядок. разработчик-стажер здесь. Да, моя ситуация связана с зацикливанием без пропусков, и я искал эталонное репо, чтобы начать с веб-аудио API, и нашел его (veltman-loopify). Сейчас он работает великолепно, так как Эмиэль Зуурбир дал мне решение. Но вы сказали, что это устарело. Есть ли более выгодный способ сделать бесконечную звуковую петлю?
Да, @EmielZuurbier провел для вас отличное исследование и устранил неполадки. Что касается библиотек без пробелов, та, которую вы используете, не обновлялась 7 лет и действительно написана не очень хорошо. Я не специалист по аудио, но на GitHub есть более новые и популярные библиотеки. Например, вот тот, который был недавно обновлен и кажется намного проще в использовании: Без зазоров 5



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


После некоторых экспериментов и попыток воспроизвести ваш код я наткнулся на кое-что любопытное.
Всякий раз, когда мы используем 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, так как я новичок в разработке. И из-за того, что я был новичком в вещах, мой репрекс был большим беспорядком, но вы все равно потратили свое время, так что ценю, сэр.
Что означает динамично в этом контексте? И можете ли вы создать минимальный воспроизводимый пример для отладки вашей проблемы?