如何使用NAudio在C#中以精确的间隔播放音频文件



我正试图使用NAudio在C#中创建一个精确的节拍器,但在播放音频文件时,任何方向都会有20毫秒的延迟。无论是在听节拍器的时候,还是在像大胆这样的软件中录制和检查节拍器时,它都是值得注意的。

我从这条评论中获得灵感,编写了以下代码:

using System;
using NAudio.Wave;
namespace audio_timing_test
{
class Program
{
public static int bpm = 120;
public static DirectSoundOut player;
public static WaveFileReader waveReader;
public static AccurateTimer AudioTickTimer;
static void Main(string[] args)
{
player = new DirectSoundOut();
waveReader = new WaveFileReader(System.AppContext.BaseDirectory + "ticksound.wav");
player.Init(new WaveChannel32(waveReader));
AudioTickTimer = new AccurateTimer(new Action(AudioTick), (int)(60000 / bpm));
waveReader.CurrentTime = waveReader.TotalTime + TimeSpan.FromSeconds(1);
player.Play();
Console.WriteLine("Press key to exit.");
Console.ReadKey();
}
static void AudioTick()
{
waveReader.CurrentTime = TimeSpan.FromSeconds(0);
}
}
}

这会以480和520毫秒的交替间隔播放音频,但它应该是每个刻度500毫秒。使用的AccurateTimer方法可以在这里找到。我还尝试过使用System.Timers.Timer,正如这里所建议的那样,这给了我相同的结果。

我应该补充一点;waveReader.CurrentTime=waveReader.TotalTime+TimeSpan.FromSeconds(1("就是跳过第一个勾号,这就是它在最终程序中的表现。删除该行不会影响结果。

这里的问题是什么?如何实现500毫秒的一致且精确的间隔?非常感谢。

我发现了问题所在:

事实证明,保持音频运行并将位置重置为0作为滴答声的一种方式并不奏效,相反,你必须处理音频的结束/停止,并在每次滴答声时正确地重新启动它。

这是更新的工作代码:

using System;
using NAudio.Wave;
namespace audio_timing_test
{
class Program
{
public static double bpm = 100;
public static DirectSoundOut player;
public static WaveFileReader waveReader;
public static WaveChannel32 wave32;
public static AccurateTimer audioTickTimer;
static void Main(string[] args)
{
waveReader = new WaveFileReader(System.AppContext.BaseDirectory + "ticksound.wav");
wave32 = new WaveChannel32(waveReader);
wave32.PadWithZeroes = false;
player = new DirectSoundOut();
player.PlaybackStopped += new EventHandler<StoppedEventArgs>(StopAudio);
player.Init(wave32);
audioTickTimer = new AccurateTimer(new Action(AudioTick), (int)(60000 / bpm));
Console.WriteLine("Press key to exit.");
Console.ReadKey();
}
static void AudioTick()
{
player.Play();
}
static void StopAudio(object sender, StoppedEventArgs e)
{
player.Stop();
waveReader.CurrentTime = TimeSpan.FromSeconds(0);
}
}
}

最新更新