gpt4 book ai didi

javascript - Web Audio API 故障/失真问题

转载 作者:行者123 更新时间:2023-11-30 15:55:56 24 4
gpt4 key购买 nike

我是网络音频 API 的新手,制作了一个简单的合成器来了解来龙去脉。问题是我的音频在输入大量声音后会失真很多。因此,如果我通过它插入大量频率,它就会失真。任何了解 API 的人都可以快速浏览一下我的代码,看看是否有任何重大错误/遗漏?可以在 Safari、chrome 和 Firefox 中重现问题。演示版是HERE感谢您的帮助!!

//start new audio session.
var context = new (window.webkitAudioContext || window.AudioContext || window.mozAudioContext)



function playSound(note) {
oscillator = context.createOscillator();

//create volume controller
var gainNode = context.createGain();

//connect signal to audio output(speakers by default)
oscillator.connect(gainNode);
gainNode.connect(context.destination);

//adjusts frequency played by 50%, 100% or 200%
var octave = document.getElementById('octave').value;

//sets oscillator frequency
oscillator.frequency.value = frequencies[note] * octave;

//oscillator wave type
oscillator.type = document.getElementById('waveSelect').value;


//initialize gain at 0 and ramp up to full volume very quikcly (prevents audible 'pop')
gainNode.gain.value = 0
var quickFadeIn = gainNode.gain.setTargetAtTime(1, context.currentTime, 0.1);

//starts oscillator. Delayed start can be achieved by adding time(in secs) after currentTime
oscillator.start(context.currentTime + .05);

/**
* AUDIO EFFECTS
*/

function delayNode() {
//create delay
var delay = context.createDelay();
delay.delayTime.value = .5;

//create gain
gainNode;
//gainNode.gain.value = 0.8;
quickFadeIn;

//create feedback loop
oscillator.connect(gainNode);
gainNode.connect(delay);
delay.connect(gainNode);
delay.connect(context.destination);

//decrease gain
quickFadeOut;
}

function distortionNode() {
var distortion = context.createWaveShaper();

//distortion curve taken from MDN which they in turn took from Stack Overflow
function makeDistortionCurve(amount) {
var k = typeof amount === 'number' ? amount : 50,
n_samples = 44100,
curve = new Float32Array(n_samples),
deg = Math.PI / 90,
i = 0,
x;
for ( ; i < n_samples; ++i ) {
x = i * 2 / n_samples - 1;
curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) );
}
return curve;
};

distortion.curve = makeDistortionCurve(500);
distortion.oversample = '4x';

gainNode;

quickFadeIn;

oscillator.connect(gainNode);
gainNode.connect(distortion);
distortion.connect(context.destination);

//decrease gain
quickFadeOut;
}

if (document.getElementById('toggleDelay').value == 'true'){delayNode();}
if (document.getElementById('toggleDistortion').value == 'true'){distortionNode();}

//determines note duration
var sustain = parseFloat(document.getElementById('sustain').value);

//stops oscillator by exponentially ramping down sound over .015 seconds to avoid audible click
var quickFadeOut = gainNode.gain.setTargetAtTime(0, context.currentTime + sustain, 0.0015);

//change key color on keypress

//append the word "note" to the object.name note to identify the correct key div
var divId = "note" + String(note);
var element = document.getElementById(divId);

//change background color for durarion of note length
var currentColor = element.style.backgroundColor;
element.style.backgroundColor = '#3cf7ac';
setTimeout(function () {
if (currentColor != 'rgb(60, 247, 172)') {
element.style.backgroundColor = currentColor
}
}, 1000 * sustain);



//for testing
console.log('playSound Hz:' + frequencies[note] * octave + ' octave:' + octave + ' wave:' + oscillator.type + ' duration: ' + sustain + ' time:' + context.currentTime.toFixed(2));
}

//controls 2nd keyboard. Same logic as playSound()
function playSoundb(note) {
oscillator = context.createOscillator();
var gainNode = context.createGain();
oscillator.connect(gainNode);
gainNode.connect(context.destination);



var octaveb = document.getElementById('octaveb').value;
oscillator.frequency.value = frequencies[note] * octaveb;


oscillator.type = document.getElementById('waveSelectb').value;

gainNode.gain.value = 0
var quickFadeIn = gainNode.gain.setTargetAtTime(.75, context.currentTime, .1);
oscillator.start(context.currentTime + .05);

/**
* AUDIO EFFECTS
*/

function delayNode() {
var delay = context.createDelay();
delay.delayTime.value = .5;

gainNode;
quickFadeIn;

//create feedback loop
oscillator.connect(gainNode);
gainNode.connect(delay);
delay.connect(gainNode);
delay.connect(context.destination);

//decrease gain
quickFadeOut;
}

function distortionNode() {
var distortion = context.createWaveShaper();

function makeDistortionCurve(amount) {
var k = typeof amount === 'number' ? amount : 50,
n_samples = 44100,
curve = new Float32Array(n_samples),
deg = Math.PI / 90,
i = 0,
x;
for ( ; i < n_samples; ++i ) {
x = i * 2 / n_samples - 1;
curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) );
}
return curve;
};

distortion.curve = makeDistortionCurve(900);
distortion.oversample = '4x';

gainNode;
quickFadeIn;

oscillator.connect(gainNode);
gainNode.connect(distortion);
distortion.connect(context.destination);

quickFadeOut;
}

if (document.getElementById('toggleDelayb').value == 'true'){delayNode();}
if (document.getElementById('toggleDistortionb').value == 'true'){distortionNode();}

var sustainb = parseFloat(document.getElementById('sustainb').value);

var quickFadeOut = gainNode.gain.setTargetAtTime(0, context.currentTime + sustainb, 0.0015);

//change key color on keypress
var divId = "note" + String(note) + "b";
var element = document.getElementById(divId);
var currentColor = element.style.backgroundColor;
element.style.backgroundColor = '#3ce4f7';
setTimeout(function () {
if (currentColor != 'rgb(60, 228, 247)') {
element.style.backgroundColor = currentColor
}
}, 1000 * sustainb);

//for testing
console.log('playSound*B* Hz:' + frequencies[note] * octave + ' octave:' + octave + ' wave:' + oscillator.type + ' duration: ' + sustain + ' time:' + context.currentTime);

//reveals 2nd keyboard
function displayKeyboard2(lowersynth, uppersynth) {
var bottom = document.getElementById(lowersynth);
var top = document.getElementById(uppersynth);

if (bottom.style.display == 'block') {
bottom.style.display = 'none';
top.style.marginTop = '150px';
}

else {
bottom.style.display = 'block';
top.style.marginTop = '0';
}

//Frequencies in Hz of notes to be played. 
var frequencies = {
'C_1': 130.81,
'C#1': 139.00,
'D_1': 146.83,
'D#1': 156.00,
'E_1': 164.81,
'F_1': 174.61,
'F#1': 185.00,
'G_1': 196.00,
'G#1': 208.00,
'A_1': 220.00,
'A#1': 233.00,
'B_1': 246.94,
'C_2': 261.63,
'C#2': 277.00,
'D_2': 293.66,
'D#2': 311.00,
'E_2': 329.63,
'F_2': 349.23,
'F#2': 370.00,
'G_2': 392.00,
'G#2': 415.00,
'A_2': 440.00,
'A#2': 466.00,
'B_2': 493.88,
'C_3': 523.25,
};

//triggers playSound() to create note
document.getElementById('noteC_1').addEventListener(('click' || 'touchstart'),function() { playSound('C_1');});
document.getElementById('noteC#1').addEventListener(('click' || 'touchstart'),function() { playSound('C#1');});
document.getElementById('noteD_1').addEventListener(('click' || 'touchstart'),function() { playSound('D_1');});
document.getElementById('noteD#1').addEventListener(('click' || 'touchstart'),function() { playSound('D#1');});
document.getElementById('noteE_1').addEventListener(('click' || 'touchstart'),function() { playSound('E_1');});
document.getElementById('noteF_1').addEventListener(('click' || 'touchstart'),function() { playSound('F_1');});
document.getElementById('noteF#1').addEventListener(('click' || 'touchstart'),function() { playSound('F#1');});
document.getElementById('noteG_1').addEventListener(('click' || 'touchstart'),function() { playSound('G_1');});
document.getElementById('noteG#1').addEventListener(('click' || 'touchstart'),function() { playSound('G#1');});
document.getElementById('noteA_1').addEventListener(('click' || 'touchstart'),function() { playSound('A_1');});
document.getElementById('noteA#1').addEventListener(('click' || 'touchstart'),function() { playSound('A#1');});
document.getElementById('noteB_1').addEventListener(('click' || 'touchstart'),function() { playSound('B_1');});
document.getElementById('noteC_2').addEventListener(('click' || 'touchstart'),function() { playSound('C_2');});
document.getElementById('noteC#2').addEventListener(('click' || 'touchstart'),function() { playSound('C#2');});
document.getElementById('noteD_2').addEventListener(('click' || 'touchstart'),function() { playSound('D_2');});
document.getElementById('noteD#2').addEventListener(('click' || 'touchstart'),function() { playSound('D#2');});
document.getElementById('noteE_2').addEventListener(('click' || 'touchstart'),function() { playSound('E_2');});
document.getElementById('noteF_2').addEventListener(('click' || 'touchstart'),function() { playSound('F_2');});
document.getElementById('noteF#2').addEventListener(('click' || 'touchstart'),function() { playSound('F#2');});
document.getElementById('noteG_2').addEventListener(('click' || 'touchstart'),function() { playSound('G_2');});
document.getElementById('noteG#2').addEventListener(('click' || 'touchstart'),function() { playSound('G#2');});
document.getElementById('noteA_2').addEventListener(('click' || 'touchstart'),function() { playSound('A_2');});
document.getElementById('noteA#2').addEventListener(('click' || 'touchstart'),function() { playSound('A#2');});
document.getElementById('noteB_2').addEventListener(('click' || 'touchstart'),function() { playSound('B_2');});
document.getElementById('noteC_3').addEventListener(('click' || 'touchstart'),function() { playSound('C_3');});


document.getElementById('noteC_1b').addEventListener(('click' || 'touchstart'),function() { playSoundb('C_1');});
document.getElementById('noteC#1b').addEventListener(('click' || 'touchstart'),function() { playSoundb('C#1');});
document.getElementById('noteD_1b').addEventListener(('click' || 'touchstart'),function() { playSoundb('D_1');});
document.getElementById('noteD#1b').addEventListener(('click' || 'touchstart'),function() { playSoundb('D#1');});
document.getElementById('noteE_1b').addEventListener(('click' || 'touchstart'),function() { playSoundb('E_1');});
document.getElementById('noteF_1b').addEventListener(('click' || 'touchstart'),function() { playSoundb('F_1');});
document.getElementById('noteF#1b').addEventListener(('click' || 'touchstart'),function() { playSoundb('F#1');});
document.getElementById('noteG_1b').addEventListener(('click' || 'touchstart'),function() { playSoundb('G_1');});
document.getElementById('noteG#1b').addEventListener(('click' || 'touchstart'),function() { playSoundb('G#1');});
document.getElementById('noteA_1b').addEventListener(('click' || 'touchstart'),function() { playSoundb('A_1');});
document.getElementById('noteA#1b').addEventListener(('click' || 'touchstart'),function() { playSoundb('A#1');});
document.getElementById('noteB_1b').addEventListener(('click' || 'touchstart'),function() { playSoundb('B_1');});
document.getElementById('noteC_2b').addEventListener(('click' || 'touchstart'),function() { playSoundb('C_2');});
document.getElementById('noteC#2b').addEventListener(('click' || 'touchstart'),function() { playSoundb('C#2');});
document.getElementById('noteD_2b').addEventListener(('click' || 'touchstart'),function() { playSoundb('D_2');});
document.getElementById('noteD#2b').addEventListener(('click' || 'touchstart'),function() { playSoundb('D#2');});
document.getElementById('noteE_2b').addEventListener(('click' || 'touchstart'),function() { playSoundb('E_2');});
document.getElementById('noteF_2b').addEventListener(('click' || 'touchstart'),function() { playSoundb('F_2');});
document.getElementById('noteF#2b').addEventListener(('click' || 'touchstart'),function() { playSoundb('F#2');});
document.getElementById('noteG_2b').addEventListener(('click' || 'touchstart'),function() { playSoundb('G_2');});
document.getElementById('noteG#2b').addEventListener(('click' || 'touchstart'),function() { playSoundb('G#2');});
document.getElementById('noteA_2b').addEventListener(('click' || 'touchstart'),function() { playSoundb('A_2');});
document.getElementById('noteA#2b').addEventListener(('click' || 'touchstart'),function() { playSoundb('A#2');});
document.getElementById('noteB_2b').addEventListener(('click' || 'touchstart'),function() { playSoundb('B_2');});
document.getElementById('noteC_3b').addEventListener(('click' || 'touchstart'),function() { playSoundb('C_3');});

最佳答案

没有重大遗漏 - 这正是当输出过载时数字音频中发生的情况(即音频的瞬时值是 <-1 或 >+1) - 你会出现削波,这通常听起来很糟糕。可能最好的做法(除了保持增益值低于 1)是在输出上放置一个 DynamicsCompressor(即通过 context.createDynamicsCompressor() 创建一个 DynamicsCompressorNode,将其连接到 context.destination,然后将音符连接到压缩器而不是比 context.destination)。在这种情况下,默认值是合理的(压缩器设置是一个音乐决定,但这至少有助于剪辑)。

关于javascript - Web Audio API 故障/失真问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38547340/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com