使用python为音调添加随机噪声

Posted

技术标签:

【中文标题】使用python为音调添加随机噪声【英文标题】:Add random noise to tone using python 【发布时间】:2021-03-31 13:48:49 【问题描述】:

我正在尝试检测录音中突然出现的巨大噪音。我发现这样做的一种方法是创建音频的频谱图并添加每列的值。通过绘制每列中值的总和,可以看到每次突然出现巨响时都会出现峰值。问题是,在我的用例中,我需要在录制音频时播放哔声(频率为 2350 Hz)。哔声的频谱图如下所示:

如您所见,在此哔声(频率为 2350 Hz 的简单音调)的开头和结尾处,还存在其他频率,但我未能成功移除这些频率。这些不需要的频率在对频谱图的列求和时会在哔声的开始和结束时导致尖峰。我想避免这种情况,因为我不希望我的哔哔声被检测为突然的巨响。请参阅下面的频谱图以供参考:

这是频谱图中每列之和的图表:

显然,我想避免在我的算法中出现误报。所以我需要一些方法来消除由哔哔声的开始和结束引起的尖峰。到目前为止,我的一个想法是在上面的哔声频谱图中添加高于和/或低于 2350 Hz 线的低分贝值的随机噪声。理想情况下,这将创建一个听起来与原始音非常相似的音调,但是当我将列中的所有值相加时不会产生尖峰,而是会产生更多的平稳状态。这个想法是我的问题的可行解决方案吗?如果是这样,我将如何使用 python 来创建具有随机噪音的哔哔声?对于我忽略的问题,还有其他更简单的解决方案吗?

目前,我正在使用以下代码来生成哔声:

import math
import wave
import struct

audio = []
sample_rate = 44100.0

def append_sinewave(
        freq=440.0, 
        duration_milliseconds=500, 
        volume=1.0):
    """
    The sine wave generated here is the standard beep.  If you want something
    more aggresive you could try a square or saw tooth waveform.   Though there
    are some rather complicated issues with making high quality square and
    sawtooth waves... which we won't address here :) 
    """ 

    global audio # using global variables isn't cool.

    num_samples = duration_milliseconds * (sample_rate / 1000.0)

    for x in range(int(num_samples)):
        audio.append(volume * math.sin(2 * math.pi * freq * ( x / sample_rate )))

    return


def save_wav(file_name):
    # Open up a wav file
    wav_file=wave.open(file_name,"w")

    # wav params
    nchannels = 1

    sampwidth = 2

    # 44100 is the industry standard sample rate - CD quality.  If you need to
    # save on file size you can adjust it downwards. The stanard for low quality
    # is 8000 or 8kHz.
    nframes = len(audio)
    comptype = "NONE"
    compname = "not compressed"
    wav_file.setparams((nchannels, sampwidth, sample_rate, nframes, comptype, compname))

    # WAV files here are using short, 16 bit, signed integers for the 
    # sample size.  So we multiply the floating point data we have by 32767, the
    # maximum value for a short integer.  NOTE: It is theortically possible to
    # use the floating point -1.0 to 1.0 data directly in a WAV file but not
    # obvious how to do that using the wave module in python.
    for sample in audio:
        wav_file.writeframes(struct.pack('h', int( sample * 32767.0 )))

    wav_file.close()

    return


append_sinewave(volume=1, freq=2350)
save_wav("output.wav")

【问题讨论】:

【参考方案1】:

不是真正的答案 - 更多的是一个问题。

您要求扬声器瞬间从静止波变为正弦波 - 这很难做到(尽管频率不是那么高)。如果它确实管理它,那么接收到的信号应该是大礼帽和正弦波的卷积(有点像你所看到的,但没有一些数据并且知道你在为频谱图做什么很难说)。

在任何一种情况下,您都可以通过平滑音调的开头和结尾来检查这一点。像这样用于您的音调生成:

tr = 0.05  # rise time, in seconds
tf = duration_milliseconds / 1000  # finish time of tone, in seconds

for x in range(int(num_samples)):
    t = x / sample_rate  # Time of sample in seconds
    
    # Calculate a bump function
    bump_function = 1
    if 0 < t < tr:  # go smoothly from 0 to 1 at the start of the tone
        tp = 1 - t / tr
        bump_function = math.e * math.exp(1/(tp**2 - 1))
    elif tf - tr < t < tf:  # go smoothly from 1 to 0 at the end of the tone
        tp = 1 + (t - tf) / tr
        bump_function = math.e * math.exp(1/(tp**2 - 1))

    audio.append(volume * bump_function * math.sin(2 * math.pi * freq * t))

您可能需要稍微调整一下上升时间。通过这种形式的凹凸功能,您知道您有一个完整的音量,从开始后的tr 到结束前的tr。存在许多其他功能,但如果这可以平滑频谱图中的开始/停止效果,那么您至少知道它们为什么存在。而且预防通常比试图在后处理中消除影响要好。

【讨论】:

以上是关于使用python为音调添加随机噪声的主要内容,如果未能解决你的问题,请参考以下文章

图像处理:随机添加椒盐噪声和高斯噪声Python

如何在 python 中向 Mnist 数据集添加 50% 的随机正常噪声

Python-给图像添加椒盐噪声和高斯噪声

使用Python为图片添加空间相关噪声(相干噪声)

如何使用 OpenCV 在 Python 中为图像添加噪声(高斯/盐和胡椒等)[重复]

OpenCV给图像添加噪声