【音频处理】Channel Vocoder 算法简介

系列文章目录



Channel Vocoder

在各类剪辑软件中,有一类音效非常的魔幻、富有科技感,例如:

这类音效背后的原理来自原 Channel Vocoder(声道声码器)。Channel vocoder 最初由 Homer Dudley 在 1930s 发明,发明的初衷是为了做语音通信,但就目前来看,它在音效上取得了更多的进展。

Channel vocoder 的输入有两个两个信号:载波信号(carrier)和调制信号(modulator)。在音效场景中,carrier 通常是一个谐波丰富的音频,例如锯齿波或者小提琴等声音,而 modulator 通常是语音信号;算法的输出,则是将两个信号进行了某种混合,使得两种信号被叠加在一起,可以产生经典的机器人音效,它作为一种特殊效果在好莱坞中被广泛使用。下面视频是本人实现的 channel vocoder 示例,是一种非常「机械」的声音。

channel_vocoder_video

算法原理

Channel vocoder 的算法实现可以分为时域滤波器实现和频域傅里叶变换实现。

时域滤波器实现

请添加图片描述

Channel vocoder 在时域上可以被描述为 filter-bank 模型,算法处理逻辑如上图,我们对着图来说。

首先,需要选定一组 Band-Pass Filter,用来过滤出特定频率的音频信息,例如我可以选定 [337.5, 575, 850, 1200, 1700, 2350]。

接着,对于 carrier,经过 BPF 后得到不同频段的信号即可;对于 modulator,经过 BPF 处理后,我们还要获取到这个信号的包络(envelope)。获取包络方式多种多样,一种简易的方式是取信号的能量值,并经过一个 Low-Pass Filter 即可。

然后,将 modulator 的包络与 carrier 的相同频段信号做一个相乘,最后累加所有频段信号就可得到最终的输出。这里 有一个在线体验 channel vocoder 的页面,用的就是 filter-band 模型。

这里思考几个问题:

  1. 我要选多少个频段?没有一个固定的值,它可以被设置为算法的一个参数。频段越多计算量越大,但输出信号中 modulator 信号越清晰;频段越少,计算越快,但输出信号「机械感」越强,modulator 信号越不清晰。具体感受可以注意文章开头中视频中对 「Number Band」参数的调整。
  2. modulator 与 carrier 信号长度不一致怎么办?modulator 通常是语音信号,考虑在直播场景下使用 channel vocoder 音效的话,modulator 是无限长的,carrier 是一段固定长度的音频,可以重复循环使用 carrier。

频域傅里叶变换

请添加图片描述

时域上实现 channel vocoder ,需要使用了非常多的 Band-Pass Filter 来过滤出特定的频段,这种方式计算量很大。Channel Vocoder 音效的原理无非是:

  1. 在 carrier 和 modulator 信号中,找到特定频率的信息
  2. 将 modulator 频段信息进行某种非线性操作(例如找到包络),然后将这个结果与 carrier 频段信息相结合

为了达到上述两个目标,Channel Vocoder 现代实现通常用 FFT 替换 Band-Pass Filter。当使用很多频段时,这种方法更快,而且非线性和低通滤波都可以很容易地使用 FFT 的幅度来完成。FFT Channel vocoder 算法处理逻辑如上图,具体的:

  1. 对 modulator 进行 FFT,得到 FFT Bins,将 FFT Bins 分为 N 个 band,对每个 band 的幅度取均值,得到 b N b_N bN
  2. 对 carrier 进行 FFT,得到 FFT Bins,将 FFT Bins 分为 N 个 band,对每个 band 的幅度取均值,得到 a N a_N aN
  3. 完成 1、2 后,对于每个 band,我们计算得到 s = b N a N s = \frac{b_N}{a_N} s=aNbN,将 s 与当前的 carrier band 相乘,使 carrier 带上 modulator 的信息
  4. 最后,对相乘后的 FFT Bins 做 IFFT 得到时域输出信号

频域上实现 channel vocoder,计算量骤降,Number Bands 轻松设置到 256 都没有问题,而 Band-Filter 模型设置到 64 已经非常吃性能了,并且 Number Bands 参数可以实时调整不影响效果。但频域实现代码复杂性较高,需要在输入和输出两个入口设置 ringbuffer 以保证信号连续性,这同时也会引入一定的延迟(取决与 FFT 的 window size)。

总结

本文介绍了 Channel vocoder,它是一种非常神奇的音效,可以用来实现经典的机器人音效。Channel vocoder 可以使用时域和频域两种实现方法。时域方法中,它被看出是一种 filter-band 模型,通过 band-pass filter 过滤出特定频段的信号,然后将 modulator 中的包络信息附加到 carrier 中来实现;频域方法,经过 FFT 后,对每个 band 进行取均值的,将 modulator 中的各 band 的均值与 carrier 的 band 相乘,然后 IFFT 得到时域输出信号。频域方法计算量更小,参数调整更优化,因此目前大多实现都是频域方法,但它会引入算法延迟。

参考

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是VB Phase Vocoder算法的matlab代码,用于实现音频信号的时间伸缩和音高变化: ```matlab % VB Phase Vocoder算法 % 输入:x - 原始音频信号 % alpha - 时间伸缩系数 % beta - 音高变化系数 % hop - 帧移参数 % 输出:y - 处理后的音频信号 function y = vb_phase_vocoder(x, alpha, beta, hop) % 窗函数 win = hann(hop*2); % 参数设置 N = length(win); % 窗口长度 M = round(N/hop); % 每帧采样点数 L = length(x); % 信号长度 K = ceil(L/hop); % 帧数 t = (0:L-1)'/fs; % 时间向量 % 初始化 y = zeros(round(L/alpha),1); % 输出信号长度 phi = zeros(N/2+1,1); % 初始相位 omega = 2*pi*(0:N/2)'/N; % 基本频率 pd = zeros(N/2+1,1); % 相位差 last_y = zeros(N,1); % 上一帧输出 % 处理每帧信号 for i = 1:K % 获取当前帧信号 idx = (i-1)*hop + (1:N); if idx(end) > L x(end+1:idx(end)) = 0; L = idx(end); end xw = x(idx).*win; % 短时傅里叶变换 X = fft(xw); Xmag = abs(X(1:N/2+1)); Xphase = angle(X(1:N/2+1)); % 相位差计算 pd = Xphase - phi - omega*hop; phi = Xphase; % 时间伸缩 pd = pd - round(pd/hop)*hop; pd = pd*alpha/hop; % 音高变化 new_Xmag = interp1((0:N/2)'/N, Xmag, (0:N/2)'*beta/N); new_Xmag(2:end-1) = 2*new_Xmag(2:end-1); % 重构信号 Y = new_Xmag.*exp(1i*(phi+pd)); yw = real(ifft([Y;conj(Y(end-1:-1:2))])); yw = yw.*win; y((i-1)*hop+1:i*hop) = y((i-1)*hop+1:i*hop) + yw(1:hop); % 重叠相加 y((i-1)*hop+1:i*hop) = y((i-1)*hop+1:i*hop) + last_y(hop+1:end); last_y = yw; end end ``` 需要说明的是,该代码中的变量含义如下: - `x`:原始音频信号 - `alpha`:时间伸缩系数 - `beta`:音高变化系数 - `hop`:帧移参数 - `win`:窗函数 - `N`:窗口长度 - `M`:每帧采样点数 - `L`:信号长度 - `K`:帧数 - `t`:时间向量 - `y`:处理后的音频信号 - `phi`:初始相位 - `omega`:基本频率 - `pd`:相位差 - `last_y`:上一帧的输出

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值