Javascript 动态创建振荡器会导致p5声音中的内存问题

Javascript 动态创建振荡器会导致p5声音中的内存问题,javascript,audio,p5.js,Javascript,Audio,P5.js,在我的代码中(下面的代码是一个非常简短的版本),我在draw中创建了振荡器()。最终,音频开始噼啪作响,变得很奇怪,我想这是因为振荡器没有被垃圾收集?当查看Inspect元素中的Memory选项卡时,它会不断上升,最终音频会发出噼啪声 我尝试使用断开变量/函数中的两个函数来解引用振荡器。这将在我希望的特定时间后将振荡器设置为空。我不确定如何将引用参数设置为null 也许p5声音库仍然为他们保留参考资料 function createOsc(grid) { let osc = new p5.O

在我的代码中(下面的代码是一个非常简短的版本),我在draw中创建了振荡器()。最终,音频开始噼啪作响,变得很奇怪,我想这是因为振荡器没有被垃圾收集?当查看Inspect元素中的Memory选项卡时,它会不断上升,最终音频会发出噼啪声

我尝试使用断开变量/函数中的两个函数来解引用振荡器。这将在我希望的特定时间后将振荡器设置为空。我不确定如何将引用参数设置为null

也许p5声音库仍然为他们保留参考资料

function createOsc(grid) {
  let osc = new p5.Oscillator();
  if (grids[grid].type == 1) {
    osc.setType("triangle");
  } else if (grids[grid].type == 2) {
    osc.setType("sawtooth");
  } else if (grids[grid].type == 3) {
    osc.setType("square");
  }
  return osc;
}

function createEnv(grid) {
  let env = new p5.Envelope();
  env.set(grids[grid].ADSR.attack, grids[grid].vol, grids[grid].ADSR.decay, grids[grid].ADSR.sustain * grids[grid].vol, grids[grid].ADSR.release, 0);
  return env;
}

let disconnect = {
  list: [],
  osc: function(osc, time) {
    this.list.push([osc, time, 0]);
  },
  update: function() {
    for (i = 0; i < this.list.length; i++) {
      this.list[i][2] += 1 / 60.0;

      if (this.list[i][2] >= this.list[i][1]) {
        this.list[i][0].a.disconnect();
        this.list[i][0].a = null;
        this.list.splice(i, 1);
        i += -1;
      }
    }
  }
}

function draw() {
  let osc = createOsc(0);
  let env = createEnv(0);

  osc.start();
  osc.freq(420);
  env.triggerAttack(osc);
  env.triggerRelease(osc, env.aTime + env.dTime);
  osc.stop(env.aTime + env.dTime + env.rTime);
  disconnect.osc({a: osc}, env.aTime + env.dTime + env.rTime);
}
函数createOsc(网格){
设osc=新的p5.振荡器();
if(网格[grid].type==1){
osc.集合类型(“三角形”);
}else if(网格[grid]。类型==2){
osc.setType(“锯齿”);
}else if(网格[grid]。类型==3){
osc.设置类型(“方形”);
}
返回osc;
}
函数createEnv(网格){
设env=new p5.Envelope();
环境集合(网格[grid].ADSR.attack,网格[grid].vol,网格[grid].ADSR.decay,网格[grid].ADSR.sustain*grids[grid].vol,网格[grid].ADSR.release,0);
返回环境;
}
让我们断开连接={
名单:[],
osc:功能(osc,时间){
这个.list.push([osc,time,0]);
},
更新:函数(){
对于(i=0;i=this.list[i][1]){
此.list[i][0].a.disconnect();
此.list[i][0].a=null;
本列表拼接(i,1);
i+=-1;
}
}
}
}
函数绘图(){
设osc=createOsc(0);
设env=createEnv(0);
osc.start();
操作频率(420);
环境触发攻击(osc);
环境触发释放(osc、环境时间+环境数据时间);
osc.stop(环境时间+环境数据时间+环境时间);
disconnect.osc({a:osc},env.aTime+env.dTime+env.rTime);
}
我试图使用PolySynth()对象,但由于缺乏清晰的文档,我无法弄清楚如何更改波形或任何东西

编辑: 这个新的独立代码会在一段时间后产生相同的噼啪声。我现在也按照建议使用Millis()。同样的问题是记忆在不断增加

let disconnect = {
  list: [],
  osc: function(osc, time) {
    this.list.push([osc, time, millis()]);
  },
  update: function() {
    for (i = 0; i < this.list.length; i++) {
      if (millis() - this.list[i][2] >= this.list[i][1]) {
        this.list[i][0].a.disconnect();
        this.list[i][0].a = null;
        this.list.splice(i, 1);
        i += -1;
      }
    }
  }
}

function createOsc() {
  let osc = new p5.Oscillator();
  osc.setType("triangle");
  return osc;
}

function createEnv() {
  let env = new p5.Envelope();
  env.set(0.1, 1, 0.1, 0.8, 0.1, 0);
  return env;
}

function setup() {
  frameRate(60);
}

function draw() {
  disconnect.update();
  print(disconnect.list.length);
  
  if (frameCount % 2 == 0) {
    let osc = createOsc();
    let env = createEnv();
    
    osc.start();
    osc.freq(420);
    
    env.triggerAttack(osc);
    env.triggerRelease(osc, 0.2);
    
    osc.stop(0.3);
    
    disconnect.osc({a: osc}, 300);
  }
}

let disconnect={
名单:[],
osc:功能(osc,时间){
this.list.push([osc,time,millis()]);
},
更新:函数(){
对于(i=0;i=this.list[i][1]){
此.list[i][0].a.disconnect();
此.list[i][0].a=null;
本列表拼接(i,1);
i+=-1;
}
}
}
}
函数createOsc(){
设osc=新的p5.振荡器();
osc.集合类型(“三角形”);
返回osc;
}
函数createEnv(){
设env=new p5.Envelope();
环境组(0.1,1,0.1,0.8,0.1,0);
返回环境;
}
函数设置(){
帧率(60);
}
函数绘图(){
断开连接。更新();
打印(断开连接。列表。长度);
如果(帧数%2==0){
设osc=createOsc();
设env=createEnv();
osc.start();
操作频率(420);
环境触发攻击(osc);
环境触发释放(osc,0.2);
osc.停止(0.3);
断开连接.osc({a:osc},300);
}
}

1)您可能在未显示的地方调用update,因为如果不这样做,
断开连接.list
将无限增长。2) 断开连接的逻辑似乎有点奇怪。为什么要假设每秒会精确调用60次更新?当实时时间(从
millis()
newdate()
或其他内容)超过该时间时,为什么不计算期望振荡器停止的时间并将其移除。3) 在每次调用draw时创建一个新的振荡器似乎有点奇怪,除非您显著限制帧速率。。。。。。如果包络持续时间长于帧之间的间隔,那么您将积累越来越多的同时运行的振荡器(并且您的
disconnect.list
数组将不断增长)。如果您能够提供一个最小的工作示例,重现问题,并且没有中断/丢失代码,这将非常有用(什么是
网格
?您的
设置
功能在哪里?您在哪里/如何调用
断开连接.更新
?)。在创建最小复制的过程中,您很有可能会发现导致内存泄漏的原因。@a.Rad出于好奇,为什么您每帧需要30-60个振荡器?(在设置中创建一些并重新使用它们是否还不够)?@GeorgeProfenza我的项目让用户放下音符并播放给他们,一个音乐网格。我可以通过制作一个限制最大声音和内容的系统来重复使用振荡器,但我想知道我是否遗漏了一些明显的可以修复的东西,直到我尝试为止。