使用 NAudio 改变左右声道的声音平衡
Changing the sound balance in the right and left channels with NAudio
播放声音时,需要分别调节左右声道的音量。
我有 class 来播放声音:
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();
}
}
但是在这个class中你只能调整整体音量。如何制作这样的属性:
soundPlayer.LeftChannelVolume = 1.0f
soundPlayer.RightChannelVolume = 0.5f
在 PanningSampleProvider 的帮助下制作。但是为此你必须转换为单声道。此外,对改变 Pan - 的反应会稍有延迟。如何避免这种情况?如何使用立体声并仅更改其左右声道的音量?我认为这应该工作得更快。
_audioFile = new AudioFileReader(_fileName) { Volume = _volume };
var mono = new StereoToMonoSampleProvider(_audioFile) { LeftVolume = 1f, RightVolume = 1f };
var panner = new PanningSampleProvider(mono);
_outputDevice.Init(panner);
我创建了我的提供商并且它成功了!)
如果有人需要,那么这里:
/// <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;
}
}
播放声音时,需要分别调节左右声道的音量。 我有 class 来播放声音:
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();
}
}
但是在这个class中你只能调整整体音量。如何制作这样的属性: soundPlayer.LeftChannelVolume = 1.0f soundPlayer.RightChannelVolume = 0.5f
在 PanningSampleProvider 的帮助下制作。但是为此你必须转换为单声道。此外,对改变 Pan - 的反应会稍有延迟。如何避免这种情况?如何使用立体声并仅更改其左右声道的音量?我认为这应该工作得更快。
_audioFile = new AudioFileReader(_fileName) { Volume = _volume };
var mono = new StereoToMonoSampleProvider(_audioFile) { LeftVolume = 1f, RightVolume = 1f };
var panner = new PanningSampleProvider(mono);
_outputDevice.Init(panner);
我创建了我的提供商并且它成功了!) 如果有人需要,那么这里:
/// <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;
}
}