OscillatorNode
OscillatorNode 接口表示一个周期性波形,例如正弦波。它是一个 AudioScheduledSourceNode 音频处理模块,用于创建给定波形的指定频率——实际上是一个恒定的音调。
| 输入数量 | 0 |
|---|---|
| 输出数量 | 1 |
| 通道计数模式 | max |
| 声道数 | 2 (在默认计数模式下未使用) |
| 通道解释 | 扬声器 |
构造函数
OscillatorNode()-
创建一个新的
OscillatorNode对象实例,可以选择提供一个对象来指定节点的 属性 的默认值。或者,您可以使用BaseAudioContext.createOscillator()工厂方法;请参阅 创建 AudioNode。
实例属性
还继承了其父类 AudioScheduledSourceNode 的属性。
OscillatorNode.frequency-
一个 a-rate
AudioParam,表示振动的频率(以赫兹为单位)(尽管返回的AudioParam是只读的,但它表示的值不是)。默认值为 440 Hz(标准的中央 A 音)。 OscillatorNode.detune-
一个 a-rate
AudioParam,表示振动的失谐(以音分为单位)(尽管返回的AudioParam是只读的,但它表示的值不是)。默认值为 0。 OscillatorNode.type-
一个字符串,指定要播放的波形形状;它可以是许多标准值之一,或者
custom,用于使用PeriodicWave来描述自定义波形。不同的波形会产生不同的音调。标准值是"sine"、"square"、"sawtooth"、"triangle"和"custom"。默认值为"sine"。
实例方法
还继承了其父类 AudioScheduledSourceNode 的方法。
OscillatorNode.setPeriodicWave()-
设置一个
PeriodicWave,该波形描述了用于替代标准波形之一的周期性波形;调用此方法会将type设置为custom。 AudioScheduledSourceNode.start()-
指定开始播放音调的确切时间。
AudioScheduledSourceNode.stop()-
指定停止播放音调的时间。
事件
还继承了其父类 AudioScheduledSourceNode 的事件。
示例
使用 OscillatorNode
以下示例展示了如何使用 AudioContext 创建一个振荡器节点并开始播放其音调。有关实际应用示例,请查看我们的 Violent Theremin 演示(相关代码请参见 app.js)。
// create web audio api context
const audioCtx = new AudioContext();
// create Oscillator node
const oscillator = audioCtx.createOscillator();
oscillator.type = "square";
oscillator.frequency.setValueAtTime(440, audioCtx.currentTime); // value in hertz
oscillator.connect(audioCtx.destination);
oscillator.start();
不同的振荡器节点类型
四个内置的振荡器 类型 是 sine、square、triangle 和 sawtooth。它们是振荡器生成的波形的形状。有趣的事实:这些是大多数合成器的默认设置,因为它们是易于电子生成的波形。此示例可视化了不同类型在不同频率下的波形。
<div class="controls">
<label for="type-select">
Oscillator type
<select id="type-select">
<option>sine</option>
<option>square</option>
<option>triangle</option>
<option>sawtooth</option>
</select>
</label>
<label for="freq-range">
Frequency
<input
type="range"
min="100"
max="800"
step="10"
value="250"
id="freq-range" />
</label>
<button data-playing="init" id="play-button">Play</button>
</div>
<canvas id="wave-graph"></canvas>
代码分为两部分:第一部分,我们设置了声音相关的部分。
const typeSelect = document.getElementById("type-select");
const frequencyControl = document.getElementById("freq-range");
const playButton = document.getElementById("play-button");
const audioCtx = new AudioContext();
const osc = new OscillatorNode(audioCtx, {
type: typeSelect.value,
frequency: frequencyControl.valueAsNumber,
});
// Rather than creating a new oscillator for every start and stop
// which you would do in an audio application, we are just going
// to mute/un-mute for demo purposes - this means we need a gain node
const gain = new GainNode(audioCtx);
const analyser = new AnalyserNode(audioCtx, {
fftSize: 1024,
smoothingTimeConstant: 0.8,
});
osc.connect(gain).connect(analyser).connect(audioCtx.destination);
typeSelect.addEventListener("change", () => {
osc.type = typeSelect.value;
});
frequencyControl.addEventListener("input", () => {
osc.frequency.value = frequencyControl.valueAsNumber;
});
playButton.addEventListener("click", () => {
if (audioCtx.state === "suspended") {
audioCtx.resume();
}
if (playButton.dataset.playing === "init") {
osc.start(audioCtx.currentTime);
playButton.dataset.playing = "true";
playButton.innerText = "Pause";
} else if (playButton.dataset.playing === "false") {
gain.gain.linearRampToValueAtTime(1, audioCtx.currentTime + 0.2);
playButton.dataset.playing = "true";
playButton.innerText = "Pause";
} else if (playButton.dataset.playing === "true") {
gain.gain.linearRampToValueAtTime(0.0001, audioCtx.currentTime + 0.2);
playButton.dataset.playing = "false";
playButton.innerText = "Play";
}
});
至于第二部分,我们使用上面创建的 AnalyserNode 将波形绘制在画布上。
const dpr = window.devicePixelRatio;
const w = 500 * dpr;
const h = 300 * dpr;
const canvasEl = document.getElementById("wave-graph");
canvasEl.width = w;
canvasEl.height = h;
const canvasCtx = canvasEl.getContext("2d");
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
analyser.getByteTimeDomainData(dataArray);
// draw an oscilloscope of the current oscillator
function draw() {
analyser.getByteTimeDomainData(dataArray);
canvasCtx.fillStyle = "white";
canvasCtx.fillRect(0, 0, w, h);
canvasCtx.lineWidth = 4.0;
canvasCtx.strokeStyle = "black";
canvasCtx.beginPath();
const sliceWidth = (w * 1.0) / bufferLength;
let x = 0;
for (let i = 0; i < bufferLength; i++) {
const v = dataArray[i] / 128.0;
const y = (v * h) / 2;
if (i === 0) {
canvasCtx.moveTo(x, y);
} else {
canvasCtx.lineTo(x, y);
}
x += sliceWidth;
}
canvasCtx.lineTo(w, h / 2);
canvasCtx.stroke();
requestAnimationFrame(draw);
}
draw();
警告:此示例会发出噪音!
规范
| 规范 |
|---|
| Web Audio API # OscillatorNode |
浏览器兼容性
加载中…