NAudio - ASIO 播放到设备(仅限静态)
NAudio - ASIO Playback to device (static only)
我正在尝试将 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;
}
您的代码有两个主要问题。首先,InputBuffers
是每个通道一个,而不是样本。其次,当您设置 e.WrittenToOutputBuffers = true
时,您是在说您已经写入 e.OutputBuffers
而您没有。所以它们将只包含未初始化的数据。
如果您想查看 ASIO 缓冲区的低级操作示例,请查看我的 ASIO patch bay 示例项目。
我正在尝试将 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;
}
您的代码有两个主要问题。首先,InputBuffers
是每个通道一个,而不是样本。其次,当您设置 e.WrittenToOutputBuffers = true
时,您是在说您已经写入 e.OutputBuffers
而您没有。所以它们将只包含未初始化的数据。
如果您想查看 ASIO 缓冲区的低级操作示例,请查看我的 ASIO patch bay 示例项目。