SDL2之SDL_OpenAudioDevice无法播放声音

最近在自己抽时间做一个通用的视频监控客户端,通过rtsp协议获取媒体流然后解码渲染,在这个过程中发现音频流比视频流慢大概4~5秒,初步怀疑是音频播放模块引发的。

旧的音频播放使用SDL_OpenAudio、SDL_PauseAudio加回调实现,因为回调中何时读取音频数据不由我的程序控制,怀疑问题出现在这里,查看SDL2相关资料后发现有新的音频播放接口代替SDL_OpenAudio,即SDL_OpenAudioDevice,但是使用过程中发现,切换为SDL_OpenAudioDevice播放音频时一直没有声音,通过多次分析测试发现问题出现在SDL_OpenAudioDevice的参数中,当第5个参数为SDL_AUDIO_ALLOW_ANY_CHANGE时,会发生无法播放声音的问题,将该值改为SDL_AUDIO_ALLOW_FREQUENCY_CHANGE后可以正常播放声音。可正常播放代码如下:

	int num = SDL_GetNumAudioDevices(0);
	const char* deviceName = SDL_GetAudioDeviceName(num, 0);
	m_deviceID = SDL_OpenAudioDevice(deviceName, 0, &m_audioSpec, NULL, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
	if (m_deviceID < 2)
	{
		LOG_DEBUG("SDL_OpenAudioDevice with error deviceID : %d", m_deviceID);
		return false;
	}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
SDL_AudioSpec结构体中的callback字段是一个函数指针,用于指定音频处理回调函数。回调函数的原型如下: ```c typedef void (*SDL_AudioCallback)(void *userdata, Uint8 *stream, int len); ``` 其中,`userdata`参数是传递给回调函数的用户数据指针,`stream`参数是指向音频缓冲区的指针,`len`是音频缓冲区的字节数。 在回调函数中,你可以对音频缓冲区进行读取和写入操作。回调函数将在每次需要填充音频缓冲区时被调用,因此你可以在这里以实时的方式处理音频数据。 下面是一个简单的例子,演示了如何使用SDL_AudioSpec结构体中的callback字段: ```c #include <SDL2/SDL.h> // 音频处理回调函数 void audio_callback(void *userdata, Uint8 *stream, int len) { // 从用户数据中获取音频数据 float *samples = (float*)userdata; // 将音频数据写入到音频缓冲区中 SDL_memcpy(stream, samples, len); } int main(int argc, char* argv[]) { SDL_Init(SDL_INIT_AUDIO); SDL_AudioSpec spec; spec.freq = 44100; spec.format = AUDIO_F32; spec.channels = 2; spec.samples = 1024; spec.callback = audio_callback; // 创建音频设备 SDL_AudioDeviceID device = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0); // 创建音频数据 float samples[1024 * 2]; for (int i = 0; i < 1024 * 2; i++) { samples[i] = sinf(i * 2 * M_PI / 44100 * 440); } // 开始播放音频 SDL_PauseAudioDevice(device, 0); // 等待一段时间 SDL_Delay(5000); // 停止播放音频 SDL_CloseAudioDevice(device); SDL_Quit(); return 0; } ``` 在这个例子中,我们首先使用SDL_Init函数初始化SDL库。然后,我们定义了一个SDL_AudioSpec结构体,并设置了音频参数和回调函数。接着,我们使用SDL_OpenAudioDevice函数创建音频设备,并将音频数据写入到缓冲区中。最后,我们使用SDL_PauseAudioDevice函数开始播放音频,并使用SDL_Delay函数等待一段时间,然后停止播放音频并关闭音频设备。 注意,这只是一个非常简单的例子,实际的音频处理可能需要更复杂的算法。同时,由于回调函数需要在实时处理音频数据,因此需要尽可能地避免阻塞操作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heibao111728

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值