AudioBufferのみだと一時停止やシークが難しくなるので、そのような操作はMediaElement(Audioタグ)に任せて、AudioBufferに結線してから加工する方法をとってみました。
確認のためにディレイをインサートしています。他のFXをどんどん入れていくと冗長になるので、外部モジュール化する予定です。
ちなみに、再生速度の変更はMediaElementだと音程は維持できますが音が切れます。
AudioBufferだと滑らかに遷移しますが、音程が速度に比例します。
html
<input id="Afile" type="file">
<audio id="Aplayer"></audio>
<input type="checkbox" id="play_pause">PLAY/PAUSE
<input type="checkbox" id="loop">LOOP
<br>
<input type="range" id="volume" value="1" min="0" max="1" step="0.05">GAIN
<input type="range" id="pitchAdj" value="1.00" min="0.7" max="1.16" step="0.01">PITCH
<br>
<input type="range" id="repeatRate" value="0" min="0" max="1" step="0.05">repeatRate
<input type="range" id="intensity" value="0" min="0" max="1" step="0.05">intensity
<input type="range" id="echoVolume" value="0" min="0" max="1" step="0.05">echo volume
javascript
//ファイルの読み込み
Afile.onchange = function() {
Aplayer.src = URL.createObjectURL(this.files[0]);
play_pause.checked = false;
};
//再生、一時停止
play_pause.onchange = function() {
(play_pause.checked) ? Aplayer.play(): Aplayer.pause();
};
//ループ
loop.onchange = function() {
(loop.checked) ? Aplayer.loop = true: Aplayer.loop = false;
};
window.onload = function() {
var source;
var Actx = new(window.AudioContext || window.webkitAudioContext);
var gain = Actx.createGain();
source = Actx.createMediaElementSource(Aplayer);
//ディレイ
var delay = Actx.createDelay();
var delayIn, delayOut = Actx.createGain();
var dry, wet, feedback = Actx.createGain();
delayIn.gain.value = delayOut.gain.value = dry.gain.value = 1.0;
wet.gain.value = feedback.gain.value = 0.0;
//ルーティング
delayIn.connect(dry).connect(delayOut);
delayIn.connect(delay).connect(wet).connect(delayOut);
delay.connect(feedback).connect(delay);
source.connect(delayIn)
delayOut.connect(gain).connect(Actx.destination);
//再生速度の変更
pitchAdj.addEventListener('input', function() {
Aplayer.playbackRate = this.valueAsNumber;
});
//音量
volume.addEventListener('input', function() {
gain.gain.value = this.valueAsNumber;
});
//ディレイタイム
repeatRate.addEventListener('input', function() {
delay.delayTime.value = this.valueAsNumber;
});
//フィードバック
intensity.addEventListener('input', function() {
feedback.gain.value = this.valueAsNumber;
});
//ディレイボリューム
echoVolume.addEventListener('input', () => wet.gain.value = this.valueAsNumber);
};