摘要:在ubuntu 20.04中使用QAudioInput、PortAduio、ffmpeg打开音频设备录制音频都显示失败,最后没办法选择了SDL2.0,SDL2.0录制音频十分方便,使用也非常简单。
疑问:不知道SDL是如何区分打开的设备是录制还是播放。(已解决,通过打开设备时设置iscapture参数的值,0表示录制,非0表示播放)
主要函数简介:
cpp
SDL_Init(SDL_INIT_AUDIO)
此函数用于初始化音频。
cpp
SDL_AudioSpec want, have;
SDL_zero(want);
want.freq = 44100;
want.format = AUDIO_S16SYS;
want.channels = 2;
want.samples = 288;
want.callback = audioCallback;
设置音频数据的格式。
cpp
//参数iscapture 0表示播放音频 非0表示录制音频
SDL_AudioDeviceID deviceId = SDL_OpenAudioDevice(nullptr, 2, &want, &have, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
此函数用于打开音频设备,音频的录制和播放取决于第二个参数,若第二个参数设置为0,此函数表示的打开录制音频。非0表示打开播放音频。
cpp
SDL_QueueAudio(deviceIdO,stream,len);
若不用回调函数,可以使用此函数对音频进行播放操作。
cpp
SDL_DequeueAudio(deviceIdO,stream,len);
若不用回调函数,可以使用此函数定时读取录制的音频数据。
cpp
SDL_MixAudioFormat(stream, stream, AUDIO_S16SYS, len, 100);
可用于混音和调节音频的音量。
在下面的demo中,音频的录制采用了回调函数,音频的播放采用了SDL_QueueAudio函数。
cpp
SDL_AudioDeviceID deviceIdO;//全局播放音频设备id
cpp
//回调函数,用在音频录制
void audioCallback(void *userdata, Uint8 * stream,
int len)
{
Q_UNUSED(userdata);
// Sint16* audioData = reinterpret_cast<Sint16*>(stream);
// int numSamples = len / sizeof(Sint16);
// for (int i = 0; i < numSamples; ++i) {
// // 假设放大倍数为 2
// audioData[i] *= 2;
// }
SDL_MixAudioFormat(stream, stream, AUDIO_S16SYS, len, 100);
mp3InFILE.write((char *)stream,len);
//从缓存区播放音频
SDL_QueueAudio(deviceIdO,stream,len);
}
cpp
if(SDL_Init(SDL_INIT_AUDIO) < 0){
qDebug() << "SDL INIT ERROR" << SDL_GetError();
return ;
}
SDL_AudioSpec want, have;
SDL_zero(want);
want.freq = 44100;
want.format = AUDIO_S16SYS;
want.channels = 2;
want.samples = 288;
want.callback = audioCallback;
//参数iscapture 0表示播放音频 非0表示录制音频
SDL_AudioDeviceID deviceId = SDL_OpenAudioDevice(nullptr, 2, &want, &have, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
//开启音频播放设备
want.callback = nullptr;
deviceIdO = SDL_OpenAudioDevice(nullptr, 0, &want, &have, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
if (deviceIdO == 0) {
qDebug() << "SDL could not open audio device! SDL Error: " << SDL_GetError();
return;
}
//分别开启音频录制和音频播放。
SDL_PauseAudioDevice(deviceId,0);
SDL_PauseAudioDevice(deviceIdO,0);