1 /*
2 * OpenAL audio output driver for MPlayer
3 *
4 * Copyleft 2006 by Reimar Döffinger (Reimar.Doeffinger@stud.uni-karlsruhe.de)
5 *
6 * This file is part of mpv.
7 *
8 * mpv is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * mpv is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "config.h"
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <inttypes.h>
27 #ifdef OPENAL_AL_H
28 #include <OpenAL/alc.h>
29 #include <OpenAL/al.h>
30 #include <OpenAL/alext.h>
31 #else
32 #include <AL/alc.h>
33 #include <AL/al.h>
34 #include <AL/alext.h>
35 #endif
36
37 #include "common/msg.h"
38
39 #include "ao.h"
40 #include "internal.h"
41 #include "audio/format.h"
42 #include "osdep/timer.h"
43 #include "options/m_option.h"
44
45 #define MAX_CHANS MP_NUM_CHANNELS
46 #define MAX_BUF 128
47 #define MAX_SAMPLES 32768
48 static ALuint buffers[MAX_BUF];
49 static ALuint buffer_size[MAX_BUF];
50 static ALuint source;
51
52 static int cur_buf;
53 static int unqueue_buf;
54
55 static struct ao *ao_data;
56
57 struct priv {
58 ALenum al_format;
59 int num_buffers;
60 int num_samples;
61 int direct_channels;
62 };
63
control(struct ao * ao,enum aocontrol cmd,void * arg)64 static int control(struct ao *ao, enum aocontrol cmd, void *arg)
65 {
66 switch (cmd) {
67 case AOCONTROL_GET_VOLUME:
68 case AOCONTROL_SET_VOLUME: {
69 ALfloat volume;
70 ao_control_vol_t *vol = (ao_control_vol_t *)arg;
71 if (cmd == AOCONTROL_SET_VOLUME) {
72 volume = (vol->left + vol->right) / 200.0;
73 alListenerf(AL_GAIN, volume);
74 }
75 alGetListenerf(AL_GAIN, &volume);
76 vol->left = vol->right = volume * 100;
77 return CONTROL_TRUE;
78 }
79 case AOCONTROL_GET_MUTE:
80 case AOCONTROL_SET_MUTE: {
81 bool mute = *(bool *)arg;
82
83 // openal has no mute control, only gain.
84 // Thus reverse the muted state to get required gain
85 ALfloat al_mute = (ALfloat)(!mute);
86 if (cmd == AOCONTROL_SET_MUTE) {
87 alSourcef(source, AL_GAIN, al_mute);
88 }
89 alGetSourcef(source, AL_GAIN, &al_mute);
90 *(bool *)arg = !((bool)al_mute);
91 return CONTROL_TRUE;
92 }
93
94 }
95 return CONTROL_UNKNOWN;
96 }
97
get_supported_format(int format)98 static enum af_format get_supported_format(int format)
99 {
100 switch (format) {
101 case AF_FORMAT_U8:
102 if (alGetEnumValue((ALchar*)"AL_FORMAT_MONO8"))
103 return AF_FORMAT_U8;
104 break;
105
106 case AF_FORMAT_S16:
107 if (alGetEnumValue((ALchar*)"AL_FORMAT_MONO16"))
108 return AF_FORMAT_S16;
109 break;
110
111 case AF_FORMAT_S32:
112 if (strstr(alGetString(AL_RENDERER), "X-Fi") != NULL)
113 return AF_FORMAT_S32;
114 break;
115
116 case AF_FORMAT_FLOAT:
117 if (alIsExtensionPresent((ALchar*)"AL_EXT_float32") == AL_TRUE)
118 return AF_FORMAT_FLOAT;
119 break;
120 }
121 return AL_FALSE;
122 }
123
get_supported_layout(int format,int channels)124 static ALenum get_supported_layout(int format, int channels)
125 {
126 const char *channel_str[] = {
127 [1] = "MONO",
128 [2] = "STEREO",
129 [4] = "QUAD",
130 [6] = "51CHN",
131 [7] = "61CHN",
132 [8] = "71CHN",
133 };
134 const char *format_str[] = {
135 [AF_FORMAT_U8] = "8",
136 [AF_FORMAT_S16] = "16",
137 [AF_FORMAT_S32] = "32",
138 [AF_FORMAT_FLOAT] = "_FLOAT32",
139 };
140 if (channel_str[channels] == NULL || format_str[format] == NULL)
141 return AL_FALSE;
142
143 char enum_name[32];
144 // AF_FORMAT_FLOAT uses same enum name as AF_FORMAT_S32 for multichannel
145 // playback, while it is different for mono and stereo.
146 // OpenAL Soft does not support AF_FORMAT_S32 and seems to reuse the names.
147 if (channels > 2 && format == AF_FORMAT_FLOAT)
148 format = AF_FORMAT_S32;
149 snprintf(enum_name, sizeof(enum_name), "AL_FORMAT_%s%s", channel_str[channels],
150 format_str[format]);
151
152 if (alGetEnumValue((ALchar*)enum_name)) {
153 return alGetEnumValue((ALchar*)enum_name);
154 }
155 return AL_FALSE;
156 }
157
158 // close audio device
uninit(struct ao * ao)159 static void uninit(struct ao *ao)
160 {
161 struct priv *p = ao->priv;
162 alSourceStop(source);
163 alSourcei(source, AL_BUFFER, 0);
164
165 alDeleteBuffers(p->num_buffers, buffers);
166 alDeleteSources(1, &source);
167
168 ALCcontext *ctx = alcGetCurrentContext();
169 ALCdevice *dev = alcGetContextsDevice(ctx);
170 alcMakeContextCurrent(NULL);
171 alcDestroyContext(ctx);
172 alcCloseDevice(dev);
173 ao_data = NULL;
174 }
175
init(struct ao * ao)176 static int init(struct ao *ao)
177 {
178 float position[3] = {0, 0, 0};
179 float direction[6] = {0, 0, -1, 0, 1, 0};
180 ALCdevice *dev = NULL;
181 ALCcontext *ctx = NULL;
182 ALCint freq = 0;
183 ALCint attribs[] = {ALC_FREQUENCY, ao->samplerate, 0, 0};
184 struct priv *p = ao->priv;
185 if (ao_data) {
186 MP_FATAL(ao, "Not reentrant!\n");
187 return -1;
188 }
189 ao_data = ao;
190 char *dev_name = ao->device;
191 dev = alcOpenDevice(dev_name && dev_name[0] ? dev_name : NULL);
192 if (!dev) {
193 MP_FATAL(ao, "could not open device\n");
194 goto err_out;
195 }
196 ctx = alcCreateContext(dev, attribs);
197 alcMakeContextCurrent(ctx);
198 alListenerfv(AL_POSITION, position);
199 alListenerfv(AL_ORIENTATION, direction);
200
201 alGenSources(1, &source);
202 if (p->direct_channels && alGetEnumValue((ALchar*)"AL_DIRECT_CHANNELS_SOFT")) {
203 alSourcei(source, alGetEnumValue((ALchar*)"AL_DIRECT_CHANNELS_SOFT"), AL_TRUE);
204 }
205
206 cur_buf = 0;
207 unqueue_buf = 0;
208 for (int i = 0; i < p->num_buffers; ++i) {
209 buffer_size[i] = 0;
210 }
211
212 alGenBuffers(p->num_buffers, buffers);
213
214 alcGetIntegerv(dev, ALC_FREQUENCY, 1, &freq);
215 if (alcGetError(dev) == ALC_NO_ERROR && freq)
216 ao->samplerate = freq;
217
218 // Check sample format
219 int try_formats[AF_FORMAT_COUNT + 1];
220 enum af_format sample_format = 0;
221 af_get_best_sample_formats(ao->format, try_formats);
222 for (int n = 0; try_formats[n]; n++) {
223 sample_format = get_supported_format(try_formats[n]);
224 if (sample_format != AF_FORMAT_UNKNOWN) {
225 ao->format = try_formats[n];
226 break;
227 }
228 }
229
230 if (sample_format == AF_FORMAT_UNKNOWN) {
231 MP_FATAL(ao, "Can't find appropriate sample format.\n");
232 uninit(ao);
233 goto err_out;
234 }
235
236 // Check if OpenAL driver supports the desired number of channels.
237 int num_channels = ao->channels.num;
238 do {
239 p->al_format = get_supported_layout(sample_format, num_channels);
240 if (p->al_format == AL_FALSE) {
241 num_channels = num_channels - 1;
242 }
243 } while (p->al_format == AL_FALSE && num_channels > 1);
244
245 // Request number of speakers for output from ao.
246 const struct mp_chmap possible_layouts[] = {
247 {0}, // empty
248 MP_CHMAP_INIT_MONO, // mono
249 MP_CHMAP_INIT_STEREO, // stereo
250 {0}, // 2.1
251 MP_CHMAP4(FL, FR, BL, BR), // 4.0
252 {0}, // 5.0
253 MP_CHMAP6(FL, FR, FC, LFE, BL, BR), // 5.1
254 MP_CHMAP7(FL, FR, FC, LFE, SL, SR, BC), // 6.1
255 MP_CHMAP8(FL, FR, FC, LFE, BL, BR, SL, SR), // 7.1
256 };
257 ao->channels = possible_layouts[num_channels];
258 if (!ao->channels.num)
259 mp_chmap_set_unknown(&ao->channels, num_channels);
260
261 if (p->al_format == AL_FALSE || !mp_chmap_is_valid(&ao->channels)) {
262 MP_FATAL(ao, "Can't find appropriate channel layout.\n");
263 uninit(ao);
264 goto err_out;
265 }
266
267 ao->device_buffer = p->num_buffers * p->num_samples;
268 return 0;
269
270 err_out:
271 ao_data = NULL;
272 return -1;
273 }
274
unqueue_buffers(struct ao * ao)275 static void unqueue_buffers(struct ao *ao)
276 {
277 struct priv *q = ao->priv;
278 ALint p;
279 int till_wrap = q->num_buffers - unqueue_buf;
280 alGetSourcei(source, AL_BUFFERS_PROCESSED, &p);
281 if (p >= till_wrap) {
282 alSourceUnqueueBuffers(source, till_wrap, &buffers[unqueue_buf]);
283 unqueue_buf = 0;
284 p -= till_wrap;
285 }
286 if (p) {
287 alSourceUnqueueBuffers(source, p, &buffers[unqueue_buf]);
288 unqueue_buf += p;
289 }
290 }
291
reset(struct ao * ao)292 static void reset(struct ao *ao)
293 {
294 alSourceStop(source);
295 unqueue_buffers(ao);
296 }
297
audio_set_pause(struct ao * ao,bool pause)298 static bool audio_set_pause(struct ao *ao, bool pause)
299 {
300 if (pause) {
301 alSourcePause(source);
302 } else {
303 alSourcePlay(source);
304 }
305 return true;
306 }
307
audio_write(struct ao * ao,void ** data,int samples)308 static bool audio_write(struct ao *ao, void **data, int samples)
309 {
310 struct priv *p = ao->priv;
311
312 int num = (samples + p->num_samples - 1) / p->num_samples;
313
314 for (int i = 0; i < num; i++) {
315 char *d = *data;
316 buffer_size[cur_buf] =
317 MPMIN(samples - i * p->num_samples, p->num_samples);
318 d += i * buffer_size[cur_buf] * ao->sstride;
319 alBufferData(buffers[cur_buf], p->al_format, d,
320 buffer_size[cur_buf] * ao->sstride, ao->samplerate);
321 alSourceQueueBuffers(source, 1, &buffers[cur_buf]);
322 cur_buf = (cur_buf + 1) % p->num_buffers;
323 }
324
325 return true;
326 }
327
audio_start(struct ao * ao)328 static void audio_start(struct ao *ao)
329 {
330 alSourcePlay(source);
331 }
332
get_state(struct ao * ao,struct mp_pcm_state * state)333 static void get_state(struct ao *ao, struct mp_pcm_state *state)
334 {
335 struct priv *p = ao->priv;
336
337 ALint queued;
338 unqueue_buffers(ao);
339 alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
340
341 double source_offset = 0;
342 if(alIsExtensionPresent("AL_SOFT_source_latency")) {
343 ALdouble offsets[2];
344 LPALGETSOURCEDVSOFT alGetSourcedvSOFT = alGetProcAddress("alGetSourcedvSOFT");
345 alGetSourcedvSOFT(source, AL_SEC_OFFSET_LATENCY_SOFT, offsets);
346 // Additional latency to the play buffer, the remaining seconds to be
347 // played minus the offset (seconds already played)
348 source_offset = offsets[1] - offsets[0];
349 } else {
350 float offset = 0;
351 alGetSourcef(source, AL_SEC_OFFSET, &offset);
352 source_offset = -offset;
353 }
354
355 int queued_samples = 0;
356 for (int i = 0, index = cur_buf; i < queued; ++i) {
357 queued_samples += buffer_size[index];
358 index = (index + 1) % p->num_buffers;
359 }
360
361 state->delay = queued_samples / (double)ao->samplerate + source_offset;
362
363 state->queued_samples = queued_samples;
364 state->free_samples = MPMAX(p->num_buffers - queued, 0) * p->num_samples;
365
366 ALint source_state = 0;
367 alGetSourcei(source, AL_SOURCE_STATE, &source_state);
368 state->playing = source_state == AL_PLAYING;
369 }
370
371 #define OPT_BASE_STRUCT struct priv
372
373 const struct ao_driver audio_out_openal = {
374 .description = "OpenAL audio output",
375 .name = "openal",
376 .init = init,
377 .uninit = uninit,
378 .control = control,
379 .get_state = get_state,
380 .write = audio_write,
381 .start = audio_start,
382 .set_pause = audio_set_pause,
383 .reset = reset,
384 .priv_size = sizeof(struct priv),
385 .priv_defaults = &(const struct priv) {
386 .num_buffers = 4,
387 .num_samples = 8192,
388 .direct_channels = 0,
389 },
390 .options = (const struct m_option[]) {
391 {"num-buffers", OPT_INT(num_buffers), M_RANGE(2, MAX_BUF)},
392 {"num-samples", OPT_INT(num_samples), M_RANGE(256, MAX_SAMPLES)},
393 {"direct-channels", OPT_FLAG(direct_channels)},
394 {0}
395 },
396 .options_prefix = "openal",
397 };
398