audioworkletProcessor process() 在事件 onmessage 时停止

问题描述 投票:0回答:1

我的 AudioWorkletProcessor 类遇到问题。 我有连续的音频数据流,我的客户端获取此流,准备缓冲区并将其发送到我的 AudioWorkletProcessor。 但是,当它发送时,进程函数会停止以让“port.onmessage”运行,这并不是停止太久,而是足以在我的音频中产生剪切。 这是我的代码:

worklet-processor.js :

class AudioProcessor extends AudioWorkletProcessor {
    constructor() {
        super();
        this.queue = [];
        this.queueLengthMinload = 750
        this.queueLengthPreload = 950
        this.port.onmessage = (event) => {
            if (event.data) {
                this.queue.push(event.data);
                console.log(this.queue.length)
            }
        };
    }

    process(inputs, outputs, parameters) {
        const output = outputs[0];
        if (this.queue.length > this.queueLengthMinload) {
            let segment = this.queue.shift()
            for (let x = 0; x < output.length; ++x) {
                if (x < segment.length){
                    output[x].set(segment[x]);
                }
            }
        }
        if(this.queue.length < this.queueLengthPreload){
           // this.port.postMessage('need-more-data');
        }
        return true;
    }
}

registerProcessor('audio-processor', AudioProcessor);

main.js

socket.on('audio', chunk => {
    if(!oneTime) return;
    const uint8Chunk = new Uint8Array(chunk);
    if (context === null) {
        initializeAudioContext().then(() => {
            decodeAndQueueAudio(uint8Chunk);

        });
    } else {
        decodeAndQueueAudio(uint8Chunk);
    }
});

async function initializeAudioContext() {
    context = new AudioContext();
    gainNode = context.createGain();
    gainNode.gain.value = volumeRange.value / 10;
    gainNode.connect(context.destination);

    await context.audioWorklet.addModule('worklet-processor.js');
    audioWorkletNode = new AudioWorkletNode(context, 'audio-processor');
    audioWorkletNode.connect(gainNode);
    audioWorkletNode.port.onmessage = (event) => {
        if (event.data === 'need-more-data') {
            console.log("waiting data");
            sendNextSegment()
        }
    };
}

function decodeAndQueueAudio(uint8Chunk) {
    context.decodeAudioData(uint8Chunk.buffer, buffer => {
        const numberOfChannels = buffer.numberOfChannels
        let channelData = [];
        for (let i = 0; i < numberOfChannels; ++i) {
            channelData[i] = buffer.getChannelData(i);
        }
        
        const segmentSize = 128;
        const channelDataLength = channelData.length
        let maxLength = 0;
        
        for (let i = 0; i < channelDataLength; ++i) {
            const length = channelData[i].length;
            if (length > maxLength) {
                maxLength = length;
            }
        }

        for (let i = 0; i < maxLength; i += segmentSize) {
            let segment = [];
            for (let x = 0; x < channelDataLength; ++x) {
                let bound =  Math.min(i + segmentSize, maxLength)
                segment[x] = channelData[x].subarray(i,bound)
            }
            audioQueue.push(segment);
        }
        sendNextSegment()        
    });
}

function sendNextSegment() {
    if (audioQueue.length > 0 && audioWorkletNode) {
        let audioData = []
        audioData = audioQueue;
        for (let i = 0; i < audioData.length; ++i){
            audioWorkletNode.port.postMessage(audioData.shift());
        }
    }
}

我有一个想法,但我不确定是否可能:制作一个工作集来处理队列,制作另一个工作集来处理“worklet1.queue”

您有进一步的提示或文档吗?如果是的话,我的想法可以吗:我不知道如何使该提取物起作用?

worklet-processor.js

class AudioProcessor extends AudioWorkletProcessor {
    constructor() {
        super();
    }

    process(inputs, outputs, parameters) {
        const output = outputs[0];
        if (queueWorkletNode.queue.length > queueWorkletNode.queueLengthMinload) {
            let segment = queueWorkletNode.queue.shift()
            for (let x = 0; x < output.length; ++x) {
                if (x < segment.length){
                    output[x].set(segment[x]);
                }
            }
        }
        if(queueWorkletNode.queue.length < queueWorkletNode.queueLengthPreload){
           //this.port.postMessage('need-more-data');
        }
        return true;
    }
}

registerProcessor('audio-processor', AudioProcessor);

worklet-queue.js

class AudioQueue extends AudioWorkletProcessor {
    constructor() {
        super();
        this.queue = [];
        this.queueLengthMinload = 750
        this.queueLengthPreload = 950
        this.port.onmessage = (event) => {
            if (event.data) {
                this.queue.push(event.data);
                console.log(this.queue.length)
            }
        };
    }

    process(inputs, outputs, parameters) {
        return true;
    }
}

registerProcessor('audio-queue', AudioProcessor);

main.js

socket.on('audio', chunk => {
    if(!oneTime) return;
    const uint8Chunk = new Uint8Array(chunk);
    if (context === null) {
        initializeAudioContext().then(() => {
            decodeAndQueueAudio(uint8Chunk);

        });
    } else {
        decodeAndQueueAudio(uint8Chunk);
    }
});

async function initializeAudioContext() {
    context = new AudioContext();
    gainNode = context.createGain();
    gainNode.gain.value = volumeRange.value / 10;
    gainNode.connect(context.destination);

    await context.audioWorklet.addModule('worklet-queue.js');
    await context.audioWorklet.addModule('worklet-processor.js');

    procWorkletNode = new AudioWorkletNode(context, 'audio-processor');
    queueWorkletNode = new AudioWorkletNode(context, 'audio-queue');
    procWorkletNode.connect(gainNode);
    procWorkletNode.port.onmessage = (event) => {
        if (event.data === 'need-more-data') {
            console.log("waiting data");
            sendNextSegment()
        }
    };
}

function decodeAndQueueAudio(uint8Chunk) {
    context.decodeAudioData(uint8Chunk.buffer, buffer => {
        const numberOfChannels = buffer.numberOfChannels
        let channelData = [];
        for (let i = 0; i < numberOfChannels; ++i) {
            channelData[i] = buffer.getChannelData(i);
        }
        
        const segmentSize = 128;
        const channelDataLength = channelData.length
        let maxLength = 0;
        
        for (let i = 0; i < channelDataLength; ++i) {
            const length = channelData[i].length;
            if (length > maxLength) {
                maxLength = length;
            }
        }

        for (let i = 0; i < maxLength; i += segmentSize) {
            let segment = [];
            for (let x = 0; x < channelDataLength; ++x) {
                let bound =  Math.min(i + segmentSize, maxLength)
                segment[x] = channelData[x].subarray(i,bound)
            }
            audioQueue.push(segment);
        }
        sendNextSegment()        
    });
}

function sendNextSegment() {
    if (audioQueue.length > 0 && queueWorkletNode) {
        let audioData = []
        audioData = audioQueue;
        for (let i = 0; i < audioData.length; ++i){
            queueWorkletNode.port.postMessage(audioData.shift());
        }
    }
}
javascript audio audio-worklet
1个回答
0
投票

问题解决,队列达到最小值。 我需要等待一段时间。

© www.soinside.com 2019 - 2024. All rights reserved.