在 C# 中使用 DirectX 进行无缝(循环)音频播放

Posted

技术标签:

【中文标题】在 C# 中使用 DirectX 进行无缝(循环)音频播放【英文标题】:Gapless (looping) audio playback with DirectX in C# 【发布时间】:2010-03-17 16:21:00 【问题描述】:

我目前正在使用以下代码 (C#):

    private static void PlayLoop(string filename)
    
        Audio player = new Audio(filename);
        player.Play();
        while (player.Playing)
        
            if (player.CurrentPosition >= player.Duration)
            
                player.SeekCurrentPosition(0, SeekPositionFlags.AbsolutePositioning);
            
            System.Threading.Thread.Sleep(100);
        
    

此代码有效,我正在播放的文件正在循环播放。但是,很明显,每次播放之间都有一个小的差距。

我尝试将 Thread.Sleep 减少到 10 或 5,但差距仍然存在。 我也尝试过将其完全移除,但随后 CPU 使用率上升到 100%,并且仍然有一点差距。

有什么(简单的)方法可以在 DirectX 中无缝播放吗? 这没什么大不了的,因为它只是一个个人项目,但如果我做的事情很愚蠢或完全错误,我很想知道。

提前致谢。

【问题讨论】:

【参考方案1】:

你的方法的问题是你有一个线程在旋转,检查玩家的位置。增加睡眠的时间越长,消耗的 CPU 越少,但它会越晚注意到剪辑的结束。睡眠时间越短,它会越快注意到,但检查器线程消耗的 CPU 越多。

我在文档中看不到任何东西告诉剪辑循环。我唯一的建议是使用 Audio.Ending 事件重新开始播放剪辑。这将消除对单独监控线程的需要,但我不确定这是否足够快以消除差距。

您还需要检查以确保您的音频剪辑不会以一段沉默开始或结束。

【讨论】:

【参考方案2】:

既然你知道歌曲的时长,只需使用定时器定期调用你的“倒带”方法,并给定时器一个比实际歌曲时长略短的间隔。

private static void PlayLoop(string filename)

    Audio player = new Audio(filename);
    player.Play();

    //System.Timers.Timer (i reduce the length by 100 ms to try to avoid blank)
    var timer = new Timer((player.Duration - TimeSpan.FromMilliseconds(100)).TotalMilliseconds());
    timer.Elapsed += (sender, arg) =>
    
        player.SeekCurrentPosition(0, SeekPositionFlags.AbsolutePositioning);
    ;
    timer.Start();

当然,您需要停止计时器,使其成为实例成员而不是方法的局部变量,这样您就可以使用 Stop() 方法禁用它。

我希望这会对你有所帮助。 咒语

【讨论】:

以上是关于在 C# 中使用 DirectX 进行无缝(循环)音频播放的主要内容,如果未能解决你的问题,请参考以下文章

DirectX 3D 之C#开发

在 C# 中使用 DirectX11 和 SlimDX 的 Nvidia 3d 视频

C# Directx App 在 Release 中崩溃

使用 C#、DirectX 和 XNA 播放音频和最终用户的要求

如何从使用directx c# visual studio播放的视频中获取和处理每一帧(位图图像​​)

在 C# WPF 或 Windows 窗体应用程序中使用 DirectX c++ DLL