diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/audio')
20 files changed, 271 insertions, 80 deletions
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc b/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc index 24e122b12ac..1c98e7ca63f 100644 --- a/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc +++ b/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc @@ -36,6 +36,7 @@ #include "third_party/blink/public/platform/web_audio_latency_hint.h" #include "third_party/blink/renderer/platform/audio/audio_utilities.h" #include "third_party/blink/renderer/platform/audio/push_pull_fifo.h" +#include "third_party/blink/renderer/platform/audio/vector_math.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/histogram.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" @@ -149,6 +150,23 @@ void AudioDestination::Render(const WebVector<float*>& destination_data, delay_timestamp, "delay (s)", delay); } +// Determine if the rendered data is audible. +static bool IsAudible(const AudioBus* rendered_data) { + // Compute the energy in each channel and sum up the energy in each channel + // for the total energy. + float energy = 0; + + unsigned data_size = rendered_data->length(); + for (unsigned k = 0; k < rendered_data->NumberOfChannels(); ++k) { + const float* data = rendered_data->Channel(k)->Data(); + float channel_energy; + VectorMath::Vsvesq(data, 1, &channel_energy, data_size); + energy += channel_energy; + } + + return energy > 0; +} + void AudioDestination::RequestRender(size_t frames_requested, size_t frames_to_render, double delay, @@ -183,8 +201,26 @@ void AudioDestination::RequestRender(size_t frames_requested, output_position.position = 0.0; // Process WebAudio graph and push the rendered output to FIFO. - callback_.Render(nullptr, render_bus_.get(), + callback_.Render(render_bus_.get(), AudioUtilities::kRenderQuantumFrames, output_position); + + // Detect silence (or not) for MEI + bool is_audible = IsAudible(render_bus_.get()); + + if (is_audible) { + ++total_audible_renders_; + } + + if (was_audible_) { + if (!is_audible) { + was_audible_ = false; + } + } else { + if (is_audible) { + was_audible_ = true; + } + } + fifo_->Push(render_bus_.get()); } diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_destination.h b/chromium/third_party/blink/renderer/platform/audio/audio_destination.h index a42f2ee932b..71388f76156 100644 --- a/chromium/third_party/blink/renderer/platform/audio/audio_destination.h +++ b/chromium/third_party/blink/renderer/platform/audio/audio_destination.h @@ -138,6 +138,15 @@ class PLATFORM_EXPORT AudioDestination // graph into the FIFO. scoped_refptr<AudioBus> render_bus_; + // Keeps track if the output of this destination was audible, before the + // current rendering quantum. Used for recording "playback" time. + bool was_audible_ = false; + + // Counts the number of render quanta where audible sound was played. We + // determine audibility on render quantum boundaries, so counting quanta is + // all that's needed. + size_t total_audible_renders_ = 0; + // Accessed by rendering thread: the render callback function of WebAudio // engine. (i.e. DestinationNode) AudioIOCallback& callback_; diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc b/chromium/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc index 27a4021ce25..e15026be65f 100644 --- a/chromium/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc +++ b/chromium/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc @@ -28,8 +28,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "third_party/blink/renderer/platform/audio/audio_dsp_kernel.h" #include "third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.h" +#include "third_party/blink/renderer/platform/audio/audio_dsp_kernel.h" +#include "third_party/blink/renderer/platform/wtf/wtf.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_io_callback.h b/chromium/third_party/blink/renderer/platform/audio/audio_io_callback.h index 079bb199e5f..e97f83a8a0c 100644 --- a/chromium/third_party/blink/renderer/platform/audio/audio_io_callback.h +++ b/chromium/third_party/blink/renderer/platform/audio/audio_io_callback.h @@ -46,11 +46,9 @@ struct AudioIOPosition { // Abstract base-class for isochronous audio I/O client. class AudioIOCallback { public: - // render() is called periodically to get the next render quantum of audio - // into destinationBus. Optional audio input is given in sourceBus (if it's - // not 0). - virtual void Render(AudioBus* source_bus, - AudioBus* destination_bus, + // Called periodically to get the next render quantum of audio into + // |destination_bus|. + virtual void Render(AudioBus* destination_bus, size_t frames_to_process, const AudioIOPosition& output_position) = 0; diff --git a/chromium/third_party/blink/renderer/platform/audio/biquad.cc b/chromium/third_party/blink/renderer/platform/audio/biquad.cc index c9a643d5505..a97089040c0 100644 --- a/chromium/third_party/blink/renderer/platform/audio/biquad.cc +++ b/chromium/third_party/blink/renderer/platform/audio/biquad.cc @@ -276,7 +276,7 @@ void Biquad::SetLowpassParams(int index, double cutoff, double resonance) { resonance = pow10(resonance / 20); - double theta = piDouble * cutoff; + double theta = kPiDouble * cutoff; double alpha = sin(theta) / (2 * resonance); double cosw = cos(theta); double beta = (1 - cosw) / 2; @@ -308,7 +308,7 @@ void Biquad::SetHighpassParams(int index, double cutoff, double resonance) { // Compute biquad coefficients for highpass filter resonance = pow10(resonance / 20); - double theta = piDouble * cutoff; + double theta = kPiDouble * cutoff; double alpha = sin(theta) / (2 * resonance); double cosw = cos(theta); double beta = (1 + cosw) / 2; @@ -357,7 +357,7 @@ void Biquad::SetLowShelfParams(int index, double frequency, double db_gain) { // The z-transform is a constant gain. SetNormalizedCoefficients(index, a * a, 0, 0, 1, 0, 0); } else if (frequency > 0) { - double w0 = piDouble * frequency; + double w0 = kPiDouble * frequency; double s = 1; // filter slope (1 is max value) double alpha = 0.5 * sin(w0) * sqrt((a + 1 / a) * (1 / s - 1) + 2); double k = cos(w0); @@ -389,7 +389,7 @@ void Biquad::SetHighShelfParams(int index, double frequency, double db_gain) { // The z-transform is 1. SetNormalizedCoefficients(index, 1, 0, 0, 1, 0, 0); } else if (frequency > 0) { - double w0 = piDouble * frequency; + double w0 = kPiDouble * frequency; double s = 1; // filter slope (1 is max value) double alpha = 0.5 * sin(w0) * sqrt((a + 1 / a) * (1 / s - 1) + 2); double k = cos(w0); @@ -425,7 +425,7 @@ void Biquad::SetPeakingParams(int index, if (frequency > 0 && frequency < 1) { if (q > 0) { - double w0 = piDouble * frequency; + double w0 = kPiDouble * frequency; double alpha = sin(w0) / (2 * q); double k = cos(w0); @@ -458,7 +458,7 @@ void Biquad::SetAllpassParams(int index, double frequency, double q) { if (frequency > 0 && frequency < 1) { if (q > 0) { - double w0 = piDouble * frequency; + double w0 = kPiDouble * frequency; double alpha = sin(w0) / (2 * q); double k = cos(w0); @@ -491,7 +491,7 @@ void Biquad::SetNotchParams(int index, double frequency, double q) { if (frequency > 0 && frequency < 1) { if (q > 0) { - double w0 = piDouble * frequency; + double w0 = kPiDouble * frequency; double alpha = sin(w0) / (2 * q); double k = cos(w0); @@ -523,7 +523,7 @@ void Biquad::SetBandpassParams(int index, double frequency, double q) { q = std::max(0.0, q); if (frequency > 0 && frequency < 1) { - double w0 = piDouble * frequency; + double w0 = kPiDouble * frequency; if (q > 0) { double alpha = sin(w0) / (2 * q); double k = cos(w0); @@ -585,7 +585,7 @@ void Biquad::GetFrequencyResponse(int n_frequencies, mag_response[k] = std::nanf(""); phase_response[k] = std::nanf(""); } else { - double omega = -piDouble * frequency[k]; + double omega = -kPiDouble * frequency[k]; std::complex<double> z = std::complex<double>(cos(omega), sin(omega)); std::complex<double> numerator = b0 + (b1 + b2 * z) * z; std::complex<double> denominator = diff --git a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_impl.h b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_impl.h index 8562a56d8d8..ef87b87e120 100644 --- a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_impl.h +++ b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_impl.h @@ -3,9 +3,9 @@ // found in the LICENSE file. // This file intentionally does not have header guards, it's included from -// VectorMathAVX.h and from VectorMathSSE.h with different macro definitions. -// The following line silences a presubmit warning that would otherwise be -// triggered by this: no-include-guard-because-multiply-included +// vector_math_avx.h and from vector_math_sse.h with different macro +// definitions. The following line silences a presubmit warning that would +// otherwise be triggered by this: no-include-guard-because-multiply-included #include "build/build_config.h" diff --git a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x8_6.h b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x86.h index cc35b44b7bf..f023b8f2dc1 100644 --- a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x8_6.h +++ b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x86.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_CPU_X86_VECTOR_MATH_X8_6_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_CPU_X86_VECTOR_MATH_X8_6_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_CPU_X86_VECTOR_MATH_X86_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_CPU_X86_VECTOR_MATH_X86_H_ #include "base/cpu.h" #include "third_party/blink/renderer/platform/audio/cpu/x86/vector_math_avx.h" @@ -410,4 +410,4 @@ static ALWAYS_INLINE void Zvmul(const float* real1p, } // namespace VectorMath } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_CPU_X86_VECTOR_MATH_X8_6_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_CPU_X86_VECTOR_MATH_X86_H_ diff --git a/chromium/third_party/blink/renderer/platform/audio/down_sampler.cc b/chromium/third_party/blink/renderer/platform/audio/down_sampler.cc index 90415979257..ad5fb79d5eb 100644 --- a/chromium/third_party/blink/renderer/platform/audio/down_sampler.cc +++ b/chromium/third_party/blink/renderer/platform/audio/down_sampler.cc @@ -60,14 +60,14 @@ std::unique_ptr<AudioFloatArray> MakeReducedKernel(size_t size) { // processing after doing the main convolution using m_reducedKernel. for (int i = 1; i < n; i += 2) { // Compute the sinc() with offset. - double s = sinc_scale_factor * piDouble * (i - half_size); + double s = sinc_scale_factor * kPiDouble * (i - half_size); double sinc = !s ? 1.0 : sin(s) / s; sinc *= sinc_scale_factor; // Compute Blackman window, matching the offset of the sinc(). double x = static_cast<double>(i) / n; double window = - a0 - a1 * cos(twoPiDouble * x) + a2 * cos(twoPiDouble * 2.0 * x); + a0 - a1 * cos(kTwoPiDouble * x) + a2 * cos(kTwoPiDouble * 2.0 * x); // Window the sinc() function. // Then store only the odd terms in the kernel. diff --git a/chromium/third_party/blink/renderer/platform/audio/down_sampler.h b/chromium/third_party/blink/renderer/platform/audio/down_sampler.h index 21b5f127f8a..7f1f17429e8 100644 --- a/chromium/third_party/blink/renderer/platform/audio/down_sampler.h +++ b/chromium/third_party/blink/renderer/platform/audio/down_sampler.h @@ -32,7 +32,7 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_DOWN_SAMPLER_H_ #include "third_party/blink/renderer/platform/audio/audio_array.h" -#include "third_party/blink/renderer/platform/audio/direct_convolver.h" +#include "third_party/blink/renderer/platform/audio/simple_fft_convolver.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/noncopyable.h" @@ -62,8 +62,8 @@ class PLATFORM_EXPORT DownSampler { size_t input_block_size_; - // Half-band filter. - DirectConvolver convolver_; + // Half-band filter. SimpleFFTConvolver is always faster than DirectConvolver. + SimpleFFTConvolver convolver_; AudioFloatArray temp_buffer_; diff --git a/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc b/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc index 94ad47bd512..34a85f0e77e 100644 --- a/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc +++ b/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc @@ -297,7 +297,7 @@ void DynamicsCompressorKernel::Process( float desired_gain = detector_average_; // Pre-warp so we get desiredGain after sin() warp below. - float scaled_desired_gain = asinf(desired_gain) / (piOverTwoFloat); + float scaled_desired_gain = asinf(desired_gain) / kPiOverTwoFloat; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Deal with envelopes @@ -440,7 +440,7 @@ void DynamicsCompressorKernel::Process( // Warp pre-compression gain to smooth out sharp exponential transition // points. float post_warp_compressor_gain = - sinf(piOverTwoFloat * compressor_gain); + sinf(kPiOverTwoFloat * compressor_gain); // Calculate total gain using master gain and effect blend. float total_gain = diff --git a/chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc b/chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc index c6a80d72e91..a87f17b0021 100644 --- a/chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc +++ b/chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc @@ -101,8 +101,8 @@ void EqualPowerPanner::Pan(double azimuth, } } - desired_gain_l = std::cos(piOverTwoDouble * desired_pan_position); - desired_gain_r = std::sin(piOverTwoDouble * desired_pan_position); + desired_gain_l = std::cos(kPiOverTwoDouble * desired_pan_position); + desired_gain_r = std::sin(kPiOverTwoDouble * desired_pan_position); int n = frames_to_process; @@ -170,8 +170,8 @@ void EqualPowerPanner::CalculateDesiredGain(double& desired_gain_l, } } - desired_gain_l = std::cos(piOverTwoDouble * desired_pan_position); - desired_gain_r = std::sin(piOverTwoDouble * desired_pan_position); + desired_gain_l = std::cos(kPiOverTwoDouble * desired_pan_position); + desired_gain_r = std::sin(kPiOverTwoDouble * desired_pan_position); } void EqualPowerPanner::PanWithSampleAccurateValues( diff --git a/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc b/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc index bde6baf4aa4..55c658a54ff 100644 --- a/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc +++ b/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc @@ -139,32 +139,35 @@ void FFTFrame::InterpolateFrequencyComponents(const FFTFrame& frame1, last_phase2 = phase2; // Unwrap phase deltas - if (delta_phase1 > piDouble) - delta_phase1 -= twoPiDouble; - if (delta_phase1 < -piDouble) - delta_phase1 += twoPiDouble; - if (delta_phase2 > piDouble) - delta_phase2 -= twoPiDouble; - if (delta_phase2 < -piDouble) - delta_phase2 += twoPiDouble; + if (delta_phase1 > kPiDouble) + delta_phase1 -= kTwoPiDouble; + if (delta_phase1 < -kPiDouble) + delta_phase1 += kTwoPiDouble; + if (delta_phase2 > kPiDouble) + delta_phase2 -= kTwoPiDouble; + if (delta_phase2 < -kPiDouble) + delta_phase2 += kTwoPiDouble; // Blend group-delays double delta_phase_blend; - if (delta_phase1 - delta_phase2 > piDouble) - delta_phase_blend = s1 * delta_phase1 + s2 * (twoPiDouble + delta_phase2); - else if (delta_phase2 - delta_phase1 > piDouble) - delta_phase_blend = s1 * (twoPiDouble + delta_phase1) + s2 * delta_phase2; - else + if (delta_phase1 - delta_phase2 > kPiDouble) { + delta_phase_blend = + s1 * delta_phase1 + s2 * (kTwoPiDouble + delta_phase2); + } else if (delta_phase2 - delta_phase1 > kPiDouble) { + delta_phase_blend = + s1 * (kTwoPiDouble + delta_phase1) + s2 * delta_phase2; + } else { delta_phase_blend = s1 * delta_phase1 + s2 * delta_phase2; + } phase_accum += delta_phase_blend; // Unwrap - if (phase_accum > piDouble) - phase_accum -= twoPiDouble; - if (phase_accum < -piDouble) - phase_accum += twoPiDouble; + if (phase_accum > kPiDouble) + phase_accum -= kTwoPiDouble; + if (phase_accum < -kPiDouble) + phase_accum += kTwoPiDouble; std::complex<double> c = std::polar(mag, phase_accum); @@ -184,7 +187,7 @@ double FFTFrame::ExtractAverageGroupDelay() { int half_size = FftSize() / 2; const double sample_phase_delay = - (twoPiDouble) / static_cast<double>(FftSize()); + kTwoPiDouble / static_cast<double>(FftSize()); // Calculate weighted average group delay for (int i = 0; i < half_size; i++) { @@ -196,10 +199,10 @@ double FFTFrame::ExtractAverageGroupDelay() { last_phase = phase; // Unwrap - if (delta_phase < -piDouble) - delta_phase += twoPiDouble; - if (delta_phase > piDouble) - delta_phase -= twoPiDouble; + if (delta_phase < -kPiDouble) + delta_phase += kTwoPiDouble; + if (delta_phase > kPiDouble) + delta_phase -= kTwoPiDouble; ave_sum += mag * delta_phase; weight_sum += mag; @@ -230,7 +233,7 @@ void FFTFrame::AddConstantGroupDelay(double sample_frame_delay) { float* imag_p = ImagData(); const double sample_phase_delay = - (twoPiDouble) / static_cast<double>(FftSize()); + kTwoPiDouble / static_cast<double>(FftSize()); double phase_adj = -sample_frame_delay * sample_phase_delay; diff --git a/chromium/third_party/blink/renderer/platform/audio/iir_filter.cc b/chromium/third_party/blink/renderer/platform/audio/iir_filter.cc index 6ce33eb6cb9..b9e435eeea2 100644 --- a/chromium/third_party/blink/renderer/platform/audio/iir_filter.cc +++ b/chromium/third_party/blink/renderer/platform/audio/iir_filter.cc @@ -135,7 +135,7 @@ void IIRFilter::GetFrequencyResponse(int n_frequencies, phase_response[k] = std::nanf(""); } else { // zRecip = 1/z = exp(-j*frequency) - double omega = -piDouble * frequency[k]; + double omega = -kPiDouble * frequency[k]; std::complex<double> z_recip = std::complex<double>(cos(omega), sin(omega)); diff --git a/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.cc b/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.cc new file mode 100644 index 00000000000..eefe344a9b7 --- /dev/null +++ b/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.cc @@ -0,0 +1,61 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/audio/simple_fft_convolver.h" +#include "third_party/blink/renderer/platform/audio/vector_math.h" + +namespace blink { + +SimpleFFTConvolver::SimpleFFTConvolver( + size_t input_block_size, + const std::unique_ptr<AudioFloatArray>& convolution_kernel) + : convolution_kernel_size_(convolution_kernel->size()), + fft_kernel_(2 * input_block_size), + frame_(2 * input_block_size), + input_buffer_(2 * + input_block_size), // 2nd half of buffer is always zeroed + output_buffer_(2 * input_block_size), + last_overlap_buffer_(input_block_size) { + DCHECK_LE(convolution_kernel_size_, FftSize() / 2); + // Do padded FFT to get frequency-domain version of the convolution kernel. + // This FFT and caching is done once in here so that it does not have to be + // done repeatedly in |Process|. + fft_kernel_.DoPaddedFFT(convolution_kernel->Data(), convolution_kernel_size_); +} + +void SimpleFFTConvolver::Process(const float* source_p, + float* dest_p, + size_t frames_to_process) { + size_t half_size = FftSize() / 2; + + // frames_to_process must be exactly half_size. + DCHECK(source_p); + DCHECK(dest_p); + DCHECK_EQ(frames_to_process, half_size); + if (!(source_p && dest_p && frames_to_process == half_size)) + return; + + // Do padded FFT (get frequency-domain version) by copying samples to the 1st + // half of the input buffer (the second half is always zero), multiply in + // frequency-domain and do inverse FFT to get output samples. + input_buffer_.CopyToRange(source_p, 0, half_size); + frame_.DoFFT(input_buffer_.Data()); + frame_.Multiply(fft_kernel_); + frame_.DoInverseFFT(output_buffer_.Data()); + + // Overlap-add 1st half with 2nd half from previous time and write + // to destination. + VectorMath::Vadd(output_buffer_.Data(), 1, last_overlap_buffer_.Data(), 1, + dest_p, 1, half_size); + + // Finally, save 2nd half for the next time. + last_overlap_buffer_.CopyToRange(output_buffer_.Data() + half_size, 0, + half_size); +} + +void SimpleFFTConvolver::Reset() { + last_overlap_buffer_.Zero(); +} + +} // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.h b/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.h new file mode 100644 index 00000000000..571ac9e0f5e --- /dev/null +++ b/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.h @@ -0,0 +1,58 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_SIMPLE_FFT_CONVOLVER_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_SIMPLE_FFT_CONVOLVER_H_ + +#include <memory> + +#include "third_party/blink/renderer/platform/audio/audio_array.h" +#include "third_party/blink/renderer/platform/audio/fft_frame.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" +#include "third_party/blink/renderer/platform/wtf/noncopyable.h" + +namespace blink { + +// The SimpleFFTConvolver does an FFT convolution. It differs from +// the FFTConvolver in that it restricts the maximum size of +// |convolution_kernel| to |input_block_size|. This restriction allows it to do +// an FFT on every Process call. Therefore, the processing delay of +// the SimpleFFTConvolver is the same as that of the DirectConvolver and thus +// smaller than that of the FFTConvolver. +class PLATFORM_EXPORT SimpleFFTConvolver { + USING_FAST_MALLOC(SimpleFFTConvolver); + WTF_MAKE_NONCOPYABLE(SimpleFFTConvolver); + + public: + SimpleFFTConvolver( + size_t input_block_size, + const std::unique_ptr<AudioFloatArray>& convolution_kernel); + + void Process(const float* source_p, float* dest_p, size_t frames_to_process); + + void Reset(); + + size_t ConvolutionKernelSize() const { return convolution_kernel_size_; } + + private: + size_t FftSize() const { return frame_.FftSize(); } + + size_t convolution_kernel_size_; + FFTFrame fft_kernel_; + FFTFrame frame_; + + // Buffer input until we get fftSize / 2 samples then do an FFT + AudioFloatArray input_buffer_; + + // Stores output which we read a little at a time + AudioFloatArray output_buffer_; + + // Saves the 2nd half of the FFT buffer, so we can do an overlap-add with the + // 1st half of the next one + AudioFloatArray last_overlap_buffer_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_SIMPLE_FFT_CONVOLVER_H_ diff --git a/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.cc b/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.cc index 79a1681ef2e..c949fa60bce 100644 --- a/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.cc +++ b/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.cc @@ -117,14 +117,14 @@ void SincResampler::InitializeKernel() { for (int i = 0; i < n; ++i) { // Compute the sinc() with offset. double s = - sinc_scale_factor * piDouble * (i - half_size - subsample_offset); + sinc_scale_factor * kPiDouble * (i - half_size - subsample_offset); double sinc = !s ? 1.0 : std::sin(s) / s; sinc *= sinc_scale_factor; // Compute Blackman window, matching the offset of the sinc(). double x = (i - subsample_offset) / n; - double window = a0 - a1 * std::cos(twoPiDouble * x) + - a2 * std::cos(twoPiDouble * 2.0 * x); + double window = a0 - a1 * std::cos(kTwoPiDouble * x) + + a2 * std::cos(kTwoPiDouble * 2.0 * x); // Window the sinc() function and store at the correct offset. kernel_storage_[i + offset_index * kernel_size_] = sinc * window; diff --git a/chromium/third_party/blink/renderer/platform/audio/stereo_panner.cc b/chromium/third_party/blink/renderer/platform/audio/stereo_panner.cc index 6c911eba328..d375cd24adb 100644 --- a/chromium/third_party/blink/renderer/platform/audio/stereo_panner.cc +++ b/chromium/third_party/blink/renderer/platform/audio/stereo_panner.cc @@ -63,7 +63,7 @@ void StereoPanner::PanWithSampleAccurateValues(const AudioBus* input_bus, float input_l = *source_l++; double pan = clampTo(*pan_values++, -1.0, 1.0); // Pan from left to right [-1; 1] will be normalized as [0; 1]. - pan_radian = (pan * 0.5 + 0.5) * piOverTwoDouble; + pan_radian = (pan * 0.5 + 0.5) * kPiOverTwoDouble; gain_l = std::cos(pan_radian); gain_r = std::sin(pan_radian); *destination_l++ = static_cast<float>(input_l * gain_l); @@ -75,7 +75,7 @@ void StereoPanner::PanWithSampleAccurateValues(const AudioBus* input_bus, float input_r = *source_r++; double pan = clampTo(*pan_values++, -1.0, 1.0); // Normalize [-1; 0] to [0; 1]. Do nothing when [0; 1]. - pan_radian = (pan <= 0 ? pan + 1 : pan) * piOverTwoDouble; + pan_radian = (pan <= 0 ? pan + 1 : pan) * kPiOverTwoDouble; gain_l = std::cos(pan_radian); gain_r = std::sin(pan_radian); if (pan <= 0) { @@ -126,7 +126,7 @@ void StereoPanner::PanToTargetValue(const AudioBus* input_bus, if (number_of_input_channels == 1) { // For mono source case. // Pan from left to right [-1; 1] will be normalized as [0; 1]. - double pan_radian = (target_pan * 0.5 + 0.5) * piOverTwoDouble; + double pan_radian = (target_pan * 0.5 + 0.5) * kPiOverTwoDouble; double gain_l = std::cos(pan_radian); double gain_r = std::sin(pan_radian); @@ -141,7 +141,7 @@ void StereoPanner::PanToTargetValue(const AudioBus* input_bus, // Normalize [-1; 0] to [0; 1] for the left pan position (<= 0), and // do nothing when [0; 1]. double pan_radian = - (target_pan <= 0 ? target_pan + 1 : target_pan) * piOverTwoDouble; + (target_pan <= 0 ? target_pan + 1 : target_pan) * kPiOverTwoDouble; double gain_l = std::cos(pan_radian); double gain_r = std::sin(pan_radian); diff --git a/chromium/third_party/blink/renderer/platform/audio/up_sampler.cc b/chromium/third_party/blink/renderer/platform/audio/up_sampler.cc index 62eae93248d..99bdf05257d 100644 --- a/chromium/third_party/blink/renderer/platform/audio/up_sampler.cc +++ b/chromium/third_party/blink/renderer/platform/audio/up_sampler.cc @@ -57,13 +57,13 @@ std::unique_ptr<AudioFloatArray> MakeKernel(size_t size) { for (int i = 0; i < n; ++i) { // Compute the sinc() with offset. - double s = piDouble * (i - half_size - subsample_offset); + double s = kPiDouble * (i - half_size - subsample_offset); double sinc = !s ? 1.0 : sin(s) / s; // Compute Blackman window, matching the offset of the sinc(). double x = (i - subsample_offset) / n; double window = - a0 - a1 * cos(twoPiDouble * x) + a2 * cos(twoPiDouble * 2.0 * x); + a0 - a1 * cos(kTwoPiDouble * x) + a2 * cos(kTwoPiDouble * 2.0 * x); // Window the sinc() function. (*kernel)[i] = sinc * window; @@ -76,13 +76,30 @@ std::unique_ptr<AudioFloatArray> MakeKernel(size_t size) { UpSampler::UpSampler(size_t input_block_size) : input_block_size_(input_block_size), - convolver_(input_block_size, MakeKernel(kDefaultKernelSize)), temp_buffer_(input_block_size), - input_buffer_(input_block_size * 2) {} + input_buffer_(input_block_size * 2) { + std::unique_ptr<AudioFloatArray> convolution_kernel = + MakeKernel(kDefaultKernelSize); + if (input_block_size_ <= 128) { + // If the input block size is small enough, use direct convolution because + // it is faster than FFT convolution for such input block sizes. + direct_convolver_ = std::make_unique<DirectConvolver>( + input_block_size_, std::move(convolution_kernel)); + } else { + // Otherwise, use FFT convolution because it is faster than direct + // convolution for large input block sizes. + simple_fft_convolver_ = std::make_unique<SimpleFFTConvolver>( + input_block_size_, std::move(convolution_kernel)); + } +} void UpSampler::Process(const float* source_p, float* dest_p, size_t source_frames_to_process) { + const size_t convolution_kernel_size = + direct_convolver_ ? direct_convolver_->ConvolutionKernelSize() + : simple_fft_convolver_->ConvolutionKernelSize(); + bool is_input_block_size_good = source_frames_to_process == input_block_size_; DCHECK(is_input_block_size_good); if (!is_input_block_size_good) @@ -93,13 +110,7 @@ void UpSampler::Process(const float* source_p, if (!is_temp_buffer_good) return; - bool is_kernel_good = - convolver_.ConvolutionKernelSize() == kDefaultKernelSize; - DCHECK(is_kernel_good); - if (!is_kernel_good) - return; - - size_t half_size = convolver_.ConvolutionKernelSize() / 2; + size_t half_size = convolution_kernel_size / 2; // Copy source samples to 2nd half of input buffer. bool is_input_buffer_good = @@ -119,7 +130,13 @@ void UpSampler::Process(const float* source_p, // Compute odd sample-frames 1,3,5,7... float* odd_samples_p = temp_buffer_.Data(); - convolver_.Process(source_p, odd_samples_p, source_frames_to_process); + if (direct_convolver_) { + direct_convolver_->Process(source_p, odd_samples_p, + source_frames_to_process); + } else { + simple_fft_convolver_->Process(source_p, odd_samples_p, + source_frames_to_process); + } for (unsigned i = 0; i < source_frames_to_process; ++i) dest_p[i * 2 + 1] = odd_samples_p[i]; @@ -130,14 +147,18 @@ void UpSampler::Process(const float* source_p, } void UpSampler::Reset() { - convolver_.Reset(); + direct_convolver_.reset(); + simple_fft_convolver_.reset(); input_buffer_.Zero(); } size_t UpSampler::LatencyFrames() const { + const size_t convolution_kernel_size = + direct_convolver_ ? direct_convolver_->ConvolutionKernelSize() + : simple_fft_convolver_->ConvolutionKernelSize(); // Divide by two since this is a linear phase kernel and the delay is at the // center of the kernel. - return convolver_.ConvolutionKernelSize() / 2; + return convolution_kernel_size / 2; } } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/audio/up_sampler.h b/chromium/third_party/blink/renderer/platform/audio/up_sampler.h index 69000eeb843..e76a8d84ecc 100644 --- a/chromium/third_party/blink/renderer/platform/audio/up_sampler.h +++ b/chromium/third_party/blink/renderer/platform/audio/up_sampler.h @@ -31,8 +31,11 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_UP_SAMPLER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_UP_SAMPLER_H_ +#include <memory> + #include "third_party/blink/renderer/platform/audio/audio_array.h" #include "third_party/blink/renderer/platform/audio/direct_convolver.h" +#include "third_party/blink/renderer/platform/audio/simple_fft_convolver.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/noncopyable.h" @@ -63,7 +66,8 @@ class PLATFORM_EXPORT UpSampler { size_t input_block_size_; // Computes the odd sample-frames of the output. - DirectConvolver convolver_; + std::unique_ptr<DirectConvolver> direct_convolver_; + std::unique_ptr<SimpleFFTConvolver> simple_fft_convolver_; AudioFloatArray temp_buffer_; diff --git a/chromium/third_party/blink/renderer/platform/audio/vector_math.cc b/chromium/third_party/blink/renderer/platform/audio/vector_math.cc index 388fecddd00..af76fad0b2b 100644 --- a/chromium/third_party/blink/renderer/platform/audio/vector_math.cc +++ b/chromium/third_party/blink/renderer/platform/audio/vector_math.cc @@ -38,7 +38,7 @@ #elif HAVE_MIPS_MSA_INTRINSICS #include "third_party/blink/renderer/platform/audio/cpu/mips/vector_math_msa.h" #elif defined(ARCH_CPU_X86_FAMILY) -#include "third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x8_6.h" +#include "third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x86.h" #else #include "third_party/blink/renderer/platform/audio/vector_math_scalar.h" #endif |