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

11

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

我想在这个信号中添加噪声。 "噪声信号部分" 的周期应该在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) 

但是这个解决方案对我的目的来说仍然过于“确定性”。

我如何生成随机改变幅度和周期的噪声?


1
一个典型的方法是生成一些白噪声(例如使用np.random.randn),然后进行带通滤波,以赋予其所需的频率特性,然后再将其添加到您的信号中。 - ali_m
@ali_m 是的,那是典型的和完全正确的方法。你是对的。但如果可能的话,我想避免过滤。所以我想要的解决方案应该像我建议的那样简单,但结果更好(不那么确定性)。 - matousc
你为什么想要“避免过滤”? - ali_m
@ali_m 看起来你是对的,你的解决方案最终似乎是最简单的。你想创建一个答案,这样我就可以将其标记为解决方案吗? - matousc
没问题,我会在今天晚些时候回来处理它。 - ali_m
显示剩余2条评论
3个回答

20
在MathWorks的文件交换中心:fftnoise - 生成具有指定功率谱的噪声,您可以找到来自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)

2

不要使用多个具有不同振幅的正弦函数,而应该使用具有随机相位的正弦函数:

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是离散的,因此只需要考虑给定采样率下实际出现的离散频率。


-3

生成全频谱白噪声,然后对其进行滤波就好像你想把你房子的墙面漆成白色,所以你决定把整个房子都漆成白色,再除了这一面墙以外全部重新再漆。这是愚蠢的。(但在电子学中是有意义的。)

我编写了一个小的C程序,可以在任何频率和带宽下产生白噪声(比如在16kHz中心频率和2kHz“宽”的情况下)。不需要进行过滤。

我所做的很简单: 在主(无限)循环内,我在中心频率上产生一个正弦波+/-一个在-halffbwidth和+halffbwidth之间的随机数,然后我保持这个频率达到一个任意数量的样本(粒度),这就是结果:

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

White noise 2kHz wide at 16kHz center frequency

伪代码:

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
    }


}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接