Skip to content

Noise Appears When Connecting Microphone to AudioWorkletNode, Preventing Sine Wave Output #2647

@liangfriend

Description

@liangfriend

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;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions