From 7ebebc2bc36e8b447a6ad3d51edb1be2c9d7b1ea Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 30 Jun 2020 23:15:14 +0400 Subject: [PATCH] Detect OpenAL effects at runtime --- Telegram/CMakeLists.txt | 2 + .../SourceFiles/media/audio/media_audio.cpp | 75 ++++++++-------- .../SourceFiles/media/audio/media_audio.h | 6 -- .../media/audio/media_openal_functions.cpp | 90 +++++++++++++++++++ .../media/audio/media_openal_functions.h | 56 ++++++++++++ 5 files changed, 184 insertions(+), 45 deletions(-) create mode 100644 Telegram/SourceFiles/media/audio/media_openal_functions.cpp create mode 100644 Telegram/SourceFiles/media/audio/media_openal_functions.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index f9b3cba745..385ba580d1 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -723,6 +723,8 @@ PRIVATE media/audio/media_audio_track.h media/audio/media_child_ffmpeg_loader.cpp media/audio/media_child_ffmpeg_loader.h + media/audio/media_openal_functions.cpp + media/audio/media_openal_functions.h media/clip/media_clip_check_streaming.cpp media/clip/media_clip_check_streaming.h media/clip/media_clip_ffmpeg.cpp diff --git a/Telegram/SourceFiles/media/audio/media_audio.cpp b/Telegram/SourceFiles/media/audio/media_audio.cpp index 473bf691cd..cca93dc13f 100644 --- a/Telegram/SourceFiles/media/audio/media_audio.cpp +++ b/Telegram/SourceFiles/media/audio/media_audio.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/audio/media_child_ffmpeg_loader.h" #include "media/audio/media_audio_loaders.h" #include "media/audio/media_audio_track.h" +#include "media/audio/media_openal_functions.h" #include "media/streaming/media_streaming_utility.h" #include "data/data_document.h" #include "data/data_file_origin.h" @@ -22,9 +23,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include -#ifndef TDESKTOP_DISABLE_OPENAL_EFFECTS -#include -#endif // !TDESKTOP_DISABLE_OPENAL_EFFECTS #include @@ -205,6 +203,7 @@ void Start(not_null instance) { auto loglevel = getenv("ALSOFT_LOGLEVEL"); LOG(("OpenAL Logging Level: %1").arg(loglevel ? loglevel : "(not set)")); + OpenAL::LoadEFXExtension(); EnumeratePlaybackDevices(); EnumerateCaptureDevices(); @@ -281,11 +280,7 @@ void StopDetachIfNotUsedSafe() { } bool SupportsSpeedControl() { -#ifndef TDESKTOP_DISABLE_OPENAL_EFFECTS - return true; -#else // TDESKTOP_DISABLE_OPENAL_EFFECTS - return false; -#endif // TDESKTOP_DISABLE_OPENAL_EFFECTS + return OpenAL::HasEFXExtension(); } } // namespace Audio @@ -331,40 +326,44 @@ void Mixer::Track::createStream(AudioMsgId::Type type) { alSourcei(stream.source, AL_SOURCE_RELATIVE, 1); alSourcei(stream.source, AL_ROLLOFF_FACTOR, 0); alGenBuffers(3, stream.buffers); -#ifndef TDESKTOP_DISABLE_OPENAL_EFFECTS if (speedEffect) { applySourceSpeedEffect(); } else { removeSourceSpeedEffect(); } -#endif // TDESKTOP_DISABLE_OPENAL_EFFECTS } -#ifndef TDESKTOP_DISABLE_OPENAL_EFFECTS void Mixer::Track::removeSourceSpeedEffect() { - alSource3i(stream.source, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, 0); - alSourcei(stream.source, AL_DIRECT_FILTER, AL_FILTER_NULL); + if (!Audio::SupportsSpeedControl()) { + return; + } + + alSource3i(stream.source, alGetEnumValue("AL_AUXILIARY_SEND_FILTER"), alGetEnumValue("AL_EFFECTSLOT_NULL"), 0, 0); + alSourcei(stream.source, alGetEnumValue("AL_DIRECT_FILTER"), alGetEnumValue("AL_FILTER_NULL")); alSourcef(stream.source, AL_PITCH, 1.f); } void Mixer::Track::applySourceSpeedEffect() { + if (!Audio::SupportsSpeedControl()) { + return; + } + Expects(speedEffect != nullptr); - if (!speedEffect->effect || !alIsEffect(speedEffect->effect)) { - alGenAuxiliaryEffectSlots(1, &speedEffect->effectSlot); - alGenEffects(1, &speedEffect->effect); - alGenFilters(1, &speedEffect->filter); - alEffecti(speedEffect->effect, AL_EFFECT_TYPE, AL_EFFECT_PITCH_SHIFTER); - alFilteri(speedEffect->filter, AL_FILTER_TYPE, AL_FILTER_LOWPASS); - alFilterf(speedEffect->filter, AL_LOWPASS_GAIN, 0.f); + if (!speedEffect->effect || !OpenAL::alIsEffect(speedEffect->effect)) { + OpenAL::alGenAuxiliaryEffectSlots(1, &speedEffect->effectSlot); + OpenAL::alGenEffects(1, &speedEffect->effect); + OpenAL::alGenFilters(1, &speedEffect->filter); + OpenAL::alEffecti(speedEffect->effect, alGetEnumValue("AL_EFFECT_TYPE"), alGetEnumValue("AL_EFFECT_PITCH_SHIFTER")); + OpenAL::alFilteri(speedEffect->filter, alGetEnumValue("AL_FILTER_TYPE"), alGetEnumValue("AL_FILTER_LOWPASS")); + OpenAL::alFilterf(speedEffect->filter, alGetEnumValue("AL_LOWPASS_GAIN"), 0.f); } - alEffecti(speedEffect->effect, AL_PITCH_SHIFTER_COARSE_TUNE, speedEffect->coarseTune); - alAuxiliaryEffectSloti(speedEffect->effectSlot, AL_EFFECTSLOT_EFFECT, speedEffect->effect); + OpenAL::alEffecti(speedEffect->effect, alGetEnumValue("AL_PITCH_SHIFTER_COARSE_TUNE"), speedEffect->coarseTune); + OpenAL::alAuxiliaryEffectSloti(speedEffect->effectSlot, alGetEnumValue("AL_EFFECTSLOT_EFFECT"), speedEffect->effect); alSourcef(stream.source, AL_PITCH, speedEffect->speed); - alSource3i(stream.source, AL_AUXILIARY_SEND_FILTER, speedEffect->effectSlot, 0, 0); - alSourcei(stream.source, AL_DIRECT_FILTER, speedEffect->filter); + alSource3i(stream.source, alGetEnumValue("AL_AUXILIARY_SEND_FILTER"), speedEffect->effectSlot, 0, 0); + alSourcei(stream.source, alGetEnumValue("AL_DIRECT_FILTER"), speedEffect->filter); } -#endif // TDESKTOP_DISABLE_OPENAL_EFFECTS void Mixer::Track::destroyStream() { if (isStreamCreated()) { @@ -375,26 +374,26 @@ void Mixer::Track::destroyStream() { for (auto i = 0; i != 3; ++i) { stream.buffers[i] = 0; } -#ifndef TDESKTOP_DISABLE_OPENAL_EFFECTS resetSpeedEffect(); -#endif // TDESKTOP_DISABLE_OPENAL_EFFECTS } -#ifndef TDESKTOP_DISABLE_OPENAL_EFFECTS void Mixer::Track::resetSpeedEffect() { + if (!Audio::SupportsSpeedControl()) { + return; + } + if (!speedEffect) { return; - } else if (speedEffect->effect && alIsEffect(speedEffect->effect)) { + } else if (speedEffect->effect && OpenAL::alIsEffect(speedEffect->effect)) { if (isStreamCreated()) { removeSourceSpeedEffect(); } - alDeleteEffects(1, &speedEffect->effect); - alDeleteAuxiliaryEffectSlots(1, &speedEffect->effectSlot); - alDeleteFilters(1, &speedEffect->filter); + OpenAL::alDeleteEffects(1, &speedEffect->effect); + OpenAL::alDeleteAuxiliaryEffectSlots(1, &speedEffect->effectSlot); + OpenAL::alDeleteFilters(1, &speedEffect->filter); } speedEffect->effect = speedEffect->effectSlot = speedEffect->filter = 0; } -#endif // TDESKTOP_DISABLE_OPENAL_EFFECTS void Mixer::Track::reattach(AudioMsgId::Type type) { if (isStreamCreated() @@ -531,14 +530,15 @@ int Mixer::Track::getNotQueuedBufferIndex() { void Mixer::Track::setExternalData( std::unique_ptr data) { -#ifndef TDESKTOP_DISABLE_OPENAL_EFFECTS changeSpeedEffect(data ? data->speed : 1.); -#endif // TDESKTOP_DISABLE_OPENAL_EFFECTS externalData = std::move(data); } -#ifndef TDESKTOP_DISABLE_OPENAL_EFFECTS void Mixer::Track::changeSpeedEffect(float64 speed) { + if (!Audio::SupportsSpeedControl()) { + return; + } + if (speed != 1.) { if (!speedEffect) { speedEffect = std::make_unique(); @@ -553,7 +553,6 @@ void Mixer::Track::changeSpeedEffect(float64 speed) { speedEffect = nullptr; } } -#endif // TDESKTOP_DISABLE_OPENAL_EFFECTS void Mixer::Track::resetStream() { if (isStreamCreated()) { @@ -830,13 +829,11 @@ void Mixer::forceToBufferExternal(const AudioMsgId &audioId) { } void Mixer::setSpeedFromExternal(const AudioMsgId &audioId, float64 speed) { -#ifndef TDESKTOP_DISABLE_OPENAL_EFFECTS QMutexLocker lock(&AudioMutex); const auto track = trackForType(audioId.type()); if (track->state.id == audioId) { track->changeSpeedEffect(speed); } -#endif // TDESKTOP_DISABLE_OPENAL_EFFECTS } Streaming::TimePoint Mixer::getExternalSyncTimePoint( diff --git a/Telegram/SourceFiles/media/audio/media_audio.h b/Telegram/SourceFiles/media/audio/media_audio.h index 57bbaa01e5..369ee4507a 100644 --- a/Telegram/SourceFiles/media/audio/media_audio.h +++ b/Telegram/SourceFiles/media/audio/media_audio.h @@ -215,9 +215,7 @@ private: int getNotQueuedBufferIndex(); void setExternalData(std::unique_ptr data); -#ifndef TDESKTOP_DISABLE_OPENAL_EFFECTS void changeSpeedEffect(float64 speed); -#endif // TDESKTOP_DISABLE_OPENAL_EFFECTS ~Track(); @@ -243,7 +241,6 @@ private: Stream stream; std::unique_ptr externalData; -#ifndef TDESKTOP_DISABLE_OPENAL_EFFECTS struct SpeedEffect { uint32 effect = 0; uint32 effectSlot = 0; @@ -252,7 +249,6 @@ private: float64 speed = 1.; }; std::unique_ptr speedEffect; -#endif // TDESKTOP_DISABLE_OPENAL_EFFECTS crl::time lastUpdateWhen = 0; crl::time lastUpdatePosition = 0; @@ -260,11 +256,9 @@ private: void createStream(AudioMsgId::Type type); void destroyStream(); void resetStream(); -#ifndef TDESKTOP_DISABLE_OPENAL_EFFECTS void resetSpeedEffect(); void applySourceSpeedEffect(); void removeSourceSpeedEffect(); -#endif // TDESKTOP_DISABLE_OPENAL_EFFECTS }; diff --git a/Telegram/SourceFiles/media/audio/media_openal_functions.cpp b/Telegram/SourceFiles/media/audio/media_openal_functions.cpp new file mode 100644 index 0000000000..8b3390ec9f --- /dev/null +++ b/Telegram/SourceFiles/media/audio/media_openal_functions.cpp @@ -0,0 +1,90 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "media/audio/media_openal_functions.h" + +#include + +namespace OpenAL { + +void LoadEFXExtension() { +#define LOAD_PROC(x) ((x) = reinterpret_cast(alGetProcAddress(#x))) + LOAD_PROC(alGenEffects); + LOAD_PROC(alDeleteEffects); + LOAD_PROC(alIsEffect); + LOAD_PROC(alEffecti); + LOAD_PROC(alEffectiv); + LOAD_PROC(alEffectf); + LOAD_PROC(alEffectfv); + LOAD_PROC(alGetEffecti); + LOAD_PROC(alGetEffectiv); + LOAD_PROC(alGetEffectf); + LOAD_PROC(alGetEffectfv); + + LOAD_PROC(alGenFilters); + LOAD_PROC(alDeleteFilters); + LOAD_PROC(alIsFilter); + LOAD_PROC(alFilteri); + LOAD_PROC(alFilteriv); + LOAD_PROC(alFilterf); + LOAD_PROC(alFilterfv); + LOAD_PROC(alGetFilteri); + LOAD_PROC(alGetFilteriv); + LOAD_PROC(alGetFilterf); + LOAD_PROC(alGetFilterfv); + + LOAD_PROC(alGenAuxiliaryEffectSlots); + LOAD_PROC(alDeleteAuxiliaryEffectSlots); + LOAD_PROC(alIsAuxiliaryEffectSlot); + LOAD_PROC(alAuxiliaryEffectSloti); + LOAD_PROC(alAuxiliaryEffectSlotiv); + LOAD_PROC(alAuxiliaryEffectSlotf); + LOAD_PROC(alAuxiliaryEffectSlotfv); + LOAD_PROC(alGetAuxiliaryEffectSloti); + LOAD_PROC(alGetAuxiliaryEffectSlotiv); + LOAD_PROC(alGetAuxiliaryEffectSlotf); + LOAD_PROC(alGetAuxiliaryEffectSlotfv); +#undef LOAD_PROC +} + +bool HasEFXExtension() { + return (alGenEffects != nullptr) + && (alDeleteEffects != nullptr) + && (alIsEffect != nullptr) + && (alEffecti != nullptr) + && (alEffectiv != nullptr) + && (alEffectf != nullptr) + && (alEffectfv != nullptr) + && (alGetEffecti != nullptr) + && (alGetEffectiv != nullptr) + && (alGetEffectf != nullptr) + && (alGetEffectfv != nullptr) + && (alGenFilters != nullptr) + && (alDeleteFilters != nullptr) + && (alIsFilter != nullptr) + && (alFilteri != nullptr) + && (alFilteriv != nullptr) + && (alFilterf != nullptr) + && (alFilterfv != nullptr) + && (alGetFilteri != nullptr) + && (alGetFilteriv != nullptr) + && (alGetFilterf != nullptr) + && (alGetFilterfv != nullptr) + && (alGenAuxiliaryEffectSlots != nullptr) + && (alDeleteAuxiliaryEffectSlots != nullptr) + && (alIsAuxiliaryEffectSlot != nullptr) + && (alAuxiliaryEffectSloti != nullptr) + && (alAuxiliaryEffectSlotiv != nullptr) + && (alAuxiliaryEffectSlotf != nullptr) + && (alAuxiliaryEffectSlotfv != nullptr) + && (alGetAuxiliaryEffectSloti != nullptr) + && (alGetAuxiliaryEffectSlotiv != nullptr) + && (alGetAuxiliaryEffectSlotf != nullptr) + && (alGetAuxiliaryEffectSlotfv != nullptr); +} + +} // namespace OpenAL diff --git a/Telegram/SourceFiles/media/audio/media_openal_functions.h b/Telegram/SourceFiles/media/audio/media_openal_functions.h new file mode 100644 index 0000000000..939ce982ae --- /dev/null +++ b/Telegram/SourceFiles/media/audio/media_openal_functions.h @@ -0,0 +1,56 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include + +namespace OpenAL { + +/* Effect object functions */ +inline LPALGENEFFECTS alGenEffects; +inline LPALDELETEEFFECTS alDeleteEffects; +inline LPALISEFFECT alIsEffect; +inline LPALEFFECTI alEffecti; +inline LPALEFFECTIV alEffectiv; +inline LPALEFFECTF alEffectf; +inline LPALEFFECTFV alEffectfv; +inline LPALGETEFFECTI alGetEffecti; +inline LPALGETEFFECTIV alGetEffectiv; +inline LPALGETEFFECTF alGetEffectf; +inline LPALGETEFFECTFV alGetEffectfv; + +/* Filter object functions */ +inline LPALGENFILTERS alGenFilters; +inline LPALDELETEFILTERS alDeleteFilters; +inline LPALISFILTER alIsFilter; +inline LPALFILTERI alFilteri; +inline LPALFILTERIV alFilteriv; +inline LPALFILTERF alFilterf; +inline LPALFILTERFV alFilterfv; +inline LPALGETFILTERI alGetFilteri; +inline LPALGETFILTERIV alGetFilteriv; +inline LPALGETFILTERF alGetFilterf; +inline LPALGETFILTERFV alGetFilterfv; + +/* Auxiliary Effect Slot object functions */ +inline LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots; +inline LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots; +inline LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot; +inline LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti; +inline LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv; +inline LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf; +inline LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv; +inline LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti; +inline LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv; +inline LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf; +inline LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv; + +void LoadEFXExtension(); +bool HasEFXExtension(); + +} // namespace OpenAL