我试图通过我的电脑使用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.5秒)。
有没有办法解决这个延迟?我需要重写回调方法吗?
编辑:
所以,使用此代码代替基本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-Bencina的帮助下发现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
中的suggestLatency设置为0,延迟现在消失,声音很好(虽然它现在是单声道)。
答案 0 :(得分:4)
使用paFramesPerBufferUnspecified
,您走在正确的轨道上。
ASIO延迟行为取决于驱动程序。有两种可能性:
ASIO驱动程序允许代码(即PortAudio)请求延迟(可能有一些约束)。 PortAudio发现支持的驱动程序缓冲区大小与您请求的延迟之间的匹配最佳。
另一种可能性是您的音频接口不提供对延迟设置的编程控制。相反,延迟只能从驱动程序的ASIO控制面板UI中选择(驱动程序将在PortAudio上强制使用固定的缓冲区大小)。在这种情况下,您应该调查驱动程序控制面板UI以设置最低可行延迟。
在任何一种情况下,使用Pa_OpenStream
的方法都接近最优,但您应该为输入和输出请求零延迟(在您的编辑中,您要求50ms输入延迟,零输出延迟)。最终结果是PortAudio选择最低的可用ASIO缓冲区大小。如果事实证明这是不稳定的(音频故障),那么你需要增加所要求的延迟。
include/pa_asio.h
公开了一个特定于主机API的接口,用于查询驱动程序允许的ASIO缓冲区大小(请注意,如果更改控制面板中的设置,这可能会发生变化)。它还提供显示驱动程序控制面板UI的功能。
编辑:请注意,Pa_GetDefaultInputDevice()
和Pa_GetDefaultOutputDevice()
仅在您为ASIO构建PortAudio时才会返回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设备索引。