Skip to content

Commit

Permalink
Added basic SteamAudio integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Xottab-DUTY committed May 31, 2024
1 parent 8c47998 commit 5d960c2
Show file tree
Hide file tree
Showing 11 changed files with 396 additions and 11 deletions.
97 changes: 97 additions & 0 deletions src/xrSound/SoundRender_Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,85 @@ void CSoundRender_Core::_initialize()

bPresent = true;

#ifdef USE_PHONON
if (supports_float_pcm && psSoundFlags.test(ss_UseFloat32) && psSoundFlags.test(ss_EFX))
{
IPLSIMDLevel simdLevel = IPL_SIMDLEVEL_SSE2;
if (CPU::HasAVX512F)
simdLevel = IPL_SIMDLEVEL_AVX512;
else if (CPU::HasAVX2)
simdLevel = IPL_SIMDLEVEL_AVX2;
else if (CPU::HasAVX)
simdLevel = IPL_SIMDLEVEL_AVX;
else if (CPU::HasSSE42)
simdLevel = IPL_SIMDLEVEL_SSE4;

const IPLContextFlags flags
{
strstr(Core.Params, "-steamaudio_validate")
? IPL_CONTEXTFLAGS_VALIDATION
: IPLContextFlags{}
};

IPLContextSettings contextSettings
{
STEAMAUDIO_VERSION,
[](IPLLogLevel level, const char* message)
{
// These warnings are incorrect, values are correct.
if (0 == xr_strcmp(message, "Warning: setInputs: invalid IPLfloat32: (&inputs->directivity)->dipoleWeight = 0.000000\n"))
return;
if (0 == xr_strcmp(message, "Warning: apply: invalid IPLTransmissionType: params->flags = 31\n"))
return;

char mark = '\0';
switch (level)
{
case IPL_LOGLEVEL_INFO: mark = '*'; break;
case IPL_LOGLEVEL_WARNING: mark = '~'; break;
case IPL_LOGLEVEL_ERROR: mark = '!'; break;
case IPL_LOGLEVEL_DEBUG: mark = '#'; break;
}
Msg("%c SOUND: SteamAudio: %s", mark, message);
},
[](IPLsize size, IPLsize alignment)
{
return Memory.mem_alloc(size, alignment);
},
[](void* memoryBlock)
{
Memory.mem_free(memoryBlock);
},
simdLevel,
flags,
};

iplContextCreate(&contextSettings, &m_ipl_context);
IPLHRTFSettings hrtfSettings
{
IPL_HRTFTYPE_DEFAULT,
nullptr, nullptr, 0,
1.0f, IPL_HRTFNORMTYPE_NONE
};

m_ipl_settings = { 48000, 19200 };
iplHRTFCreate(m_ipl_context, &m_ipl_settings, &hrtfSettings, &m_ipl_hrtf);
}
#endif
bReady = true;
}

void CSoundRender_Core::_clear()
{
bReady = false;

#ifdef USE_PHONON
if (m_ipl_hrtf)
iplHRTFRelease(&m_ipl_hrtf);
if (m_ipl_context)
iplContextRelease(&m_ipl_context);
#endif

// remove sources
for (auto& kv : s_sources)
{
Expand Down Expand Up @@ -187,6 +259,31 @@ void CSoundRender_Core::update_listener(const Fvector& P, const Fvector& D, cons
if (!psSoundFlags.test(ss_EFX) || !bListenerMoved)
return;

#ifdef USE_PHONON
if (m_ipl_context)
{
const IPLCoordinateSpace3 listenerCoordinates
{
reinterpret_cast<const IPLVector3&>(R),
reinterpret_cast<const IPLVector3&>(N),
reinterpret_cast<const IPLVector3&>(D),
reinterpret_cast<const IPLVector3&>(P)
}; // the world-space position and orientation of the listener

IPLSimulationSharedInputs sharedInputs
{
listenerCoordinates,
64, 8,
2.0f, 1,
1.0f,
nullptr, nullptr
};

for (const auto scene : m_scenes)
iplSimulatorSetSharedInputs(scene->ipl_simulator(), IPL_SIMULATIONFLAGS_DIRECT, &sharedInputs);
}
#endif

bListenerMoved = false;
}

Expand Down
13 changes: 13 additions & 0 deletions src/xrSound/SoundRender_Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ class CSoundRender_Core : public ISoundManager
u32 s_emitters_u; // emitter update marker
xr_vector<CSoundRender_Target*> s_targets;

#ifdef USE_PHONON
IPLContext m_ipl_context{};
IPLHRTF m_ipl_hrtf{};
IPLAudioSettings m_ipl_settings{};
#endif

public:
bool supports_float_pcm{};

Expand Down Expand Up @@ -111,6 +117,13 @@ class CSoundRender_Core : public ISoundManager

void refresh_sources() override;

#ifdef USE_PHONON
[[nodiscard]]
auto ipl_context() const { return m_ipl_context; }
const auto& ipl_settings() const { return m_ipl_settings; }
auto ipl_hrtf() const { return m_ipl_hrtf; }
#endif

public:
CSoundRender_Source* i_create_source(pcstr name);

Expand Down
6 changes: 3 additions & 3 deletions src/xrSound/SoundRender_Core_Processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ void CSoundRender_Core::update(const Fvector& P, const Fvector& D, const Fvector
}
s_emitters_u++;

// update listener
update_listener(P, D, N, R, fTimer_Delta);

const auto update_emitter = [this](CSoundRender_Emitter* emitter)
{
const bool ignore = emitter->bIgnoringTimeFactor;
Expand Down Expand Up @@ -69,9 +72,6 @@ void CSoundRender_Core::update(const Fvector& P, const Fvector& D, const Fvector
}
}

// update listener
update_listener(P, D, N, R, fTimer_Delta);

// Events
for (CSoundRender_Scene* scene : m_scenes)
scene->update();
Expand Down
43 changes: 40 additions & 3 deletions src/xrSound/SoundRender_Emitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ extern float psSoundVEffects;

void CSoundRender_Emitter::set_position(const Fvector& pos)
{
if (source()->channels_num() == 1)
if (source()->channels_num() == 1
#ifdef USE_PHONON
|| m_ipl_source
#endif
)
p_source.position = pos;
else
p_source.position.set(0, 0, 0);
Expand Down Expand Up @@ -43,10 +47,24 @@ CSoundRender_Emitter::CSoundRender_Emitter(CSoundRender_Scene* s)
fade_volume(1.f),
m_current_state(stStopped),
bMoved(true),
marker(0xabababab) {}
marker(0xabababab)
{
#ifdef USE_PHONON
if (const auto simulator = scene->ipl_simulator())
{
IPLSourceSettings sourceSettings{ IPL_SIMULATIONFLAGS_DIRECT };
iplSourceCreate(simulator, &sourceSettings, &m_ipl_source);
}
#endif
}

CSoundRender_Emitter::~CSoundRender_Emitter()
{
#ifdef USE_PHONON
if (m_ipl_source)
iplSourceRelease(&m_ipl_source);
#endif

// try to release dependencies, events, for example
Event_ReleaseOwner();
wait_prefill();
Expand Down Expand Up @@ -143,7 +161,7 @@ void CSoundRender_Emitter::move_cursor(int offset)
set_cursor(get_cursor(true) + offset);
}

void CSoundRender_Emitter::fill_data(void* dest, u32 offset, u32 size) const
void CSoundRender_Emitter::fill_data(void* dest, u32 offset, u32 size)
{
source()->decompress(dest, offset, size, ovf);
}
Expand Down Expand Up @@ -237,6 +255,25 @@ std::pair<u8*, size_t> CSoundRender_Emitter::obtain_block()
if (current_block >= sdef_target_count_prefill)
current_block = 0;
--filled_blocks;
#ifdef USE_PHONON
if (psSoundFlags.test(ss_EFX) && scene->ipl_scene_mesh() && !is_2D())
{
const auto context = SoundRender->ipl_context();

IPLSimulationOutputs outputs{};
outputs.direct.flags = static_cast<IPLDirectEffectFlags>(
IPL_DIRECTEFFECTFLAGS_APPLYAIRABSORPTION |
IPL_DIRECTEFFECTFLAGS_APPLYDIRECTIVITY |
IPL_DIRECTEFFECTFLAGS_APPLYOCCLUSION |
IPL_DIRECTEFFECTFLAGS_APPLYTRANSMISSION
);
iplSourceGetOutputs(m_ipl_source, IPL_SIMULATIONFLAGS_DIRECT, &outputs);

iplAudioBufferDeinterleave(context, (float*)result.first, &ipl_buffers.direct_input);
iplDirectEffectApply(ipl_effects.direct, &outputs.direct, &ipl_buffers.direct_input, &ipl_buffers.direct_output);
iplAudioBufferInterleave(context, &ipl_buffers.direct_output, (float*)result.first);
}
#endif
return std::move(result);
}

Expand Down
22 changes: 21 additions & 1 deletion src/xrSound/SoundRender_Emitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,26 @@ class CSoundRender_Emitter final : public CSound_emitter
[[nodiscard]]
CSoundRender_Source* source() const { return (CSoundRender_Source*)owner_data->handle; }

#ifdef USE_PHONON
private:
IPLSource m_ipl_source{};

struct
{
IPLDirectEffect direct{};
IPLReflectionEffect reflection{};
IPLPathEffect path{};
} ipl_effects{};
struct
{
IPLAudioBuffer direct_input{};
IPLAudioBuffer direct_output{};
} ipl_buffers{};

public:
auto ipl_source() const { return m_ipl_source; }
#endif

[[nodiscard]]
u32 get_bytes_total() const;
[[nodiscard]]
Expand Down Expand Up @@ -85,7 +105,7 @@ class CSoundRender_Emitter final : public CSound_emitter
int filled_blocks{};

void fill_block(void* ptr, u32 size);
void fill_data(void* dest, u32 offset, u32 size) const;
void fill_data(void* dest, u32 offset, u32 size);

void fill_all_blocks();
void dispatch_prefill();
Expand Down
45 changes: 45 additions & 0 deletions src/xrSound/SoundRender_Emitter_FSM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,51 @@ void CSoundRender_Emitter::update(float fTime, float dt)
owner_data->feedback = 0;
owner_data = 0;
}

#ifdef USE_PHONON
if (m_ipl_source && !bStopping)
{
const auto& listener = SoundRender->listener_params();

const IPLCoordinateSpace3 sourceCoordinates
{
reinterpret_cast<const IPLVector3&>(listener.orientation[2]),
reinterpret_cast<const IPLVector3&>(listener.orientation[1]),
reinterpret_cast<const IPLVector3&>(listener.orientation[0]),
reinterpret_cast<const IPLVector3&>(p_source.position)
};
IPLSimulationInputs inputs
{
/*.flags =*/ IPL_SIMULATIONFLAGS_DIRECT,
/*.directFlags =*/ static_cast<IPLDirectSimulationFlags>(
IPL_DIRECTSIMULATIONFLAGS_AIRABSORPTION |
IPL_DIRECTSIMULATIONFLAGS_DIRECTIVITY |
IPL_DIRECTSIMULATIONFLAGS_OCCLUSION |
IPL_DIRECTSIMULATIONFLAGS_TRANSMISSION),
/*.source =*/ sourceCoordinates,
/*.distanceAttenuationModel =*/ {},
/*.airAbsorptionModel =*/ {},
/*.directivity =*/ {},
/*.occlusionType =*/ IPL_OCCLUSIONTYPE_VOLUMETRIC,
/*.occlusionRadius =*/ p_source.max_distance,
/*.numOcclusionSamples =*/ 16,
/*.reverbScale =*/ { 1.0f, 1.0f, 1.0f },
/*.hybridReverbTransitionTime =*/ 1.0f,
/*.hybridReverbOverlapPercent =*/ 0.25f,
/*.baked =*/ IPL_FALSE,
/*.bakedDataIdentifier =*/ {},
/*.pathingProbes =*/ nullptr/*scene->ipl_scene_probes*/,
/*.visRadius =*/ 1.0f,
/*.visThreshold =*/ 0.1f,
/*.visRange =*/ p_source.max_distance,
/*.pathingOrder =*/ 1,
/*.enableValidation =*/ IPL_FALSE,
/*.findAlternatePaths =*/ IPL_FALSE,
/*.numTransmissionRays =*/ 2,
};
iplSourceSetInputs(m_ipl_source, IPL_SIMULATIONFLAGS_DIRECT, &inputs);
}
#endif
}

IC void volume_lerp(float& c, float t, float s, float dt)
Expand Down
39 changes: 38 additions & 1 deletion src/xrSound/SoundRender_Emitter_StartStop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,52 @@ void CSoundRender_Emitter::start(const ref_sound& _owner, u32 flags, float delay
bStopping = FALSE;
bRewind = FALSE;

const auto data_info = source()->data_info();

// Calc storage
for (auto& buf : temp_buf)
buf.resize(source()->data_info().bytesPerBuffer);
buf.resize(data_info.bytesPerBuffer);

ovf = source()->open();

#ifdef USE_PHONON
if (const auto simulator = scene->ipl_simulator())
{
iplSourceAdd(m_ipl_source, simulator);

const auto context = SoundRender->ipl_context();
auto& settings = source()->ipl_audio_settings();

IPLDirectEffectSettings direct{ data_info.channels };
iplDirectEffectCreate(context, &settings, &direct, &ipl_effects.direct);

IPLReflectionEffectSettings refl{ IPL_REFLECTIONEFFECTTYPE_CONVOLUTION, settings.frameSize * 2, 4 };
iplReflectionEffectCreate(context, &settings, &refl, &ipl_effects.reflection);

IPLPathEffectSettings path{ 1, IPL_TRUE, {}, SoundRender->ipl_hrtf() };
iplPathEffectCreate(context, &settings, &path, &ipl_effects.path);

iplAudioBufferAllocate(context, data_info.channels, settings.frameSize, &ipl_buffers.direct_input);
iplAudioBufferAllocate(context, data_info.channels, settings.frameSize, &ipl_buffers.direct_output);
}
#endif
}

void CSoundRender_Emitter::i_stop()
{
#ifdef USE_PHONON
if (const auto context = SoundRender->ipl_context())
{
iplSourceRemove(m_ipl_source, scene->ipl_simulator());

iplDirectEffectRelease(&ipl_effects.direct);
iplReflectionEffectRelease(&ipl_effects.reflection);
iplPathEffectRelease(&ipl_effects.path);

iplAudioBufferFree(context, &ipl_buffers.direct_output);
iplAudioBufferFree(context, &ipl_buffers.direct_input);
}
#endif
bRewind = FALSE;
if (target)
stop_target();
Expand Down
Loading

0 comments on commit 5d960c2

Please sign in to comment.