naudio - NAudio:如何在使用 AudioFileReader 和 WaveOutEvent 更改播放位置时准确获取当前播放位置
问题描述
我正在创建一个应用程序,该应用程序需要允许用户在文件播放时选择音频文件的播放位置。但是,一旦位置发生变化,我就无法确定当前位置。
这是一个示例程序,显示了我将如何处理它。
using NAudio.Utils;
using NAudio.Wave;
using System;
namespace NAudioTest
{
class Program
{
static void Main()
{
var audioFileReader = new AudioFileReader("test.mp3");
var waveOutEvent = new WaveOutEvent();
waveOutEvent.Init(audioFileReader);
waveOutEvent.Play();
while (true)
{
var key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Enter)
{
var playLocationSeconds =
waveOutEvent.GetPositionTimeSpan().TotalSeconds;
Console.WriteLine(
"Play location is " + playLocationSeconds + "seconds");
}
else if (key.Key == ConsoleKey.RightArrow)
{
audioFileReader.CurrentTime =
audioFileReader.CurrentTime.Add(TimeSpan.FromSeconds(30));
}
else
{
break;
}
}
}
}
}
重现问题的步骤
- 启动程序:音频文件开始播放
- 按回车键:当前播放时间写入控制台
- 按右箭头键:播放的音频向前跳(大概)到预期的位置
- 再次按 Enter 键:将播放时间写入控制台,但它看起来是自音频第一次开始播放以来的时间量,而不是当前播放位置的时间。
我尝试获取 AudioFileReader.CurrentTime 的值,而不是在 WaveOutEvent 上调用 GetPositionTimeSpan。这种方法的问题是 AudioFileReader.CurrentTime 值在跳跃中进行,大概是因为这个底层流在与 WaveOutEvent 一起使用时被缓冲,所以 CurrentTime 不能准确地反映播放位置,只反映底层流中的位置。
如何在支持任意播放定位的同时继续获得当前时间的准确播放位置?
解决方案
音频文件阅读器的“CurrentTime”属性足以告诉当前播放位置,尤其是在延迟不是很高的情况下。我发现它和 waveOutEvent.GetPositionTimeSpan() 之间的差异是 100-200 毫秒。最多。
您确实在使用 CurrentTime 属性的设置器在流中重新定位。使用 getter 来查询当前位置也是一致的。如果您关心精度,则可以使用较低的延迟。
扩展方法“GetPositionTimeSpan()”似乎返回了迄今为止播放的总长度,而不是流中的位置。诚然,我不知道为什么会这样。
推荐阅读
- python - Python:从 JSON 中读取颜色代码
- android - 从另一个片段返回时保留片段内的对讲焦点?
- google-cloud-platform - 将 Google Cloud Platform 服务帐户的访问权限限制为特定的 Gmail 帐户
- javascript - 如何使用 react-hook-form 在 React 中存储无线电组的状态
- javascript - HTML5 / JavaScript / JQuery - 获取与输入相关联的表单的最佳方式
- search - 如何匹配特定列中的精确文本并输出整行信息?
- r - 如何使用 R 从数组中选择行?
- chart.js - 如何限制chart.js中显示的点数?
- php - 我的 Ajax 不显示通知消息
- php - 如何声明在 PhpDoc 中定义了一个常量(用于 intelephense)?