c# - 连续调用 Console.Beep() 之间的延迟
问题描述
我正在尝试制作一个简单的程序来生成可以根据输入值变化的音调。我想起诉 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 源代码通常会有所帮助。查看Console.Beep 的源代码:
public static void Beep(int frequency, int duration)
{
ConsolePal.Beep(frequency, duration);
}
有两种实现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);
}
这里的关键是调用Interop.Kernel32.Beep
. 这是我们即将调用本机 Windows API 的一个强有力的指标,但让我们验证一下。 被分割成一堆文件Interop.Kernel32
——通常这可能会给我们带来一些困难,但碰巧列表中的第一个是——方便!Interop.Beep.cs
打开文件,我们对本地调用的怀疑得到了证实:
[DllImport(Libraries.Kernel32, SetLastError = true)]
internal static extern bool Beep(int frequency, int duration);
这是使用一种称为平台调用的技术,通常缩写为 P/Invoke。有一个很棒的站点 pinvoke.net,它提供了常见的 P/Invoke 片段以及一些附带的实现。让我们看看pinvoke.net 对 kernel32.dll 中的 Beep 有什么看法:
与 MessageBeep 不同,此函数是同步的。(在声音结束之前,它不会将控制权返回给它的调用者。)
由于您的代码中没有其他内容或Console.Beep
会导致延迟,这意味着 Windows API 可能是罪魁祸首。幸运的是,pinvoke.net 提供了一种可行的解决方法。为了确保这一点,让我们查看MSDN 在 Windows 上的文档Beep
,pinvoke.net 可以方便地链接到该文档。它带有一些非常迷人的历史Beep
,以及切换到的建议MessageBeep
。
不幸的是,MSDN 文档MessageBeep
令人失望:我们不能使用它来生成任意音调。
这使我们得出了最终结论:kernel32Beep
并不是真正用于生成花哨的声音。它既依赖于硬件,也依赖于平台,如果您试图在各种设备上生成一致的声音,这两者都不是理想的。它本质上是过去的遗物。它甚至在 Windows XP 中被删除,但后来在 Windows 7 中又被添加回来。这意味着 .NETConsole.Beep(int, int)
具有所有相同的问题,因为它只是 kernel32 的包装器Beep
。
一个更强大的解决方案是研究各种音频框架,但这些可能会复杂得多。目前,如果您刚开始使用 C# 并希望保持简单,您可能会遇到不一致的情况,例如您观察到的延迟。
推荐阅读
- aws-lambda - AWS cloudformation 自定义资源为另一个 lambda 生成配置文件
- python - python请求发送带有图像和json数据的表单数据
- ubuntu - 带有 Ubuntu 的 Raspberry Pi 4 B 上带有 MCP2515 的 CAN 屏蔽
- c# - 如何将 optionLabel 的值设置为 null 并将其传递给模型
- javascript - NodeJS将数据返回到客户端浏览器
- sql - 在 BigQuery 中使用“hits.{column name}”为未嵌套的匹配列添加前缀
- python - 如何使用不可选择的文本创建 PDF 文件?
- html - 使用CSS如何解决隐藏在前一个标签下的问题?
- reactjs - React 函数式组件 - Styleguidist
- typescript - 打字稿在正确键入的参数上引发错误