Я решил немного пособирать часто задаваемые вопросы и некоторые неочевидные факты про OpenAL. Как говорится: “мыши плакали кололись, но продолжали есть кактус” - это всё про OpenAL :)
Прежде всего, что вы получаете используя OpenAL в сравнению с другими библиотеками ?
- Простота и минималистичность API
- Кроссплатформенность.
- Бесплатность и открытость кода.
Минусы будут перечислены в этом faq :)
Как определить количество источников доступных для OpenAL?
К сожалению, в документации этот вопрос не освящён вообще. Многие люди используют alut для инициализации OpenAL, хотя на самом деле инициализация “руками” занимает совсем немного места и позволяет контролировать разные аспекты типа перечисления устройств. Не используйте alut для этого :)
- Выбираете устройство (как показано в следующем пункте, либо NULL для устройства по умолчанию, вызываете alcOpenDevice(name)
- Необязательный шаг : создание массива атрибутов типа :
ALCint attrs[] = {
ALC_STEREO_SOURCES, stereo_sources,
ALC_MONO_SOURCES, mono_sources,
ALC_INVALID, ALC_INVALID,
}; // stereo_sources и mono_sources - хинты OpenAL. Минимально
“работающее везде” решение - 16 источников суммарно. Учтите что один
стерео источник тратит 2 реальных. Итого, по умолчанию стоит ставить
хинты так чтобы stereo_sources * 2 + mono_sources == 16. Вы можете
предложить пользователю попробовать увеличить это значение, или
попробовать угадать в процессе исполнения. - создаёте контекст alcCreateContext(alc_device, attrs);
- Теперь надо получить обратно атрибуты :)
ALCInt attr_size;
alcGetIntegerv(alc_device, ALC_ATTRIBUTES_SIZE, sizeof(attr_size), &attr_size);
const ALCInt * attributes = (ALCint *)malloc(attr_size * sizeof(ALCint));
alcGetIntegerv(alc_device, ALC_ALL_ATTRIBUTES, attr_size, attributes);
по указателю attributes теперь лежат атрибуты в том же формате в котором они передаются в OpenAL в п.2. Теперь циклом до ALC_INVALID бежим по attributes и ищем ALC_MONO/STEREO_SOURCES. Если вам повезёт и у вас не linux - вуаля! OpenAL вернул реальные числа для устройства.
Как выбрать устройство используемое OpenAL ?
alcGetString(NULL, ALC_DEVICE_SPECIFIER) возвращает не только устройство по умолчанию. Оно возвращает указатель на массив всех устройств следующим образом:
“Generic Hardware”, 0, “Generic Software”, 0, 0
Для чистоты эксперимента можно проверить наличие ALC_ENUMERATION_EXT, но если мне не изменяет память, спецификация OpenAL 1.1 сделала его обязательным. (поправьте?)
Я хочу заниматься микшированием в своём треде. Я не хочу чтобы OpenAL создавал тред!
Проще простого: поставьте контексту атрибут ALC_SYNC, AL_TRUE, и периодически вызывайте alcProcessContext(context);
У меня возникают случайные очень странные ошибки, которые никак не относятся к делу.
Решений могу предложить несколько, применять их следует в этой же последовательности:
- После каждого вызова OpenAL вызывать alGetError(), например используя макросы для экономии места.
- Выделять источники один раз, при инициализации звука. Не динамически. Учтите это при проектировании приложения.
- у вас 64 битный linux ? попробуйте мою сборку openAL и не забудьте написать в bugtracker openal, дистрибутива, чего угодно чтобы выключили MMX в openal на x86_64 :)
16 источников это очень мало - у меня “сто звучащих” обьектов на уровне.
Больше вам вряд ли надо :) OpenAL не содержит менеджера источников, поэтому вам эту сущность придётся написать самим или взять из какого-нибудь проекта. Чем эта сущность должна заниматься ?
- Инициализацией OpenAL и созданием источников.
- Отслеживать расстояние до обьектов и реально играть только самыми близкими обьектами.
- Перезапускать приблизившиеся обьекты с зациклеными звуками (например вертолёт)
Как сделать источник звучащий слушателю “в голову” ?
Ключевые моменты инициализации:
alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE);
alSourcef (source, AL_ROLLOFF_FACTOR, 0.0);
По умолчанию эти значения выставлены в AL_FALSE и 1.0 соответственно.
©2007 Меньшаков Владимир, Netive Media Group.