下图展示了基本的OpenAL对象以及它们和上下文(context)、设备对象(device objects)之间的关系
初始化OpenAL的时候,至少一个设备要被打开。在这个设备中至少会创建一个上下文(context),在这个上下文中必然有一个listener(听众),许多source(声源)对象也会被创建。每个source会有1到多个依附的buffer(缓冲器)对象。buffer对象不是特定的上下文的一部分------它们被一个设备的所有上下文共享。
打开设备
ALCdevice *alcOpenDevice(const ALCchar *devicename);
如果只需打开默认设备, 参数传NULL即可。否则请使用const ALCchar *alcGetString(ALCdevice *device, ALenum param);来获取你想要的设备名称。第一个参数通常设为NULL,第二个参数可能的取值为:
ALC_DEFAULT_DEVICE_SPECIFIER : 默认音频输出设备
ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER : 默认音频捕获设备
ALC_DEVICE_SPECIFIER : 所有音频输出设备
ALC_CAPTURE_DEVICE_SPECIFIER : 所有音频捕获设备
ALC_EXTENSIONS : 扩展
使用示例代码如下:
//打开默认声音输出设备
ALCdevice *device = alcOpenDevice(NULL);
if (!device)
return -1;
//在设备上创建上下文
ALCcontext *cc = alcCreateContext(device, NULL);
alcMakeContextCurrent(cc);
//创建声源
alGenSources(1, &uiSource);
//创建buffer
alGenBuffers(NUMBUFFERS, uiBuffers);
int i;
for (i = 0; i < NUMBUFFERS; i++) {
//将PCM数据填充到buffer
alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, (uint8_t*)(audio_frame->data[0]),
buff_size, g_player_ctx->audio_codec_ctx->sample_rate);
//将buffer放到声源队列
alSourceQueueBuffers(uiSource, 1, uiBuffers + i);
}
//开始播放声源
alSourcePlay(uiSource);
为了实现声音的连续播放,在开始播放之后,需要不停的查询这些buffer已经播放完几个了?并填充下一帧的PCM数据。
//查询已经播放的buffer的数量,bufferProecssed就是已播放完的buffer数
alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &bufferProcessed);
与上面函数对应的有一些关闭函数
alDeleteBuffers(NUMBUFFERS, uiBuffers);
alDeleteSources(1, &uiSource);
alcMakeContextCurrent(NULL);
alcDestroyContext(cc);
alcCloseDevice(device);