音视频开发之SDL2播放音频

音视频开发之SDL2播放音频

使用SDL来播放音频非常简单,只需要根据指定的参数开启音频设备,然后设置音频回调函数,在音频回调函数中,将数据写入到指定的buffer中即可。
对于音频播放来讲,是音频设备主动向我们要数据,而并非我们主动写入数据到音频设备,音频设备维护了一个数据缓冲区,会将数据存放在缓冲区中进行逐一播放,当缓冲区中有空位时,就会通过回调函数向我们要数据,当缓冲区中数据已经填满时,则不会回调。

开启音频设备

SDL_AudioSpec是对音频参数的组合,开启音频设备的时候需要传入一组期望的参数组合,开启成功后会返回一个真正开启的参数组合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
SDL_AudioSpec wanted_spec, spec;

// 设置SDL音频播放参数

// 设置 采样率、声道数
wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout);
wanted_spec.channels = wanted_nb_channels;
wanted_spec.freq = wanted_sample_rate;


// 采样位数
wanted_spec.format = AUDIO_S16SYS;
// 静音
wanted_spec.silence = 0;
// 缓冲区样本数量(单声道样本数量)
wanted_spec.samples =
FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE,
2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC));
// 回调函数
wanted_spec.callback = sdl_audio_callback;
// 回调函数参数
wanted_spec.userdata = opaque;
// 开启音频播放设备,如果开启失败,则更换参数不断重试
while (
!(audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec,
SDL_AUDIO_ALLOW_FREQUENCY_CHANGE |
SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) {
// 更换参数组合,重新尝试
}

回调函数

回调函数是在一个单独的线程中,第一个参数就是开启设备时设置的回调函数上下文。第二个参数就是需要写入的缓冲区,第三个参数是需要的数据字节大小。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) {
VideoState *is = opaque;
int audio_size, len1;

while (len > 0) {
// 计算还未读取的字节大小
len1 = is->audio_buf_size - is->audio_buf_index;
// 如果为读取的字节大小大于音频设备想要的大小,则使用音频设备想要的大小
if (len1 > len) len1 = len;
// 将audio_buf中的数据copy到stream中
if (!is->muted && is->audio_buf && is->audio_volume == SDL_MIX_MAXVOLUME)
memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
else {
memset(stream, 0, len1);
if (!is->muted && is->audio_buf)
SDL_MixAudioFormat(stream,
(uint8_t *)is->audio_buf + is->audio_buf_index,
AUDIO_S16SYS, len1, is->audio_volume);
}
// 减去已经传递给音频设备的buffer大小,如果剩下的还有,则再次读取传递
len -= len1;
// stream加上偏移量
stream += len1;
// 更新audio_buf的偏移量
is->audio_buf_index += len1;
}
}

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×