-
Notifications
You must be signed in to change notification settings - Fork 171
Description
Issue Description:
I am using the microphone as an input source, connected to a sine wave. When I open the page, the browser asks for my permission to access the microphone. If I deny the permission, the play function works normally and outputs a pure sine wave. However, if I allow the permission, noise appears instead of the sine wave.
The issue occurs when the AudioWorkletNode is connected to the microphone input. This causes noise and prevents the AudioWorkletNode from functioning as expected.
I hope this issue can be addressed soon.
XiaoProcessor.js
class MyAudioProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return [
{name: 'frequency', defaultValue: 440, minValue: 20, maxValue: 20000, automationRate: 'a-rate',},
{name: 'volume', defaultValue: 0.2, minValue: 0, maxValue: 1,},
];
}
constructor(options) {
super();
this.phase = 0;
this.lastProcessTime = currentTime; // 使用 AudioWorklet 内置时间
}
process(inputs, outputs, parameters) {
const now = currentTime; // AudioContext.currentTime
const delta = now - this.lastProcessTime;
this.lastProcessTime = now;
const output = outputs[0];
const freqValues = parameters.frequency;
const volValues = parameters.volume;
const sampleRate = globalThis.sampleRate;
const twoPi = 2 * Math.PI;
for (let channel = 0; channel < output.length; ++channel) {
const outputChannel = output[channel];
for (let i = 0; i < outputChannel.length; ++i) {
const f = freqValues[0];
const v = volValues[0];
const t = 1 / sampleRate;
this.phase += twoPi * f * t;
if (this.phase >= twoPi) {
this.phase -= twoPi;
}
outputChannel[i] = Math.sin(this.phase) * v;
}
}
return true;
}
}
registerProcessor('xiao-processor', MyAudioProcessor);
InstrumentPlayer.ts
import Player from "./Player";
class InstrumentPlayer extends Player {
audioWorklet: AudioWorkletNode | null = null
constructor({context}: { context: AudioContext }) {
super({context})
}
/**
* 将 MIDI 转换为频率 (Hz)
*/
private midiToHz(midi: number): number {
return 440 * Math.pow(2, (midi - 69) / 12);
}
async createAudioProcessor() {
this.context = new AudioContext();
await this.context.audioWorklet.addModule(
new URL("./processors/XiaoProcessor.js", import.meta.url).href
);
this.audioWorklet = new AudioWorkletNode(this.context, "xiao-processor", {
parameterData: {
frequency:440
},
processorOptions: { // 这里可以随便写点变量
},
});
// 平滑调频
// this.audioWorklet.parameters.get('frequency').linearRampToValueAtTime(880, this.context.currentTime + 2);
this.audioWorklet.connect(this.context!.destination);
const stream = await navigator.mediaDevices.getUserMedia({audio: true});
const mic = this.context.createMediaStreamSource(stream);
mic.connect(this.audioWorklet);
}
play() {
if (this.context?.state === "suspended") {
this.context.resume();
}
}
stop() {
this.context.suspend();
}
updateParameters(data: Record<string, any>) {
this.audioWorklet?.port.postMessage(data);
}
}
export default InstrumentPlayer;