static ALenum openal_audio_format(struct audio_format *audio_format) { switch (audio_format->format) { case SAMPLE_FORMAT_S16: if (audio_format->channels == 2) return AL_FORMAT_STEREO16; if (audio_format->channels == 1) return AL_FORMAT_MONO16; /* fall back to mono */ audio_format->channels = 1; return openal_audio_format(audio_format); case SAMPLE_FORMAT_S8: if (audio_format->channels == 2) return AL_FORMAT_STEREO8; if (audio_format->channels == 1) return AL_FORMAT_MONO8; /* fall back to mono */ audio_format->channels = 1; return openal_audio_format(audio_format); default: /* fall back to 16 bit */ audio_format->format = SAMPLE_FORMAT_S16; return openal_audio_format(audio_format); } }
static ALenum openal_audio_format(struct audio_format *audio_format) { /* note: cannot map SAMPLE_FORMAT_S8 to AL_FORMAT_STEREO8 or AL_FORMAT_MONO8 since OpenAL expects unsigned 8 bit samples, while MPD uses signed samples */ switch (audio_format->format) { case SAMPLE_FORMAT_S16: if (audio_format->channels == 2) return AL_FORMAT_STEREO16; if (audio_format->channels == 1) return AL_FORMAT_MONO16; /* fall back to mono */ audio_format->channels = 1; return openal_audio_format(audio_format); default: /* fall back to 16 bit */ audio_format->format = SAMPLE_FORMAT_S16; return openal_audio_format(audio_format); } }
static bool openal_open(void *data, struct audio_format *audio_format, GError **error) { struct openal_data *od = data; od->format = openal_audio_format(audio_format); if (!od->format) { struct audio_format_string s; g_set_error(error, openal_output_quark(), 0, "Unsupported audio format: %s", audio_format_to_string(audio_format, &s)); return false; } if (!openal_setup_context(od, error)) { return false; } alcMakeContextCurrent(od->context); alGenBuffers(NUM_BUFFERS, od->buffers); if (alGetError() != AL_NO_ERROR) { g_set_error(error, openal_output_quark(), 0, "Failed to generate buffers"); return false; } alGenSources(1, &od->source); if (alGetError() != AL_NO_ERROR) { g_set_error(error, openal_output_quark(), 0, "Failed to generate source"); alDeleteBuffers(NUM_BUFFERS, od->buffers); return false; } od->filled = 0; od->timer = timer_new(audio_format); od->frequency = audio_format->sample_rate; return true; }