#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "third_party/blink/renderer/modules/webaudio/periodic_wave.h"
#include <algorithm>
#include <memory>
#include "build/build_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_periodic_wave_options.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
#include "third_party/blink/renderer/modules/webaudio/oscillator_node.h"
#include "third_party/blink/renderer/platform/audio/fft_frame.h"
#include "third_party/blink/renderer/platform/audio/vector_math.h"
#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#if defined(ARCH_CPU_X86_FAMILY)
#include <xmmintrin.h>
#elif defined(CPU_ARM_NEON)
#include <arm_neon.h>
#endif
namespace blink {
namespace {
constexpr unsigned kNumberOfOctaveBands = …;
constexpr unsigned kMaxPeriodicWaveSize = …;
constexpr float kCentsPerRange = …;
}
PeriodicWave* PeriodicWave::Create(BaseAudioContext& context,
const Vector<float>& real,
const Vector<float>& imag,
bool disable_normalization,
ExceptionState& exception_state) { … }
PeriodicWave* PeriodicWave::Create(BaseAudioContext* context,
const PeriodicWaveOptions* options,
ExceptionState& exception_state) { … }
PeriodicWave* PeriodicWave::CreateSine(float sample_rate) { … }
PeriodicWave* PeriodicWave::CreateSquare(float sample_rate) { … }
PeriodicWave* PeriodicWave::CreateSawtooth(float sample_rate) { … }
PeriodicWave* PeriodicWave::CreateTriangle(float sample_rate) { … }
PeriodicWave::PeriodicWave(float sample_rate)
: … { … }
void PeriodicWave::Trace(Visitor* visitor) const { … }
PeriodicWaveImpl::PeriodicWaveImpl(float sample_rate)
: … { … }
PeriodicWaveImpl::~PeriodicWaveImpl() { … }
unsigned PeriodicWaveImpl::PeriodicWaveSize() const { … }
unsigned PeriodicWaveImpl::MaxNumberOfPartials() const { … }
void PeriodicWaveImpl::WaveDataForFundamentalFrequency(
float fundamental_frequency,
float*& lower_wave_data,
float*& higher_wave_data,
float& table_interpolation_factor) { … }
#if defined(ARCH_CPU_X86_FAMILY)
void PeriodicWaveImpl::WaveDataForFundamentalFrequency(
const float fundamental_frequency[4],
float* lower_wave_data[4],
float* higher_wave_data[4],
float table_interpolation_factor[4]) { … }
#elif defined(CPU_ARM_NEON)
void PeriodicWaveImpl::WaveDataForFundamentalFrequency(
const float fundamental_frequency[4],
float* lower_wave_data[4],
float* higher_wave_data[4],
float table_interpolation_factor[4]) {
float32x4_t frequency = vabsq_f32(vld1q_f32(fundamental_frequency));
uint32x4_t pos = vcgtq_f32(frequency, vdupq_n_f32(0));
float32x4_t v_ratio =
vmulq_f32(frequency, vdupq_n_f32(1 / lowest_fundamental_frequency_));
v_ratio = vbslq_f32(pos, v_ratio, vdupq_n_f32(0.5));
float ratio[4] __attribute__((aligned(16)));
vst1q_f32(ratio, v_ratio);
float cents_above_lowest_frequency[4] __attribute__((aligned(16)));
for (int k = 0; k < 4; ++k) {
cents_above_lowest_frequency[k] = log2f(ratio[k]) * 1200;
}
float32x4_t v_pitch_range = vaddq_f32(
vdupq_n_f32(1.0), vmulq_f32(vld1q_f32(cents_above_lowest_frequency),
vdupq_n_f32(1 / cents_per_range_)));
v_pitch_range = vmaxq_f32(v_pitch_range, vdupq_n_f32(0));
v_pitch_range = vminq_f32(v_pitch_range, vdupq_n_f32(NumberOfRanges() - 1));
const uint32x4_t v_index1 = vcvtq_u32_f32(v_pitch_range);
uint32x4_t v_index2 = vaddq_u32(v_index1, vdupq_n_u32(1));
v_index2 = vminq_u32(v_index2, vdupq_n_u32(NumberOfRanges() - 1));
uint32_t range_index1[4] __attribute__((aligned(16)));
uint32_t range_index2[4] __attribute__((aligned(16)));
vst1q_u32(range_index1, v_index1);
vst1q_u32(range_index2, v_index2);
const float32x4_t table_factor =
vsubq_f32(v_pitch_range, vcvtq_f32_u32(v_index1));
vst1q_f32(table_interpolation_factor, table_factor);
for (int k = 0; k < 4; ++k) {
lower_wave_data[k] = band_limited_tables_[range_index2[k]]->Data();
higher_wave_data[k] = band_limited_tables_[range_index1[k]]->Data();
}
}
#else
void PeriodicWaveImpl::WaveDataForFundamentalFrequency(
const float fundamental_frequency[4],
float* lower_wave_data[4],
float* higher_wave_data[4],
float table_interpolation_factor[4]) {
for (int k = 0; k < 4; ++k) {
WaveDataForFundamentalFrequency(fundamental_frequency[k],
lower_wave_data[k], higher_wave_data[k],
table_interpolation_factor[k]);
}
}
#endif
unsigned PeriodicWaveImpl::NumberOfPartialsForRange(
unsigned range_index) const { … }
void PeriodicWaveImpl::AdjustV8ExternalMemory(int64_t delta) { … }
void PeriodicWaveImpl::CreateBandLimitedTables(const float* real_data,
const float* imag_data,
unsigned number_of_components,
bool disable_normalization) { … }
void PeriodicWaveImpl::GenerateBasicWaveform(int shape) { … }
}