Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/471.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
是否可以使用javascript将频率赫兹阵列转换为音频缓冲区?_Javascript_Audiocontext_Audiobuffer - Fatal编程技术网

是否可以使用javascript将频率赫兹阵列转换为音频缓冲区?

是否可以使用javascript将频率赫兹阵列转换为音频缓冲区?,javascript,audiocontext,audiobuffer,Javascript,Audiocontext,Audiobuffer,数组的第一列是频率,第二列是播放时间 //创建web音频api上下文 var audioCtx=new(window.AudioContext | | window.webkitadiocontext)(); 功能播放说明(频率、持续时间){ //创建振荡器节点 var振荡器=audioCtx.create振荡器(); 振荡器类型='锯齿'; 振荡器.frequency.value=频率;//以赫兹为单位的值 振荡器。连接(audioCtx。目的地); start(); 设置超时( 函数(){

数组的第一列是频率,第二列是播放时间

//创建web音频api上下文
var audioCtx=new(window.AudioContext | | window.webkitadiocontext)();
功能播放说明(频率、持续时间){
//创建振荡器节点
var振荡器=audioCtx.create振荡器();
振荡器类型='锯齿';
振荡器.frequency.value=频率;//以赫兹为单位的值
振荡器。连接(audioCtx。目的地);
start();
设置超时(
函数(){
振荡器。停止();
播放旋律();
},持续时间);
}
函数playmody(){
如果(notes.length>0){
note=notes.pop();
playNote(注[0],注[1]);
}
}
注=[[67.40,14.84],
[58.60,17.06],
[69.80,14.33],
[69.80,14.33],
[66.30,15.08],
[62.30,16.05],
[66.90,14.95],
[65.00,15.38],
[66.00,15.15],
[88.40,11.31],
[60.60,16.50],
[63.90,15.65],
[114.20,8.76],
[114.20,8.76],
[99.70,10.03],
[344.90,2.90],
[344.90,2.90],
[70.00,14.29],
[310.90,3.22],
[310.90,3.22],
[68.30,14.64],
[71.30,14.03],
[69.40,14.41],
[101.70,9.83],
[70.40,14.20],
[67.20,14.88],
[76.00,13.16],
[59.60,16.78],
[73.30,13.64],
[62.10,16.10],
[72.60,13.77],
[76.60,13.05],
[76.80,13.02],
[52.90,18.90],
[69.50,14.39],
[72.90,13.72],
[69.90,14.31],
[69.60,14.37]];
注:反向();
节奏=100;

播放旋律()我不完全确定上面的示例是否真的在做您想要的事情。如果我理解正确的话,它或多或少是一次演奏所有的音符。它还使用setTimeout停止振荡器,这不是超精确的。因此,我创建了一个简单的示例,其中播放。这是众所周知的,因此希望更容易验证代码是否真的在做我们希望它做的事情

const NOTES = [ [ 783.99, 0.5 ], [ 0, 0.25 ], [ 587.33, 0.25 ], [ 783.99, 0.5 ], [ 0, 0.25 ], [ 587.33, 0.25 ], [ 783.99, 0.25 ], [ 587.33, 0.25 ], [ 783.99, 0.25 ], [ 987.77, 0.25 ], [ 1174.7, 0.25] ];
起初,我创建了一个注释数组。在您的示例中,每个音符由频率和持续时间组成

接下来,我定义了一个函数,该函数预期使用AudioContext和音符数组调用,然后安排按顺序播放这些音符

function playNotes (context, notes) {
    notes.reduce((offset, [ frequency, duration ]) => {
        const oscillatorNode = context.createOscillator();

        oscillatorNode.frequency.value = frequency;

        oscillatorNode.start(offset);
        oscillatorNode.stop(offset + duration);

        oscillatorNode.connect(context.destination);

        return offset + duration;
    }, context.currentTime);
}
函数循环遍历所有给定的注释。它将为它们中的每一个创建一个振荡器节点。它在前一个结束时启动该振荡节点,在达到持续时间时再次停止该振荡节点

该功能现在可以如下使用:

const audioContext = new AudioContext();

playNotes(audioContext, NOTES);
但最大的优点是,我们可以使用OfflineAudioContext调用相同的函数

const sampleRate = 44100;
const offlineAudioContext = new OfflineAudioContext({ length: 3.25 * sampleRate, sampleRate });

playNotes(offlineAudioContext, NOTES);
这只会安排音符,但不会产生任何可听见的声音。OfflineAudioContext将生成一个音频缓冲区,这可能是您想要的。可以通过调用startRendering来呈现该缓冲区

offlineAudioContext
    .startRendering()
    .then((audioBuffer) => console.log(audioBuffer));
请注意,此代码在Safari中不起作用,因为它不支持最新版本的Web Audio API。但是,您可以通过编写一些附加代码来实现它。由于我是的作者,我当然建议使用它,而不是编写自己的polyfill代码