123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- #pragma once
- #include <AK/SoundEngine/Common/AkTypes.h>
- #include <AK/SpatialAudio/Common/AkSpatialAudio.h>
- #include <AK/SoundEngine/Common/AkVirtualAcoustics.h>
- namespace AK {
- namespace SpatialAudio {
- namespace ReverbEstimation
- {
-
-
-
-
-
-
-
- float CalculateSlope(const AkAcousticTexture& texture)
- {
-
- const float meanX = 1.5f;
- const float sdX = 1.11803399;
- const int N = 4;
- float meanY = (texture.fAbsorptionLow + texture.fAbsorptionMidLow + texture.fAbsorptionMidHigh + texture.fAbsorptionHigh) / (float)N;
- float absorptions[4] = { texture.fAbsorptionLow, texture.fAbsorptionMidLow, texture.fAbsorptionMidHigh, texture.fAbsorptionHigh };
- float sdY = 0.0f;
- float meanDiffDotProd = 0.0f;
- for (int i = 0; i < N; ++i)
- {
- const float yMeanDiff = absorptions[i] - meanY;
- const float xMeanDiff = (float)i - meanX;
- meanDiffDotProd += yMeanDiff * xMeanDiff;
- sdY += yMeanDiff * yMeanDiff;
- }
- if (sdY == 0.0f)
- return 0.0f;
- sdY = sqrtf(sdY / (float)N);
- const float correlationCoeff = (1.0f / (N - 1.0f)) * (meanDiffDotProd / (sdY * sdX));
- return correlationCoeff * (sdY / sdX);
- }
-
- void GetAverageAbsorptionValues(AkAcousticTexture* in_textures, float* in_surfaceAreas, int in_numTextures, AkAcousticTexture& out_average)
- {
- float surfaceArea = 0.0f;
- float totalSurfaceArea = 0.0f;
- out_average.fAbsorptionLow = 0.0f;
- out_average.fAbsorptionMidLow = 0.0f;
- out_average.fAbsorptionMidHigh = 0.0f;
- out_average.fAbsorptionHigh = 0.0f;
- for (int textureIndex = 0; textureIndex < in_numTextures; ++textureIndex)
- {
- AkAcousticTexture& texture = in_textures[textureIndex];
- surfaceArea = in_surfaceAreas[textureIndex];
- out_average.fAbsorptionLow += texture.fAbsorptionLow * surfaceArea;
- out_average.fAbsorptionMidLow += texture.fAbsorptionMidLow * surfaceArea;
- out_average.fAbsorptionMidHigh += texture.fAbsorptionMidHigh * surfaceArea;
- out_average.fAbsorptionHigh += texture.fAbsorptionHigh * surfaceArea;
- totalSurfaceArea += surfaceArea;
- }
- if (totalSurfaceArea > 0.0f)
- {
- out_average.fAbsorptionLow = out_average.fAbsorptionLow / totalSurfaceArea;
- out_average.fAbsorptionMidLow = out_average.fAbsorptionMidLow / totalSurfaceArea;
- out_average.fAbsorptionMidHigh = out_average.fAbsorptionMidHigh / totalSurfaceArea;
- out_average.fAbsorptionHigh = out_average.fAbsorptionHigh / totalSurfaceArea;
- }
- }
-
-
- AK_EXTERNAPIFUNC(AKRESULT, EstimateT60Decay)(
- AkReal32 in_volumeCubicMeters,
- AkReal32 in_surfaceAreaSquaredMeters,
- AkReal32 in_environmentAverageAbsorption,
- AkReal32& out_decayEstimate
- )
- {
- if (in_volumeCubicMeters <= 0.0f)
- {
- out_decayEstimate = 0.0f;
- return AKRESULT::AK_Success;
- }
- if (in_surfaceAreaSquaredMeters < AK_SA_MIN_ENVIRONMENT_SURFACE_AREA)
- {
- AKASSERT(false && "AK::SpatialAudio::ReverbEstimation::EstimateT60Decay: Invalid surface area. in_SurfaceAreaSquaredMeters Must be >= AK_SA_MIN_ENVIRONMENT_SURFACE_AREA");
- return AKRESULT::AK_Fail;
- }
- if (in_environmentAverageAbsorption < AK_SA_MIN_ENVIRONMENT_ABSORPTION || in_environmentAverageAbsorption > 1.0f)
- {
- AKASSERT(false && "AK::SpatialAudio::ReverbEstimation::EstimateT60Decay: Invalid absorption value. in_EnvironmentAverageAbsorption Must be between AK_SA_MIN_ENVIRONMENT_ABSORPTION and 1");
- return AKRESULT::AK_Fail;
- }
-
- out_decayEstimate = (0.161f * in_volumeCubicMeters) / (in_surfaceAreaSquaredMeters * in_environmentAverageAbsorption);
- return AKRESULT::AK_Success;
- }
-
-
- AK_EXTERNAPIFUNC(AKRESULT, EstimateTimeToFirstReflection)(
- AkVector in_environmentExtentMeters,
- AkReal32& out_timeToFirstReflectionMs,
- AkReal32 in_speedOfSound = 343.0f
- )
- {
- if (in_speedOfSound <= 0.0f)
- {
- AKASSERT(false && "AK::SpatialAudio::ReverbEstimation::EstimateTimeToFirstReflection: Invalid speed of sound. in_speedOfSound must be greater than 0.");
- return AKRESULT::AK_Fail;
- }
- if (in_environmentExtentMeters.X < 0.0f || in_environmentExtentMeters.Y < 0.0f || in_environmentExtentMeters.Z < 0.0f)
- {
- AKASSERT(false && "AK::SpatialAudio::ReverbEstimation::EstimateTimeToFirstReflection: Invalid extent. All components must be positive numbers.");
- return AKRESULT::AK_Fail;
- }
- const float minDimension = AkMin(AkMin(in_environmentExtentMeters.X, in_environmentExtentMeters.Y), in_environmentExtentMeters.Z);
- out_timeToFirstReflectionMs = (minDimension / in_speedOfSound) * 1000.0f;
- return AKRESULT::AK_Success;
- }
-
-
-
-
-
- AK_EXTERNAPIFUNC(AkReal32, EstimateHFDamping)(
- AkAcousticTexture* in_textures,
- float* in_surfaceAreas,
- int in_numTextures
- )
- {
- if (in_textures == nullptr || in_surfaceAreas == nullptr || in_numTextures == 0)
- {
- return 0.0f;
- }
- AkAcousticTexture averageAbsorptionValues;
- GetAverageAbsorptionValues(in_textures, in_surfaceAreas, in_numTextures, averageAbsorptionValues);
- return CalculateSlope(averageAbsorptionValues) * 2.f;
- }
-
- }
- }
- }
|