我正在尝试制作一个简单的程序来生成可根据输入值变化的音调。我想使用 Console.Beep() 函数,因为它似乎是最简单的解决方案,但遇到了问题。我注意到当我连续调用 Console.beep() 函数时,如下所示:
System.Console.Beep(440, 500);
System.Console.Beep(460, 500);
System.Console.Beep(480, 500);
当前音调停止和下一个音调开始之间有一个小的延迟(大约 100-200 毫秒左右)。我想知道是否有任何方法可以减少这种延迟,以便在频率更新时音调不会出现暂时停顿?
最佳答案
当试图理解为什么 .NET 以不受欢迎的方式运行时,在 GitHub 上查看 .NET Core 的源代码通常会很有帮助。看着the source code for Console.Beep :
public static void Beep(int frequency, int duration)
{
ConsolePal.Beep(frequency, duration);
}
ConsolePal
有两种实现方式:一种用于 Windows,另一种用于类 Unix 系统。假设您使用的是 Windows,让我们看一下 the Beep
implementation in 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);
}
这里的关键行是调用 Interop.Kernel32.Beep
。这是一个强有力的指标,表明我们将调用 native Windows API,但让我们验证一下。 Interop.Kernel32
是 split over a bunch of files --通常这可能会给我们带来一些困难,但碰巧列表中的第一个是 Interop.Beep.cs
--方便!
打开文件,我们对原生调用的怀疑are confirmed :
[DllImport(Libraries.Kernel32, SetLastError = true)]
internal static extern bool Beep(int frequency, int duration);
这是使用一种称为平台调用的技术,通常缩写为 P/Invoke。有一个很棒的站点 pinvoke.net,它提供了常见的 P/Invoke 代码段以及一些附带的实现。让我们看看what pinvoke.net has to say about Beep in kernel32.dll :
Unlike MessageBeep, this function is synchronous. (It doesn’t return control to its caller until the sound finishes.)
由于您的代码或 Console.Beep
中没有任何其他内容会导致延迟,这意味着 Windows API 可能是罪魁祸首。幸运的是,pinvoke.net 提供了一种可能有效的解决方法。为了确定,让我们检查一下 MSDN's documentation on Windows' Beep
, pinvoke.net 方便地链接到它。它附带了一些关于 Beep
的非常有趣的历史,以及切换到 MessageBeep
的建议。
不幸的是,the MSDN documentation for MessageBeep
带来失望:我们不能用它来生成任意音调。
这使我们得出了最终结论:kernel32 的 Beep
并不是真正用于生成奇特的声音。它既依赖于硬件又依赖于平台,如果您试图在各种设备上生成一致的声音,那么这两者都不是理想的选择。它本质上是过去的遗物。它甚至在 Windows XP 中被删除,尽管它后来被添加回 Windows 7。这意味着 .NET 的 Console.Beep(int, int)
有所有相同的问题,因为它只是 kernel32 的包装器嘟嘟声
。
更可靠的解决方案是研究各种音频框架,但这些框架可能会复杂得多。现在,如果您刚刚开始使用 C# 并希望让事情变得简单,您可能会遇到不一致的情况,例如您观察到的延迟。
关于c# - 连续调用 Console.Beep() 之间的延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57650484/