NAudio - ASIO 播放到设备(仅限静态)

Posted

技术标签:

【中文标题】NAudio - ASIO 播放到设备(仅限静态)【英文标题】:NAudio - ASIO Playback to device (static only) 【发布时间】:2018-10-12 17:40:24 【问题描述】:

我正在尝试将 ASIO 音频路由到我的播放设备,但是,我听到的都是静态的。

ASIO 设置

BIT_PER_SAMPLE = 24

SAMPLE_RATE = 48000

目前,正在尝试将 1 个通道插入 1 个称为“Line 1”的播放设备进行测试。声音的播放是静态的。

编辑:下面的代码已更新。它将需要 64 个 ASIO 输入通道,并一次将它们路由到 Waveout 设备(我正在使用虚拟音频线来创建它们)

    private static AsioOut asioOut;
    private static AsioInputPatcher inputPatcher;
    private static readonly int BIT_PER_SAMPLE = 16;
    private static readonly int SAMPLE_RATE = 48000;
    private static readonly int NUMBER_OF_CHANNELS = 64;

    private static BufferedWaveProvider[] bufferedWaveProviders = new BufferedWaveProvider[NUMBER_OF_CHANNELS];
    private static WaveOut[] waveouts = new WaveOut[NUMBER_OF_CHANNELS];

    [STAThread]
    static void Main(string[] args)
    
        InitDevices();
        Record();
        while (true)
        
            Console.WriteLine("Recording...press any key to Exit.");

            Console.ReadKey(true);
            break;
        

        asioOut.Stop();
        asioOut.Dispose();
        asioOut = null;
    

    private static void Record()
    
        inputPatcher = new AsioInputPatcher(SAMPLE_RATE, NUMBER_OF_CHANNELS, NUMBER_OF_CHANNELS);

        asioOut = new AsioOut(AsioOut.GetDriverNames()[0]);
        asioOut.InitRecordAndPlayback(new SampleToWaveProvider(inputPatcher),
            NUMBER_OF_CHANNELS, 0);
        asioOut.AudioAvailable += OnAsioOutAudioAvailable;
        asioOut.Play();
    

    private static void InitDevices()
    
        for (int n = -1; n < WaveOut.DeviceCount; n++)
        
            WaveOutCapabilities caps = WaveOut.GetCapabilities(n);
            if (caps.ProductName.StartsWith("Line"))
            
                int _number = int.Parse(caps.ProductName.Split(' ')[1]);

                if (_number <= NUMBER_OF_CHANNELS)
                
                    waveouts[_number - 1] = new WaveOut()  DeviceNumber = n ;
                    bufferedWaveProviders[_number - 1] = new BufferedWaveProvider(new WaveFormat(SAMPLE_RATE, BIT_PER_SAMPLE, 2));
                    waveouts[_number - 1].Init(bufferedWaveProviders[_number - 1]);
                    waveouts[_number - 1].Play();
                
            
        
    
    static void OnAsioOutAudioAvailable(object sender, AsioAudioAvailableEventArgs e)
    
        inputPatcher.ProcessBuffer(e.InputBuffers, e.OutputBuffers,
            e.SamplesPerBuffer, e.AsiosampleType);

        for (int outputChannel = 0; outputChannel < e.OutputBuffers.Length; outputChannel++)
        
            byte[] buf = new byte[e.SamplesPerBuffer * (BIT_PER_SAMPLE / 8)];
            Marshal.Copy(e.OutputBuffers[outputChannel], buf, 0, e.SamplesPerBuffer * (BIT_PER_SAMPLE / 8));

            bufferedWaveProviders[outputChannel].AddSamples(buf, 0, buf.Length);
        

        e.WrittenToOutputBuffers = true;
    

【问题讨论】:

【参考方案1】:

您的代码存在两个主要问题。首先,InputBuffers 是每个通道一个,而不是样本。其次,当您设置e.WrittenToOutputBuffers = true 时,您是在说您已经写信给e.OutputBuffers,而您还没有。所以它们只会包含未初始化的数据。

如果您想查看 ASIO 缓冲区的低级操作示例,请查看我的 ASIO patch bay 示例项目。

【讨论】:

谢谢马克。我能够让它工作。以上代码已更新。 BufferedWaveProvider 是否可以将Samples 添加到特定通道? BufferedWaveProvider 适用于交错样本。如果您设置WrittenToOutputBuffers,则意味着您绕过了 NAudio 的正常音频播放机制并直接对 ASIO 缓冲区进行低级访问,这更难以正确实现,但会提供最佳性能

以上是关于NAudio - ASIO 播放到设备(仅限静态)的主要内容,如果未能解决你的问题,请参考以下文章

NAudio ASIO Playback 在某些设备上挂起

NAudio Asio 录制和播放

NAudio Asio 同时录制和播放

如何使用 NAudio 和 ASIO 直接读取输入缓冲区和播放?

尝试在 ASIO 输出上使用 NAudio 播放音频时的空引用

Naudio Asio 在多个通道上同时录制和播放