AllPass Reverberator的lowpass反馈环路代码实现方法
全通混响器带低通反馈环路实现方案
问题背景
正在开发全通混响器(AllPass Reverberator),已掌握三级级联全通滤波器实现原理,但不清楚如何编写低通滤波器所在反馈环路的代码逻辑,需要实现完整的目标混响结构。

当前代码问题
现有代码仅实现了三级全通的块级联逻辑,无法支持反馈环路:
- 现有逻辑是整段音频一次性通过单级全通再传入下一级,属于离线块处理
- 反馈环路需要逐样本迭代计算:每个时刻的输出样本会按衰减系数回灌到环路输入端,块处理无法获取实时反馈状态
现有未完成代码如下:
def allpassfb(DataIn, sr, Mix, Spread, Diffusion = 0.7): delayAllPassMs = [23.8, 7.6, 2.6] print('lista delay AllPass ms', delayAllPassMs) # 延迟扰动最大比例为基准延迟的10% SpreadPerc = 0.1 # 初始化最大延迟长度 delayMaxMs = delayAllPassMs[-3] * (1 + Spread * SpreadPerc) pAllPass = np.zeros(len(delayAllPassMs)) # 计算各全通级的延迟扰动量 for i in range(len(delayAllPassMs)): pAllPass[i] = delayAllPassMs[i] * Spread * SpreadPerc # 逐次处理三级全通级联 for i in range(len(delayAllPassMs)): delayAllPassL = delayAllPassMs[i] delayAllPassR = delayAllPassMs[i] + pAllPass[i] if isStereo: InL = DataIn[:, 0] InR = DataIn[:, 1] Y0 = np.zeros(len(InL)) Y1 = np.zeros(len(InR)) Y0 = allpassSch2(InL, sr, delayAllPassL, Diffusion, delayMaxMs) Y1 = allpassSch2(InR, sr, delayAllPassR, Diffusion, delayMaxMs) else: In = DataIn Y0 = np.zeros(len(In)) Y1 = np.zeros(len(In)) Y0 = allpassSch2(In, sr, delayAllPassL, Diffusion, delayMaxMs) Y1 = allpassSch2(In, sr, delayAllPassR, Diffusion, delayMaxMs) # 干湿信号混合 if isStereo: DataOut0 = Y0 * Mix + InL * (1.0 - Mix) DataOut1 = Y1 * Mix + InR * (1.0 - Mix) else: DataOut0 = Y0 * Mix + In * (1.0 - Mix) DataOut1 = Y1 * Mix + In * (1.0 - Mix) return(np.column_stack((DataOut0, DataOut1)))
实现方法
核心信号流逻辑
带低通的反馈全通级(单通道单级)计算顺序:
- 环路输入 = 当前输入样本 + 反馈增益 * 低通上一时刻输出
- 环路输入送入全通滤波器,得到全通输出
- 全通输出送入低通滤波器,得到当前时刻反馈值,存入延迟线供下一时刻迭代使用
- 三级结构按顺序级联,前一级全通输出作为后一级的环路输入
代码修改要点
- 提前将毫秒级延迟转换为采样点长度,初始化每一级全通的延迟缓冲区、读写指针、低通滤波器的状态寄存器
- 外层遍历所有音频样本,内层按顺序遍历三级全通,逐样本计算反馈值,禁止整段数组批量处理
- 立体声通道独立维护各自的延迟缓冲区与滤波器状态,右通道延迟长度叠加Spread对应的采样点偏移即可
核心逐样本处理参考代码(单通道):
import numpy as np def one_pole_lp(x, prev_y, cutoff, sr): """一阶低通滤波器,用于反馈环路阻尼控制""" g = np.exp(-2*np.pi*cutoff/sr) y = x*(1-g) + prev_y*g return y, y def allpassfb(DataIn, sr, Mix, Spread, Diffusion=0.7, lp_cutoff=2000, feedback_gain=0.5): # 基础参数初始化 delayAllPassMs = [23.8, 7.6, 2.6] SpreadPerc = 0.1 n_samples = len(DataIn) DataOut = np.zeros(n_samples) # 延迟转换为采样点,初始化每级全通的延迟缓冲、读写指针、低通状态 ap_delays = [int(m * sr / 1000) for m in delayAllPassMs] ap_buffers = [np.zeros(d + 2) for d in ap_delays] ap_read_ptr = [0 for _ in ap_delays] ap_write_ptr = [d for d in ap_delays] lp_states = [0.0 for _ in ap_delays] # 逐样本处理全通级联与反馈环路 for n in range(n_samples): stage_in = DataIn[n] for stage in range(3): # 计算反馈环路输入 fb = feedback_gain * lp_states[stage] stage_in = stage_in + fb # 读取延迟线历史样本 delayed_sample = ap_buffers[stage][ap_read_ptr[stage]] # 全通滤波计算 ap_out = delayed_sample*(-Diffusion) + stage_in ap_buffers[stage][ap_write_ptr[stage]] = stage_in + delayed_sample*Diffusion # 更新环形缓冲读写指针 ap_read_ptr[stage] = (ap_read_ptr[stage] + 1) % len(ap_buffers[stage]) ap_write_ptr[stage] = (ap_write_ptr[stage] + 1) % len(ap_buffers[stage]) # 低通处理更新反馈状态 _, lp_states[stage] = one_pole_lp(ap_out, lp_states[stage], lp_cutoff, sr) # 本级输出作为下一级输入 stage_in = ap_out # 干湿信号混合 DataOut[n] = stage_in * Mix + DataIn[n] * (1-Mix) return DataOut
立体声实现只需复制一套单通道状态变量,右通道延迟长度叠加Spread对应的采样点偏移即可。
内容的提问来源于stack exchange,提问作者Gherardo Vitali
相关产品推荐
相关产品推荐

