如何执行逐块频率下移?

信息处理 自由度
2022-02-10 17:02:00

我正在编写一个 Python 函数,它将音频信号的频率降低到指定范围。我通过将时间序列与复指数相乘来执行降档,然后对结果进行低通滤波以消除低频移动到更高频率的循环效应。

该函数将用于在循环中逐块处理音频信号。我的问题是,启动索引会有什么影响n每个块的复指数为零?

X(ej2π(ff0))=F{x[n]ej2πf0n}

在哪里n{0,..N1}, 和N是块长度。

直觉上,我认为块之间会有不一致的相移,但我不确定。

有没有办法避免这种情况,而无需在程序的整个生命周期中不断增加索引?

这是代码:

from numpy import fft, pi, r_, exp, int16, array, fromstring, zeros
from scipy.signal import firwin, lfilter

def shiftFreq(data, cutoff, fs, hist=None):
    """ Downshift audio data

    Parameters
    ------------
    data: str
        Binary data string of 16-bit audio data
    cutoff: float
        The new max frequency component after downshift and filtering
    fs: float
        Sample rate of audio data
    hist: ndarray
        Filter delay line

    """
    data = fromstring(data, dtype=int16)
    N = len(data)
    num_taps = 128
    delay = num_taps - 2
    nyquist = fs/2

    # initialize history
    if hist is None:
        hist = zeros(delay, dtype=data.dtype)

    # Down-shift the data
    shift = nyquist - cutoff
    n = r_[0: N]
    new_data = (data * exp(-1j * 2 * pi * shift * n/fs)).real

    # Apply lowpass filter to remove cyclic effect
    fir = firwin(num_taps, cutoff, nyq=nyquist)
    new_data, hist = lfilter(fir, 1, new_data, zi=hist)

    return int16(new_data).tostring(), hist

顺便说一句,在执行降档时我还应该注意哪些其他注意事项,而我在这里没有考虑到这些注意事项?

1个回答

顺便说一句,在执行降档时我还应该注意哪些其他注意事项,而我在这里没有考虑到这些注意事项?

是的,有一个,让我在执行频率修改时提出最重要的警告之一。声学声音信号(以音乐、语音等形式)在物理上以所谓的谐波结构存在(更深入的讨论参见声音合成、声音分析等),其直接含义是对频率内容的感知是以八度为单位而不是线性频率十进制(八度是频率之间的跨度f02f0)。

现在,尽管对于大多数技术应用(例如在那些通信算法中),频带可以移动到任何所需的频率而不会丢失信息(这是调制理论的本质),但在音频感知方面却没有抓住。

很容易看出,当一个完整的频段以线性方式移动到其他频率时,音频频段的谐波结构会发生失真。作为一个可靠的例子,考虑一个由以下组成的原始音频波形440赫兹,880赫兹和1320赫兹(这些是f0,2f03f0一个荒谬的乐器,更自然的乐器将有更复杂的结构,包括不和谐等)

现在,如果您将此波形基数从f01.5f0那么新的频率分布将是1.5f0,2.5f03.5f0不再是谐波。这在自然音高变换应用中产生了一个重要问题。