【问题标题】:Playing WAVE file in C# using DirectX and threading?使用 DirectX 和线程在 C# 中播放 WAVE 文件?
【发布时间】:2012-10-11 07:15:46
【问题描述】:

目前,我试图弄清楚如何通过线程使用波形文件中的数据填充辅助缓冲区,然后播放波形文件,从而设法在 C# 中播放波形文件。

我可以使用任何帮助或示例编码吗?

谢谢

正在使用的示例代码:

public delegate void PullAudio(short[] buffer, int length);

public class SoundPlayer : IDisposable
{
    private Device soundDevice;
    private SecondaryBuffer soundBuffer;
    private int samplesPerUpdate;
    private AutoResetEvent[] fillEvent = new AutoResetEvent[2];
    private Thread thread;
    private PullAudio pullAudio;
    private short channels;
    private bool halted;
    private bool running;

    public SoundPlayer(Control owner, PullAudio pullAudio, short channels)
    {
        this.channels = channels;
        this.pullAudio = pullAudio;

        this.soundDevice = new Device();
        this.soundDevice.SetCooperativeLevel(owner, CooperativeLevel.Priority);

        // Set up our wave format to 44,100Hz, with 16 bit resolution
        WaveFormat wf = new WaveFormat();
        wf.FormatTag = WaveFormatTag.Pcm;
        wf.SamplesPerSecond = 44100;
        wf.BitsPerSample = 16;
        wf.Channels = channels;
        wf.BlockAlign = (short)(wf.Channels * wf.BitsPerSample / 8);
        wf.AverageBytesPerSecond = wf.SamplesPerSecond * wf.BlockAlign;

        this.samplesPerUpdate = 512;

        // Create a buffer with 2 seconds of sample data
        BufferDescription bufferDesc = new BufferDescription(wf);
        bufferDesc.BufferBytes = this.samplesPerUpdate * wf.BlockAlign * 2;
        bufferDesc.ControlPositionNotify = true;
        bufferDesc.GlobalFocus = true;

        this.soundBuffer = new SecondaryBuffer(bufferDesc, this.soundDevice);

        Notify notify = new Notify(this.soundBuffer);

        fillEvent[0] = new AutoResetEvent(false);
        fillEvent[1] = new AutoResetEvent(false);

        // Set up two notification events, one at halfway, and one at the end of the buffer
        BufferPositionNotify[] posNotify = new BufferPositionNotify[2];
        posNotify[0] = new BufferPositionNotify();
        posNotify[0].Offset = bufferDesc.BufferBytes / 2 - 1;
        posNotify[0].EventNotifyHandle = fillEvent[0].Handle;
        posNotify[1] = new BufferPositionNotify();
        posNotify[1].Offset = bufferDesc.BufferBytes - 1;
        posNotify[1].EventNotifyHandle = fillEvent[1].Handle;

        notify.SetNotificationPositions(posNotify);

        this.thread = new Thread(new ThreadStart(SoundPlayback));
        this.thread.Priority = ThreadPriority.Highest;

        this.Pause();
        this.running = true;

        this.thread.Start();
    }

    public void Pause()
    {
        if (this.halted) return;

        this.halted = true;

        Monitor.Enter(this.thread);
    }

    public void Resume()
    {
        if (!this.halted) return;

        this.halted = false;

        Monitor.Pulse(this.thread);
        Monitor.Exit(this.thread);
    }

    private void SoundPlayback()
    {
        lock (this.thread)
        {
            if (!this.running) return;

            // Set up the initial sound buffer to be the full length
            int bufferLength = this.samplesPerUpdate * 2 * this.channels;
            short[] soundData = new short[bufferLength];

            // Prime it with the first x seconds of data
            this.pullAudio(soundData, soundData.Length);
            this.soundBuffer.Write(0, soundData, LockFlag.None);

            // Start it playing
            this.soundBuffer.Play(0, BufferPlayFlags.Looping);

            int lastWritten = 0;
            while (this.running)
            {
                if (this.halted)
                {
                    Monitor.Pulse(this.thread);
                    Monitor.Wait(this.thread);
                }

                // Wait on one of the notification events
                WaitHandle.WaitAny(this.fillEvent, 3, true);

                // Get the current play position (divide by two because we are using 16 bit samples)
                int tmp = this.soundBuffer.PlayPosition / 2;

                // Generate new sounds from lastWritten to tmp in the sound buffer
                if (tmp == lastWritten)
                {
                    continue;
                }
                else
                {
                    soundData = new short[(tmp - lastWritten + bufferLength) % bufferLength];
                }

                this.pullAudio(soundData, soundData.Length);

                // Write in the generated data
                soundBuffer.Write(lastWritten * 2, soundData, LockFlag.None);

                // Save the position we were at
                lastWritten = tmp;
            }
        }
    }

    public void Dispose()
    {
        this.running = false;
        this.Resume();

        if (this.soundBuffer != null)
        {
            this.soundBuffer.Dispose();
        }
        if (this.soundDevice != null)
        {
            this.soundDevice.Dispose();
        }
    }
}

}

概念与我使用的相同,但我无法获得一组要播放的波字节 [] 数据

【问题讨论】:

  • 这里是强制使用 DirectX 还是只需要异步播放波形文件?

标签: c# directx


【解决方案1】:

我没有这样做。

但我首先要看的是 XNA。

我知道 C# 托管的 directx 项目已被 XNA 抛弃,我发现它对图形很有用 - 我更喜欢使用它而不是 directx。

【讨论】:

    【解决方案2】:

    根据下面的这个 msdn 条目,您决定不只使用声音播放器的原因是什么?

        private SoundPlayer Player = new SoundPlayer();
        private void loadSoundAsync()
        {
            // Note: You may need to change the location specified based on
            // the location of the sound to be played.
            this.Player.SoundLocation = http://www.tailspintoys.com/sounds/stop.wav";
            this.Player.LoadAsync();
        }
    
        private void Player_LoadCompleted (
            object sender, 
            System.ComponentModel.AsyncCompletedEventArgs e)
        {
            if (this.Player.IsLoadCompleted)
            {
                this.Player.PlaySync();
            }
        }
    

    通常我只是将它们全部加载到一个线程或异步委托中,然后在需要时播放或同步它们。

    【讨论】:

    • 例如是在会话 0 上播放声音。
    【解决方案3】:

    您可以在 SlimDX 中使用 DirectSound 支持:http://slimdx.org/ :-)

    【讨论】:

      【解决方案4】:

      您可以使用 nBASS 或更好的 FMOD,它们都是很棒的音频库,并且可以与 .NET 很好地协同工作。

      【讨论】:

        【解决方案5】:

        DirectSound 是您想去的地方。这是小菜一碟,但我不确定它除了.wav还能播放什么格式

        http://msdn.microsoft.com/en-us/library/windows/desktop/ee416960(v=vs.85).aspx

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-05-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-07-20
          相关资源
          最近更新 更多