从头开始创建DSP系统

| 我喜欢电子音乐,并且对所有的音高都很感兴趣。 我在库的Stack Overflow上发现了许多有用的问题,这些库可用于播放音频,过滤器等。但是我真正好奇的是实际上发生了什么:如何在效果和振荡器之间传递数据?我已经对dsp的数学方面进行了研究,但我怀疑问题的结局已被搁置,但我不确定要使用哪种缓冲系统等。最终目标是使效果的简单对象层次结构和通过彼此之间的数据(如果我最终不尽全力尝试实现它,则可能使用多线程)。它不会成为下一个Propellerhead原因,但我对它的工作方式很感兴趣,这比起最终产品的生产,更是一种练习。 目前,我使用.net和C#,并且最近学习了F#(这可能会或可能不会导致一些有趣的数据处理方式),但是如果这些方式不适合我,我可以在必要时学习其他系统。 问题是:使用缓冲区通过程序获取大量信号数据的最佳方法是什么?例如,使用队列,数组,链接列表等会更好吗?每次将效果应用到系统或只是编辑缓冲区中的值时,是否应该使样本不可变并创建一组新的数据?我应该有一个调度程序/线程池样式的对象来组织传递数据,或者效果函数应该直接在彼此之间传递数据? 谢谢。 编辑:另一个相关的问题是然后我将如何使用Windows API播放此数组?我真的不想使用DirectShow,因为微软现在已经让它死了 EDIT2:感谢您的所有答案。看完所有技术后,我将使用XNA 4(我花了一段时间浏览互联网并找到了说明操作方法的网站)或NAudio输出音乐...不确定哪种,取决于先进程度该系统最终被存在。当C#5.0发布时,我将使用其异步功能在此之上创建效果体系结构。我几乎都平等地使用了每个人的答案,所以现在我很难确定谁应该提供赏金给...     
已邀请:
        您是否看过VST.NET(http://vstnet.codeplex.com/)?这是一个使用C#编写VST的库,并提供了一些示例。您还可以考虑编写VST,以便可以在任何主机应用程序中使用您的代码(但即使您不愿意,查看它们的代码也很有用)。 信号数据通常很大,需要大量处理。不要使用链表!我知道的大多数库都只是使用数组来放置所有音频数据(毕竟,这就是声卡所期望的)。 从VST.NET示例:
    public override void Process(VstAudioBuffer[] inChannels, VstAudioBuffer[] outChannels)
    {
        VstAudioBuffer audioChannel = outChannels[0];

        for (int n = 0; n < audioChannel.SampleCount; n++)
        {
            audioChannel[n] = Delay.ProcessSample(inChannels[0][n]);
        }
    }
audioChannel是围绕非托管float *缓冲区的包装。 您可能将样本存储在不可变数组中。然后,当您要播放它们时,将数据复制到输出缓冲区中(如果需要,可以更改频率)并在此缓冲区中执行效果。请注意,您可以使用多个输出缓冲区(或通道)并在最后对它们求和。 编辑 我知道两种播放数组的低级方法:Windows API中的DirectSound和WaveOut。使用DirectSound的C#示例。 WaveOut的C#示例。但是,您可能更喜欢使用外部高级库,例如NAudio。 NAudio对于.NET音频操作很方便-请参阅此博客文章,以向音频卡发送正弦波。您可以看到它们也使用了float数组,这是我的建议(如果您使用字节进行计算,最终会在声音中产生很多混叠)。     
F#在这里可能是一个不错的选择,因为它非常适合操纵函数。功能可能是信号创建和处理的良好构建块。 由于Array模块中的高阶函数,F#通常还擅长处理集合,尤其是数组。 我想,这些品质使F#在金融领域颇受欢迎,并且对信号处理也很有用。 用于技术计算的Visual F#2010专门讨论了傅里叶变换,这可能与您要执行的操作有关。我想尽管有很多关于网络转换的免费信息。 最后,要播放样本,您可以使用XNA。我认为最新版本的API(4.0)也允许记录,但我从未使用过。 Xbox上有一个著名的音乐编辑应用程序,名为ezmuse + Hamst3r Edition,它使用XNA,因此绝对有可能。     
        关于缓冲和异步/线程/同步问题,我建议您看一下新的TPL数据流库。凭借其块原语,并发数据结构,数据流网络,异步消息处理和TPL基于任务的抽象(可与async / await C#5功能一起使用),它非常适合此类应用程序。     
        我不知道这是否真的是您要寻找的东西,但这是我上大学时的个人项目之一。在我自己实现声音和DSP之前,我并没有真正理解声音和DSP的工作原理。我试图尽可能地靠近说话者,所以我仅使用libsndfile来处理文件格式问题。 基本上,我的第一个项目是创建一个大的双精度数组,用正弦波填充它,然后使用sf_writef_double()将数组写入文件以创建可以播放的内容,并在波形编辑器中查看结果。 接下来,我在正弦调用和写调用之间添加了另一个函数,以添加效果。 这样,您就可以开始使用非常低级的振荡器和效果,并且可以立即看到结果。另外,只需很少的代码就能完成类似的工作。 就个人而言,我将从尽可能简单的解决方案开始,然后慢慢添加。尝试只写一个文件并使用音频播放器播放该文件,这样就不必处理音频api。只需使用单个数组即可开始并就地修改。绝对从单线程开始。随着项目的发展,您可以开始使用其他解决方案,例如管道而不是数组,对其进行多线程处理或使用音频API。 如果您想创建一个可以交付的项目,具体取决于它的实际情况,则可能必须移至更复杂的库,例如一些实时音频处理。但是,通过上述简单方法学习的基础知识绝对可以帮助您达到这一点。 祝好运!     
        尽管没有音频,但我已经做了很多实时DSP。尽管您的想法(不可变缓冲区)与(修改了可变缓冲区)中的任何一个都可行,但我更愿意为信号路径中的每个链接创建一个永久缓冲区。大多数效果都无法很好地进行修改,因为每个输入样本都会影响多个输出样本。当您有重采样阶段时,每个链接缓冲区技术特别有效。 在这里,当采样到达时,第一个缓冲区将被覆盖。然后,第一个过滤器从其输入缓冲区(第一个缓冲区)读取新数据,并写入其输出(第二个缓冲区)。然后,它调用第二阶段从第二个缓冲区读取并写入第三个缓冲区。 这种模式完全消除了动态分配,允许每个阶段保留可变数量的历史记录(因为效果需要一些内存),并且在允许在路径中重新排列滤镜方面非常灵活。     
好吧,我也会在赏金上刺一口:) 我实际上处于非常相似的情况。我从事电子音乐的制作已经有很长的历史了,但是仅在过去的几年中,我才开始探索实际的音频处理。 您提到您已经研究了数学。我认为这很关键。我目前正在通过Ken Steiglitz的《数字信号处理入门》(针对数字音频和计算机音乐的应用)进行斗争。如果您不知道复数和相量,则将非常困难。 我是Linux专家,所以我已经开始用C编写LADSPA插件。我认为从基本级别开始,以真正了解正在发生的事情是很好的。如果我使用Windows,则需要从Steinberg下载VST SDK并编写一个概念证明快速插件,该插件只会增加噪音或其他影响。 选择VST或LADSPA之类的框架的另一个好处是,您可以立即在常规音频套件中使用插件。将您的第一个自制插件应用于音轨的满意度无与伦比。另外,您将能够与其他音乐家共享您的插件。 在C#/ F#中可能有多种方法可以执行此操作,但是如果您打算编写VST插件,则我建议使用C ++,以避免任何不必要的开销。这似乎是行业标准。 在缓冲方面,我一直在使用循环缓冲区(此处的好文章:http://www.dspguide.com/ch28/2.htm)。一个好的练习是实现有限响应滤波器(Steiglitz称为前馈滤波器)-这些依赖于缓冲并且很有趣。 我在Github上有一些非常基本的LADSPA插件回购。除了架构上的差异外,它们对于编写VST插件的人也可能很有用。 https://github.com/andreasjansson/my_ladspa_plugins 示例代码的另一个很好的来源是CSound项目。那里有大量的DSP代码,并且该软件主要针对音乐家。     
        从阅读本和本开始。 这将使您对必须执行的操作有所了解。 然后,学习DirectShow体系结构-学习如何不这样做,而是尝试创建它的简化版本。     
        您可以看看BYOND。这是用于在C#中创建程序音频/ MIDI乐器和效果的环境。它可以独立使用,也可以VST插入和效果使用。 完全公开我是BYOND的开发人员。     

要回复问题请先登录注册