|
25 | 25 |
|
26 | 26 | #include "third_party/blink/renderer/modules/webaudio/audio_param.h"
|
27 | 27 |
|
| 28 | +#include "build/build_config.h" |
28 | 29 | #include "third_party/blink/renderer/core/inspector/console_message.h"
|
29 | 30 | #include "third_party/blink/renderer/modules/webaudio/audio_node.h"
|
30 | 31 | #include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
|
31 | 32 | #include "third_party/blink/renderer/platform/audio/audio_utilities.h"
|
| 33 | +#include "third_party/blink/renderer/platform/audio/vector_math.h" |
32 | 34 | #include "third_party/blink/renderer/platform/bindings/exception_state.h"
|
33 | 35 | #include "third_party/blink/renderer/platform/histogram.h"
|
34 | 36 | #include "third_party/blink/renderer/platform/wtf/math_extras.h"
|
@@ -227,6 +229,48 @@ void AudioParamHandler::CalculateSampleAccurateValues(
|
227 | 229 | CalculateFinalValues(values, number_of_values, IsAudioRate());
|
228 | 230 | }
|
229 | 231 |
|
| 232 | +// Replace NaN values in |values| with |default_value|. |
| 233 | +static void HandleNaNValues(float* values, |
| 234 | + unsigned number_of_values, |
| 235 | + float default_value) { |
| 236 | + unsigned k = 0; |
| 237 | +#if defined(ARCH_CPU_X86_FAMILY) |
| 238 | + if (number_of_values >= 4) { |
| 239 | + __m128 defaults = _mm_set1_ps(default_value); |
| 240 | + for (k = 0; k < number_of_values; k += 4) { |
| 241 | + __m128 v = _mm_loadu_ps(values + k); |
| 242 | + // cmpuord returns all 1's if v is NaN for each elmeent of v. |
| 243 | + __m128 isnan = _mm_cmpunord_ps(v, v); |
| 244 | + // Replace NaN parts with default. |
| 245 | + __m128 result = _mm_and_ps(isnan, defaults); |
| 246 | + // Merge in the parts that aren't NaN |
| 247 | + result = _mm_or_ps(_mm_andnot_ps(isnan, v), result); |
| 248 | + _mm_storeu_ps(values + k, result); |
| 249 | + } |
| 250 | + } |
| 251 | +#elif defined(CPU_ARM_NEON) |
| 252 | + if (number_of_values >= 4) { |
| 253 | + uint32x4_t defaults = vreinterpretq_u32_f32(vdupq_n_f32(default_value)); |
| 254 | + for (k = 0; k < number_of_values; k += 4) { |
| 255 | + float32x4_t v = vld1q_f32(values + k); |
| 256 | + // Returns true (all ones) if v is not NaN |
| 257 | + uint32x4_t is_not_nan = vceqq_f32(v, v); |
| 258 | + // Get the parts that are not NaN |
| 259 | + uint32x4_t result = vandq_u32(is_not_nan, vreinterpretq_u32_f32(v)); |
| 260 | + // Replace the parts that are NaN with the default and merge with previous |
| 261 | + // result. (Note: vbic_u32(x, y) = x and not y) |
| 262 | + result = vorrq_u32(result, vbicq_u32(defaults, is_not_nan)); |
| 263 | + vst1q_f32(values + k, vreinterpretq_f32_u32(result)); |
| 264 | + } |
| 265 | + } |
| 266 | +#endif |
| 267 | + for (; k < number_of_values; ++k) { |
| 268 | + if (std::isnan(values[k])) { |
| 269 | + values[k] = default_value; |
| 270 | + } |
| 271 | + } |
| 272 | +} |
| 273 | + |
230 | 274 | void AudioParamHandler::CalculateFinalValues(float* values,
|
231 | 275 | unsigned number_of_values,
|
232 | 276 | bool sample_accurate) {
|
@@ -276,6 +320,25 @@ void AudioParamHandler::CalculateFinalValues(float* values,
|
276 | 320 | // Sum, with unity-gain.
|
277 | 321 | summing_bus->SumFrom(*connection_bus);
|
278 | 322 | }
|
| 323 | + |
| 324 | + float min_value = MinValue(); |
| 325 | + float max_value = MaxValue(); |
| 326 | + |
| 327 | + if (NumberOfRenderingConnections() > 0) { |
| 328 | + // AudioParams by themselves don't produce NaN because of the finite min |
| 329 | + // and max values. But an input to an AudioParam could have NaNs. |
| 330 | + // |
| 331 | + // NaN values in AudioParams must be replaced by the AudioParam's |
| 332 | + // defaultValue. Then these values must be clamped to lie in the nominal |
| 333 | + // range between the AudioParam's minValue and maxValue. |
| 334 | + // |
| 335 | + // See https://webaudio.github.io/web-audio-api/#computation-of-value. |
| 336 | + HandleNaNValues(values, number_of_values, DefaultValue()); |
| 337 | + } |
| 338 | + |
| 339 | + VectorMath::Vclip(values, 1, &min_value, &max_value, values, 1, |
| 340 | + number_of_values); |
| 341 | + |
279 | 342 | }
|
280 | 343 |
|
281 | 344 | void AudioParamHandler::CalculateTimelineValues(float* values,
|
|
0 commit comments