Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用web音频API在javascript中连续生成原始音频样本?_Javascript_Audio_Web Audio Api_Webapi_Audiobuffer - Fatal编程技术网

如何使用web音频API在javascript中连续生成原始音频样本?

如何使用web音频API在javascript中连续生成原始音频样本?,javascript,audio,web-audio-api,webapi,audiobuffer,Javascript,Audio,Web Audio Api,Webapi,Audiobuffer,对于音乐应用程序,我需要能够使用web audio API连续无缝地生成原始音频样本。搜索之后,我发现了AudioBuffer(),这似乎就是我所需要的。但是,音频缓冲区只能播放一次(),因此无法真正连续播放。我尝试了以下解决方法: const buffer = audioCtx.createBuffer(1, 10000, audioCtx.sampleRate); for(let i = 0; i < bu

对于音乐应用程序,我需要能够使用web audio API连续无缝地生成原始音频样本。搜索之后,我发现了AudioBuffer(),这似乎就是我所需要的。但是,音频缓冲区只能播放一次(),因此无法真正连续播放。我尝试了以下解决方法:

                    const buffer = audioCtx.createBuffer(1, 10000, audioCtx.sampleRate);
                    for(let i = 0; i < buffer.length; i++)
                        buffer.getChannelData(0)[i] = ((i / audioCtx.sampleRate) * 440) % 1;
                    
                    const source = audioCtx.createBufferSource();
                    source.buffer = buffer;
                    source.onended = function() {
                        console.log(this);
                        const newSource = audioCtx.createBufferSource();
                        for(let i = 0; i < buffer.length; i++)
                            buffer.getChannelData(0)[i] = ((i / audioCtx.sampleRate) * 440) % 1;
                        newSource.buffer = buffer;
                        newSource.connect(audioCtx.destination);
                        newSource.onended = (this.onended as Function).bind(newSource);
                        newSource.start();
                    }
                    source.connect(audioCtx.destination);
                    source.start();

希望我能让它工作。如果我没有,我可能会尝试用C++绑定编写一个NPM包来做这个。

< P>我认为你要找的API是<代码> AudioWoRKe> 。这是一种直接在音频线程上运行代码的方法。它允许您在缓冲区开始播放之前填充缓冲区

设置它通常有点复杂,因为需要在单独的JavaScript文件中定义处理器。但也可以使用
Blob
,如下所示

该示例基于生成随机样本的代码段

const blob = new Blob(
    [`
        class MyProcessor extends AudioWorkletProcessor {
            process(_, outputs) {
                for (const output of outputs) {
                    for (const channelData of output) {
                        for (let i = 0; i < channelData.length; i += 1) {
                            channelData[i] = Math.random() * 2 - 1;
                        }
                    }
                }

                return true;
            }
        }

        registerProcessor('my-processor', MyProcessor);
    `],
    { type: 'application/javascript' }
);
const url = URL.createObjectURL(blob);
const audioContext = new AudioContext();

await audioContext.audioWorklet.addModule(url);

const myAudioWorkletNode = new AudioWorkletNode(audioContext, 'my-processor');

myAudioWorkletNode.connect(audioContext.destination);
const blob=新blob(
[`
类MyProcessor扩展了AudioWorkletProcessor{
过程(输出){
for(输出的常量输出){
for(输出的常量通道数据){
对于(设i=0;i
由于此代码直接在音频线程上运行,是否有办法在主线程和音频线程之间交换数据?是的,您可以与构造函数传递数据。或者,您可以在运行时使用MessagePort发送数据。或者,您可以使用AudioParams将数据发送到process函数。或者你可以使用SharedArrayBuffer。Chrome团队发布了几个示例,展示了不同的选项。谢谢你的帮助。我试过了,效果和预期的一样,但是有限的通信api对于我的用例来说太苛刻了,因为我无法将函数传递到工作集中。我会做一些electron/node.js魔术来让它工作。你也可以使用
ScriptProcessorNode
。它在主线程上运行,因此与其他所有线程竞争资源。它也被弃用,但它可能永远不会消失。
const blob = new Blob(
    [`
        class MyProcessor extends AudioWorkletProcessor {
            process(_, outputs) {
                for (const output of outputs) {
                    for (const channelData of output) {
                        for (let i = 0; i < channelData.length; i += 1) {
                            channelData[i] = Math.random() * 2 - 1;
                        }
                    }
                }

                return true;
            }
        }

        registerProcessor('my-processor', MyProcessor);
    `],
    { type: 'application/javascript' }
);
const url = URL.createObjectURL(blob);
const audioContext = new AudioContext();

await audioContext.audioWorklet.addModule(url);

const myAudioWorkletNode = new AudioWorkletNode(audioContext, 'my-processor');

myAudioWorkletNode.connect(audioContext.destination);