chromium/media/filters/audio_renderer_algorithm.cc

// Copyright 2012 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/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "media/filters/audio_renderer_algorithm.h"

#include <algorithm>
#include <cmath>

#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "cc/base/math_util.h"
#include "media/base/audio_bus.h"
#include "media/base/audio_timestamp_helper.h"
#include "media/base/limits.h"
#include "media/base/media_switches.h"
#include "media/filters/wsola_internals.h"

namespace media {

// Waveform Similarity Overlap-and-add (WSOLA).
//
// One WSOLA iteration
//
// 1) Extract |target_block_| as input frames at indices
//    [|target_block_index_|, |target_block_index_| + |ola_window_size_|).
//    Note that |target_block_| is the "natural" continuation of the output.
//
// 2) Extract |search_block_| as input frames at indices
//    [|search_block_index_|,
//     |search_block_index_| + |num_candidate_blocks_| + |ola_window_size_|).
//
// 3) Find a block within the |search_block_| that is most similar
//    to |target_block_|. Let |optimal_index| be the index of such block and
//    write it to |optimal_block_|.
//
// 4) Update:
//    |optimal_block_| = |transition_window_| * |target_block_| +
//    (1 - |transition_window_|) * |optimal_block_|.
//
// 5) Overlap-and-add |optimal_block_| to the |wsola_output_|.
//
// 6) Update:
//    |target_block_| = |optimal_index| + |ola_window_size_| / 2.
//    |output_index_| = |output_index_| + |ola_window_size_| / 2,
//    |search_block_center_index| = |output_index_| * |playback_rate|, and
//    |search_block_index_| = |search_block_center_index| -
//        |search_block_center_offset_|.

// Overlap-and-add window size in milliseconds.
constexpr base::TimeDelta kOlaWindowSize =;

// Size of search interval in milliseconds. The search interval is
// [-delta delta] around |output_index_| * |playback_rate|. So the search
// interval is 2 * delta.
constexpr base::TimeDelta kWsolaSearchInterval =;

// The maximum size for the |audio_buffer_|. Arbitrarily determined.
constexpr base::TimeDelta kMaxCapacity =;

// The minimum size for the |audio_buffer_|. Arbitrarily determined.
constexpr base::TimeDelta kStartingCapacity =;

// The minimum size for the |audio_buffer_| for encrypted streams.
// Set this to be larger than |kStartingCapacity| because the performance of
// encrypted playback is always worse than clear playback, due to decryption and
// potentially IPC overhead. For the context, see https://crbug.com/403462,
// https://crbug.com/718161 and https://crbug.com/879970.
constexpr base::TimeDelta kMinStartingCapacityForEncrypted =;

AudioRendererAlgorithm::AudioRendererAlgorithm(MediaLog* media_log)
    :{}

AudioRendererAlgorithm::AudioRendererAlgorithm(
    MediaLog* media_log,
    AudioRendererAlgorithmParameters params)
    :{}

AudioRendererAlgorithm::~AudioRendererAlgorithm() = default;

void AudioRendererAlgorithm::Initialize(const AudioParameters& params,
                                        bool is_encrypted) {}

void AudioRendererAlgorithm::SetChannelMask(std::vector<bool> channel_mask) {}

void AudioRendererAlgorithm::OnResamplerRead(int frame_delay,
                                             AudioBus* audio_bus) {}

void AudioRendererAlgorithm::MarkEndOfStream() {}

int AudioRendererAlgorithm::ResampleAndFill(AudioBus* dest,
                                            int dest_offset,
                                            int requested_frames,
                                            double playback_rate) {}

int AudioRendererAlgorithm::RunWsolaAndFill(AudioBus* dest,
                                            int dest_offset,
                                            int requested_frames,
                                            double playback_rate) {}

int AudioRendererAlgorithm::FillBuffer(AudioBus* dest,
                                       int dest_offset,
                                       int requested_frames,
                                       double playback_rate) {}

AudioRendererAlgorithm::FillBufferMode AudioRendererAlgorithm::ChooseBufferMode(
    double playback_rate) {}

void AudioRendererAlgorithm::SetFillBufferMode(FillBufferMode mode) {}

void AudioRendererAlgorithm::FlushBuffers() {}

void AudioRendererAlgorithm::EnqueueBuffer(
    scoped_refptr<AudioBuffer> buffer_in) {}

void AudioRendererAlgorithm::SetLatencyHint(
    std::optional<base::TimeDelta> latency_hint) {}

bool AudioRendererAlgorithm::IsQueueAdequateForPlayback() {}

bool AudioRendererAlgorithm::IsQueueFull() {}

void AudioRendererAlgorithm::IncreasePlaybackThreshold() {}

int64_t AudioRendererAlgorithm::GetMemoryUsage() const {}

int AudioRendererAlgorithm::BufferedFrames() const {}

double AudioRendererAlgorithm::DelayInFrames(double playback_rate) const {}

std::optional<base::TimeDelta> AudioRendererAlgorithm::FrontTimestamp() const {}

bool AudioRendererAlgorithm::CanPerformWsola() const {}

bool AudioRendererAlgorithm::RunOneWsolaIteration(double playback_rate) {}

void AudioRendererAlgorithm::UpdateOutputTime(double playback_rate,
                                              double time_change) {}

void AudioRendererAlgorithm::RemoveOldInputFrames(double playback_rate) {}

int AudioRendererAlgorithm::WriteCompletedFramesTo(
    int requested_frames, int dest_offset, AudioBus* dest) {}

bool AudioRendererAlgorithm::TargetIsWithinSearchRegion() const {}

void AudioRendererAlgorithm::GetOptimalBlock() {}

void AudioRendererAlgorithm::PeekAudioWithZeroPrepend(
    int read_offset_frames, AudioBus* dest) {}

void AudioRendererAlgorithm::CreateSearchWrappers() {}

void AudioRendererAlgorithm::SetPreservesPitch(bool preserves_pitch) {}

}  // namespace media