输入延迟与PortAudio回调和ASIO sdk
input delay with PortAudio callback and ASIO sdk
我想让我的吉他输入通过我的电脑使用portaudio库和ASIO sdk播放。
我一直在跟随官方网站上的一些教程来获得基础设置。目前,我让它工作,以便portaudio正在收听正确的输入和输出设备,我有回调设置,只输出输入,不做任何事情,像这样:
static int paTestCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
{
float *out = (float*)outputBuffer;
float* in = (float*)inputBuffer;
for (int i = 0; i<framesPerBuffer; i++)
{
*out++ = *in++; /* left */
*out++ = *in++; /* right */
}
return 0;
}
这个回调是通过调用这个设置的:
PaError error = Pa_OpenDefaultStream(&stream, 2, 2, paFloat32, 44100, paFramesPerBufferUnspecified, paTestCallback, &data);
Pa_StartStream(stream);
现在,这确实有效,但是当我在吉他上敲击弦和通过监视器听到它时,我有很多延迟(大约0.5s)。
有办法解决这个延迟吗?我需要重写回调方法吗?
编辑:因此,使用这个代码而不是基本的Pa_OpenDefaultStream()
int defaultIn = Pa_GetDefaultInputDevice();
int defaultOut = Pa_GetDefaultOutputDevice();
PaStreamParameters *inParam = new PaStreamParameters();
inParam->channelCount = 2;
inParam->device = defaultIn;
inParam->sampleFormat = paFloat32;
inParam->suggestedLatency = 0.05;
PaStreamParameters *outParam = new PaStreamParameters();
outParam->channelCount = 2;
outParam->device = defaultOut;
outParam->sampleFormat = paFloat32;
outParam->suggestedLatency = 0;
error = Pa_OpenStream(&stream, inParam, outParam, 44100, paFramesPerBufferUnspecified, paNoFlag, paTestCallback, &data);
if (error != paNoError) {
Logger::log("[PortAudioManager] Could not open default stream. Exiting function...");
return;
}
Pa_StartStream(stream);
仍然有一点延迟,主要是在演奏多个音符时明显的。
编辑:我在ross - benina的帮助下发现,windows默认的输入设备和输出设备不会改变PortAudio中主机api的索引。我似乎一直在用MME。为了获得ASIO设备的正确索引,我做了以下操作:
int hostNr = Pa_GetHostApiCount();
std::vector<const PaHostApiInfo*> infoVertex;
for (int t = 0; t < hostNr; ++t) {
infoVertex.push_back(Pa_GetHostApiInfo(t));
}
然后我检查了哪一个是ASIO,并将PaStreamParameters
中的建议延迟设置为0,延迟现在消失了,声音很好(虽然现在是单声道)。
您使用paFramesPerBufferUnspecified
的方法是正确的。
ASIO延迟行为取决于驱动程序。有两种可能:
-
ASIO驱动程序允许代码(即PortAudio)请求延迟(可能有一些限制)。PortAudio找到支持的驱动程序缓冲区大小和您请求的延迟之间的最佳匹配。
-
另一种可能是您的音频接口没有提供对延迟设置的编程控制。相反,延迟只能从驱动程序的ASIO控制面板UI中选择(驱动程序将在PortAudio上强制设置固定的缓冲区大小)。在这种情况下,您应该研究驱动程序控制面板UI,以设置最低的可用延迟。
无论哪种情况,您使用Pa_OpenStream
的方法都接近于最优,但是您应该为输入和输出请求零延迟(在您的编辑中,您请求50ms输入延迟,零输出延迟)。最终的结果将是PortAudio选择最低可用的ASIO缓冲区大小。如果结果证明这是不稳定的(音频故障),那么你需要增加请求的延迟。
include/pa_asio.h
公开了一个特定于主机api的接口,用于查询驱动程序允许的ASIO缓冲区大小(注意,如果在控制面板中更改设置,这可能会更改)。它还提供了显示驾驶员控制面板UI的功能。
EDIT:请注意,如果您仅为ASIO构建PortAudio, Pa_GetDefaultInputDevice()
和Pa_GetDefaultOutputDevice()
将只返回ASIO设备。如果您在构建中包含任何其他更常见的api(例如WMME或DirectSound),它们将被优先考虑为(最低公分母)默认设备。您可以添加一个检查,检查您是否正在实际访问ASIO设备:
assert(Pa_GetHostApiInfo(Pa_GetDeviceInfo(Pa_GetDefaultOutputDevice())->hostApi)->type == paASIO);
如果PortAudio编译支持多个主机API:要获得默认的ASIO设备:使用Pa_GetHostApiCount
和Pa_GetHostApiInfo
枚举主机API来查找ASIO主机API。然后从返回的PaHostApiInfo
结构体中提取默认的ASIO设备索引。
- 理解boost::asio-async_read在无需读取内容时的行为
- 提升 ASIO 无法识别计时器对象
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- boost::asio::steady_timer()与sleep()我应该使用哪一个
- boost::asio如何生成多个协同程序,然后加入它们
- 使用外部SDK工具链文件在VisualStudio上生成项目编译错误
- 缓慢提升ASIO
- 从 Boost ASIO 获取 epoll 描述符 io_service对象
- 如何在 Boost.Asio 中使用 Zero-copy sendmsg/receive
- C++ Boost::asio串行通信与Arduino无法写入
- 如何使用 Boost Asio 在 Android 上获取我的本地 udp IP 地址?
- 提升 Asio TCP 服务器 处理多个客户端
- Vulkan SDK 版本 1.1.85.0 在 Kubuntu 18.10 上链接
- boost::asio UDP 广播客户端仅接收"fast"数据包
- 提升 ASIO - io_service 不要等待连接到线程
- 执行时使用 boost::asio::d eadline_timer 时出错
- Boost.Asio/OpenSSL HTTPS GET certificate trouble
- C++ boost::asio::ip::tcp::acceptor 有时不接受连接器?
- 升级到 Windows 10 版本 1809 SDK 后,我无法编译使用 C++/WinRT 的项目
- 输入延迟与PortAudio回调和ASIO sdk