diff --git a/CHANGELOG.md b/CHANGELOG.md index f8f2e21..566dd14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # EAXEFX changelog +## [1.0.5] - 2021-05-13 +### Added +- Bypass EAX 5.0 Speaker Levels feature. + + ## [1.0.4] - 2021-04-23 ### Added - Quake 4 (2005) source occlusion patch. diff --git a/README.md b/README.md index a18d9d5..a879bbf 100644 --- a/README.md +++ b/README.md @@ -82,13 +82,13 @@ Context: - Macro FX Factor (EAX 5.0) - Speaker configuration (EAX 5.0) +Source: +- Speaker levels (EAX 5.0) + 6.2 - Not supported =================== -Source: -- Speaker levels (EAX 5.0) - General: - X-RAM diff --git a/src/eaxefx/CMakeLists.txt b/src/eaxefx/CMakeLists.txt index 780560f..ebe3b6b 100644 --- a/src/eaxefx/CMakeLists.txt +++ b/src/eaxefx/CMakeLists.txt @@ -26,7 +26,7 @@ OR OTHER DEALINGS IN THE SOFTWARE. cmake_minimum_required (VERSION 3.8.2 FATAL_ERROR) -project (eaxefx VERSION 1.0.4 LANGUAGES CXX) +project (eaxefx VERSION 1.0.5 LANGUAGES CXX) if (NOT WIN32) diff --git a/src/eaxefx/include/eaxefx_eaxx_source.h b/src/eaxefx/include/eaxefx_eaxx_source.h index 16a0a74..0b522cd 100644 --- a/src/eaxefx/include/eaxefx_eaxx_source.h +++ b/src/eaxefx/include/eaxefx_eaxx_source.h @@ -97,6 +97,7 @@ struct EaxxSourceSourceDirtyMiscFlags EaxxSourceSourceDirtyMiscFlagsValue flAirAbsorptionFactor : 1; EaxxSourceSourceDirtyMiscFlagsValue ulFlags : 1; EaxxSourceSourceDirtyMiscFlagsValue flMacroFXFactor : 1; + EaxxSourceSourceDirtyMiscFlagsValue speaker_levels : 1; }; // EaxxSourceSourceMiscDirtyFlags static_assert(sizeof(EaxxSourceSourceDirtyMiscFlags) == sizeof(EaxxSourceSourceDirtyMiscFlagsValue)); @@ -179,8 +180,11 @@ class EaxxSource private: + static constexpr auto max_speakers = 9; + + using ActiveFxSlots = std::array; - using ActiveFxSlotsDirtyFlags = std::array; + using SpeakerLevels = std::array; struct Al @@ -196,6 +200,7 @@ class EaxxSource ::EAX50ACTIVEFXSLOTS active_fx_slots{}; ::EAX50SOURCEPROPERTIES source{}; Sends sends{}; + SpeakerLevels speaker_levels{}; }; // Eax @@ -230,6 +235,8 @@ class EaxxSource void set_eax_sends_defaults(); + void set_eax_speaker_levels_defaults(); + void set_eax_defaults(); @@ -486,6 +493,15 @@ class EaxxSource const ::EAX50SOURCEPROPERTIES& all, int eax_version); + static void validate_source_speaker_id( + const std::int32_t speaker_id); + + static void validate_source_speaker_level( + const std::int32_t speaker_level); + + static void validate_source_speaker_level_all( + const ::EAXSPEAKERLEVELPROPERTIES& all); + void defer_source_direct( std::int32_t lDirect); @@ -565,6 +581,9 @@ class EaxxSource void defer_source_all( const ::EAX50SOURCEPROPERTIES& all); + void defer_source_speaker_level_all( + const ::EAXSPEAKERLEVELPROPERTIES& all); + void defer_source_direct( const EaxxEaxCall& eax_call); @@ -638,6 +657,9 @@ class EaxxSource void defer_source_all( const EaxxEaxCall& eax_call); + void defer_source_speaker_level_all( + const EaxxEaxCall& eax_call); + // Source // ---------------------------------------------------------------------- @@ -664,6 +686,8 @@ class EaxxSource void set_macro_fx_factor(); + void set_speaker_levels(); + void apply_deferred(); @@ -737,6 +761,9 @@ class EaxxSource void api_get_source_all_2d( const EaxxEaxCall& eax_call); + void api_get_source_speaker_level_all( + const EaxxEaxCall& eax_call); + void get( const EaxxEaxCall& eax_call); }; // EaxxSource diff --git a/src/eaxefx/src/eaxefx_eaxx_source.cpp b/src/eaxefx/src/eaxefx_eaxx_source.cpp index 12dce68..d5ec5db 100644 --- a/src/eaxefx/src/eaxefx_eaxx_source.cpp +++ b/src/eaxefx/src/eaxefx_eaxx_source.cpp @@ -306,11 +306,17 @@ void EaxxSource::set_eax_sends_defaults() } } +void EaxxSource::set_eax_speaker_levels_defaults() +{ + std::fill(eax_.speaker_levels.begin(), eax_.speaker_levels.end(), ::EAXSOURCE_DEFAULTSPEAKERLEVEL); +} + void EaxxSource::set_eax_defaults() { set_eax_source_defaults(); set_eax_active_fx_slots_defaults(); set_eax_sends_defaults(); + set_eax_speaker_levels_defaults(); } float EaxxSource::calculate_dst_occlusion_mb( @@ -1345,6 +1351,35 @@ void EaxxSource::validate_source_all( validate_source_macro_fx_factor(all.flMacroFXFactor); } +void EaxxSource::validate_source_speaker_id( + const std::int32_t speaker_id) +{ + eaxx_validate_range( + "Speaker Id", + speaker_id, + static_cast(::EAXSPEAKER_FRONT_LEFT), + static_cast(::EAXSPEAKER_LOW_FREQUENCY) + ); +} + +void EaxxSource::validate_source_speaker_level( + const std::int32_t speaker_level) +{ + eaxx_validate_range( + "Speaker Level", + speaker_level, + ::EAXSOURCE_MINSPEAKERLEVEL, + ::EAXSOURCE_MAXSPEAKERLEVEL + ); +} + +void EaxxSource::validate_source_speaker_level_all( + const ::EAXSPEAKERLEVELPROPERTIES& all) +{ + validate_source_speaker_id(all.lSpeakerID); + validate_source_speaker_level(all.lLevel); +} + void EaxxSource::defer_source_direct( std::int32_t lDirect) { @@ -1559,6 +1594,15 @@ void EaxxSource::defer_source_all( defer_source_macro_fx_factor(all.flMacroFXFactor); } +void EaxxSource::defer_source_speaker_level_all( + const ::EAXSPEAKERLEVELPROPERTIES& all) +{ + const auto speaker_index = all.lSpeakerID - 1; + auto& speaker_level_d = eax_d_.speaker_levels[speaker_index]; + const auto& speaker_level = eax_.speaker_levels[speaker_index]; + source_dirty_misc_flags_.speaker_levels |= (speaker_level != speaker_level_d); +} + void EaxxSource::defer_source_direct( const EaxxEaxCall& eax_call) { @@ -1813,6 +1857,15 @@ void EaxxSource::defer_source_all( } } +void EaxxSource::defer_source_speaker_level_all( + const EaxxEaxCall& eax_call) +{ + const auto speaker_level_properties = eax_call.get_value(); + + validate_source_speaker_level_all(speaker_level_properties); + defer_source_speaker_level_all(speaker_level_properties); +} + void EaxxSource::set_outside_volume_hf() { const auto efx_gain_hf = std::clamp( @@ -1868,6 +1921,7 @@ void EaxxSource::set_flags() set_direct_hf_auto_flag(); set_room_auto_flag(); set_room_hf_auto_flag(); + set_speaker_levels(); } void EaxxSource::set_macro_fx_factor() @@ -1875,6 +1929,11 @@ void EaxxSource::set_macro_fx_factor() // TODO } +void EaxxSource::set_speaker_levels() +{ + // TODO +} + void EaxxSource::apply_deferred() { if ( @@ -2080,7 +2139,8 @@ void EaxxSource::set( break; case ::EAXSOURCE_SPEAKERLEVELS: - throw EaxxSourceException{"Speaker levels not implemented."}; + defer_source_speaker_level_all(eax_call); + break; case ::EAXSOURCE_ALL2DPARAMETERS: defer_source_2d_all(eax_call); @@ -2292,6 +2352,16 @@ void EaxxSource::api_get_source_all_2d( eax_call.set_value(eax_2d_all); } +void EaxxSource::api_get_source_speaker_level_all( + const EaxxEaxCall& eax_call) +{ + auto& all = eax_call.get_value(); + + validate_source_speaker_id(all.lSpeakerID); + const auto speaker_index = all.lSpeakerID - 1; + all.lLevel = eax_.speaker_levels[speaker_index]; +} + void EaxxSource::get( const EaxxEaxCall& eax_call) { @@ -2413,7 +2483,8 @@ void EaxxSource::get( break; case ::EAXSOURCE_SPEAKERLEVELS: - throw EaxxSourceException{"Speaker levels not implemented."}; + api_get_source_speaker_level_all(eax_call); + break; case ::EAXSOURCE_ALL2DPARAMETERS: api_get_source_all_2d(eax_call);