【发布时间】:2021-11-07 19:16:48
【问题描述】:
我正在尝试使用 Naudio 输入音频,然后在经过插件处理后再次输出。为了执行输出步骤,我创建了一个自定义 SampleProvider,但缓冲区的行为不像我预期的那样,我听不到任何声音。读取音频并尝试再次播放的代码如下
var audioFile = new AudioFileReader(@"C:\Users\alex.clayton\Downloads\Rhythm guitar.mp3");
PluginContext.PluginCommandStub.Commands.MainsChanged(true);
PluginContext.PluginCommandStub.Commands.StartProcess();
var vstSampleProvider = new VstSampleProvider(44100, 2);
var devices = DirectSoundOut.Devices.Last();
var output = new DirectSoundOut(devices.Guid);
output.Init(vstSampleProvider);
int chunckStep = 0;
while (chunckStep < audioFile.Length)
{
var nAudiobuffer = new float[blockSize * 2];
audioFile.Read(nAudiobuffer, 0, blockSize * 2);
var leftSpan = inputMgr.Buffers.ToArray()[0].AsSpan();
for (int i = 0; i < blockSize; i++)
{
leftSpan[i] = nAudiobuffer[i*2] / int.MaxValue;
}
var rightSpan = inputMgr.Buffers.ToArray()[0].AsSpan();
for (int i = 1; i < blockSize; i++)
{
rightSpan[i] = nAudiobuffer[i*2 + 1] / int.MaxValue;
}
PluginContext.PluginCommandStub.Commands.ProcessReplacing(inputBuffers, outputBuffers);
vstSampleProvider.LoadBuffer(outputBuffers);
chunckStep += blockSize;
}
PluginContext.PluginCommandStub.Commands.StopProcess();
PluginContext.PluginCommandStub.Commands.MainsChanged(false);
output.Play();
示例提供程序代码是这样的
public class VstSampleProvider : ISampleProvider
{
private readonly int _sampleRate;
private readonly int _channels;
private readonly Queue<float> _buffer;
public VstSampleProvider(int sampleRate, int channels)
{
_sampleRate = sampleRate;
_channels = channels;
_buffer = new Queue<float>();
}
public WaveFormat WaveFormat => WaveFormat.CreateIeeeFloatWaveFormat(_sampleRate, _channels);
public void LoadBuffer(VstAudioBuffer[] outputBuffers)
{
var totalSampleCount = outputBuffers[0].SampleCount * _channels;
try
{
if (_channels == 1)
for (int i = 0; i < totalSampleCount; i++)
{
_buffer.Enqueue(outputBuffers[0][i]);
}
else
{
for (int i = 0; i < totalSampleCount; i++)
{
if (i % 2 == 0)
{
var value = outputBuffers[0][i / 2];
_buffer.Enqueue(value);
}
else
_buffer.Enqueue(outputBuffers[1][(i - 1) / 2]);
}
}
}
catch (Exception ex)
{
// Probably should log or something
}
}
public int Read(float[] buffer, int offset, int count)
{
if (_buffer.Count < count)
return 0;
if (offset > 0)
throw new NotImplementedException();
for (int i = 0; i < count; i++)
{
var value = _buffer.Dequeue();
buffer[i] = value;
}
if (buffer.Any(f => f > 1))
{
return count;
}
return count;
}
}
当我查看出列的值时,它们都在 -1 和 1 之间,正如预期的那样,但是当我在 if (buffer.Any(f => f > 1)) 之后的行上放置一个断点时,我可以看到缓冲区值是大于 1 或 0 的整数并且与我认为添加到缓冲区的出列值没有任何相似之处。
我希望我不了解 SampleProvider 应该如何工作,因为我在 Naudio 中寻找已经存在的内容,我看不出我做错了什么。
任何帮助将不胜感激。谢谢
【问题讨论】: