【问题标题】:NAudio SampleProvider not updating buffer on Read as expectedNAudio SampleProvider 未按预期更新读取缓冲区
【发布时间】: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 =&gt; f &gt; 1)) 之后的行上放置一个断点时,我可以看到缓冲区值是大于 1 或 0 的整数并且与我认为添加到缓冲区的出列值没有任何相似之处。

我希望我不了解 SampleProvider 应该如何工作,因为我在 Naudio 中寻找已经存在的内容,我看不出我做错了什么。

任何帮助将不胜感激。谢谢

【问题讨论】:

    标签: c# naudio


    【解决方案1】:

    所以事实证明主要问题是读取输入文件并调低音量,所以我在玩但非常安静。

    leftSpan[i] = nAudiobuffer[i*2] / int.MaxValue
    

    不需要/ int.MaxValue

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-28
      • 2012-09-19
      • 1970-01-01
      • 2018-06-29
      • 1970-01-01
      相关资源
      最近更新 更多