我一直在使用NAudio "用NAudio"消防和忘记音频播放教程(谢谢你标记这个很棒的实用工具!),如下所示: http://mark-dot-net.blogspot.nl/2014/02/fire-and-forget-audio-playback-with.html
我设法使用MixingSampleProvider作为输入添加了VolumeSampleProvider。然而,当我现在一个接一个地播放两个声音时,第一个声音总是得到第二个声音的音量,即使第一个声音已经播放了。
所以我的问题是:如何在每个声音中添加单个音量的声音?
这就是我使用的:
mixer = new MixingSampleProvider(waveformat);
mixer.ReadFully = true;
volumeProvider = new VolumeSampleProvider(mixer);
panProvider = new PanningSampleProvider(volumeProvider);
outputDevice.Init(panProvider);
outputDevice.Play();
答案 0 :(得分:1)
我并不是100%肯定你在问什么,我不知道你是否已经解决了这个问题,但我在这里采取了这个措施。
ISampleProvider
个对象播放"传递降压"通过ISampleProvider
方法将游戏发送到他们的来源Read()
。最终,有人会对音频字节进行实际读取。各个ISampleProvider
类对字节执行任何操作。
MixingSampleProvider
需要N个音频源......那些混合在一起。调用Read()
时,它会迭代音频源并从每个源中读取count
个字节。
将其传递给VolumeSampleProvider
作为一个组来处理所有字节(来自各种来源)...它说:
buffer[offset+n] *= volume;
这将调整整个电路板的字节...所以每个字节都由volume
乘数在缓冲区中调整;
PanningSampleProvider
只是提供立体声音频的倍增器并相应地调整字节,与VolumeSampleProvider
做同样的事情。
如果要单独处理音频源卷,则需要处理MixingSampleProvider
的上游。基本上,传递给MixingSampleProvider的东西需要能够独立调整其音量。
如果您将一堆SampleChannel
个对象传递给MixingSampleProvider
...您可以完成独立的音量调整。 Samplechannel
类包含VolumeSampleProvider
对象,并提供Volume
属性,允许用户在VolumeSampleProvider
对象上设置音量。
SampleChannel
还包含一个MeteringSampleProvider
,用于提供给定时间段内最大样本值的报告。它会引发一个事件,为您提供这些值的数组,每个通道一个。
答案 1 :(得分:0)
我意识到(感谢其匹配)使这项工作的唯一方法是在将混合器添加到混合器之前,单独留下混合器并单独调整每个CachedSound的平移和音量。因此,我需要使用pan和volume作为额外的输入参数来重写CachedSoundSampleProvider。
这是新的构造函数:
public CachedSoundSampleProvider(CachedSound cachedSound, float volume = 1, float pan = 0)
{
this.cachedSound = cachedSound;
LeftVolume = volume * (0.5f - pan / 2);
RightVolume = volume * (0.5f + pan / 2);
}
这是新的Read()函数:
public int Read(float[] buffer, int offset, int count)
{
long availableSamples = cachedSound.AudioData.Length - position;
long samplesToCopy = Math.Min(availableSamples, count);
int destOffset = offset;
for (int sourceSample = 0; sourceSample < samplesToCopy; sourceSample += 2)
{
float outL = cachedSound.AudioData[position + sourceSample + 0];
float outR = cachedSound.AudioData[position + sourceSample + 1];
buffer[destOffset + 0] = outL * LeftVolume;
buffer[destOffset + 1] = outR * RightVolume;
destOffset += 2;
}
position += samplesToCopy;
return (int)samplesToCopy;
}