如何使用 numpy 在频率范围内产生噪声?

How to generate noise in frequency range with numpy?

我有一个主信号,例如周期为 200 个样本的正弦波。

我想给这个信号加点噪音。 "noise signal parts" 的周期应在范围内,例如 5-30 个样本。

我认为这足以在此范围内生成具有不同随机选择振幅的多个窦:

noise = np.sin(np.array(range(N))/0.7)*np.random.random(1) + np.sin(np.array(range(N))/1.1)*np.random.random(1) + np.sin(np.array(range(N))/1.5)*np.random.random(1) 

但是这个解决方案对我的目的来说还是太多了"deterministic"。

如何生成振幅和周期随机变化的噪声?

在 MathWorks 的文件交换中:fftnoise - generate noise with a specified power spectrum 您可以找到来自 Aslak Grinsted 的 matlab 代码,创建具有指定功率谱的噪声。它可以很容易地移植到 python:

def fftnoise(f):
    f = np.array(f, dtype='complex')
    Np = (len(f) - 1) // 2
    phases = np.random.rand(Np) * 2 * np.pi
    phases = np.cos(phases) + 1j * np.sin(phases)
    f[1:Np+1] *= phases
    f[-1:-1-Np:-1] = np.conj(f[1:Np+1])
    return np.fft.ifft(f).real

您可以像这样在您的案例中使用它:

def band_limited_noise(min_freq, max_freq, samples=1024, samplerate=1):
    freqs = np.abs(np.fft.fftfreq(samples, 1/samplerate))
    f = np.zeros(samples)
    idx = np.where(np.logical_and(freqs>=min_freq, freqs<=max_freq))[0]
    f[idx] = 1
    return fftnoise(f)

据我所知似乎可行。聆听您新创造的噪音:

from scipy.io import wavfile

x = band_limited_noise(200, 2000, 44100, 44100)
x = np.int16(x * (2**15 - 1))
wavfile.write("test.wav", 44100, x)

产生全频谱白噪声然后对其进行过滤就像您想将房子的墙壁刷成白色,因此您决定将整个房子刷成白色,然后将除墙壁以外的所有房子都刷回去。是白痴。 (但对电子学有了解)。

我制作了一个小的 C 程序,它可以在任何频率和任何带宽下产生白噪声(假设在 16kHz 中心频率和 2kHz "wide")。 不涉及过滤。

我做的很简单: 在主(无限)循环内,我在中心频率 +/- 生成一个正弦波,一个介于 -half 带宽和 +halfbandwidth 之间的随机数,然后我将该频率保持为任意数量的样本(粒度),结果如下:

16kHz 中心频率处 2kHz 宽的白噪声

伪代码:

while (true)
{

    f = center frequency
    r = random number between -half of bandwidth and + half of bandwidth

<secondary loop (for managing "granularity")>

    for x = 0 to 8 (or 16 or 32....)

    {

        [generate sine Nth value at frequency f+r]

        output = generated Nth value
    }


}

与其使用具有不同振幅的多个正弦波,不如使用具有随机相位的它们:

import numpy as np
from functools import reduce

def band_limited_noise(min_freq, max_freq, samples=44100, samplerate=44100):
    t = np.linspace(0, samples/samplerate, samples)
    freqs = np.arange(min_freq, max_freq+1, samples/samplerate)
    phases = np.random.rand(len(freqs))*2*np.pi
    signals = [np.sin(2*np.pi*freq*t + phase) for freq,phase in zip(freqs,phases)]
    signal = reduce(lambda a,b: a+b,signals)
    signal /= np.max(signal)
    return signal

背景:白噪声意味着功率谱包含每个频率,所以如果你想要带限噪声,你可以将频带内的每个频率加在一起。噪声部分来自随机阶段。因为DFT是离散的,你只需要考虑在给定采样率的情况下实际出现的离散频率。