我正在尝试制作一个简单的程序,该程序生成的音调可能会因输入值而异。我想起诉Console.Beep()函数,因为它似乎是最简单的解决方案,但却遇到了问题。我注意到当我连续调用Console.beep()函数时,如下所示:
System.Console.Beep(440, 500);
System.Console.Beep(460, 500);
System.Console.Beep(480, 500);
Run Code Online (Sandbox Code Playgroud)
当前音调停止和下一个音调开始之间存在很小的延迟(大约100-200毫秒左右)。我想知道是否有任何方法可以减少此延迟,以便每当频率更新时音调都不会立即暂停?
当试图了解.NET为什么会以不良方式运行时,在GitHub上查看.NET Core的源代码通常会很有帮助。看着为Console.Beep的源代码:
public static void Beep(int frequency, int duration)
{
ConsolePal.Beep(frequency, duration);
}
Run Code Online (Sandbox Code Playgroud)
有两种实现ConsolePal:一种用于Windows,另一种用于类似Unix的系统。假设您使用的是Windows,我们来看看中的Beep实现ConsolePal.Windows.cs:
public static void Beep(int frequency, int duration)
{
const int MinBeepFrequency = 37;
const int MaxBeepFrequency = 32767;
if (frequency < MinBeepFrequency || frequency > MaxBeepFrequency)
throw new ArgumentOutOfRangeException(nameof(frequency), frequency, SR.Format(SR.ArgumentOutOfRange_BeepFrequency, MinBeepFrequency, MaxBeepFrequency));
if (duration <= 0)
throw new ArgumentOutOfRangeException(nameof(duration), duration, SR.ArgumentOutOfRange_NeedPosNum);
Interop.Kernel32.Beep(frequency, duration);
}
Run Code Online (Sandbox Code Playgroud)
这里的关键是呼叫Interop.Kernel32.Beep。这是我们即将调用本机Windows API的有力指标,但让我们验证一下。 Interop.Kernel32被劈了过来一堆文件 --normally这可能会造成一些困难,对我们来说,但它只是恰巧,在列表中的第一个是Interop.Beep.cs--convenient!
打开文件,证实了我们对本地调用的怀疑:
[DllImport(Libraries.Kernel32, SetLastError = true)]
internal static extern bool Beep(int frequency, int duration);
Run Code Online (Sandbox Code Playgroud)
这是使用一种称为Platform Invoke的技术,通常缩写为P / Invoke。有一个很棒的网站pinvoke.net,其中提供了常见的P / Invoke代码片段以及一些随附的实现。让我们来看看pinvoke.net在kernel32.dll中对Beep怎么说:
与MessageBeep不同,此功能是同步的。(直到声音结束,它才将控制权返回给其调用方。)
由于您的代码中没有别的东西,否则Console.Beep会导致延迟,这意味着Windows API可能是罪魁祸首。幸运的是,pinvoke.net提供了一种可能可行的解决方法。为了确保这一点,让我们查看一下Windows上的MSDN文档Beep,pinvoke.net可以方便地链接到该文档。它附带了一些令人着迷的历史Beep,并推荐改用MessageBeep。
不幸的是,有关MSDN的文档MessageBeep令人失望:我们不能使用它来产生任意音调。
这使我们得出了最终结论:kernel32 Beep并不是真的要产生奇特的声音。它既依赖于硬件,又依赖于平台,如果您想在各种设备上生成一致的声音,那么这两者都不是理想的选择。从本质上讲,它是过去的遗物。它甚至在Windows XP中被删除,尽管后来又与Windows 7一起添加了。这意味着.NET Console.Beep(int, int)具有所有相同的问题,因为它只是kernel32的包装Beep。
更加健壮的解决方案是研究各种音频框架,但是这些框架可能会复杂得多。现在,如果您只是从C#开始,并且想使事情保持简单,那么您可能会遇到诸如观察到的延迟之类的不一致性。
| 归档时间: |
|
| 查看次数: |
70 次 |
| 最近记录: |