Update to current webrtc library

This is from the upstream library commit id
3326535126e435f1ba647885ce43a8f0f3d317eb, corresponding to Chromium
88.0.4290.1.
This commit is contained in:
Arun Raghavan
2020-10-12 18:08:02 -04:00
parent b1b02581d3
commit bcec8b0b21
859 changed files with 76187 additions and 49580 deletions

View File

@ -8,11 +8,11 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_COMMON_AUDIO_RESAMPLER_INCLUDE_PUSH_RESAMPLER_H_
#define WEBRTC_COMMON_AUDIO_RESAMPLER_INCLUDE_PUSH_RESAMPLER_H_
#ifndef COMMON_AUDIO_RESAMPLER_INCLUDE_PUSH_RESAMPLER_H_
#define COMMON_AUDIO_RESAMPLER_INCLUDE_PUSH_RESAMPLER_H_
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/typedefs.h"
#include <memory>
#include <vector>
namespace webrtc {
@ -28,25 +28,32 @@ class PushResampler {
// Must be called whenever the parameters change. Free to be called at any
// time as it is a no-op if parameters have not changed since the last call.
int InitializeIfNeeded(int src_sample_rate_hz, int dst_sample_rate_hz,
int num_channels);
int InitializeIfNeeded(int src_sample_rate_hz,
int dst_sample_rate_hz,
size_t num_channels);
// Returns the total number of samples provided in destination (e.g. 32 kHz,
// 2 channel audio gives 640 samples).
int Resample(const T* src, size_t src_length, T* dst, size_t dst_capacity);
private:
rtc::scoped_ptr<PushSincResampler> sinc_resampler_;
rtc::scoped_ptr<PushSincResampler> sinc_resampler_right_;
int src_sample_rate_hz_;
int dst_sample_rate_hz_;
int num_channels_;
rtc::scoped_ptr<T[]> src_left_;
rtc::scoped_ptr<T[]> src_right_;
rtc::scoped_ptr<T[]> dst_left_;
rtc::scoped_ptr<T[]> dst_right_;
};
size_t num_channels_;
// Vector that is needed to provide the proper inputs and outputs to the
// interleave/de-interleave methods used in Resample. This needs to be
// heap-allocated on the state to support an arbitrary number of channels
// without doing run-time heap-allocations in the Resample method.
std::vector<T*> channel_data_array_;
struct ChannelResampler {
std::unique_ptr<PushSincResampler> resampler;
std::vector<T> source;
std::vector<T> destination;
};
std::vector<ChannelResampler> channel_resamplers_;
};
} // namespace webrtc
#endif // WEBRTC_COMMON_AUDIO_RESAMPLER_INCLUDE_PUSH_RESAMPLER_H_
#endif // COMMON_AUDIO_RESAMPLER_INCLUDE_PUSH_RESAMPLER_H_

View File

@ -8,88 +8,92 @@
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* A wrapper for resampling a numerous amount of sampling combinations.
*/
#ifndef WEBRTC_RESAMPLER_RESAMPLER_H_
#define WEBRTC_RESAMPLER_RESAMPLER_H_
#ifndef COMMON_AUDIO_RESAMPLER_INCLUDE_RESAMPLER_H_
#define COMMON_AUDIO_RESAMPLER_INCLUDE_RESAMPLER_H_
#include <stddef.h>
#include "webrtc/typedefs.h"
#include <stdint.h>
namespace webrtc {
// All methods return 0 on success and -1 on failure.
class Resampler
{
class Resampler {
public:
Resampler();
Resampler(int inFreq, int outFreq, size_t num_channels);
~Resampler();
public:
Resampler();
Resampler(int inFreq, int outFreq, int num_channels);
~Resampler();
// Reset all states
int Reset(int inFreq, int outFreq, size_t num_channels);
// Reset all states
int Reset(int inFreq, int outFreq, int num_channels);
// Reset all states if any parameter has changed
int ResetIfNeeded(int inFreq, int outFreq, size_t num_channels);
// Reset all states if any parameter has changed
int ResetIfNeeded(int inFreq, int outFreq, int num_channels);
// Resample samplesIn to samplesOut.
int Push(const int16_t* samplesIn,
size_t lengthIn,
int16_t* samplesOut,
size_t maxLen,
size_t& outLen); // NOLINT: to avoid changing APIs
// Resample samplesIn to samplesOut.
int Push(const int16_t* samplesIn, size_t lengthIn, int16_t* samplesOut,
size_t maxLen, size_t &outLen);
private:
enum ResamplerMode {
kResamplerMode1To1,
kResamplerMode1To2,
kResamplerMode1To3,
kResamplerMode1To4,
kResamplerMode1To6,
kResamplerMode1To12,
kResamplerMode2To3,
kResamplerMode2To11,
kResamplerMode4To11,
kResamplerMode8To11,
kResamplerMode11To16,
kResamplerMode11To32,
kResamplerMode2To1,
kResamplerMode3To1,
kResamplerMode4To1,
kResamplerMode6To1,
kResamplerMode12To1,
kResamplerMode3To2,
kResamplerMode11To2,
kResamplerMode11To4,
kResamplerMode11To8
};
private:
enum ResamplerMode
{
kResamplerMode1To1,
kResamplerMode1To2,
kResamplerMode1To3,
kResamplerMode1To4,
kResamplerMode1To6,
kResamplerMode1To12,
kResamplerMode2To3,
kResamplerMode2To11,
kResamplerMode4To11,
kResamplerMode8To11,
kResamplerMode11To16,
kResamplerMode11To32,
kResamplerMode2To1,
kResamplerMode3To1,
kResamplerMode4To1,
kResamplerMode6To1,
kResamplerMode12To1,
kResamplerMode3To2,
kResamplerMode11To2,
kResamplerMode11To4,
kResamplerMode11To8
};
// Computes the resampler mode for a given sampling frequency pair.
// Returns -1 for unsupported frequency pairs.
static int ComputeResamplerMode(int in_freq_hz,
int out_freq_hz,
ResamplerMode* mode);
// Generic pointers since we don't know what states we'll need
void* state1_;
void* state2_;
void* state3_;
// Generic pointers since we don't know what states we'll need
void* state1_;
void* state2_;
void* state3_;
// Storage if needed
int16_t* in_buffer_;
int16_t* out_buffer_;
size_t in_buffer_size_;
size_t out_buffer_size_;
size_t in_buffer_size_max_;
size_t out_buffer_size_max_;
// Storage if needed
int16_t* in_buffer_;
int16_t* out_buffer_;
size_t in_buffer_size_;
size_t out_buffer_size_;
size_t in_buffer_size_max_;
size_t out_buffer_size_max_;
int my_in_frequency_khz_;
int my_out_frequency_khz_;
ResamplerMode my_mode_;
int num_channels_;
int my_in_frequency_khz_;
int my_out_frequency_khz_;
ResamplerMode my_mode_;
size_t num_channels_;
// Extra instance for stereo
Resampler* slave_left_;
Resampler* slave_right_;
// Extra instance for stereo
Resampler* helper_left_;
Resampler* helper_right_;
};
} // namespace webrtc
#endif // WEBRTC_RESAMPLER_RESAMPLER_H_
#endif // COMMON_AUDIO_RESAMPLER_INCLUDE_RESAMPLER_H_

View File

@ -8,40 +8,78 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/common_audio/resampler/include/push_resampler.h"
#include "common_audio/resampler/include/push_resampler.h"
#include <stdint.h>
#include <string.h>
#include "webrtc/common_audio/include/audio_util.h"
#include "webrtc/common_audio/resampler/include/resampler.h"
#include "webrtc/common_audio/resampler/push_sinc_resampler.h"
#include <memory>
#include "common_audio/include/audio_util.h"
#include "common_audio/resampler/push_sinc_resampler.h"
#include "rtc_base/checks.h"
namespace webrtc {
namespace {
// These checks were factored out into a non-templatized function
// due to problems with clang on Windows in debug builds.
// For some reason having the DCHECKs inline in the template code
// caused the compiler to generate code that threw off the linker.
// TODO(tommi): Re-enable when we've figured out what the problem is.
// http://crbug.com/615050
void CheckValidInitParams(int src_sample_rate_hz,
int dst_sample_rate_hz,
size_t num_channels) {
// The below checks are temporarily disabled on WEBRTC_WIN due to problems
// with clang debug builds.
#if !defined(WEBRTC_WIN) && defined(__clang__)
RTC_DCHECK_GT(src_sample_rate_hz, 0);
RTC_DCHECK_GT(dst_sample_rate_hz, 0);
RTC_DCHECK_GT(num_channels, 0);
#endif
}
void CheckExpectedBufferSizes(size_t src_length,
size_t dst_capacity,
size_t num_channels,
int src_sample_rate,
int dst_sample_rate) {
// The below checks are temporarily disabled on WEBRTC_WIN due to problems
// with clang debug builds.
// TODO(tommi): Re-enable when we've figured out what the problem is.
// http://crbug.com/615050
#if !defined(WEBRTC_WIN) && defined(__clang__)
const size_t src_size_10ms = src_sample_rate * num_channels / 100;
const size_t dst_size_10ms = dst_sample_rate * num_channels / 100;
RTC_DCHECK_EQ(src_length, src_size_10ms);
RTC_DCHECK_GE(dst_capacity, dst_size_10ms);
#endif
}
} // namespace
template <typename T>
PushResampler<T>::PushResampler()
: src_sample_rate_hz_(0),
dst_sample_rate_hz_(0),
num_channels_(0) {
}
: src_sample_rate_hz_(0), dst_sample_rate_hz_(0), num_channels_(0) {}
template <typename T>
PushResampler<T>::~PushResampler() {
}
PushResampler<T>::~PushResampler() {}
template <typename T>
int PushResampler<T>::InitializeIfNeeded(int src_sample_rate_hz,
int dst_sample_rate_hz,
int num_channels) {
size_t num_channels) {
CheckValidInitParams(src_sample_rate_hz, dst_sample_rate_hz, num_channels);
if (src_sample_rate_hz == src_sample_rate_hz_ &&
dst_sample_rate_hz == dst_sample_rate_hz_ &&
num_channels == num_channels_)
num_channels == num_channels_) {
// No-op if settings haven't changed.
return 0;
}
if (src_sample_rate_hz <= 0 || dst_sample_rate_hz <= 0 ||
num_channels <= 0 || num_channels > 2)
if (src_sample_rate_hz <= 0 || dst_sample_rate_hz <= 0 || num_channels <= 0) {
return -1;
}
src_sample_rate_hz_ = src_sample_rate_hz;
dst_sample_rate_hz_ = dst_sample_rate_hz;
@ -51,29 +89,28 @@ int PushResampler<T>::InitializeIfNeeded(int src_sample_rate_hz,
static_cast<size_t>(src_sample_rate_hz / 100);
const size_t dst_size_10ms_mono =
static_cast<size_t>(dst_sample_rate_hz / 100);
sinc_resampler_.reset(new PushSincResampler(src_size_10ms_mono,
dst_size_10ms_mono));
if (num_channels_ == 2) {
src_left_.reset(new T[src_size_10ms_mono]);
src_right_.reset(new T[src_size_10ms_mono]);
dst_left_.reset(new T[dst_size_10ms_mono]);
dst_right_.reset(new T[dst_size_10ms_mono]);
sinc_resampler_right_.reset(new PushSincResampler(src_size_10ms_mono,
dst_size_10ms_mono));
channel_resamplers_.clear();
for (size_t i = 0; i < num_channels; ++i) {
channel_resamplers_.push_back(ChannelResampler());
auto channel_resampler = channel_resamplers_.rbegin();
channel_resampler->resampler = std::make_unique<PushSincResampler>(
src_size_10ms_mono, dst_size_10ms_mono);
channel_resampler->source.resize(src_size_10ms_mono);
channel_resampler->destination.resize(dst_size_10ms_mono);
}
channel_data_array_.resize(num_channels_);
return 0;
}
template <typename T>
int PushResampler<T>::Resample(const T* src, size_t src_length, T* dst,
int PushResampler<T>::Resample(const T* src,
size_t src_length,
T* dst,
size_t dst_capacity) {
const size_t src_size_10ms =
static_cast<size_t>(src_sample_rate_hz_ * num_channels_ / 100);
const size_t dst_size_10ms =
static_cast<size_t>(dst_sample_rate_hz_ * num_channels_ / 100);
if (src_length != src_size_10ms || dst_capacity < dst_size_10ms)
return -1;
CheckExpectedBufferSizes(src_length, dst_capacity, num_channels_,
src_sample_rate_hz_, dst_sample_rate_hz_);
if (src_sample_rate_hz_ == dst_sample_rate_hz_) {
// The old resampler provides this memcpy facility in the case of matching
@ -81,26 +118,30 @@ int PushResampler<T>::Resample(const T* src, size_t src_length, T* dst,
memcpy(dst, src, src_length * sizeof(T));
return static_cast<int>(src_length);
}
if (num_channels_ == 2) {
const size_t src_length_mono = src_length / num_channels_;
const size_t dst_capacity_mono = dst_capacity / num_channels_;
T* deinterleaved[] = {src_left_.get(), src_right_.get()};
Deinterleave(src, src_length_mono, num_channels_, deinterleaved);
size_t dst_length_mono =
sinc_resampler_->Resample(src_left_.get(), src_length_mono,
dst_left_.get(), dst_capacity_mono);
sinc_resampler_right_->Resample(src_right_.get(), src_length_mono,
dst_right_.get(), dst_capacity_mono);
const size_t src_length_mono = src_length / num_channels_;
const size_t dst_capacity_mono = dst_capacity / num_channels_;
deinterleaved[0] = dst_left_.get();
deinterleaved[1] = dst_right_.get();
Interleave(deinterleaved, dst_length_mono, num_channels_, dst);
return static_cast<int>(dst_length_mono * num_channels_);
} else {
return static_cast<int>(
sinc_resampler_->Resample(src, src_length, dst, dst_capacity));
for (size_t ch = 0; ch < num_channels_; ++ch) {
channel_data_array_[ch] = channel_resamplers_[ch].source.data();
}
Deinterleave(src, src_length_mono, num_channels_, channel_data_array_.data());
size_t dst_length_mono = 0;
for (auto& resampler : channel_resamplers_) {
dst_length_mono = resampler.resampler->Resample(
resampler.source.data(), src_length_mono, resampler.destination.data(),
dst_capacity_mono);
}
for (size_t ch = 0; ch < num_channels_; ++ch) {
channel_data_array_[ch] = channel_resamplers_[ch].destination.data();
}
Interleave(channel_data_array_.data(), dst_length_mono, num_channels_, dst);
return static_cast<int>(dst_length_mono * num_channels_);
}
// Explictly generate required instantiations.

View File

@ -8,12 +8,12 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/common_audio/resampler/push_sinc_resampler.h"
#include "common_audio/resampler/push_sinc_resampler.h"
#include <cstring>
#include "webrtc/base/checks.h"
#include "webrtc/common_audio/include/audio_util.h"
#include "common_audio/include/audio_util.h"
#include "rtc_base/checks.h"
namespace webrtc {
@ -28,8 +28,7 @@ PushSincResampler::PushSincResampler(size_t source_frames,
first_pass_(true),
source_available_(0) {}
PushSincResampler::~PushSincResampler() {
}
PushSincResampler::~PushSincResampler() {}
size_t PushSincResampler::Resample(const int16_t* source,
size_t source_length,

View File

@ -8,13 +8,16 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_COMMON_AUDIO_RESAMPLER_PUSH_SINC_RESAMPLER_H_
#define WEBRTC_COMMON_AUDIO_RESAMPLER_PUSH_SINC_RESAMPLER_H_
#ifndef COMMON_AUDIO_RESAMPLER_PUSH_SINC_RESAMPLER_H_
#define COMMON_AUDIO_RESAMPLER_PUSH_SINC_RESAMPLER_H_
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/common_audio/resampler/sinc_resampler.h"
#include "webrtc/typedefs.h"
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "common_audio/resampler/sinc_resampler.h"
#include "rtc_base/constructor_magic.h"
namespace webrtc {
@ -35,8 +38,10 @@ class PushSincResampler : public SincResamplerCallback {
// at least as large as |destination_frames|. Returns the number of samples
// provided in destination (for convenience, since this will always be equal
// to |destination_frames|).
size_t Resample(const int16_t* source, size_t source_frames,
int16_t* destination, size_t destination_capacity);
size_t Resample(const int16_t* source,
size_t source_frames,
int16_t* destination,
size_t destination_capacity);
size_t Resample(const float* source,
size_t source_frames,
float* destination,
@ -56,8 +61,8 @@ class PushSincResampler : public SincResamplerCallback {
friend class PushSincResamplerTest;
SincResampler* get_resampler_for_testing() { return resampler_.get(); }
rtc::scoped_ptr<SincResampler> resampler_;
rtc::scoped_ptr<float[]> float_buffer_;
std::unique_ptr<SincResampler> resampler_;
std::unique_ptr<float[]> float_buffer_;
const float* source_ptr_;
const int16_t* source_ptr_int_;
const size_t destination_frames_;
@ -73,4 +78,4 @@ class PushSincResampler : public SincResamplerCallback {
} // namespace webrtc
#endif // WEBRTC_COMMON_AUDIO_RESAMPLER_PUSH_SINC_RESAMPLER_H_
#endif // COMMON_AUDIO_RESAMPLER_PUSH_SINC_RESAMPLER_H_

File diff suppressed because it is too large Load Diff

View File

@ -85,16 +85,17 @@
// MSVC++ requires this to be set before any other includes to get M_PI.
#define _USE_MATH_DEFINES
#include "webrtc/common_audio/resampler/sinc_resampler.h"
#include "common_audio/resampler/sinc_resampler.h"
#include <assert.h>
#include <math.h>
#include <stdint.h>
#include <string.h>
#include <limits>
#include "webrtc/system_wrappers/include/cpu_features_wrapper.h"
#include "webrtc/typedefs.h"
#include "rtc_base/checks.h"
#include "rtc_base/system/arch.h"
#include "system_wrappers/include/cpu_features_wrapper.h" // kSSE2, WebRtc_G...
namespace webrtc {
@ -118,35 +119,25 @@ double SincScaleFactor(double io_ratio) {
} // namespace
// If we know the minimum architecture at compile time, avoid CPU detection.
#if defined(WEBRTC_ARCH_X86_FAMILY)
#if defined(__SSE2__)
#define CONVOLVE_FUNC Convolve_SSE
void SincResampler::InitializeCPUSpecificFeatures() {}
#else
// x86 CPU detection required. Function will be set by
// InitializeCPUSpecificFeatures().
// TODO(dalecurtis): Once Chrome moves to an SSE baseline this can be removed.
#define CONVOLVE_FUNC convolve_proc_
const size_t SincResampler::kKernelSize;
// If we know the minimum architecture at compile time, avoid CPU detection.
void SincResampler::InitializeCPUSpecificFeatures() {
convolve_proc_ = WebRtc_GetCPUInfo(kSSE2) ? Convolve_SSE : Convolve_C;
}
#endif
#elif defined(WEBRTC_HAS_NEON)
#define CONVOLVE_FUNC Convolve_NEON
void SincResampler::InitializeCPUSpecificFeatures() {}
#elif defined(WEBRTC_DETECT_NEON)
#define CONVOLVE_FUNC convolve_proc_
void SincResampler::InitializeCPUSpecificFeatures() {
convolve_proc_ = WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON ?
Convolve_NEON : Convolve_C;
}
#if defined(WEBRTC_HAS_NEON)
convolve_proc_ = Convolve_NEON;
#elif defined(WEBRTC_ARCH_X86_FAMILY)
// Using AVX2 instead of SSE2 when AVX2 supported.
if (GetCPUInfo(kAVX2))
convolve_proc_ = Convolve_AVX2;
else if (GetCPUInfo(kSSE2))
convolve_proc_ = Convolve_SSE;
else
convolve_proc_ = Convolve_C;
#else
// Unknown architecture.
#define CONVOLVE_FUNC Convolve_C
void SincResampler::InitializeCPUSpecificFeatures() {}
// Unknown architecture.
convolve_proc_ = Convolve_C;
#endif
}
SincResampler::SincResampler(double io_sample_rate_ratio,
size_t request_frames,
@ -155,27 +146,23 @@ SincResampler::SincResampler(double io_sample_rate_ratio,
read_cb_(read_cb),
request_frames_(request_frames),
input_buffer_size_(request_frames_ + kKernelSize),
// Create input buffers with a 16-byte alignment for SSE optimizations.
// Create input buffers with a 32-byte alignment for SIMD optimizations.
kernel_storage_(static_cast<float*>(
AlignedMalloc(sizeof(float) * kKernelStorageSize, 16))),
AlignedMalloc(sizeof(float) * kKernelStorageSize, 32))),
kernel_pre_sinc_storage_(static_cast<float*>(
AlignedMalloc(sizeof(float) * kKernelStorageSize, 16))),
AlignedMalloc(sizeof(float) * kKernelStorageSize, 32))),
kernel_window_storage_(static_cast<float*>(
AlignedMalloc(sizeof(float) * kKernelStorageSize, 16))),
AlignedMalloc(sizeof(float) * kKernelStorageSize, 32))),
input_buffer_(static_cast<float*>(
AlignedMalloc(sizeof(float) * input_buffer_size_, 16))),
#if defined(WEBRTC_CPU_DETECTION)
convolve_proc_(NULL),
#endif
AlignedMalloc(sizeof(float) * input_buffer_size_, 32))),
convolve_proc_(nullptr),
r1_(input_buffer_.get()),
r2_(input_buffer_.get() + kKernelSize / 2) {
#if defined(WEBRTC_CPU_DETECTION)
InitializeCPUSpecificFeatures();
assert(convolve_proc_);
#endif
assert(request_frames_ > 0);
RTC_DCHECK(convolve_proc_);
RTC_DCHECK_GT(request_frames_, 0);
Flush();
assert(block_size_ > kKernelSize);
RTC_DCHECK_GT(block_size_, kKernelSize);
memset(kernel_storage_.get(), 0,
sizeof(*kernel_storage_.get()) * kKernelStorageSize);
@ -198,11 +185,11 @@ void SincResampler::UpdateRegions(bool second_load) {
block_size_ = r4_ - r2_;
// r1_ at the beginning of the buffer.
assert(r1_ == input_buffer_.get());
RTC_DCHECK_EQ(r1_, input_buffer_.get());
// r1_ left of r2_, r4_ left of r3_ and size correct.
assert(r2_ - r1_ == r4_ - r3_);
RTC_DCHECK_EQ(r2_ - r1_, r4_ - r3_);
// r2_ left of r3.
assert(r2_ < r3_);
RTC_DCHECK_LT(r2_, r3_);
}
void SincResampler::InitializeKernel() {
@ -221,23 +208,23 @@ void SincResampler::InitializeKernel() {
for (size_t i = 0; i < kKernelSize; ++i) {
const size_t idx = i + offset_idx * kKernelSize;
const float pre_sinc = static_cast<float>(M_PI *
(static_cast<int>(i) - static_cast<int>(kKernelSize / 2) -
subsample_offset));
const float pre_sinc = static_cast<float>(
M_PI * (static_cast<int>(i) - static_cast<int>(kKernelSize / 2) -
subsample_offset));
kernel_pre_sinc_storage_[idx] = pre_sinc;
// Compute Blackman window, matching the offset of the sinc().
const float x = (i - subsample_offset) / kKernelSize;
const float window = static_cast<float>(kA0 - kA1 * cos(2.0 * M_PI * x) +
kA2 * cos(4.0 * M_PI * x));
kA2 * cos(4.0 * M_PI * x));
kernel_window_storage_[idx] = window;
// Compute the sinc with offset, then window the sinc() function and store
// at the correct offset.
kernel_storage_[idx] = static_cast<float>(window *
((pre_sinc == 0) ?
sinc_scale_factor :
(sin(sinc_scale_factor * pre_sinc) / pre_sinc)));
kernel_storage_[idx] = static_cast<float>(
window * ((pre_sinc == 0)
? sinc_scale_factor
: (sin(sinc_scale_factor * pre_sinc) / pre_sinc)));
}
}
}
@ -259,10 +246,10 @@ void SincResampler::SetRatio(double io_sample_rate_ratio) {
const float window = kernel_window_storage_[idx];
const float pre_sinc = kernel_pre_sinc_storage_[idx];
kernel_storage_[idx] = static_cast<float>(window *
((pre_sinc == 0) ?
sinc_scale_factor :
(sin(sinc_scale_factor * pre_sinc) / pre_sinc)));
kernel_storage_[idx] = static_cast<float>(
window * ((pre_sinc == 0)
? sinc_scale_factor
: (sin(sinc_scale_factor * pre_sinc) / pre_sinc)));
}
}
}
@ -289,7 +276,7 @@ void SincResampler::Resample(size_t frames, float* destination) {
for (int i = static_cast<int>(
ceil((block_size_ - virtual_source_idx_) / current_io_ratio));
i > 0; --i) {
assert(virtual_source_idx_ < block_size_);
RTC_DCHECK_LT(virtual_source_idx_, block_size_);
// |virtual_source_idx_| lies in between two kernel offsets so figure out
// what they are.
@ -305,10 +292,10 @@ void SincResampler::Resample(size_t frames, float* destination) {
const float* const k1 = kernel_ptr + offset_idx * kKernelSize;
const float* const k2 = k1 + kKernelSize;
// Ensure |k1|, |k2| are 16-byte aligned for SIMD usage. Should always be
// true so long as kKernelSize is a multiple of 16.
assert(0u == (reinterpret_cast<uintptr_t>(k1) & 0x0F));
assert(0u == (reinterpret_cast<uintptr_t>(k2) & 0x0F));
// Ensure |k1|, |k2| are 32-byte aligned for SIMD usage. Should always be
// true so long as kKernelSize is a multiple of 32.
RTC_DCHECK_EQ(0, reinterpret_cast<uintptr_t>(k1) % 32);
RTC_DCHECK_EQ(0, reinterpret_cast<uintptr_t>(k2) % 32);
// Initialize input pointer based on quantized |virtual_source_idx_|.
const float* const input_ptr = r1_ + source_idx;
@ -316,8 +303,8 @@ void SincResampler::Resample(size_t frames, float* destination) {
// Figure out how much to weight each kernel's "convolution".
const double kernel_interpolation_factor =
virtual_offset_idx - offset_idx;
*destination++ = CONVOLVE_FUNC(
input_ptr, k1, k2, kernel_interpolation_factor);
*destination++ =
convolve_proc_(input_ptr, k1, k2, kernel_interpolation_factor);
// Advance the virtual index.
virtual_source_idx_ += current_io_ratio;
@ -356,7 +343,8 @@ void SincResampler::Flush() {
UpdateRegions(false);
}
float SincResampler::Convolve_C(const float* input_ptr, const float* k1,
float SincResampler::Convolve_C(const float* input_ptr,
const float* k1,
const float* k2,
double kernel_interpolation_factor) {
float sum1 = 0;
@ -372,7 +360,7 @@ float SincResampler::Convolve_C(const float* input_ptr, const float* k1,
// Linearly interpolate the two "convolutions".
return static_cast<float>((1.0 - kernel_interpolation_factor) * sum1 +
kernel_interpolation_factor * sum2);
kernel_interpolation_factor * sum2);
}
} // namespace webrtc

View File

@ -11,16 +11,17 @@
// Modified from the Chromium original here:
// src/media/base/sinc_resampler.h
#ifndef WEBRTC_COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_
#define WEBRTC_COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_
#ifndef COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_
#define COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/system_wrappers/include/aligned_malloc.h"
#ifndef WEBRTC_AUDIO_PROCESSING_ONLY_BUILD
#include "webrtc/test/testsupport/gtest_prod_util.h"
#endif
#include "webrtc/typedefs.h"
#include <stddef.h>
#include <memory>
#include "rtc_base/constructor_magic.h"
#include "rtc_base/gtest_prod_util.h"
#include "rtc_base/memory/aligned_malloc.h"
#include "rtc_base/system/arch.h"
namespace webrtc {
@ -87,10 +88,8 @@ class SincResampler {
float* get_kernel_for_testing() { return kernel_storage_.get(); }
private:
#ifndef WEBRTC_AUDIO_PROCESSING_ONLY_BUILD
FRIEND_TEST_ALL_PREFIXES(SincResamplerTest, Convolve);
FRIEND_TEST_ALL_PREFIXES(SincResamplerTest, ConvolveBenchmark);
#endif
void InitializeKernel();
void UpdateRegions(bool second_load);
@ -104,14 +103,22 @@ class SincResampler {
// Compute convolution of |k1| and |k2| over |input_ptr|, resultant sums are
// linearly interpolated using |kernel_interpolation_factor|. On x86 and ARM
// the underlying implementation is chosen at run time.
static float Convolve_C(const float* input_ptr, const float* k1,
const float* k2, double kernel_interpolation_factor);
static float Convolve_C(const float* input_ptr,
const float* k1,
const float* k2,
double kernel_interpolation_factor);
#if defined(WEBRTC_ARCH_X86_FAMILY)
static float Convolve_SSE(const float* input_ptr, const float* k1,
static float Convolve_SSE(const float* input_ptr,
const float* k1,
const float* k2,
double kernel_interpolation_factor);
#elif defined(WEBRTC_DETECT_NEON) || defined(WEBRTC_HAS_NEON)
static float Convolve_NEON(const float* input_ptr, const float* k1,
static float Convolve_AVX2(const float* input_ptr,
const float* k1,
const float* k2,
double kernel_interpolation_factor);
#elif defined(WEBRTC_HAS_NEON)
static float Convolve_NEON(const float* input_ptr,
const float* k1,
const float* k2,
double kernel_interpolation_factor);
#endif
@ -141,22 +148,22 @@ class SincResampler {
// Contains kKernelOffsetCount kernels back-to-back, each of size kKernelSize.
// The kernel offsets are sub-sample shifts of a windowed sinc shifted from
// 0.0 to 1.0 sample.
rtc::scoped_ptr<float[], AlignedFreeDeleter> kernel_storage_;
rtc::scoped_ptr<float[], AlignedFreeDeleter> kernel_pre_sinc_storage_;
rtc::scoped_ptr<float[], AlignedFreeDeleter> kernel_window_storage_;
std::unique_ptr<float[], AlignedFreeDeleter> kernel_storage_;
std::unique_ptr<float[], AlignedFreeDeleter> kernel_pre_sinc_storage_;
std::unique_ptr<float[], AlignedFreeDeleter> kernel_window_storage_;
// Data from the source is copied into this buffer for each processing pass.
rtc::scoped_ptr<float[], AlignedFreeDeleter> input_buffer_;
std::unique_ptr<float[], AlignedFreeDeleter> input_buffer_;
// Stores the runtime selection of which Convolve function to use.
// TODO(ajm): Move to using a global static which must only be initialized
// once by the user. We're not doing this initially, because we don't have
// e.g. a LazyInstance helper in webrtc.
#if defined(WEBRTC_CPU_DETECTION)
typedef float (*ConvolveProc)(const float*, const float*, const float*,
// Stores the runtime selection of which Convolve function to use.
// TODO(ajm): Move to using a global static which must only be initialized
// once by the user. We're not doing this initially, because we don't have
// e.g. a LazyInstance helper in webrtc.
typedef float (*ConvolveProc)(const float*,
const float*,
const float*,
double);
ConvolveProc convolve_proc_;
#endif
// Pointers to the various regions inside |input_buffer_|. See the diagram at
// the top of the .cc file for more information.
@ -171,4 +178,4 @@ class SincResampler {
} // namespace webrtc
#endif // WEBRTC_COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_
#endif // COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <immintrin.h>
#include <stddef.h>
#include <stdint.h>
#include <xmmintrin.h>
#include "common_audio/resampler/sinc_resampler.h"
namespace webrtc {
float SincResampler::Convolve_AVX2(const float* input_ptr,
const float* k1,
const float* k2,
double kernel_interpolation_factor) {
__m256 m_input;
__m256 m_sums1 = _mm256_setzero_ps();
__m256 m_sums2 = _mm256_setzero_ps();
// Based on |input_ptr| alignment, we need to use loadu or load. Unrolling
// these loops has not been tested or benchmarked.
bool aligned_input = (reinterpret_cast<uintptr_t>(input_ptr) & 0x1F) == 0;
if (!aligned_input) {
for (size_t i = 0; i < kKernelSize; i += 8) {
m_input = _mm256_loadu_ps(input_ptr + i);
m_sums1 = _mm256_fmadd_ps(m_input, _mm256_load_ps(k1 + i), m_sums1);
m_sums2 = _mm256_fmadd_ps(m_input, _mm256_load_ps(k2 + i), m_sums2);
}
} else {
for (size_t i = 0; i < kKernelSize; i += 8) {
m_input = _mm256_load_ps(input_ptr + i);
m_sums1 = _mm256_fmadd_ps(m_input, _mm256_load_ps(k1 + i), m_sums1);
m_sums2 = _mm256_fmadd_ps(m_input, _mm256_load_ps(k2 + i), m_sums2);
}
}
// Linearly interpolate the two "convolutions".
__m128 m128_sums1 = _mm_add_ps(_mm256_extractf128_ps(m_sums1, 0),
_mm256_extractf128_ps(m_sums1, 1));
__m128 m128_sums2 = _mm_add_ps(_mm256_extractf128_ps(m_sums2, 0),
_mm256_extractf128_ps(m_sums2, 1));
m128_sums1 = _mm_mul_ps(
m128_sums1,
_mm_set_ps1(static_cast<float>(1.0 - kernel_interpolation_factor)));
m128_sums2 = _mm_mul_ps(
m128_sums2, _mm_set_ps1(static_cast<float>(kernel_interpolation_factor)));
m128_sums1 = _mm_add_ps(m128_sums1, m128_sums2);
// Sum components together.
float result;
m128_sums2 = _mm_add_ps(_mm_movehl_ps(m128_sums1, m128_sums1), m128_sums1);
_mm_store_ss(&result, _mm_add_ss(m128_sums2,
_mm_shuffle_ps(m128_sums2, m128_sums2, 1)));
return result;
}
} // namespace webrtc

View File

@ -11,13 +11,14 @@
// Modified from the Chromium original:
// src/media/base/sinc_resampler.cc
#include "webrtc/common_audio/resampler/sinc_resampler.h"
#include <arm_neon.h>
#include "common_audio/resampler/sinc_resampler.h"
namespace webrtc {
float SincResampler::Convolve_NEON(const float* input_ptr, const float* k1,
float SincResampler::Convolve_NEON(const float* input_ptr,
const float* k1,
const float* k2,
double kernel_interpolation_factor) {
float32x4_t m_input;
@ -25,7 +26,7 @@ float SincResampler::Convolve_NEON(const float* input_ptr, const float* k1,
float32x4_t m_sums2 = vmovq_n_f32(0);
const float* upper = input_ptr + kKernelSize;
for (; input_ptr < upper; ) {
for (; input_ptr < upper;) {
m_input = vld1q_f32(input_ptr);
input_ptr += 4;
m_sums1 = vmlaq_f32(m_sums1, m_input, vld1q_f32(k1));

View File

@ -11,13 +11,16 @@
// Modified from the Chromium original:
// src/media/base/simd/sinc_resampler_sse.cc
#include "webrtc/common_audio/resampler/sinc_resampler.h"
#include <stddef.h>
#include <stdint.h>
#include <xmmintrin.h>
#include "common_audio/resampler/sinc_resampler.h"
namespace webrtc {
float SincResampler::Convolve_SSE(const float* input_ptr, const float* k1,
float SincResampler::Convolve_SSE(const float* input_ptr,
const float* k1,
const float* k2,
double kernel_interpolation_factor) {
__m128 m_input;
@ -41,17 +44,18 @@ float SincResampler::Convolve_SSE(const float* input_ptr, const float* k1,
}
// Linearly interpolate the two "convolutions".
m_sums1 = _mm_mul_ps(m_sums1, _mm_set_ps1(
static_cast<float>(1.0 - kernel_interpolation_factor)));
m_sums2 = _mm_mul_ps(m_sums2, _mm_set_ps1(
static_cast<float>(kernel_interpolation_factor)));
m_sums1 = _mm_mul_ps(
m_sums1,
_mm_set_ps1(static_cast<float>(1.0 - kernel_interpolation_factor)));
m_sums2 = _mm_mul_ps(
m_sums2, _mm_set_ps1(static_cast<float>(kernel_interpolation_factor)));
m_sums1 = _mm_add_ps(m_sums1, m_sums2);
// Sum components together.
float result;
m_sums2 = _mm_add_ps(_mm_movehl_ps(m_sums1, m_sums1), m_sums1);
_mm_store_ss(&result, _mm_add_ss(m_sums2, _mm_shuffle_ps(
m_sums2, m_sums2, 1)));
_mm_store_ss(&result,
_mm_add_ss(m_sums2, _mm_shuffle_ps(m_sums2, m_sums2, 1)));
return result;
}

View File

@ -11,7 +11,7 @@
// MSVC++ requires this to be set before any other includes to get M_PI.
#define _USE_MATH_DEFINES
#include "webrtc/common_audio/resampler/sinusoidal_linear_chirp_source.h"
#include "common_audio/resampler/sinusoidal_linear_chirp_source.h"
#include <math.h>
@ -43,8 +43,7 @@ void SinusoidalLinearChirpSource::Run(size_t frames, float* destination) {
} else {
// Sinusoidal linear chirp.
double t = (current_index_ - delay_samples_) / sample_rate_;
destination[i] =
sin(2 * M_PI * (kMinFrequency * t + (k_ / 2) * t * t));
destination[i] = sin(2 * M_PI * (kMinFrequency * t + (k_ / 2) * t * t));
}
}
}
@ -52,7 +51,7 @@ void SinusoidalLinearChirpSource::Run(size_t frames, float* destination) {
double SinusoidalLinearChirpSource::Frequency(size_t position) {
return kMinFrequency + (position - delay_samples_) *
(max_frequency_ - kMinFrequency) / total_samples_;
(max_frequency_ - kMinFrequency) / total_samples_;
}
} // namespace webrtc

View File

@ -11,11 +11,11 @@
// Modified from the Chromium original here:
// src/media/base/sinc_resampler_unittest.cc
#ifndef WEBRTC_COMMON_AUDIO_RESAMPLER_SINUSOIDAL_LINEAR_CHIRP_SOURCE_H_
#define WEBRTC_COMMON_AUDIO_RESAMPLER_SINUSOIDAL_LINEAR_CHIRP_SOURCE_H_
#ifndef COMMON_AUDIO_RESAMPLER_SINUSOIDAL_LINEAR_CHIRP_SOURCE_H_
#define COMMON_AUDIO_RESAMPLER_SINUSOIDAL_LINEAR_CHIRP_SOURCE_H_
#include "webrtc/base/constructormagic.h"
#include "webrtc/common_audio/resampler/sinc_resampler.h"
#include "common_audio/resampler/sinc_resampler.h"
#include "rtc_base/constructor_magic.h"
namespace webrtc {
@ -26,19 +26,19 @@ class SinusoidalLinearChirpSource : public SincResamplerCallback {
public:
// |delay_samples| can be used to insert a fractional sample delay into the
// source. It will produce zeros until non-negative time is reached.
SinusoidalLinearChirpSource(int sample_rate, size_t samples,
double max_frequency, double delay_samples);
SinusoidalLinearChirpSource(int sample_rate,
size_t samples,
double max_frequency,
double delay_samples);
virtual ~SinusoidalLinearChirpSource() {}
~SinusoidalLinearChirpSource() override {}
void Run(size_t frames, float* destination) override;
double Frequency(size_t position);
private:
enum {
kMinFrequency = 5
};
enum { kMinFrequency = 5 };
int sample_rate_;
size_t total_samples_;
@ -52,4 +52,4 @@ class SinusoidalLinearChirpSource : public SincResamplerCallback {
} // namespace webrtc
#endif // WEBRTC_COMMON_AUDIO_RESAMPLER_SINUSOIDAL_LINEAR_CHIRP_SOURCE_H_
#endif // COMMON_AUDIO_RESAMPLER_SINUSOIDAL_LINEAR_CHIRP_SOURCE_H_