NAudio Wasapi 录音和转换
NAudio Wasapi recording and conversion
我正在使用 NAudio 并尝试使用 WasapiLoopbackCapture 记录我电脑上正在播放的内容。我遇到的问题是我需要将记录的数据作为 PCM 16 位 44100khz 单声道。
为此,我构建了这个:
using System;
using System.Diagnostics;
using NAudio.Wave;
using NAudio.CoreAudioApi;
namespace soundtest
{
class Program {
static void Main(string[] args) {
try {
var deviceToRecord = (new MMDeviceEnumerator().EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active))[0];
var recorder = new CustomWasapiLoopbackCapture(deviceToRecord, false, 1000 / 5);
recorder.ShareMode = AudioClientShareMode.Shared;
recorder.DataAvailable += recorderDataAvailable;
var inprov = new WaveInProvider(recorder);
var fto16prov = new WaveFloatTo16Provider(inprov);
var stomprov = new StereoToMonoProvider16(fto16prov);
Console.WriteLine("Press something to stop recording.");
recorder.StartRecording();
Console.ReadKey();
recorder.StopRecording();
} catch (Exception e) {
Console.WriteLine("!!! EXCEPTION !!!" +
"\nMessage:\n " + e.Message +
"\nSource:\n " + e.Source +
"\nStack:\n" + e.StackTrace);
}
Console.WriteLine("Press something to close.");
Console.ReadKey();
}
static void recorderDataAvailable(object sender, WaveInEventArgs args) {
// how do I access PCM 16bit here?
// It's not args.Buffer, or am I wrong?
// additional calculation is done here with the PCM data
}
}
class CustomWasapiLoopbackCapture : WasapiCapture
{
public CustomWasapiLoopbackCapture()
: this(GetDefaultLoopbackCaptureDevice()){ }
public CustomWasapiLoopbackCapture(MMDevice captureDevice)
: this(captureDevice, false){ }
public CustomWasapiLoopbackCapture(MMDevice captureDevice, bool useEventSync)
: this(captureDevice, useEventSync, 100){ }
public CustomWasapiLoopbackCapture(MMDevice captureDevice, bool useEventSync, int audioBufferMillisecondsLength)
: base(captureDevice, useEventSync, audioBufferMillisecondsLength){ }
public static MMDevice GetDefaultLoopbackCaptureDevice() {
MMDeviceEnumerator devices = new MMDeviceEnumerator();
return devices.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
}
public override WaveFormat WaveFormat
{
get { return base.WaveFormat; }
set { throw new InvalidOperationException("WaveFormat cannot be set for WASAPI Loopback Capture"); }
}
protected override AudioClientStreamFlags GetAudioClientStreamFlags() {
return AudioClientStreamFlags.Loopback;
}
}
}
如何访问转换后的录音?我认为通过添加这些提供者,我可以获得用于进一步计算的数据。我假设 args.Buffer 不提供预期的 PCM 16 位 44100 kHz 单声道数据来自我在 recorderDataAvailable 方法中进行的额外处理的不切实际的结果。我在调音台的另一个输入上使用简单的 WaveInEvent 对此进行了测试,我用它循环播放声音。
WASAPI 始终将音频记录为 IEEE 浮点样本。所以在回调中得到的记录缓冲区中,每4个字节是一个float
。访问单个样本的一种简单方法是使用 BitConverter.ToSingle
。这将为您提供 +/- 1.0 范围内的值。所以乘以 32767 然后转换为 Int16
将其变成 16 位样本值。
我正在使用 NAudio 并尝试使用 WasapiLoopbackCapture 记录我电脑上正在播放的内容。我遇到的问题是我需要将记录的数据作为 PCM 16 位 44100khz 单声道。 为此,我构建了这个:
using System;
using System.Diagnostics;
using NAudio.Wave;
using NAudio.CoreAudioApi;
namespace soundtest
{
class Program {
static void Main(string[] args) {
try {
var deviceToRecord = (new MMDeviceEnumerator().EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active))[0];
var recorder = new CustomWasapiLoopbackCapture(deviceToRecord, false, 1000 / 5);
recorder.ShareMode = AudioClientShareMode.Shared;
recorder.DataAvailable += recorderDataAvailable;
var inprov = new WaveInProvider(recorder);
var fto16prov = new WaveFloatTo16Provider(inprov);
var stomprov = new StereoToMonoProvider16(fto16prov);
Console.WriteLine("Press something to stop recording.");
recorder.StartRecording();
Console.ReadKey();
recorder.StopRecording();
} catch (Exception e) {
Console.WriteLine("!!! EXCEPTION !!!" +
"\nMessage:\n " + e.Message +
"\nSource:\n " + e.Source +
"\nStack:\n" + e.StackTrace);
}
Console.WriteLine("Press something to close.");
Console.ReadKey();
}
static void recorderDataAvailable(object sender, WaveInEventArgs args) {
// how do I access PCM 16bit here?
// It's not args.Buffer, or am I wrong?
// additional calculation is done here with the PCM data
}
}
class CustomWasapiLoopbackCapture : WasapiCapture
{
public CustomWasapiLoopbackCapture()
: this(GetDefaultLoopbackCaptureDevice()){ }
public CustomWasapiLoopbackCapture(MMDevice captureDevice)
: this(captureDevice, false){ }
public CustomWasapiLoopbackCapture(MMDevice captureDevice, bool useEventSync)
: this(captureDevice, useEventSync, 100){ }
public CustomWasapiLoopbackCapture(MMDevice captureDevice, bool useEventSync, int audioBufferMillisecondsLength)
: base(captureDevice, useEventSync, audioBufferMillisecondsLength){ }
public static MMDevice GetDefaultLoopbackCaptureDevice() {
MMDeviceEnumerator devices = new MMDeviceEnumerator();
return devices.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
}
public override WaveFormat WaveFormat
{
get { return base.WaveFormat; }
set { throw new InvalidOperationException("WaveFormat cannot be set for WASAPI Loopback Capture"); }
}
protected override AudioClientStreamFlags GetAudioClientStreamFlags() {
return AudioClientStreamFlags.Loopback;
}
}
}
如何访问转换后的录音?我认为通过添加这些提供者,我可以获得用于进一步计算的数据。我假设 args.Buffer 不提供预期的 PCM 16 位 44100 kHz 单声道数据来自我在 recorderDataAvailable 方法中进行的额外处理的不切实际的结果。我在调音台的另一个输入上使用简单的 WaveInEvent 对此进行了测试,我用它循环播放声音。
WASAPI 始终将音频记录为 IEEE 浮点样本。所以在回调中得到的记录缓冲区中,每4个字节是一个float
。访问单个样本的一种简单方法是使用 BitConverter.ToSingle
。这将为您提供 +/- 1.0 范围内的值。所以乘以 32767 然后转换为 Int16
将其变成 16 位样本值。