使用SlimDX和DirectSound播放声音(C#)

4

如果这是重复的问题,我很抱歉...我已经发布过了,但没有看到它实际上是否被发送到论坛中。

我一直在尝试让SlimDX DirectSound工作。这里是我的代码。它从一个wav文件填充辅助缓冲区,然后在一个线程循环中,交替地填充缓冲区的下半部分或上半部分。

它可以正常播放缓冲区的第一次加载。AutoResetEvents在应该时触发,然后填充了缓冲区的下半部分和上半部分(通过Debug语句进行验证)。但是,在缓冲区的第一次加载后,播放不会继续进行。所以,某种方式,缓冲区的重新填充没有按照预期工作。

有什么想法吗?

(我使用DirectSound是因为这是我找到的唯一设置要使用的音频设备的guid的方法。欢迎其他.NET友好的方法。)

private void PlaySound(Guid soundCardGuid, string audioFile) {
        DirectSound ds = new DirectSound(soundCardGuid);

        ds.SetCooperativeLevel(this.Handle, CooperativeLevel.Priority);

        WaveFormat format = new WaveFormat();
        format.BitsPerSample = 16;
        format.BlockAlignment = 4;
        format.Channels = 2;
        format.FormatTag = WaveFormatTag.Pcm;
        format.SamplesPerSecond = 44100;
        format.AverageBytesPerSecond = format.SamplesPerSecond * format.BlockAlignment;

        SoundBufferDescription desc = new SoundBufferDescription();
        desc.Format = format;
        desc.Flags = BufferFlags.GlobalFocus;
        desc.SizeInBytes = 8 * format.AverageBytesPerSecond; 

        PrimarySoundBuffer pBuffer = new PrimarySoundBuffer(ds, desc);

        SoundBufferDescription desc2 = new SoundBufferDescription();
        desc2.Format = format;
        desc2.Flags = BufferFlags.GlobalFocus | BufferFlags.ControlPositionNotify | BufferFlags.GetCurrentPosition2;
        desc2.SizeInBytes = 8 * format.AverageBytesPerSecond;

        SecondarySoundBuffer sBuffer1 = new SecondarySoundBuffer(ds, desc2);

        NotificationPosition[] notifications = new NotificationPosition[2];
        notifications[0].Offset = desc2.SizeInBytes / 2 + 1;
        notifications[1].Offset = desc2.SizeInBytes - 1; ;

        notifications[0].Event = new AutoResetEvent(false);
        notifications[1].Event = new AutoResetEvent(false);
        sBuffer1.SetNotificationPositions(notifications);

        byte[] bytes1 = new byte[desc2.SizeInBytes / 2];
        byte[] bytes2 = new byte[desc2.SizeInBytes];

        Stream stream = File.Open(audioFile, FileMode.Open);

        Thread fillBuffer = new Thread(() => {
            int readNumber = 1;
            int bytesRead;

            bytesRead = stream.Read(bytes2, 0, desc2.SizeInBytes);
            sBuffer1.Write<byte>(bytes2, 0, LockFlags.None);
            sBuffer1.Play(0, PlayFlags.None); 
            while (true) {
                if (bytesRead == 0) { break; }
                notifications[0].Event.WaitOne();
                bytesRead = stream.Read(bytes1, 0, bytes1.Length);
                sBuffer1.Write<byte>(bytes1, 0, LockFlags.None);

                if (bytesRead == 0) { break; }
                notifications[1].Event.WaitOne();
                bytesRead = stream.Read(bytes1, 0, bytes1.Length);
                sBuffer1.Write<byte>(bytes1, desc2.SizeInBytes / 2, LockFlags.None); 
            }
            stream.Close();
            stream.Dispose();
        });
        fillBuffer.Start();
    }
}
1个回答

3
您还没有将其设置为在播放缓冲区上循环。请更改您的代码如下:
sBuffer1.Play(0, PlayFlags.Looping); 

1
谢谢。就这样了。在没有关于SlimDX的文档的情况下,我误解了标志的含义。 - blearyeye
完成。之前忘了返回翻译的文本。 - blearyeye
也适用于DirectSound。和blearyeye有同样的问题。感谢您指引我找到它... - Martin Hennings

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接