Изменение баланса звука в правом и левом каналах с помощью NAudio - PullRequest
0 голосов
/ 16 апреля 2020

При воспроизведении звука мне нужно отдельно регулировать громкость правого и левого каналов. У меня есть класс для воспроизведения звука:

public class SoundPlayer
{
    private WaveOutEvent _outputDevice;
    private AudioFileReader _audioFile;
    private float _volume = 1f;

    public float Volume
    {
        get => _volume;
        set
        {
            _volume = value;

            if (_audioFile != null)
                _audioFile.Volume = value;
        }
    }

    public void Play(string fileName)
    {
        if (_outputDevice == null)
        {
            _outputDevice = new WaveOutEvent();
            _outputDevice.PlaybackStopped += (sender, args) =>
            {
                _outputDevice.Dispose();
                _outputDevice = null;
                _audioFile.Dispose();
                _audioFile = null;
            };
        }
        if (_audioFile == null)
        {
            _audioFile = new AudioFileReader(fileName) { Volume = _volume };
            _outputDevice.Init(_audioFile);

        }
        else
        {
            if (string.IsNullOrWhiteSpace(fileName))
                _outputDevice = null;
            else
            {
                if (_audioFile.FileName != fileName)
                {
                    _audioFile = new AudioFileReader(fileName) { Volume = _volume };
                    _outputDevice.Init(_audioFile);
                }
            }
        }

        _outputDevice?.Play();
    }

    public void Stop()
    {
        _outputDevice?.Stop();
    }
}

Но в этом классе вы можете регулировать только общую громкость. Как сделать такое свойство: soundPlayer.LeftChannelVolume = 1.0f soundPlayer.RightChannelVolume = 0.5f

Ответы [ 2 ]

0 голосов
/ 17 апреля 2020

Я сделал свой провайдер и он заработал!) Если кому-то это нужно, то вот:

/// <summary>
/// Very simple sample provider supporting adjustable gain
/// </summary>
public class VolumeStereoSampleProvider : ISampleProvider
{
    private readonly ISampleProvider source;

    /// <summary>
    /// Allows adjusting the volume left channel, 1.0f = full volume
    /// </summary>
    public float VolumeLeft { get; set; }

    /// <summary>
    /// Allows adjusting the volume right channel, 1.0f = full volume
    /// </summary>
    public float VolumeRight { get; set; }

    /// <summary>
    /// Initializes a new instance of VolumeStereoSampleProvider
    /// </summary>
    /// <param name="source">Source sample provider, must be stereo</param>
    public VolumeStereoSampleProvider(ISampleProvider source)
    {
        if (source.WaveFormat.Channels != 2)
            throw new ArgumentException("Source sample provider must be stereo");

        this.source = source;
        VolumeLeft = 1.0f;
        VolumeRight = 1.0f;
    }

    /// <summary>
    /// WaveFormat
    /// </summary>
    public WaveFormat WaveFormat => source.WaveFormat;

    /// <summary>
    /// Reads samples from this sample provider
    /// </summary>
    /// <param name="buffer">Sample buffer</param>
    /// <param name="offset">Offset into sample buffer</param>
    /// <param name="sampleCount">Number of samples desired</param>
    /// <returns>Number of samples read</returns>
    public int Read(float[] buffer, int offset, int sampleCount)
    {
        int samplesRead = source.Read(buffer, offset, sampleCount);

        for (int n = 0; n < sampleCount; n += 2)
        {
            buffer[offset + n] *= VolumeLeft;
            buffer[offset + n + 1] *= VolumeRight;
        }

        return samplesRead;
    }
}
0 голосов
/ 17 апреля 2020

Сделано с помощью PanningSampleProvider. Но для этого вам нужно конвертировать в моно. Также реакция на смену Пан - происходит с небольшой задержкой. Как этого можно избежать? Как работать со стерео и просто менять громкость его правого и левого каналов? Я думаю, что это должно работать намного быстрее.

_audioFile = new AudioFileReader(_fileName) { Volume = _volume };
var mono = new StereoToMonoSampleProvider(_audioFile) { LeftVolume = 1f, RightVolume = 1f };
var panner = new PanningSampleProvider(mono);

_outputDevice.Init(panner);
...