С# CSCore нет звука из mp3-файла

Используя библиотеку CSCore, я написал код для воспроизведения mp3-файла в классе BGM в отдельном файле с именем BGM.cs, а метод воспроизведения — BGM.Play("file directory");, который вызывается в Form. Но почему-то у меня не получается извлечь из него звук. Я уже проверил громкость, кодек и вывод и не могу придумать ничего другого, что могло бы вызвать эту проблему.

Это код файла класса:

public class BGM
{
    public static void Play(string file)
    {
        using (IWaveSource soundSource = GetSoundSource(file))
        {
            using (ISoundOut soundOut = GetSoundOut())
            {
                soundOut.Initialize(soundSource);
                soundOut.Volume = 0.8f;
                soundOut.Play();
            }
        }
    }
    private static ISoundOut GetSoundOut()
    {
        if (WasapiOut.IsSupportedOnCurrentPlatform)
            return new WasapiOut();
        else
            return new DirectSoundOut();
    }
    private static IWaveSource GetSoundSource(string file)
    {
        return CodecFactory.Instance.GetCodec(file);
    }

person Chaos Spindash    schedule 23.12.2017    source источник


Ответы (1)


На самом деле есть несколько причин, по которым ваш mp3 не воспроизводится.

Первая причина заключается в том, что вы не указали устройство, на котором будет воспроизводиться звук. Приведенный ниже код получает первое устройство, которое может воспроизводить звук, но это не всегда будет правильно, если к компьютеру пользователя подключено несколько устройств. Вам придется обращаться с этим соответствующим образом. Устройство должно быть установлено на объекте WasapiOut.

Вторая причина заключается в использовании вами операторов using в методе Play. Хотя всегда полезно очищать объекты, реализующие IDisposable, вы не всегда можете сделать это немедленно. В данном случае soundOut.Play() не является блокирующим методом, а это означает, что элемент управления немедленно выходит из метода, что приводит к вызову Dispose() для soundOut и soundSource. Это означало, что звук фактически никогда не будет воспроизводиться (возможно, он начнется на короткий момент, но не настолько, чтобы его действительно можно было услышать). По сути, вам нужно удерживать ссылки и избавляться от них только после завершения воспроизведения.

Взгляните на AudioPlayerSample, чтобы понять, как реализовать полное решение. Мой код должен помочь вам начать.

void Main()
{
    using(var player = new BGM(@"D:\Test.mp3"))
    {
        player.Play();

        // TODO: Need to wait here in order for playback to complete
        // Otherwise, you need to hold onto the player reference and dispose of it later
        Console.ReadLine();
    }
}

public class BGM : IDisposable
{
    private bool _isDisposed = false;
    private ISoundOut _soundOut;
    private IWaveSource _soundSource;

    public BGM(string file)
    {
        _soundSource = CodecFactory.Instance.GetCodec(file);
        _soundOut = GetSoundOut();
        _soundOut.Initialize(_soundSource);
    }

    public void Play()
    {
        if(_soundOut != null)
        {
            _soundOut.Volume = 0.8f;
            _soundOut.Play();
        }
    }

    public void Stop()
    {
        if(_soundOut != null)
        {
            _soundOut.Stop();
        }
    }

    private static ISoundOut GetSoundOut()
    {
        if (WasapiOut.IsSupportedOnCurrentPlatform)
        {
            return new WasapiOut
            {
                Device = GetDevice()
            };
        }

        return new DirectSoundOut();
    }

    private static IWaveSource GetSoundSource(string file)
    {
        return CodecFactory.Instance.GetCodec(file);
    }

    public static MMDevice GetDevice()
    {
        using(var mmdeviceEnumerator = new MMDeviceEnumerator())
        {
            using(var mmdeviceCollection = mmdeviceEnumerator.EnumAudioEndpoints(DataFlow.Render, DeviceState.Active))
            {
                // This uses the first device, but that isn't what you necessarily want
                return mmdeviceCollection.First();
            }
        }
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_isDisposed)
        {
            if (disposing)
            {
                if(_soundOut != null)
                {
                    _soundOut.Dispose();
                }

                if(_soundSource != null)
                {
                    _soundSource.Dispose();
                }
            }

            _isDisposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
    }
}
person Connor    schedule 23.12.2017