求助:为何buffer数组的采样数比实际信号少1个?
问题分析与修复
你的代码存在两处核心逻辑错误,导致环形缓冲区与信号序列的长度和内容出现差异:
1. 信号更新函数(updateSignal)逻辑缺陷
当前代码中,当信号数组达到设定长度后,仅删除最旧元素但未添加新采样,导致数组长度在signalLength和signalLength-1之间波动,无法稳定保持设定长度。正确逻辑应该是每次先添加新采样,再判断是否需要删除最旧元素,确保数组长度始终不超过设定值。
2. 环形缓冲区更新函数(updateRingbuffer)逻辑缺陷
当缓冲区填满时,仅执行删除前50%元素的操作,但未将当前采样加入缓冲区,导致该次采样丢失,缓冲区长度直接从sampleLength变为sampleLength/2,后续才会继续添加新采样,因此出现长度少1的差异。正确逻辑是先添加新采样,再判断是否需要截断缓冲区。
修正后的完整代码
let ring_buffer = [] let signal = [] let sampleLength = 20 let signalLength = 0 let spacing = 16 function setup() { createCanvas(400, 400); signalLength = width / spacing frameRate(1) } function draw() { background(220); translate(0, height >> 2) // 生成模拟采样(修正写法,逻辑更清晰) let sample = random(-30, 30) > 0 ? 20 : -20 // 更新并绘制信号 stroke(255, 0, 0) updateSignal(sample) drawSignal(signal, 100) // 更新并绘制环形缓冲区 stroke(0, 0, 255) updateRingbuffer(sample) drawSignal(ring_buffer, 150) // 绘制坐标轴 drawAxis() } // 修正后的信号更新函数 function updateSignal(sample){ signal.push(sample) // 超过设定长度时删除最旧元素 if(signal.length > signalLength){ signal.shift() } } // 修正后的环形缓冲区更新函数 function updateRingbuffer(sample){ ring_buffer.push(sample) // 填满时删除前50%元素(用floor确保整数索引) if(ring_buffer.length === sampleLength){ ring_buffer.splice(0, Math.floor(sampleLength / 2)) } } function drawSignal(arr, offset){ noFill() beginShape() for(let i=0; i<arr.length; i++){ vertex(i * spacing, arr[i] + offset) } endShape() } function drawAxis(){ fill(0) noStroke() textSize(8) textAlign(CENTER) for(let i=0; i<width; i+=spacing){ text(i/spacing, i, 200) push() translate(i, 200) rotate(PI/2) stroke(0, 10) line(-width/2, 0, width/2, 0) pop() } }
关键修改说明
- updateSignal:调整为先
push新采样,再判断是否需要shift,确保信号数组长度稳定在signalLength(因signalLength由width/spacing计算可能为浮点数,最终长度会接近该值)。 - updateRingbuffer:先将新采样加入缓冲区,再检查是否填满,填满时删除前50%元素,保证每次采样都被正确记录,缓冲区在填满后会截断为原长度的50%,并继续接收新采样。
- 模拟采样生成:调整条件判断写法,使其更易读(
random(-30,30) > 0替代0<random(-30,30))。
内容的提问来源于stack exchange,提问作者Greyfrog
相关产品推荐
相关产品推荐

