c# - 同时播放三种声音C#

标签 c# audio axwindowsmediaplayer

我想同时播放三个声音,但是第二个声音必须在一秒钟后播放,第二个声音必须在两秒钟后播放。我有这个代码:

private void Play()
        {
            AxWindowsMediaPlayer player1 = new AxWindowsMediaPlayer();
            player1.CreateControl();
            AxWindowsMediaPlayer player2 = new AxWindowsMediaPlayer();
            player2.CreateControl();
            AxWindowsMediaPlayer player3 = new AxWindowsMediaPlayer();
            player3.CreateControl();
            player1.URL = "sounds\\1.wav";
            player1.Ctlcontrols.play();
            System.Threading.Thread.Sleep(1000);
            player2.URL = "sounds\\2.wav";
            player2.Ctlcontrols.play();
            System.Threading.Thread.Sleep(1000);
            player3.URL = "sounds\\3.wav";
            player3.Ctlcontrols.play();

为什么所有这些声音都在两秒钟后一次播放?

最佳答案

我最终使用了SharpDX(可通过NuGet包SharpDX获得)
SharpDX.XAudio2

在我的一个GitHub项目中可以找到其用法的示例:2DAI
您也可以在screen recording中听到各种重叠的声音。

播放声音:

var backgroundMusicSound = new AudioClip(@".\Assets\Sounds\Music\Background.wav" /*Sound path*/, 1.0 /* Volumne*/, true /*Loop Forever?*/)

backgroundMusicSound.Play();

我组装的类(class):
public class AudioClip
{
    private XAudio2 _xaudio = new XAudio2();
    private WaveFormat _waveFormat;
    private AudioBuffer _buffer;
    private SoundStream _soundstream;
    private SourceVoice _singleSourceVoice;
    private bool _loopForever;
    private bool _isPlaying = false; //Only applicable when _loopForever == false;
    private bool _isFading;
    private string _wavFilePath; //For debugging.
    private float _initialVolumne;

    public AudioClip(string wavFilePath, float initialVolumne = 1, bool loopForever = false)
    {
        _loopForever = loopForever;
        _wavFilePath = wavFilePath;
        _initialVolumne = initialVolumne;

        var masteringsound = new MasteringVoice(_xaudio); //Yes, this is required.
        var nativefilestream = new NativeFileStream(wavFilePath,
            NativeFileMode.Open, NativeFileAccess.Read, NativeFileShare.Read);

        _soundstream = new SoundStream(nativefilestream);

        _waveFormat = _soundstream.Format;
        _buffer = new AudioBuffer
        {
            Stream = _soundstream.ToDataStream(),
            AudioBytes = (int)_soundstream.Length,
            Flags = BufferFlags.EndOfStream
        };

        if (loopForever)
        {
            _buffer.LoopCount = 100;
        }
    }

    public void Play()
    {
        lock (this)
        {
            if (_loopForever == true)
            {
                if (_isPlaying)
                {
                    if (_isFading)
                    {
                        _isFading = false;
                        _singleSourceVoice.SetVolume(_initialVolumne);
                    }

                    return;
                }
                _singleSourceVoice = new SourceVoice(_xaudio, _waveFormat, true);
                _singleSourceVoice.SubmitSourceBuffer(_buffer, _soundstream.DecodedPacketsInfo);
                _singleSourceVoice.SetVolume(_initialVolumne);

                _singleSourceVoice.Start();
                _isPlaying = true;
                return;
            }
        }

        var sourceVoice = new SourceVoice(_xaudio, _waveFormat, true);
        sourceVoice.SubmitSourceBuffer(_buffer, _soundstream.DecodedPacketsInfo);
        sourceVoice.SetVolume(_initialVolumne);
        sourceVoice.Start();
    }

    public void Fade()
    {
        if (_isPlaying && _isFading == false)
        {
            _isFading = true;
            (new Thread(FadeThread)).Start();
        }
    }

    private void FadeThread()
    {
        float volumne;

        _singleSourceVoice.GetVolume(out volumne);

        while (_isFading && volumne > 0)
        {
            volumne -= 0.25f;
            volumne = volumne < 0 ? 0 : volumne;
            _singleSourceVoice.SetVolume(volumne);
            Thread.Sleep(100);
        }
        Stop();
    }

    public void Stop()
    {
        if (_loopForever == true)
        {
            if (_singleSourceVoice != null && _isPlaying)
            {
                _singleSourceVoice.Stop();
            }
            _isPlaying = false;
            _isFading = false;
        }
        else
        {
            throw new Exception("Cannot stop overlapped audio.");
        }
    }
}

还应该注意,加载声音可能是一个繁重的过程,因此,如果您经常这样做,则可能需要像我一样缓存它们:
private Dictionary<string, AudioClip> _audioClips { get; set; } = new Dictionary<string, AudioClip>();

public AudioClip GetSoundCached(string wavFilePath, float initialVolumne, bool loopForever = false)
{
    lock (_audioClips)
    {
        AudioClip result = null;

        wavFilePath = wavFilePath.ToLower();

        if (_audioClips.ContainsKey(wavFilePath))
        {
            result = _audioClips[wavFilePath];
        }
        else
        {
            result = new AudioClip(wavFilePath, initialVolumne, loopForever);
            _audioClips.Add(wavFilePath, result);
        }

        return result;
    }
}

关于c# - 同时播放三种声音C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32010755/

相关文章:

java - 如何在处理中更改 mp3 的音量(级别)?

c# - 如何在 C# 中使用 axWindowsMediaPlayer 跳转 X 秒

c# - 在 AxWindowsMediaPlayer 上叠加 Picturebox(或图像)

c# - 为非常简单的类调整和简化 DataContract 序列化?

c# - C# 中缺少 ctor 约束的基本原理

audio - FFmpeg:如何在音频文件中间降低几秒钟的音量?

c# - 是否可以在派生类或任何其他类中调用抽象类的方法

c# - 如何在 Entity Framework 5 中使用 SQL Server OFFSET 和 FETCH FIRST?

c - Linux 中 C 的 sound() 和 nosound() 函数?