如何制作粉红噪声发生器?

Posted

技术标签:

【中文标题】如何制作粉红噪声发生器?【英文标题】:How can I make a Pink Noise generator? 【发布时间】:2010-10-11 15:23:03 【问题描述】:

((已选择答案 - 请参阅下面的编辑 5。))

我需要用 C# 编写一个简单的粉红噪声生成器。问题是,我以前从未做过任何音频工作,所以我不知道如何与声卡等交互。我知道我想远离使用 DirectX,主要是因为我不想为这个小项目下载一个海量的 SDK。

所以我有两个问题:

    如何生成粉红噪声? 如何将其流式传输到声卡?

编辑:我真的想制作一个粉红噪声发生器......我知道还有其他方法可以解决根本问题。 =)

编辑 2:我们的防火墙阻止流式音频和视频 - 否则我会按照 cmets 中的建议转到 www.simplynoise.com。 :(

编辑 3:我已经降低了白噪声的产生,并将输出发送到声卡 - 现在我需要知道的是如何将白噪声变成粉红噪音。哦 - 我不想循环一个 wav 文件,因为我尝试用于循环的每个应用程序最终都会在循环之间出现一点点中断,这足以让我一开始就朝着这个方向前进...

编辑 4:...我很惊讶有这么多人跳入非常明确的回答问题。如果我对为什么需要粉红噪声撒谎,我可能会得到更好的回应......这个问题更多的是关于如何生成数据并将数据流式传输到声卡,而不是关于我应该使用哪种耳机。为此,我编辑了背景细节 - 你可以在编辑中阅读...

编辑 5:我在下面选择了 Paul 的答案,因为他提供的链接为我提供了将白噪声(很容易通过随机数生成器生成)转换为粉红噪声的公式。除此之外,我用Ianier Munoz's CodeProject entry "Programming Audio Effects in C#"学习了如何生成、修改和输出声音数据到声卡。谢谢你们的帮助。 =)

【问题讨论】:

否则你可以去 SimplyNoise.com 并专注于你的工作:) 我愿意,但我们的防火墙会阻止流式音频和视频。 听说过降噪耳机吗? 如果我听起来很疯狂,那是因为我对这个问题产生的所有非答案感到沮丧。 其实我应该applogise。这正是我两分钟前在我的问题中抱怨的事情。请回答问题,不要提供建议!大声笑对不起埃里克 【参考方案1】:

我不能谈论 C#,但你可能会更好地使用一些好的降噪耳机和你最喜欢的 mp3。

【讨论】:

好吧,高品质降噪耳机的价格在 250 美元到 400 美元之间,而且它们可以消除噪音,而不是对话,我认为自制解决方案可以更合适。 适合我的预算,也就是说。【参考方案2】:

作为一种快速而肮脏的方法,在音频播放器中循环播放粉红噪声 wav 怎么样? (是的,我知道部分乐趣在于自己动手制作......)

【讨论】:

【参考方案3】:

重复播放粉红噪声的 .mp3 样本怎么样?

【讨论】:

【参考方案4】:

粉红噪声只是通过 -3dB/倍频程 LPF 的白噪声。您可以使用 rand()(或任何生成均匀随机数的函数)生成白噪声。

只要您有 Google 方便,将内容流式传输到声卡相当简单。如果您选择避免使用 DirectX,请考虑使用 PortAudio 或 ASIO 来连接声卡……尽管我认为您将不得不使用 C++ 或 C。

除此之外,为什么要浪费 CPU 时间来生成它?循环一个该死的 WAV 文件!

【讨论】:

将内容流式传输到声卡是相当简单的。如果您没有经验,那真的不是,我认为 OP 没有经验【参考方案5】:

您可以使用Audacity 生成任意数量的粉红噪声,然后重复此操作。

或者您可以深入研究源代码,看看 Audacity 是如何生成粉红噪声的。

【讨论】:

【参考方案6】:

也许您可以将此处的 C/C++ 代码转换为 C#:

http://www.firstpr.com.au/dsp/pink-noise/

将声音传到声卡的最简单方法是生成一个 wav(输出一些硬编码的标头,然后采样数据)。然后就可以播放 .wav 文件了。

【讨论】:

我将接受这个作为我的答案,因为它包含将白噪声转换为粉红噪声所需的公式 - 感谢您的参考。 =)【参考方案7】:

这是播放线程的示例。我正在使用 DirectSound 创建一个写入样本的 SecondaryBuffer。如您所见,它非常简单:

    /// <summary>
    /// Thread in charge of feeding the playback buffer.
    /// </summary>
    private void playbackThreadFn()
    
        // Begin playing the sound buffer.
        m_playbackBuffer.Play( 0, BufferPlayFlags.Looping );

        // Change playing state.
        IsPlaying = true;

        // Playback loop.
        while( IsPlaying )
        
            // Suspend thread until the playback cursor steps into a trap...
            m_trapEvent.WaitOne();

            // ...read audio from the input stream... (In this case from your pink noise buffer)
            Input.Collect( m_target, m_target.Length );

            // ...calculate the next writing position...
            var writePosition = m_traps[ ((1 & m_pullCounter++) != 0) ? 0 : 1 ].Offset;

            // ...and copy audio to the device buffer.
            m_playbackBuffer.Write( writePosition, m_deviceBuffer, LockFlag.None );
        

        // Stop playback.
        m_playbackBuffer.Stop();
    

如果您需要有关其工作原理的更多详细信息,我很乐意提供帮助。

【讨论】:

我需要帮助 - 你如何创建和关闭 Direct Sound 设备【参考方案8】:

我意识到这有点晚了,但是任何遇到它的人都应该知道粉红噪声是 -3dB/octave 的白噪声,而不是如上所述的 -6,实际上是棕色噪声。

【讨论】:

【参考方案9】:

如果您使用的是 Linux,则可以使用 SOX(您可能已经拥有它,请尝试 play 命令)。

play -t sl - synth 3 pinknoise band -n 1200 200 tremolo .1 40 &lt; /dev/zero

【讨论】:

【参考方案10】:

这是一种创建粉红噪声的非常简单的方法,它只是将大量以对数间隔分开的波加在一起!如果您想要实时创建声音,这对于您的目的可能太慢,但肯定可以进一步优化(例如:更快的余弦函数)。

函数输出一个值从 -1 到 1 的双精度数组。这分别表示波形中的最低点和最高点。

quality 参数表示为发出声音而产生的波数。我发现 5000 个波(每个半音大约 40 个间隔)大约是我无法检测到更高值的任何明显改进的阈值,但为了安全起见,您可以(可选)将其增加到大约 10,000 个波或更高.此外,根据 Wikipedia 的说法,就我们能听到的声音而言,20 赫兹大约是人类感知的下限,但您也可以根据需要进行更改。

请注意,由于技术原因,quality 值较高时声音会变得更安静,因此您可能(可选)希望通过 volumeAdjust 参数调整音量。

public double[] createPinkNoise(double seconds, int quality=5000, double lowestFrequency=20, double highestFrequency = 20000, double volumeAdjust=1.0)

    long samples = (long)(44100 * seconds);
    double[] d = new double[samples];
    double[] offsets = new double[samples];
    double lowestWavelength = highestFrequency / lowestFrequency;
    Random r = new Random();
    for (int j = 0; j < quality; j++)
    
        double wavelength = Math.Pow(lowestWavelength, (j * 1.0) / quality)  * 44100 / highestFrequency;
        double offset = r.NextDouble() * Math.PI*2;     // Important offset is needed, as otherwise all the waves will be almost in phase, and this will ruin the effect!
        for (long i = 0; i < samples; i++)
        
            d[i] += Math.Cos(i * Math.PI * 2 / wavelength + offset) / quality * volumeAdjust;
        
    
    return d;

【讨论】:

大部分内容我不明白,它是如何工作的。最重要的是,为什么要创建 offsets 数组?但它确实发出了非常好的声音!!! 感谢您的代码。调用它highestFrequency/ 给它一个默认值 44100 可能会产生误导,因为 44100 也是您使用的采样频率。年幼的孩子通常只能听到高达 20 kHz 的声音(老年人很少超过 10 kHz),所以提高到 44100 似乎有点过头了。 @DanW 只是一个评论,当它可以循环到声明为long 的变量时,声明索引ias int 可能有问题... @ErikThysell:是的,已编辑。 @ErikThysell:我认为该限制适用于 20k 以上的单个纯频率,而不一定适用于 20k 以上的混合多个同时频率,因为幻音(如差音和虚拟音)可以发挥作用。如果您有其他研究表明,我想听听。无论如何,我已经把它降到了 20kHz,因为无论如何在 44.1kHz 或附近都有明显的失真效果。不幸的是,对此进行测试很困难,因为大多数软件、驱动程序和硬件可能会丢弃 20kHz 以上的声音信息。 FWIW,在实验室环境中,有些人显然可以听到高达 28k 的声音。

以上是关于如何制作粉红噪声发生器?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 R 中模拟粉红噪声

为啥在梯度噪声发生器中从 Mersenne twister 切换到其他 PRNG 会产生不好的结果?

matlab 产生白噪声

附加到游戏对象时,粒子系统粉红色

如何将方波、三角波发生器电路进行改进,使之产生占空比可调的矩形波和锯齿波信号

什么是机器学习中的过拟合和噪声?