summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc')
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc57
1 files changed, 56 insertions, 1 deletions
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc
index c5d329479a4..135588f56eb 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/modules/webaudio/audio_param.h"
+#include "build/build_config.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node.h"
@@ -235,6 +236,49 @@ void AudioParamHandler::CalculateSampleAccurateValues(
CalculateFinalValues(values, number_of_values, IsAudioRate());
}
+// Replace NaN values in |values| with |default_value|.
+static void HandleNaNValues(float* values,
+ unsigned number_of_values,
+ float default_value) {
+ unsigned k = 0;
+#if defined(ARCH_CPU_X86_FAMILY)
+ if (number_of_values >= 4) {
+ __m128 defaults = _mm_set1_ps(default_value);
+ for (k = 0; k < number_of_values; k += 4) {
+ __m128 v = _mm_loadu_ps(values + k);
+ // cmpuord returns all 1's if v is NaN for each elmeent of v.
+ __m128 isnan = _mm_cmpunord_ps(v, v);
+ // Replace NaN parts with default.
+ __m128 result = _mm_and_ps(isnan, defaults);
+ // Merge in the parts that aren't NaN
+ result = _mm_or_ps(_mm_andnot_ps(isnan, v), result);
+ _mm_storeu_ps(values + k, result);
+ }
+ }
+#elif defined(CPU_ARM_NEON)
+ if (number_of_values >= 4) {
+ uint32x4_t defaults = static_cast<uint32x4_t>(vdupq_n_f32(default_value));
+ for (k = 0; k < number_of_values; k += 4) {
+ float32x4_t v = vld1q_f32(values + k);
+ // Returns true (all ones) if v is not NaN
+ uint32x4_t is_not_nan = vceqq_f32(v, v);
+ // Get the parts that are not NaN
+ uint32x4_t result = vandq_u32(is_not_nan, v);
+ // Replace the parts that are NaN with the default and merge with previous
+ // result. (Note: vbic_u32(x, y) = x and not y)
+ result = vorrq_u32(result, vbicq_u32(defaults, is_not_nan));
+ vst1q_f32(values + k, static_cast<float32x4_t>(result));
+ }
+ }
+#endif
+
+ for (; k < number_of_values; ++k) {
+ if (std::isnan(values[k])) {
+ values[k] = default_value;
+ }
+ }
+}
+
void AudioParamHandler::CalculateFinalValues(float* values,
unsigned number_of_values,
bool sample_accurate) {
@@ -297,10 +341,21 @@ void AudioParamHandler::CalculateFinalValues(float* values,
}
}
- // Clamp the values now to the nominal range
float min_value = MinValue();
float max_value = MaxValue();
+ if (NumberOfRenderingConnections() > 0) {
+ // AudioParams by themselves don't produce NaN because of the finite min
+ // and max values. But an input to an AudioParam could have NaNs.
+ //
+ // NaN values in AudioParams must be replaced by the AudioParam's
+ // defaultValue. Then these values must be clamped to lie in the nominal
+ // range between the AudioParam's minValue and maxValue.
+ //
+ // See https://webaudio.github.io/web-audio-api/#computation-of-value.
+ HandleNaNValues(values, number_of_values, DefaultValue());
+ }
+
vector_math::Vclip(values, 1, &min_value, &max_value, values, 1,
number_of_values);
}