chromium/third_party/blink/renderer/modules/webaudio/oscillator_handler.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "third_party/blink/renderer/modules/webaudio/oscillator_handler.h"

#include <algorithm>
#include <limits>

#include "base/synchronization/lock.h"
#include "base/trace_event/typed_macros.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/modules/webaudio/audio_graph_tracer.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/oscillator_node.h"
#include "third_party/blink/renderer/modules/webaudio/periodic_wave.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
#include "third_party/blink/renderer/platform/audio/vector_math.h"
#include "third_party/blink/renderer/platform/bindings/enumeration_base.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"

namespace blink {

namespace {

// An oscillator is always mono.
constexpr unsigned kNumberOfOutputChannels =;

// Convert the detune value (in cents) to a frequency scale multiplier:
// 2^(d/1200)
float DetuneToFrequencyMultiplier(float detune_value) {}

// Clamp the frequency value to lie with Nyquist frequency. For NaN, arbitrarily
// clamp to +Nyquist.
void ClampFrequency(float* frequency, int frames_to_process, float nyquist) {}

float DoInterpolation(double virtual_read_index,
                      float incr,
                      unsigned read_index_mask,
                      float table_interpolation_factor,
                      const float* lower_wave_data,
                      const float* higher_wave_data) {}

}  // namespace

OscillatorHandler::OscillatorHandler(AudioNode& node,
                                     float sample_rate,
                                     const String& oscillator_type,
                                     PeriodicWaveImpl* wave_table,
                                     AudioParamHandler& frequency,
                                     AudioParamHandler& detune)
    :{}

scoped_refptr<OscillatorHandler> OscillatorHandler::Create(
    AudioNode& node,
    float sample_rate,
    const String& oscillator_type,
    PeriodicWaveImpl* wave_table,
    AudioParamHandler& frequency,
    AudioParamHandler& detune) {}

OscillatorHandler::~OscillatorHandler() {}

String OscillatorHandler::GetType() const {}

void OscillatorHandler::SetType(const String& type,
                                ExceptionState& exception_state) {}

bool OscillatorHandler::SetType(uint8_t type) {}

bool OscillatorHandler::CalculateSampleAccuratePhaseIncrements(
    uint32_t frames_to_process) {}

#if !(defined(ARCH_CPU_X86_FAMILY) || defined(CPU_ARM_NEON))
// Vector operations not supported, so there's nothing to do except return 0 and
// virtual_read_index.  The scalar version will do the necessary processing.
std::tuple<int, double> OscillatorHandler::ProcessKRateVector(
    int n,
    float* dest_p,
    double virtual_read_index,
    float frequency,
    float rate_scale) const {
  DCHECK_GE(frequency * rate_scale, kInterpolate2Point);
  return std::make_tuple(0, virtual_read_index);
}
#endif

#if !(defined(ARCH_CPU_X86_FAMILY) || defined(CPU_ARM_NEON))
double OscillatorHandler::ProcessARateVectorKernel(
    float* dest_p,
    double virtual_read_index,
    const float* phase_increments,
    unsigned periodic_wave_size,
    const float* const lower_wave_data[4],
    const float* const higher_wave_data[4],
    const float table_interpolation_factor[4]) const {
  double inv_periodic_wave_size = 1.0 / periodic_wave_size;
  unsigned read_index_mask = periodic_wave_size - 1;

  for (int m = 0; m < 4; ++m) {
    unsigned read_index_0 = static_cast<unsigned>(virtual_read_index);

    // Increment is fairly large, so we're doing no more than about 3
    // points between each wave table entry. Assume linear
    // interpolation between points is good enough.
    unsigned read_index2 = read_index_0 + 1;

    // Contain within valid range.
    read_index_0 = read_index_0 & read_index_mask;
    read_index2 = read_index2 & read_index_mask;

    float sample1_lower = lower_wave_data[m][read_index_0];
    float sample2_lower = lower_wave_data[m][read_index2];
    float sample1_higher = higher_wave_data[m][read_index_0];
    float sample2_higher = higher_wave_data[m][read_index2];

    // Linearly interpolate within each table (lower and higher).
    double interpolation_factor =
        static_cast<float>(virtual_read_index) - read_index_0;
    // Doing linear interpolation via x0 + f*(x1-x0) gives slightly
    // different results from (1-f)*x0 + f*x1, but requires fewer
    // operations.  This causes a very slight decrease in SNR (< 0.05 dB) in
    // oscillator sweep tests.
    float sample_higher =
        sample1_higher +
        interpolation_factor * (sample2_higher - sample1_higher);
    float sample_lower =
        sample1_lower + interpolation_factor * (sample2_lower - sample1_lower);

    // Then interpolate between the two tables.
    float sample = sample_higher + table_interpolation_factor[m] *
                                       (sample_lower - sample_higher);

    dest_p[m] = sample;

    // Increment virtual read index and wrap virtualReadIndex into the range
    // 0 -> periodicWaveSize.
    virtual_read_index += phase_increments[m];
    virtual_read_index -=
        floor(virtual_read_index * inv_periodic_wave_size) * periodic_wave_size;
  }

  return virtual_read_index;
}
#endif

double OscillatorHandler::ProcessKRateScalar(int start,
                                             int n,
                                             float* dest_p,
                                             double virtual_read_index,
                                             float frequency,
                                             float rate_scale) const {}

double OscillatorHandler::ProcessKRate(int n,
                                       float* dest_p,
                                       double virtual_read_index) const {}

std::tuple<int, double> OscillatorHandler::ProcessARateVector(
    int n,
    float* destination,
    double virtual_read_index,
    const float* phase_increments) const {}

double OscillatorHandler::ProcessARateScalar(
    int k,
    int n,
    float* destination,
    double virtual_read_index,
    const float* phase_increments) const {}

double OscillatorHandler::ProcessARate(int n,
                                       float* destination,
                                       double virtual_read_index,
                                       float* phase_increments) const {}

void OscillatorHandler::Process(uint32_t frames_to_process) {}

void OscillatorHandler::SetPeriodicWave(PeriodicWaveImpl* periodic_wave) {}

bool OscillatorHandler::PropagatesSilence() const {}

base::WeakPtr<AudioScheduledSourceHandler> OscillatorHandler::AsWeakPtr() {}

void OscillatorHandler::HandleStoppableSourceNode() {}

}  // namespace blink