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:
@ -6,37 +6,19 @@
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("//build/config/arm.gni")
|
||||
import("../build/webrtc.gni")
|
||||
import("../webrtc.gni")
|
||||
|
||||
config("common_audio_config") {
|
||||
include_dirs = [
|
||||
"resampler/include",
|
||||
"signal_processing/include",
|
||||
"vad/include",
|
||||
]
|
||||
}
|
||||
visibility = [ ":*" ]
|
||||
|
||||
source_set("common_audio") {
|
||||
rtc_library("common_audio") {
|
||||
visibility += [ "*" ]
|
||||
sources = [
|
||||
"audio_converter.cc",
|
||||
"audio_converter.h",
|
||||
"audio_ring_buffer.cc",
|
||||
"audio_ring_buffer.h",
|
||||
"audio_util.cc",
|
||||
"blocker.cc",
|
||||
"blocker.h",
|
||||
"channel_buffer.cc",
|
||||
"channel_buffer.h",
|
||||
"fft4g.c",
|
||||
"fft4g.h",
|
||||
"fir_filter.cc",
|
||||
"fir_filter.h",
|
||||
"fir_filter_neon.h",
|
||||
"fir_filter_sse.h",
|
||||
"include/audio_util.h",
|
||||
"lapped_transform.cc",
|
||||
"lapped_transform.h",
|
||||
"real_fourier.cc",
|
||||
"real_fourier.h",
|
||||
"real_fourier_ooura.cc",
|
||||
@ -48,7 +30,77 @@ source_set("common_audio") {
|
||||
"resampler/push_sinc_resampler.h",
|
||||
"resampler/resampler.cc",
|
||||
"resampler/sinc_resampler.cc",
|
||||
"resampler/sinc_resampler.h",
|
||||
"smoothing_filter.cc",
|
||||
"smoothing_filter.h",
|
||||
"vad/include/vad.h",
|
||||
"vad/vad.cc",
|
||||
"wav_file.cc",
|
||||
"wav_file.h",
|
||||
"wav_header.cc",
|
||||
"wav_header.h",
|
||||
"window_generator.cc",
|
||||
"window_generator.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":common_audio_c",
|
||||
":sinc_resampler",
|
||||
"../api:array_view",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:gtest_prod",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base:sanitizer",
|
||||
"../rtc_base/memory:aligned_malloc",
|
||||
"../rtc_base/system:arch",
|
||||
"../rtc_base/system:file_wrapper",
|
||||
"../system_wrappers",
|
||||
"third_party/ooura:fft_size_256",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
||||
|
||||
defines = []
|
||||
|
||||
if (rtc_build_with_neon) {
|
||||
deps += [ ":common_audio_neon" ]
|
||||
}
|
||||
|
||||
if (current_cpu == "x86" || current_cpu == "x64") {
|
||||
deps += [ ":common_audio_sse2" ]
|
||||
deps += [ ":common_audio_avx2" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_source_set("mock_common_audio") {
|
||||
visibility += webrtc_default_visibility
|
||||
testonly = true
|
||||
sources = [
|
||||
"mocks/mock_smoothing_filter.h",
|
||||
"vad/mock/mock_vad.h",
|
||||
]
|
||||
deps = [
|
||||
":common_audio",
|
||||
"../test:test_support",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("common_audio_c_arm_asm") {
|
||||
sources = []
|
||||
deps = []
|
||||
if (current_cpu == "arm") {
|
||||
sources += [ "signal_processing/complex_bit_reverse_arm.S" ]
|
||||
|
||||
if (arm_version >= 7) {
|
||||
sources += [ "signal_processing/filter_ar_fast_q12_armv7.S" ]
|
||||
} else {
|
||||
sources += [ "signal_processing/filter_ar_fast_q12.c" ]
|
||||
}
|
||||
deps += [ "../rtc_base/system:asm_defines" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_library("common_audio_c") {
|
||||
visibility += webrtc_default_visibility
|
||||
sources = [
|
||||
"ring_buffer.c",
|
||||
"ring_buffer.h",
|
||||
"signal_processing/auto_corr_to_refl_coef.c",
|
||||
@ -57,7 +109,6 @@ source_set("common_audio") {
|
||||
"signal_processing/copy_set_operations.c",
|
||||
"signal_processing/cross_correlation.c",
|
||||
"signal_processing/division_operations.c",
|
||||
"signal_processing/dot_product_with_scale.c",
|
||||
"signal_processing/downsample_fast.c",
|
||||
"signal_processing/energy.c",
|
||||
"signal_processing/filter_ar.c",
|
||||
@ -68,6 +119,7 @@ source_set("common_audio") {
|
||||
"signal_processing/include/real_fft.h",
|
||||
"signal_processing/include/signal_processing_library.h",
|
||||
"signal_processing/include/spl_inl.h",
|
||||
"signal_processing/include/spl_inl_armv7.h",
|
||||
"signal_processing/levinson_durbin.c",
|
||||
"signal_processing/lpc_to_refl_coef.c",
|
||||
"signal_processing/min_max_operations.c",
|
||||
@ -81,15 +133,12 @@ source_set("common_audio") {
|
||||
"signal_processing/resample_by_2_internal.h",
|
||||
"signal_processing/resample_fractional.c",
|
||||
"signal_processing/spl_init.c",
|
||||
"signal_processing/spl_inl.c",
|
||||
"signal_processing/spl_sqrt.c",
|
||||
"signal_processing/splitting_filter.c",
|
||||
"signal_processing/sqrt_of_one_minus_x_squared.c",
|
||||
"signal_processing/vector_scaling_operations.c",
|
||||
"sparse_fir_filter.cc",
|
||||
"sparse_fir_filter.h",
|
||||
"vad/include/vad.h",
|
||||
"vad/include/webrtc_vad.h",
|
||||
"vad/vad.cc",
|
||||
"vad/vad_core.c",
|
||||
"vad/vad_core.h",
|
||||
"vad/vad_filterbank.c",
|
||||
@ -99,47 +148,8 @@ source_set("common_audio") {
|
||||
"vad/vad_sp.c",
|
||||
"vad/vad_sp.h",
|
||||
"vad/webrtc_vad.c",
|
||||
"wav_file.cc",
|
||||
"wav_file.h",
|
||||
"wav_header.cc",
|
||||
"wav_header.h",
|
||||
"window_generator.cc",
|
||||
"window_generator.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"../system_wrappers",
|
||||
]
|
||||
|
||||
defines = []
|
||||
if (rtc_use_openmax_dl) {
|
||||
sources += [
|
||||
"real_fourier_openmax.cc",
|
||||
"real_fourier_openmax.h",
|
||||
]
|
||||
defines += [ "RTC_USE_OPENMAX_DL" ]
|
||||
if (rtc_build_openmax_dl) {
|
||||
deps += [ "//third_party/openmax_dl/dl" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (current_cpu == "arm") {
|
||||
sources += [
|
||||
"signal_processing/complex_bit_reverse_arm.S",
|
||||
"signal_processing/spl_sqrt_floor_arm.S",
|
||||
]
|
||||
|
||||
if (arm_version >= 7) {
|
||||
sources += [ "signal_processing/filter_ar_fast_q12_armv7.S" ]
|
||||
} else {
|
||||
sources += [ "signal_processing/filter_ar_fast_q12.c" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc_build_with_neon) {
|
||||
deps += [ ":common_audio_neon" ]
|
||||
}
|
||||
|
||||
if (current_cpu == "mipsel") {
|
||||
sources += [
|
||||
"signal_processing/complex_bit_reverse_mips.c",
|
||||
@ -150,7 +160,6 @@ source_set("common_audio") {
|
||||
"signal_processing/include/spl_inl_mips.h",
|
||||
"signal_processing/min_max_operations_mips.c",
|
||||
"signal_processing/resample_by_2_mips.c",
|
||||
"signal_processing/spl_sqrt_floor_mips.c",
|
||||
]
|
||||
if (mips_dsp_rev > 0) {
|
||||
sources += [ "signal_processing/vector_scaling_operations_mips.c" ]
|
||||
@ -163,81 +172,227 @@ source_set("common_audio") {
|
||||
sources += [
|
||||
"signal_processing/complex_bit_reverse.c",
|
||||
"signal_processing/filter_ar_fast_q12.c",
|
||||
"signal_processing/spl_sqrt_floor.c",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
cflags = [ "/wd4334" ] # Ignore warning on shift operator promotion.
|
||||
}
|
||||
deps = [
|
||||
":common_audio_c_arm_asm",
|
||||
":common_audio_cc",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:compile_assert_c",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base:sanitizer",
|
||||
"../rtc_base/system:arch",
|
||||
"../system_wrappers",
|
||||
"third_party/ooura:fft_size_256",
|
||||
"third_party/spl_sqrt_floor",
|
||||
]
|
||||
}
|
||||
|
||||
configs += [ "..:common_config" ]
|
||||
|
||||
public_configs = [
|
||||
"..:common_inherited_config",
|
||||
":common_audio_config",
|
||||
rtc_library("common_audio_cc") {
|
||||
sources = [
|
||||
"signal_processing/dot_product_with_scale.cc",
|
||||
"signal_processing/dot_product_with_scale.h",
|
||||
]
|
||||
|
||||
if (is_clang) {
|
||||
# Suppress warnings from Chrome's Clang plugins.
|
||||
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
|
||||
configs -= [ "//build/config/clang:find_bad_constructs" ]
|
||||
}
|
||||
deps = [
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../system_wrappers",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("sinc_resampler") {
|
||||
sources = [ "resampler/sinc_resampler.h" ]
|
||||
deps = [
|
||||
"../rtc_base:gtest_prod",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base/memory:aligned_malloc",
|
||||
"../rtc_base/system:arch",
|
||||
"../system_wrappers",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("fir_filter") {
|
||||
visibility += webrtc_default_visibility
|
||||
sources = [ "fir_filter.h" ]
|
||||
}
|
||||
|
||||
rtc_library("fir_filter_factory") {
|
||||
visibility += webrtc_default_visibility
|
||||
sources = [
|
||||
"fir_filter_c.cc",
|
||||
"fir_filter_c.h",
|
||||
"fir_filter_factory.cc",
|
||||
"fir_filter_factory.h",
|
||||
]
|
||||
deps = [
|
||||
":fir_filter",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base/system:arch",
|
||||
"../system_wrappers",
|
||||
]
|
||||
if (current_cpu == "x86" || current_cpu == "x64") {
|
||||
deps += [ ":common_audio_sse2" ]
|
||||
deps += [ ":common_audio_avx2" ]
|
||||
}
|
||||
if (rtc_build_with_neon) {
|
||||
deps += [ ":common_audio_neon" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (current_cpu == "x86" || current_cpu == "x64") {
|
||||
source_set("common_audio_sse2") {
|
||||
rtc_library("common_audio_sse2") {
|
||||
sources = [
|
||||
"fir_filter_sse.cc",
|
||||
"fir_filter_sse.h",
|
||||
"resampler/sinc_resampler_sse.cc",
|
||||
]
|
||||
|
||||
if (is_posix) {
|
||||
if (is_posix || is_fuchsia) {
|
||||
cflags = [ "-msse2" ]
|
||||
}
|
||||
|
||||
configs += [ "..:common_inherited_config" ]
|
||||
deps = [
|
||||
":fir_filter",
|
||||
":sinc_resampler",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base/memory:aligned_malloc",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_clang) {
|
||||
# Suppress warnings from Chrome's Clang plugins.
|
||||
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
|
||||
configs -= [ "//build/config/clang:find_bad_constructs" ]
|
||||
rtc_library("common_audio_avx2") {
|
||||
sources = [
|
||||
"fir_filter_avx2.cc",
|
||||
"fir_filter_avx2.h",
|
||||
"resampler/sinc_resampler_avx2.cc",
|
||||
]
|
||||
|
||||
if (is_win) {
|
||||
cflags = [ "/arch:AVX2" ]
|
||||
} else {
|
||||
cflags = [
|
||||
"-mavx2",
|
||||
"-mfma",
|
||||
]
|
||||
}
|
||||
|
||||
deps = [
|
||||
":fir_filter",
|
||||
":sinc_resampler",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base/memory:aligned_malloc",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc_build_with_neon) {
|
||||
source_set("common_audio_neon") {
|
||||
rtc_library("common_audio_neon") {
|
||||
sources = [
|
||||
"fir_filter_neon.cc",
|
||||
"fir_filter_neon.h",
|
||||
"resampler/sinc_resampler_neon.cc",
|
||||
]
|
||||
|
||||
if (current_cpu != "arm64") {
|
||||
# Enable compilation for the NEON instruction set.
|
||||
suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
|
||||
cflags = [ "-mfpu=neon" ]
|
||||
}
|
||||
|
||||
deps = [
|
||||
":common_audio_neon_c",
|
||||
":fir_filter",
|
||||
":sinc_resampler",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base/memory:aligned_malloc",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("common_audio_neon_c") {
|
||||
visibility += webrtc_default_visibility
|
||||
sources = [
|
||||
"signal_processing/cross_correlation_neon.c",
|
||||
"signal_processing/downsample_fast_neon.c",
|
||||
"signal_processing/min_max_operations_neon.c",
|
||||
]
|
||||
|
||||
if (current_cpu != "arm64") {
|
||||
# Enable compilation for the NEON instruction set. This is needed
|
||||
# since //build/config/arm.gni only enables NEON for iOS, not Android.
|
||||
# This provides the same functionality as webrtc/build/arm_neon.gypi.
|
||||
configs -= [ "//build/config/compiler:compiler_arm_fpu" ]
|
||||
# Enable compilation for the NEON instruction set.
|
||||
suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
|
||||
cflags = [ "-mfpu=neon" ]
|
||||
}
|
||||
|
||||
# Disable LTO on NEON targets due to compiler bug.
|
||||
# TODO(fdegans): Enable this. See crbug.com/408997.
|
||||
if (rtc_use_lto) {
|
||||
cflags -= [
|
||||
"-flto",
|
||||
"-ffat-lto-objects",
|
||||
]
|
||||
}
|
||||
|
||||
configs += [ "..:common_config" ]
|
||||
public_configs = [ "..:common_inherited_config" ]
|
||||
deps = [
|
||||
":common_audio_c",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base/system:arch",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc_include_tests) {
|
||||
rtc_test("common_audio_unittests") {
|
||||
visibility += webrtc_default_visibility
|
||||
testonly = true
|
||||
|
||||
sources = [
|
||||
"audio_converter_unittest.cc",
|
||||
"audio_util_unittest.cc",
|
||||
"channel_buffer_unittest.cc",
|
||||
"fir_filter_unittest.cc",
|
||||
"real_fourier_unittest.cc",
|
||||
"resampler/push_resampler_unittest.cc",
|
||||
"resampler/push_sinc_resampler_unittest.cc",
|
||||
"resampler/resampler_unittest.cc",
|
||||
"resampler/sinusoidal_linear_chirp_source.cc",
|
||||
"resampler/sinusoidal_linear_chirp_source.h",
|
||||
"ring_buffer_unittest.cc",
|
||||
"signal_processing/real_fft_unittest.cc",
|
||||
"signal_processing/signal_processing_unittest.cc",
|
||||
"smoothing_filter_unittest.cc",
|
||||
"vad/vad_core_unittest.cc",
|
||||
"vad/vad_filterbank_unittest.cc",
|
||||
"vad/vad_gmm_unittest.cc",
|
||||
"vad/vad_sp_unittest.cc",
|
||||
"vad/vad_unittest.cc",
|
||||
"vad/vad_unittest.h",
|
||||
"wav_file_unittest.cc",
|
||||
"wav_header_unittest.cc",
|
||||
"window_generator_unittest.cc",
|
||||
]
|
||||
|
||||
# Does not compile on iOS for arm: webrtc:5544.
|
||||
if (!is_ios || target_cpu != "arm") {
|
||||
sources += [ "resampler/sinc_resampler_unittest.cc" ]
|
||||
}
|
||||
|
||||
deps = [
|
||||
":common_audio",
|
||||
":common_audio_c",
|
||||
":fir_filter",
|
||||
":fir_filter_factory",
|
||||
":sinc_resampler",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base:rtc_base_tests_utils",
|
||||
"../rtc_base/system:arch",
|
||||
"../system_wrappers",
|
||||
"../test:fileutils",
|
||||
"../test:rtc_expect_death",
|
||||
"../test:test_main",
|
||||
"../test:test_support",
|
||||
"//testing/gtest",
|
||||
]
|
||||
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
|
||||
shard_timeout = 900
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,32 +8,36 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/audio_converter.h"
|
||||
#include "common_audio/audio_converter.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/safe_conversions.h"
|
||||
#include "webrtc/common_audio/channel_buffer.h"
|
||||
#include "webrtc/common_audio/resampler/push_sinc_resampler.h"
|
||||
#include "webrtc/system_wrappers/include/scoped_vector.h"
|
||||
|
||||
using rtc::checked_cast;
|
||||
#include "common_audio/channel_buffer.h"
|
||||
#include "common_audio/resampler/push_sinc_resampler.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CopyConverter : public AudioConverter {
|
||||
public:
|
||||
CopyConverter(int src_channels, size_t src_frames, int dst_channels,
|
||||
CopyConverter(size_t src_channels,
|
||||
size_t src_frames,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames)
|
||||
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
|
||||
~CopyConverter() override {};
|
||||
~CopyConverter() override {}
|
||||
|
||||
void Convert(const float* const* src, size_t src_size, float* const* dst,
|
||||
void Convert(const float* const* src,
|
||||
size_t src_size,
|
||||
float* const* dst,
|
||||
size_t dst_capacity) override {
|
||||
CheckSizes(src_size, dst_capacity);
|
||||
if (src != dst) {
|
||||
for (int i = 0; i < src_channels(); ++i)
|
||||
for (size_t i = 0; i < src_channels(); ++i)
|
||||
std::memcpy(dst[i], src[i], dst_frames() * sizeof(*dst[i]));
|
||||
}
|
||||
}
|
||||
@ -41,17 +45,21 @@ class CopyConverter : public AudioConverter {
|
||||
|
||||
class UpmixConverter : public AudioConverter {
|
||||
public:
|
||||
UpmixConverter(int src_channels, size_t src_frames, int dst_channels,
|
||||
UpmixConverter(size_t src_channels,
|
||||
size_t src_frames,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames)
|
||||
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
|
||||
~UpmixConverter() override {};
|
||||
~UpmixConverter() override {}
|
||||
|
||||
void Convert(const float* const* src, size_t src_size, float* const* dst,
|
||||
void Convert(const float* const* src,
|
||||
size_t src_size,
|
||||
float* const* dst,
|
||||
size_t dst_capacity) override {
|
||||
CheckSizes(src_size, dst_capacity);
|
||||
for (size_t i = 0; i < dst_frames(); ++i) {
|
||||
const float value = src[0][i];
|
||||
for (int j = 0; j < dst_channels(); ++j)
|
||||
for (size_t j = 0; j < dst_channels(); ++j)
|
||||
dst[j][i] = value;
|
||||
}
|
||||
}
|
||||
@ -59,19 +67,22 @@ class UpmixConverter : public AudioConverter {
|
||||
|
||||
class DownmixConverter : public AudioConverter {
|
||||
public:
|
||||
DownmixConverter(int src_channels, size_t src_frames, int dst_channels,
|
||||
DownmixConverter(size_t src_channels,
|
||||
size_t src_frames,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames)
|
||||
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {
|
||||
}
|
||||
~DownmixConverter() override {};
|
||||
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
|
||||
~DownmixConverter() override {}
|
||||
|
||||
void Convert(const float* const* src, size_t src_size, float* const* dst,
|
||||
void Convert(const float* const* src,
|
||||
size_t src_size,
|
||||
float* const* dst,
|
||||
size_t dst_capacity) override {
|
||||
CheckSizes(src_size, dst_capacity);
|
||||
float* dst_mono = dst[0];
|
||||
for (size_t i = 0; i < src_frames(); ++i) {
|
||||
float sum = 0;
|
||||
for (int j = 0; j < src_channels(); ++j)
|
||||
for (size_t j = 0; j < src_channels(); ++j)
|
||||
sum += src[j][i];
|
||||
dst_mono[i] = sum / src_channels();
|
||||
}
|
||||
@ -80,16 +91,21 @@ class DownmixConverter : public AudioConverter {
|
||||
|
||||
class ResampleConverter : public AudioConverter {
|
||||
public:
|
||||
ResampleConverter(int src_channels, size_t src_frames, int dst_channels,
|
||||
ResampleConverter(size_t src_channels,
|
||||
size_t src_frames,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames)
|
||||
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {
|
||||
resamplers_.reserve(src_channels);
|
||||
for (int i = 0; i < src_channels; ++i)
|
||||
resamplers_.push_back(new PushSincResampler(src_frames, dst_frames));
|
||||
for (size_t i = 0; i < src_channels; ++i)
|
||||
resamplers_.push_back(std::unique_ptr<PushSincResampler>(
|
||||
new PushSincResampler(src_frames, dst_frames)));
|
||||
}
|
||||
~ResampleConverter() override {};
|
||||
~ResampleConverter() override {}
|
||||
|
||||
void Convert(const float* const* src, size_t src_size, float* const* dst,
|
||||
void Convert(const float* const* src,
|
||||
size_t src_size,
|
||||
float* const* dst,
|
||||
size_t dst_capacity) override {
|
||||
CheckSizes(src_size, dst_capacity);
|
||||
for (size_t i = 0; i < resamplers_.size(); ++i)
|
||||
@ -97,69 +113,73 @@ class ResampleConverter : public AudioConverter {
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedVector<PushSincResampler> resamplers_;
|
||||
std::vector<std::unique_ptr<PushSincResampler>> resamplers_;
|
||||
};
|
||||
|
||||
// Apply a vector of converters in serial, in the order given. At least two
|
||||
// converters must be provided.
|
||||
class CompositionConverter : public AudioConverter {
|
||||
public:
|
||||
CompositionConverter(ScopedVector<AudioConverter> converters)
|
||||
: converters_(converters.Pass()) {
|
||||
RTC_CHECK_GE(converters_.size(), 2u);
|
||||
explicit CompositionConverter(
|
||||
std::vector<std::unique_ptr<AudioConverter>> converters)
|
||||
: converters_(std::move(converters)) {
|
||||
RTC_CHECK_GE(converters_.size(), 2);
|
||||
// We need an intermediate buffer after every converter.
|
||||
for (auto it = converters_.begin(); it != converters_.end() - 1; ++it)
|
||||
buffers_.push_back(new ChannelBuffer<float>((*it)->dst_frames(),
|
||||
(*it)->dst_channels()));
|
||||
buffers_.push_back(
|
||||
std::unique_ptr<ChannelBuffer<float>>(new ChannelBuffer<float>(
|
||||
(*it)->dst_frames(), (*it)->dst_channels())));
|
||||
}
|
||||
~CompositionConverter() override {};
|
||||
~CompositionConverter() override {}
|
||||
|
||||
void Convert(const float* const* src, size_t src_size, float* const* dst,
|
||||
void Convert(const float* const* src,
|
||||
size_t src_size,
|
||||
float* const* dst,
|
||||
size_t dst_capacity) override {
|
||||
converters_.front()->Convert(src, src_size, buffers_.front()->channels(),
|
||||
buffers_.front()->size());
|
||||
for (size_t i = 2; i < converters_.size(); ++i) {
|
||||
auto src_buffer = buffers_[i - 2];
|
||||
auto dst_buffer = buffers_[i - 1];
|
||||
converters_[i]->Convert(src_buffer->channels(),
|
||||
src_buffer->size(),
|
||||
dst_buffer->channels(),
|
||||
dst_buffer->size());
|
||||
auto& src_buffer = buffers_[i - 2];
|
||||
auto& dst_buffer = buffers_[i - 1];
|
||||
converters_[i]->Convert(src_buffer->channels(), src_buffer->size(),
|
||||
dst_buffer->channels(), dst_buffer->size());
|
||||
}
|
||||
converters_.back()->Convert(buffers_.back()->channels(),
|
||||
buffers_.back()->size(), dst, dst_capacity);
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedVector<AudioConverter> converters_;
|
||||
ScopedVector<ChannelBuffer<float>> buffers_;
|
||||
std::vector<std::unique_ptr<AudioConverter>> converters_;
|
||||
std::vector<std::unique_ptr<ChannelBuffer<float>>> buffers_;
|
||||
};
|
||||
|
||||
rtc::scoped_ptr<AudioConverter> AudioConverter::Create(int src_channels,
|
||||
std::unique_ptr<AudioConverter> AudioConverter::Create(size_t src_channels,
|
||||
size_t src_frames,
|
||||
int dst_channels,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames) {
|
||||
rtc::scoped_ptr<AudioConverter> sp;
|
||||
std::unique_ptr<AudioConverter> sp;
|
||||
if (src_channels > dst_channels) {
|
||||
if (src_frames != dst_frames) {
|
||||
ScopedVector<AudioConverter> converters;
|
||||
converters.push_back(new DownmixConverter(src_channels, src_frames,
|
||||
dst_channels, src_frames));
|
||||
converters.push_back(new ResampleConverter(dst_channels, src_frames,
|
||||
dst_channels, dst_frames));
|
||||
sp.reset(new CompositionConverter(converters.Pass()));
|
||||
std::vector<std::unique_ptr<AudioConverter>> converters;
|
||||
converters.push_back(std::unique_ptr<AudioConverter>(new DownmixConverter(
|
||||
src_channels, src_frames, dst_channels, src_frames)));
|
||||
converters.push_back(
|
||||
std::unique_ptr<AudioConverter>(new ResampleConverter(
|
||||
dst_channels, src_frames, dst_channels, dst_frames)));
|
||||
sp.reset(new CompositionConverter(std::move(converters)));
|
||||
} else {
|
||||
sp.reset(new DownmixConverter(src_channels, src_frames, dst_channels,
|
||||
dst_frames));
|
||||
}
|
||||
} else if (src_channels < dst_channels) {
|
||||
if (src_frames != dst_frames) {
|
||||
ScopedVector<AudioConverter> converters;
|
||||
converters.push_back(new ResampleConverter(src_channels, src_frames,
|
||||
src_channels, dst_frames));
|
||||
converters.push_back(new UpmixConverter(src_channels, dst_frames,
|
||||
dst_channels, dst_frames));
|
||||
sp.reset(new CompositionConverter(converters.Pass()));
|
||||
std::vector<std::unique_ptr<AudioConverter>> converters;
|
||||
converters.push_back(
|
||||
std::unique_ptr<AudioConverter>(new ResampleConverter(
|
||||
src_channels, src_frames, src_channels, dst_frames)));
|
||||
converters.push_back(std::unique_ptr<AudioConverter>(new UpmixConverter(
|
||||
src_channels, dst_frames, dst_channels, dst_frames)));
|
||||
sp.reset(new CompositionConverter(std::move(converters)));
|
||||
} else {
|
||||
sp.reset(new UpmixConverter(src_channels, src_frames, dst_channels,
|
||||
dst_frames));
|
||||
@ -168,22 +188,21 @@ rtc::scoped_ptr<AudioConverter> AudioConverter::Create(int src_channels,
|
||||
sp.reset(new ResampleConverter(src_channels, src_frames, dst_channels,
|
||||
dst_frames));
|
||||
} else {
|
||||
sp.reset(new CopyConverter(src_channels, src_frames, dst_channels,
|
||||
dst_frames));
|
||||
sp.reset(
|
||||
new CopyConverter(src_channels, src_frames, dst_channels, dst_frames));
|
||||
}
|
||||
|
||||
return sp.Pass();
|
||||
return sp;
|
||||
}
|
||||
|
||||
// For CompositionConverter.
|
||||
AudioConverter::AudioConverter()
|
||||
: src_channels_(0),
|
||||
src_frames_(0),
|
||||
dst_channels_(0),
|
||||
dst_frames_(0) {}
|
||||
: src_channels_(0), src_frames_(0), dst_channels_(0), dst_frames_(0) {}
|
||||
|
||||
AudioConverter::AudioConverter(int src_channels, size_t src_frames,
|
||||
int dst_channels, size_t dst_frames)
|
||||
AudioConverter::AudioConverter(size_t src_channels,
|
||||
size_t src_frames,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames)
|
||||
: src_channels_(src_channels),
|
||||
src_frames_(src_frames),
|
||||
dst_channels_(dst_channels),
|
||||
|
@ -8,11 +8,14 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_AUDIO_CONVERTER_H_
|
||||
#define WEBRTC_COMMON_AUDIO_AUDIO_CONVERTER_H_
|
||||
#ifndef COMMON_AUDIO_AUDIO_CONVERTER_H_
|
||||
#define COMMON_AUDIO_AUDIO_CONVERTER_H_
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -26,36 +29,40 @@ class AudioConverter {
|
||||
public:
|
||||
// Returns a new AudioConverter, which will use the supplied format for its
|
||||
// lifetime. Caller is responsible for the memory.
|
||||
static rtc::scoped_ptr<AudioConverter> Create(int src_channels,
|
||||
static std::unique_ptr<AudioConverter> Create(size_t src_channels,
|
||||
size_t src_frames,
|
||||
int dst_channels,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames);
|
||||
virtual ~AudioConverter() {};
|
||||
virtual ~AudioConverter() {}
|
||||
|
||||
// Convert |src|, containing |src_size| samples, to |dst|, having a sample
|
||||
// capacity of |dst_capacity|. Both point to a series of buffers containing
|
||||
// the samples for each channel. The sizes must correspond to the format
|
||||
// passed to Create().
|
||||
virtual void Convert(const float* const* src, size_t src_size,
|
||||
float* const* dst, size_t dst_capacity) = 0;
|
||||
virtual void Convert(const float* const* src,
|
||||
size_t src_size,
|
||||
float* const* dst,
|
||||
size_t dst_capacity) = 0;
|
||||
|
||||
int src_channels() const { return src_channels_; }
|
||||
size_t src_channels() const { return src_channels_; }
|
||||
size_t src_frames() const { return src_frames_; }
|
||||
int dst_channels() const { return dst_channels_; }
|
||||
size_t dst_channels() const { return dst_channels_; }
|
||||
size_t dst_frames() const { return dst_frames_; }
|
||||
|
||||
protected:
|
||||
AudioConverter();
|
||||
AudioConverter(int src_channels, size_t src_frames, int dst_channels,
|
||||
AudioConverter(size_t src_channels,
|
||||
size_t src_frames,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames);
|
||||
|
||||
// Helper to RTC_CHECK that inputs are correctly sized.
|
||||
void CheckSizes(size_t src_size, size_t dst_capacity) const;
|
||||
|
||||
private:
|
||||
const int src_channels_;
|
||||
const size_t src_channels_;
|
||||
const size_t src_frames_;
|
||||
const int dst_channels_;
|
||||
const size_t dst_channels_;
|
||||
const size_t dst_frames_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(AudioConverter);
|
||||
@ -63,4 +70,4 @@ class AudioConverter {
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_AUDIO_CONVERTER_H_
|
||||
#endif // COMMON_AUDIO_AUDIO_CONVERTER_H_
|
||||
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 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 "webrtc/common_audio/audio_ring_buffer.h"
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/common_audio/ring_buffer.h"
|
||||
|
||||
// This is a simple multi-channel wrapper over the ring_buffer.h C interface.
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
AudioRingBuffer::AudioRingBuffer(size_t channels, size_t max_frames) {
|
||||
buffers_.reserve(channels);
|
||||
for (size_t i = 0; i < channels; ++i)
|
||||
buffers_.push_back(WebRtc_CreateBuffer(max_frames, sizeof(float)));
|
||||
}
|
||||
|
||||
AudioRingBuffer::~AudioRingBuffer() {
|
||||
for (auto buf : buffers_)
|
||||
WebRtc_FreeBuffer(buf);
|
||||
}
|
||||
|
||||
void AudioRingBuffer::Write(const float* const* data, size_t channels,
|
||||
size_t frames) {
|
||||
RTC_DCHECK_EQ(buffers_.size(), channels);
|
||||
for (size_t i = 0; i < channels; ++i) {
|
||||
const size_t written = WebRtc_WriteBuffer(buffers_[i], data[i], frames);
|
||||
RTC_CHECK_EQ(written, frames);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioRingBuffer::Read(float* const* data, size_t channels, size_t frames) {
|
||||
RTC_DCHECK_EQ(buffers_.size(), channels);
|
||||
for (size_t i = 0; i < channels; ++i) {
|
||||
const size_t read =
|
||||
WebRtc_ReadBuffer(buffers_[i], nullptr, data[i], frames);
|
||||
RTC_CHECK_EQ(read, frames);
|
||||
}
|
||||
}
|
||||
|
||||
size_t AudioRingBuffer::ReadFramesAvailable() const {
|
||||
// All buffers have the same amount available.
|
||||
return WebRtc_available_read(buffers_[0]);
|
||||
}
|
||||
|
||||
size_t AudioRingBuffer::WriteFramesAvailable() const {
|
||||
// All buffers have the same amount available.
|
||||
return WebRtc_available_write(buffers_[0]);
|
||||
}
|
||||
|
||||
void AudioRingBuffer::MoveReadPositionForward(size_t frames) {
|
||||
for (auto buf : buffers_) {
|
||||
const size_t moved =
|
||||
static_cast<size_t>(WebRtc_MoveReadPtr(buf, static_cast<int>(frames)));
|
||||
RTC_CHECK_EQ(moved, frames);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioRingBuffer::MoveReadPositionBackward(size_t frames) {
|
||||
for (auto buf : buffers_) {
|
||||
const size_t moved = static_cast<size_t>(
|
||||
-WebRtc_MoveReadPtr(buf, -static_cast<int>(frames)));
|
||||
RTC_CHECK_EQ(moved, frames);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 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.
|
||||
*/
|
||||
#ifndef WEBRTC_COMMON_AUDIO_AUDIO_RING_BUFFER_H_
|
||||
#define WEBRTC_COMMON_AUDIO_AUDIO_RING_BUFFER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <vector>
|
||||
|
||||
struct RingBuffer;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// A ring buffer tailored for float deinterleaved audio. Any operation that
|
||||
// cannot be performed as requested will cause a crash (e.g. insufficient data
|
||||
// in the buffer to fulfill a read request.)
|
||||
class AudioRingBuffer final {
|
||||
public:
|
||||
// Specify the number of channels and maximum number of frames the buffer will
|
||||
// contain.
|
||||
AudioRingBuffer(size_t channels, size_t max_frames);
|
||||
~AudioRingBuffer();
|
||||
|
||||
// Copies |data| to the buffer and advances the write pointer. |channels| must
|
||||
// be the same as at creation time.
|
||||
void Write(const float* const* data, size_t channels, size_t frames);
|
||||
|
||||
// Copies from the buffer to |data| and advances the read pointer. |channels|
|
||||
// must be the same as at creation time.
|
||||
void Read(float* const* data, size_t channels, size_t frames);
|
||||
|
||||
size_t ReadFramesAvailable() const;
|
||||
size_t WriteFramesAvailable() const;
|
||||
|
||||
// Moves the read position. The forward version advances the read pointer
|
||||
// towards the write pointer and the backward verison withdraws the read
|
||||
// pointer away from the write pointer (i.e. flushing and stuffing the buffer
|
||||
// respectively.)
|
||||
void MoveReadPositionForward(size_t frames);
|
||||
void MoveReadPositionBackward(size_t frames);
|
||||
|
||||
private:
|
||||
// We don't use a ScopedVector because it doesn't support a specialized
|
||||
// deleter (like scoped_ptr for instance.)
|
||||
std::vector<RingBuffer*> buffers_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_AUDIO_RING_BUFFER_H_
|
@ -8,9 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/include/audio_util.h"
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
#include "common_audio/include/audio_util.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -24,6 +22,11 @@ void S16ToFloat(const int16_t* src, size_t size, float* dest) {
|
||||
dest[i] = S16ToFloat(src[i]);
|
||||
}
|
||||
|
||||
void S16ToFloatS16(const int16_t* src, size_t size, float* dest) {
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
dest[i] = src[i];
|
||||
}
|
||||
|
||||
void FloatS16ToS16(const float* src, size_t size, int16_t* dest) {
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
dest[i] = FloatS16ToS16(src[i]);
|
||||
|
@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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 "webrtc/common_audio/blocker.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Adds |a| and |b| frame by frame into |result| (basically matrix addition).
|
||||
void AddFrames(const float* const* a,
|
||||
size_t a_start_index,
|
||||
const float* const* b,
|
||||
int b_start_index,
|
||||
size_t num_frames,
|
||||
int num_channels,
|
||||
float* const* result,
|
||||
size_t result_start_index) {
|
||||
for (int i = 0; i < num_channels; ++i) {
|
||||
for (size_t j = 0; j < num_frames; ++j) {
|
||||
result[i][j + result_start_index] =
|
||||
a[i][j + a_start_index] + b[i][j + b_start_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copies |src| into |dst| channel by channel.
|
||||
void CopyFrames(const float* const* src,
|
||||
size_t src_start_index,
|
||||
size_t num_frames,
|
||||
int num_channels,
|
||||
float* const* dst,
|
||||
size_t dst_start_index) {
|
||||
for (int i = 0; i < num_channels; ++i) {
|
||||
memcpy(&dst[i][dst_start_index],
|
||||
&src[i][src_start_index],
|
||||
num_frames * sizeof(dst[i][dst_start_index]));
|
||||
}
|
||||
}
|
||||
|
||||
// Moves |src| into |dst| channel by channel.
|
||||
void MoveFrames(const float* const* src,
|
||||
size_t src_start_index,
|
||||
size_t num_frames,
|
||||
int num_channels,
|
||||
float* const* dst,
|
||||
size_t dst_start_index) {
|
||||
for (int i = 0; i < num_channels; ++i) {
|
||||
memmove(&dst[i][dst_start_index],
|
||||
&src[i][src_start_index],
|
||||
num_frames * sizeof(dst[i][dst_start_index]));
|
||||
}
|
||||
}
|
||||
|
||||
void ZeroOut(float* const* buffer,
|
||||
size_t starting_idx,
|
||||
size_t num_frames,
|
||||
int num_channels) {
|
||||
for (int i = 0; i < num_channels; ++i) {
|
||||
memset(&buffer[i][starting_idx], 0,
|
||||
num_frames * sizeof(buffer[i][starting_idx]));
|
||||
}
|
||||
}
|
||||
|
||||
// Pointwise multiplies each channel of |frames| with |window|. Results are
|
||||
// stored in |frames|.
|
||||
void ApplyWindow(const float* window,
|
||||
size_t num_frames,
|
||||
int num_channels,
|
||||
float* const* frames) {
|
||||
for (int i = 0; i < num_channels; ++i) {
|
||||
for (size_t j = 0; j < num_frames; ++j) {
|
||||
frames[i][j] = frames[i][j] * window[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t gcd(size_t a, size_t b) {
|
||||
size_t tmp;
|
||||
while (b) {
|
||||
tmp = a;
|
||||
a = b;
|
||||
b = tmp % b;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
Blocker::Blocker(size_t chunk_size,
|
||||
size_t block_size,
|
||||
int num_input_channels,
|
||||
int num_output_channels,
|
||||
const float* window,
|
||||
size_t shift_amount,
|
||||
BlockerCallback* callback)
|
||||
: chunk_size_(chunk_size),
|
||||
block_size_(block_size),
|
||||
num_input_channels_(num_input_channels),
|
||||
num_output_channels_(num_output_channels),
|
||||
initial_delay_(block_size_ - gcd(chunk_size, shift_amount)),
|
||||
frame_offset_(0),
|
||||
input_buffer_(num_input_channels_, chunk_size_ + initial_delay_),
|
||||
output_buffer_(chunk_size_ + initial_delay_, num_output_channels_),
|
||||
input_block_(block_size_, num_input_channels_),
|
||||
output_block_(block_size_, num_output_channels_),
|
||||
window_(new float[block_size_]),
|
||||
shift_amount_(shift_amount),
|
||||
callback_(callback) {
|
||||
RTC_CHECK_LE(num_output_channels_, num_input_channels_);
|
||||
RTC_CHECK_LE(shift_amount_, block_size_);
|
||||
|
||||
memcpy(window_.get(), window, block_size_ * sizeof(*window_.get()));
|
||||
input_buffer_.MoveReadPositionBackward(initial_delay_);
|
||||
}
|
||||
|
||||
// When block_size < chunk_size the input and output buffers look like this:
|
||||
//
|
||||
// delay* chunk_size chunk_size + delay*
|
||||
// buffer: <-------------|---------------------|---------------|>
|
||||
// _a_ _b_ _c_
|
||||
//
|
||||
// On each call to ProcessChunk():
|
||||
// 1. New input gets read into sections _b_ and _c_ of the input buffer.
|
||||
// 2. We block starting from frame_offset.
|
||||
// 3. We block until we reach a block |bl| that doesn't contain any frames
|
||||
// from sections _a_ or _b_ of the input buffer.
|
||||
// 4. We window the current block, fire the callback for processing, window
|
||||
// again, and overlap/add to the output buffer.
|
||||
// 5. We copy sections _a_ and _b_ of the output buffer into output.
|
||||
// 6. For both the input and the output buffers, we copy section _c_ into
|
||||
// section _a_.
|
||||
// 7. We set the new frame_offset to be the difference between the first frame
|
||||
// of |bl| and the border between sections _b_ and _c_.
|
||||
//
|
||||
// When block_size > chunk_size the input and output buffers look like this:
|
||||
//
|
||||
// chunk_size delay* chunk_size + delay*
|
||||
// buffer: <-------------|---------------------|---------------|>
|
||||
// _a_ _b_ _c_
|
||||
//
|
||||
// On each call to ProcessChunk():
|
||||
// The procedure is the same as above, except for:
|
||||
// 1. New input gets read into section _c_ of the input buffer.
|
||||
// 3. We block until we reach a block |bl| that doesn't contain any frames
|
||||
// from section _a_ of the input buffer.
|
||||
// 5. We copy section _a_ of the output buffer into output.
|
||||
// 6. For both the input and the output buffers, we copy sections _b_ and _c_
|
||||
// into section _a_ and _b_.
|
||||
// 7. We set the new frame_offset to be the difference between the first frame
|
||||
// of |bl| and the border between sections _a_ and _b_.
|
||||
//
|
||||
// * delay here refers to inintial_delay_
|
||||
//
|
||||
// TODO(claguna): Look at using ring buffers to eliminate some copies.
|
||||
void Blocker::ProcessChunk(const float* const* input,
|
||||
size_t chunk_size,
|
||||
int num_input_channels,
|
||||
int num_output_channels,
|
||||
float* const* output) {
|
||||
RTC_CHECK_EQ(chunk_size, chunk_size_);
|
||||
RTC_CHECK_EQ(num_input_channels, num_input_channels_);
|
||||
RTC_CHECK_EQ(num_output_channels, num_output_channels_);
|
||||
|
||||
input_buffer_.Write(input, num_input_channels, chunk_size_);
|
||||
size_t first_frame_in_block = frame_offset_;
|
||||
|
||||
// Loop through blocks.
|
||||
while (first_frame_in_block < chunk_size_) {
|
||||
input_buffer_.Read(input_block_.channels(), num_input_channels,
|
||||
block_size_);
|
||||
input_buffer_.MoveReadPositionBackward(block_size_ - shift_amount_);
|
||||
|
||||
ApplyWindow(window_.get(),
|
||||
block_size_,
|
||||
num_input_channels_,
|
||||
input_block_.channels());
|
||||
callback_->ProcessBlock(input_block_.channels(),
|
||||
block_size_,
|
||||
num_input_channels_,
|
||||
num_output_channels_,
|
||||
output_block_.channels());
|
||||
ApplyWindow(window_.get(),
|
||||
block_size_,
|
||||
num_output_channels_,
|
||||
output_block_.channels());
|
||||
|
||||
AddFrames(output_buffer_.channels(),
|
||||
first_frame_in_block,
|
||||
output_block_.channels(),
|
||||
0,
|
||||
block_size_,
|
||||
num_output_channels_,
|
||||
output_buffer_.channels(),
|
||||
first_frame_in_block);
|
||||
|
||||
first_frame_in_block += shift_amount_;
|
||||
}
|
||||
|
||||
// Copy output buffer to output
|
||||
CopyFrames(output_buffer_.channels(),
|
||||
0,
|
||||
chunk_size_,
|
||||
num_output_channels_,
|
||||
output,
|
||||
0);
|
||||
|
||||
// Copy output buffer [chunk_size_, chunk_size_ + initial_delay]
|
||||
// to output buffer [0, initial_delay], zero the rest.
|
||||
MoveFrames(output_buffer_.channels(),
|
||||
chunk_size,
|
||||
initial_delay_,
|
||||
num_output_channels_,
|
||||
output_buffer_.channels(),
|
||||
0);
|
||||
ZeroOut(output_buffer_.channels(),
|
||||
initial_delay_,
|
||||
chunk_size_,
|
||||
num_output_channels_);
|
||||
|
||||
// Calculate new starting frames.
|
||||
frame_offset_ = first_frame_in_block - chunk_size_;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_INTERNAL_BEAMFORMER_BLOCKER_H_
|
||||
#define WEBRTC_INTERNAL_BEAMFORMER_BLOCKER_H_
|
||||
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/common_audio/audio_ring_buffer.h"
|
||||
#include "webrtc/common_audio/channel_buffer.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// The callback function to process audio in the time domain. Input has already
|
||||
// been windowed, and output will be windowed. The number of input channels
|
||||
// must be >= the number of output channels.
|
||||
class BlockerCallback {
|
||||
public:
|
||||
virtual ~BlockerCallback() {}
|
||||
|
||||
virtual void ProcessBlock(const float* const* input,
|
||||
size_t num_frames,
|
||||
int num_input_channels,
|
||||
int num_output_channels,
|
||||
float* const* output) = 0;
|
||||
};
|
||||
|
||||
// The main purpose of Blocker is to abstract away the fact that often we
|
||||
// receive a different number of audio frames than our transform takes. For
|
||||
// example, most FFTs work best when the fft-size is a power of 2, but suppose
|
||||
// we receive 20ms of audio at a sample rate of 48000. That comes to 960 frames
|
||||
// of audio, which is not a power of 2. Blocker allows us to specify the
|
||||
// transform and all other necessary processing via the Process() callback
|
||||
// function without any constraints on the transform-size
|
||||
// (read: |block_size_|) or received-audio-size (read: |chunk_size_|).
|
||||
// We handle this for the multichannel audio case, allowing for different
|
||||
// numbers of input and output channels (for example, beamforming takes 2 or
|
||||
// more input channels and returns 1 output channel). Audio signals are
|
||||
// represented as deinterleaved floats in the range [-1, 1].
|
||||
//
|
||||
// Blocker is responsible for:
|
||||
// - blocking audio while handling potential discontinuities on the edges
|
||||
// of chunks
|
||||
// - windowing blocks before sending them to Process()
|
||||
// - windowing processed blocks, and overlap-adding them together before
|
||||
// sending back a processed chunk
|
||||
//
|
||||
// To use blocker:
|
||||
// 1. Impelment a BlockerCallback object |bc|.
|
||||
// 2. Instantiate a Blocker object |b|, passing in |bc|.
|
||||
// 3. As you receive audio, call b.ProcessChunk() to get processed audio.
|
||||
//
|
||||
// A small amount of delay is added to the first received chunk to deal with
|
||||
// the difference in chunk/block sizes. This delay is <= chunk_size.
|
||||
//
|
||||
// Ownership of window is retained by the caller. That is, Blocker makes a
|
||||
// copy of window and does not attempt to delete it.
|
||||
class Blocker {
|
||||
public:
|
||||
Blocker(size_t chunk_size,
|
||||
size_t block_size,
|
||||
int num_input_channels,
|
||||
int num_output_channels,
|
||||
const float* window,
|
||||
size_t shift_amount,
|
||||
BlockerCallback* callback);
|
||||
|
||||
void ProcessChunk(const float* const* input,
|
||||
size_t chunk_size,
|
||||
int num_input_channels,
|
||||
int num_output_channels,
|
||||
float* const* output);
|
||||
|
||||
private:
|
||||
const size_t chunk_size_;
|
||||
const size_t block_size_;
|
||||
const int num_input_channels_;
|
||||
const int num_output_channels_;
|
||||
|
||||
// The number of frames of delay to add at the beginning of the first chunk.
|
||||
const size_t initial_delay_;
|
||||
|
||||
// The frame index into the input buffer where the first block should be read
|
||||
// from. This is necessary because shift_amount_ is not necessarily a
|
||||
// multiple of chunk_size_, so blocks won't line up at the start of the
|
||||
// buffer.
|
||||
size_t frame_offset_;
|
||||
|
||||
// Since blocks nearly always overlap, there are certain blocks that require
|
||||
// frames from the end of one chunk and the beginning of the next chunk. The
|
||||
// input and output buffers are responsible for saving those frames between
|
||||
// calls to ProcessChunk().
|
||||
//
|
||||
// Both contain |initial delay| + |chunk_size| frames. The input is a fairly
|
||||
// standard FIFO, but due to the overlap-add it's harder to use an
|
||||
// AudioRingBuffer for the output.
|
||||
AudioRingBuffer input_buffer_;
|
||||
ChannelBuffer<float> output_buffer_;
|
||||
|
||||
// Space for the input block (can't wrap because of windowing).
|
||||
ChannelBuffer<float> input_block_;
|
||||
|
||||
// Space for the output block (can't wrap because of overlap/add).
|
||||
ChannelBuffer<float> output_block_;
|
||||
|
||||
rtc::scoped_ptr<float[]> window_;
|
||||
|
||||
// The amount of frames between the start of contiguous blocks. For example,
|
||||
// |shift_amount_| = |block_size_| / 2 for a Hann window.
|
||||
size_t shift_amount_;
|
||||
|
||||
BlockerCallback* callback_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_INTERNAL_BEAMFORMER_BLOCKER_H_
|
@ -8,18 +8,25 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/channel_buffer.h"
|
||||
#include "common_audio/channel_buffer.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "common_audio/include/audio_util.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
IFChannelBuffer::IFChannelBuffer(size_t num_frames,
|
||||
int num_channels,
|
||||
size_t num_channels,
|
||||
size_t num_bands)
|
||||
: ivalid_(true),
|
||||
ibuf_(num_frames, num_channels, num_bands),
|
||||
fvalid_(true),
|
||||
fbuf_(num_frames, num_channels, num_bands) {}
|
||||
|
||||
IFChannelBuffer::~IFChannelBuffer() = default;
|
||||
|
||||
ChannelBuffer<int16_t>* IFChannelBuffer::ibuf() {
|
||||
RefreshI();
|
||||
fvalid_ = false;
|
||||
@ -44,10 +51,11 @@ const ChannelBuffer<float>* IFChannelBuffer::fbuf_const() const {
|
||||
|
||||
void IFChannelBuffer::RefreshF() const {
|
||||
if (!fvalid_) {
|
||||
assert(ivalid_);
|
||||
RTC_DCHECK(ivalid_);
|
||||
fbuf_.set_num_channels(ibuf_.num_channels());
|
||||
const int16_t* const* int_channels = ibuf_.channels();
|
||||
float* const* float_channels = fbuf_.channels();
|
||||
for (int i = 0; i < ibuf_.num_channels(); ++i) {
|
||||
for (size_t i = 0; i < ibuf_.num_channels(); ++i) {
|
||||
for (size_t j = 0; j < ibuf_.num_frames(); ++j) {
|
||||
float_channels[i][j] = int_channels[i][j];
|
||||
}
|
||||
@ -58,13 +66,12 @@ void IFChannelBuffer::RefreshF() const {
|
||||
|
||||
void IFChannelBuffer::RefreshI() const {
|
||||
if (!ivalid_) {
|
||||
assert(fvalid_);
|
||||
RTC_DCHECK(fvalid_);
|
||||
int16_t* const* int_channels = ibuf_.channels();
|
||||
ibuf_.set_num_channels(fbuf_.num_channels());
|
||||
const float* const* float_channels = fbuf_.channels();
|
||||
for (int i = 0; i < ibuf_.num_channels(); ++i) {
|
||||
FloatS16ToS16(float_channels[i],
|
||||
ibuf_.num_frames(),
|
||||
int_channels[i]);
|
||||
for (size_t i = 0; i < fbuf_.num_channels(); ++i) {
|
||||
FloatS16ToS16(float_channels[i], ibuf_.num_frames(), int_channels[i]);
|
||||
}
|
||||
ivalid_ = true;
|
||||
}
|
||||
|
@ -8,17 +8,18 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_CHANNEL_BUFFER_H_
|
||||
#define WEBRTC_MODULES_AUDIO_PROCESSING_CHANNEL_BUFFER_H_
|
||||
#ifndef COMMON_AUDIO_CHANNEL_BUFFER_H_
|
||||
#define COMMON_AUDIO_CHANNEL_BUFFER_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/common_audio/include/audio_util.h"
|
||||
#ifndef WEBRTC_AUDIO_PROCESSING_ONLY_BUILD
|
||||
#include "webrtc/test/testsupport/gtest_prod_util.h"
|
||||
#endif
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "common_audio/include/audio_util.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/gtest_prod_util.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -41,49 +42,68 @@ namespace webrtc {
|
||||
template <typename T>
|
||||
class ChannelBuffer {
|
||||
public:
|
||||
ChannelBuffer(size_t num_frames,
|
||||
int num_channels,
|
||||
size_t num_bands = 1)
|
||||
ChannelBuffer(size_t num_frames, size_t num_channels, size_t num_bands = 1)
|
||||
: data_(new T[num_frames * num_channels]()),
|
||||
channels_(new T*[num_channels * num_bands]),
|
||||
bands_(new T*[num_channels * num_bands]),
|
||||
num_frames_(num_frames),
|
||||
num_frames_per_band_(num_frames / num_bands),
|
||||
num_allocated_channels_(num_channels),
|
||||
num_channels_(num_channels),
|
||||
num_bands_(num_bands) {
|
||||
for (int i = 0; i < num_channels_; ++i) {
|
||||
for (size_t j = 0; j < num_bands_; ++j) {
|
||||
channels_[j * num_channels_ + i] =
|
||||
&data_[i * num_frames_ + j * num_frames_per_band_];
|
||||
bands_[i * num_bands_ + j] = channels_[j * num_channels_ + i];
|
||||
num_bands_(num_bands),
|
||||
bands_view_(num_allocated_channels_,
|
||||
std::vector<rtc::ArrayView<T>>(num_bands_)),
|
||||
channels_view_(
|
||||
num_bands_,
|
||||
std::vector<rtc::ArrayView<T>>(num_allocated_channels_)) {
|
||||
// Temporarily cast away const_ness to allow populating the array views.
|
||||
auto* bands_view =
|
||||
const_cast<std::vector<std::vector<rtc::ArrayView<T>>>*>(&bands_view_);
|
||||
auto* channels_view =
|
||||
const_cast<std::vector<std::vector<rtc::ArrayView<T>>>*>(
|
||||
&channels_view_);
|
||||
|
||||
for (size_t ch = 0; ch < num_allocated_channels_; ++ch) {
|
||||
for (size_t band = 0; band < num_bands_; ++band) {
|
||||
(*channels_view)[band][ch] = rtc::ArrayView<T>(
|
||||
&data_[ch * num_frames_ + band * num_frames_per_band_],
|
||||
num_frames_per_band_);
|
||||
(*bands_view)[ch][band] = channels_view_[band][ch];
|
||||
channels_[band * num_allocated_channels_ + ch] =
|
||||
channels_view_[band][ch].data();
|
||||
bands_[ch * num_bands_ + band] =
|
||||
channels_[band * num_allocated_channels_ + ch];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a pointer array to the full-band channels (or lower band channels).
|
||||
// Usage:
|
||||
// channels()[channel][sample].
|
||||
// Where:
|
||||
// 0 <= channel < |num_channels_|
|
||||
// 0 <= sample < |num_frames_|
|
||||
T* const* channels() { return channels(0); }
|
||||
const T* const* channels() const { return channels(0); }
|
||||
|
||||
// Returns a pointer array to the channels for a specific band.
|
||||
// Usage:
|
||||
// channels(band)[channel][sample].
|
||||
// Returns a pointer array to the channels.
|
||||
// If band is explicitly specificed, the channels for a specific band are
|
||||
// returned and the usage becomes: channels(band)[channel][sample].
|
||||
// Where:
|
||||
// 0 <= band < |num_bands_|
|
||||
// 0 <= channel < |num_channels_|
|
||||
// 0 <= channel < |num_allocated_channels_|
|
||||
// 0 <= sample < |num_frames_per_band_|
|
||||
const T* const* channels(size_t band) const {
|
||||
|
||||
// If band is not explicitly specified, the full-band channels (or lower band
|
||||
// channels) are returned and the usage becomes: channels()[channel][sample].
|
||||
// Where:
|
||||
// 0 <= channel < |num_allocated_channels_|
|
||||
// 0 <= sample < |num_frames_|
|
||||
const T* const* channels(size_t band = 0) const {
|
||||
RTC_DCHECK_LT(band, num_bands_);
|
||||
return &channels_[band * num_channels_];
|
||||
return &channels_[band * num_allocated_channels_];
|
||||
}
|
||||
T* const* channels(size_t band) {
|
||||
T* const* channels(size_t band = 0) {
|
||||
const ChannelBuffer<T>* t = this;
|
||||
return const_cast<T* const*>(t->channels(band));
|
||||
}
|
||||
rtc::ArrayView<const rtc::ArrayView<T>> channels_view(size_t band = 0) {
|
||||
return channels_view_[band];
|
||||
}
|
||||
rtc::ArrayView<const rtc::ArrayView<T>> channels_view(size_t band = 0) const {
|
||||
return channels_view_[band];
|
||||
}
|
||||
|
||||
// Returns a pointer array to the bands for a specific channel.
|
||||
// Usage:
|
||||
@ -92,21 +112,28 @@ class ChannelBuffer {
|
||||
// 0 <= channel < |num_channels_|
|
||||
// 0 <= band < |num_bands_|
|
||||
// 0 <= sample < |num_frames_per_band_|
|
||||
const T* const* bands(int channel) const {
|
||||
const T* const* bands(size_t channel) const {
|
||||
RTC_DCHECK_LT(channel, num_channels_);
|
||||
RTC_DCHECK_GE(channel, 0);
|
||||
return &bands_[channel * num_bands_];
|
||||
}
|
||||
T* const* bands(int channel) {
|
||||
T* const* bands(size_t channel) {
|
||||
const ChannelBuffer<T>* t = this;
|
||||
return const_cast<T* const*>(t->bands(channel));
|
||||
}
|
||||
|
||||
rtc::ArrayView<const rtc::ArrayView<T>> bands_view(size_t channel) {
|
||||
return bands_view_[channel];
|
||||
}
|
||||
rtc::ArrayView<const rtc::ArrayView<T>> bands_view(size_t channel) const {
|
||||
return bands_view_[channel];
|
||||
}
|
||||
|
||||
// Sets the |slice| pointers to the |start_frame| position for each channel.
|
||||
// Returns |slice| for convenience.
|
||||
const T* const* Slice(T** slice, size_t start_frame) const {
|
||||
RTC_DCHECK_LT(start_frame, num_frames_);
|
||||
for (int i = 0; i < num_channels_; ++i)
|
||||
for (size_t i = 0; i < num_channels_; ++i)
|
||||
slice[i] = &channels_[i][start_frame];
|
||||
return slice;
|
||||
}
|
||||
@ -117,9 +144,14 @@ class ChannelBuffer {
|
||||
|
||||
size_t num_frames() const { return num_frames_; }
|
||||
size_t num_frames_per_band() const { return num_frames_per_band_; }
|
||||
int num_channels() const { return num_channels_; }
|
||||
size_t num_channels() const { return num_channels_; }
|
||||
size_t num_bands() const { return num_bands_; }
|
||||
size_t size() const {return num_frames_ * num_channels_; }
|
||||
size_t size() const { return num_frames_ * num_allocated_channels_; }
|
||||
|
||||
void set_num_channels(size_t num_channels) {
|
||||
RTC_DCHECK_LE(num_channels, num_allocated_channels_);
|
||||
num_channels_ = num_channels;
|
||||
}
|
||||
|
||||
void SetDataForTesting(const T* data, size_t size) {
|
||||
RTC_CHECK_EQ(size, this->size());
|
||||
@ -127,13 +159,18 @@ class ChannelBuffer {
|
||||
}
|
||||
|
||||
private:
|
||||
rtc::scoped_ptr<T[]> data_;
|
||||
rtc::scoped_ptr<T* []> channels_;
|
||||
rtc::scoped_ptr<T* []> bands_;
|
||||
std::unique_ptr<T[]> data_;
|
||||
std::unique_ptr<T*[]> channels_;
|
||||
std::unique_ptr<T*[]> bands_;
|
||||
const size_t num_frames_;
|
||||
const size_t num_frames_per_band_;
|
||||
const int num_channels_;
|
||||
// Number of channels the internal buffer holds.
|
||||
const size_t num_allocated_channels_;
|
||||
// Number of channels the user sees.
|
||||
size_t num_channels_;
|
||||
const size_t num_bands_;
|
||||
const std::vector<std::vector<rtc::ArrayView<T>>> bands_view_;
|
||||
const std::vector<std::vector<rtc::ArrayView<T>>> channels_view_;
|
||||
};
|
||||
|
||||
// One int16_t and one float ChannelBuffer that are kept in sync. The sync is
|
||||
@ -144,7 +181,8 @@ class ChannelBuffer {
|
||||
// fbuf() until the next call to any of the other functions.
|
||||
class IFChannelBuffer {
|
||||
public:
|
||||
IFChannelBuffer(size_t num_frames, int num_channels, size_t num_bands = 1);
|
||||
IFChannelBuffer(size_t num_frames, size_t num_channels, size_t num_bands = 1);
|
||||
~IFChannelBuffer();
|
||||
|
||||
ChannelBuffer<int16_t>* ibuf();
|
||||
ChannelBuffer<float>* fbuf();
|
||||
@ -153,7 +191,13 @@ class IFChannelBuffer {
|
||||
|
||||
size_t num_frames() const { return ibuf_.num_frames(); }
|
||||
size_t num_frames_per_band() const { return ibuf_.num_frames_per_band(); }
|
||||
int num_channels() const { return ibuf_.num_channels(); }
|
||||
size_t num_channels() const {
|
||||
return ivalid_ ? ibuf_.num_channels() : fbuf_.num_channels();
|
||||
}
|
||||
void set_num_channels(size_t num_channels) {
|
||||
ibuf_.set_num_channels(num_channels);
|
||||
fbuf_.set_num_channels(num_channels);
|
||||
}
|
||||
size_t num_bands() const { return ibuf_.num_bands(); }
|
||||
|
||||
private:
|
||||
@ -168,4 +212,4 @@ class IFChannelBuffer {
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_CHANNEL_BUFFER_H_
|
||||
#endif // COMMON_AUDIO_CHANNEL_BUFFER_H_
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_FFT4G_H_
|
||||
#define WEBRTC_COMMON_AUDIO_FFT4G_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Refer to fft4g.c for documentation.
|
||||
void WebRtc_rdft(size_t n, int isgn, float *a, size_t *ip, float *w);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_FFT4G_H_
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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 "webrtc/common_audio/fir_filter.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/common_audio/fir_filter_neon.h"
|
||||
#include "webrtc/common_audio/fir_filter_sse.h"
|
||||
#include "webrtc/system_wrappers/include/cpu_features_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class FIRFilterC : public FIRFilter {
|
||||
public:
|
||||
FIRFilterC(const float* coefficients,
|
||||
size_t coefficients_length);
|
||||
|
||||
void Filter(const float* in, size_t length, float* out) override;
|
||||
|
||||
private:
|
||||
size_t coefficients_length_;
|
||||
size_t state_length_;
|
||||
rtc::scoped_ptr<float[]> coefficients_;
|
||||
rtc::scoped_ptr<float[]> state_;
|
||||
};
|
||||
|
||||
FIRFilter* FIRFilter::Create(const float* coefficients,
|
||||
size_t coefficients_length,
|
||||
size_t max_input_length) {
|
||||
if (!coefficients || coefficients_length <= 0 || max_input_length <= 0) {
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FIRFilter* filter = NULL;
|
||||
// If we know the minimum architecture at compile time, avoid CPU detection.
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
#if defined(__SSE2__)
|
||||
filter =
|
||||
new FIRFilterSSE2(coefficients, coefficients_length, max_input_length);
|
||||
#else
|
||||
// x86 CPU detection required.
|
||||
if (WebRtc_GetCPUInfo(kSSE2)) {
|
||||
filter =
|
||||
new FIRFilterSSE2(coefficients, coefficients_length, max_input_length);
|
||||
} else {
|
||||
filter = new FIRFilterC(coefficients, coefficients_length);
|
||||
}
|
||||
#endif
|
||||
#elif defined(WEBRTC_HAS_NEON)
|
||||
filter =
|
||||
new FIRFilterNEON(coefficients, coefficients_length, max_input_length);
|
||||
#elif defined(WEBRTC_DETECT_NEON)
|
||||
if (WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) {
|
||||
filter =
|
||||
new FIRFilterNEON(coefficients, coefficients_length, max_input_length);
|
||||
} else {
|
||||
filter = new FIRFilterC(coefficients, coefficients_length);
|
||||
}
|
||||
#else
|
||||
filter = new FIRFilterC(coefficients, coefficients_length);
|
||||
#endif
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
FIRFilterC::FIRFilterC(const float* coefficients, size_t coefficients_length)
|
||||
: coefficients_length_(coefficients_length),
|
||||
state_length_(coefficients_length - 1),
|
||||
coefficients_(new float[coefficients_length_]),
|
||||
state_(new float[state_length_]) {
|
||||
for (size_t i = 0; i < coefficients_length_; ++i) {
|
||||
coefficients_[i] = coefficients[coefficients_length_ - i - 1];
|
||||
}
|
||||
memset(state_.get(), 0, state_length_ * sizeof(state_[0]));
|
||||
}
|
||||
|
||||
void FIRFilterC::Filter(const float* in, size_t length, float* out) {
|
||||
assert(length > 0);
|
||||
|
||||
// Convolves the input signal |in| with the filter kernel |coefficients_|
|
||||
// taking into account the previous state.
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
out[i] = 0.f;
|
||||
size_t j;
|
||||
for (j = 0; state_length_ > i && j < state_length_ - i; ++j) {
|
||||
out[i] += state_[i + j] * coefficients_[j];
|
||||
}
|
||||
for (; j < coefficients_length_; ++j) {
|
||||
out[i] += in[j + i - state_length_] * coefficients_[j];
|
||||
}
|
||||
}
|
||||
|
||||
// Update current state.
|
||||
if (length >= state_length_) {
|
||||
memcpy(
|
||||
state_.get(), &in[length - state_length_], state_length_ * sizeof(*in));
|
||||
} else {
|
||||
memmove(state_.get(),
|
||||
&state_[length],
|
||||
(state_length_ - length) * sizeof(state_[0]));
|
||||
memcpy(&state_[state_length_ - length], in, length * sizeof(*in));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -8,8 +8,8 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_FIR_FILTER_H_
|
||||
#define WEBRTC_COMMON_AUDIO_FIR_FILTER_H_
|
||||
#ifndef COMMON_AUDIO_FIR_FILTER_H_
|
||||
#define COMMON_AUDIO_FIR_FILTER_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -18,16 +18,6 @@ namespace webrtc {
|
||||
// Finite Impulse Response filter using floating-point arithmetic.
|
||||
class FIRFilter {
|
||||
public:
|
||||
// Creates a filter with the given coefficients. All initial state values will
|
||||
// be zeros.
|
||||
// The length of the chunks fed to the filter should never be greater than
|
||||
// |max_input_length|. This is needed because, when vectorizing it is
|
||||
// necessary to concatenate the input after the state, and resizing this array
|
||||
// dynamically is expensive.
|
||||
static FIRFilter* Create(const float* coefficients,
|
||||
size_t coefficients_length,
|
||||
size_t max_input_length);
|
||||
|
||||
virtual ~FIRFilter() {}
|
||||
|
||||
// Filters the |in| data supplied.
|
||||
@ -37,4 +27,4 @@ class FIRFilter {
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_FIR_FILTER_H_
|
||||
#endif // COMMON_AUDIO_FIR_FILTER_H_
|
||||
|
88
webrtc/common_audio/fir_filter_avx2.cc
Normal file
88
webrtc/common_audio/fir_filter_avx2.cc
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 "common_audio/fir_filter_avx2.h"
|
||||
|
||||
#include <immintrin.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/memory/aligned_malloc.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
FIRFilterAVX2::FIRFilterAVX2(const float* unaligned_coefficients,
|
||||
size_t unaligned_coefficients_length,
|
||||
size_t max_input_length)
|
||||
: // Closest higher multiple of eight.
|
||||
coefficients_length_((unaligned_coefficients_length + 7) & ~0x07),
|
||||
state_length_(coefficients_length_ - 1),
|
||||
coefficients_(static_cast<float*>(
|
||||
AlignedMalloc(sizeof(float) * coefficients_length_, 32))),
|
||||
state_(static_cast<float*>(
|
||||
AlignedMalloc(sizeof(float) * (max_input_length + state_length_),
|
||||
32))) {
|
||||
// Add zeros at the end of the coefficients.
|
||||
RTC_DCHECK_GE(coefficients_length_, unaligned_coefficients_length);
|
||||
size_t padding = coefficients_length_ - unaligned_coefficients_length;
|
||||
memset(coefficients_.get(), 0, padding * sizeof(coefficients_[0]));
|
||||
// The coefficients are reversed to compensate for the order in which the
|
||||
// input samples are acquired (most recent last).
|
||||
for (size_t i = 0; i < unaligned_coefficients_length; ++i) {
|
||||
coefficients_[i + padding] =
|
||||
unaligned_coefficients[unaligned_coefficients_length - i - 1];
|
||||
}
|
||||
memset(state_.get(), 0,
|
||||
(max_input_length + state_length_) * sizeof(state_[0]));
|
||||
}
|
||||
|
||||
FIRFilterAVX2::~FIRFilterAVX2() = default;
|
||||
|
||||
void FIRFilterAVX2::Filter(const float* in, size_t length, float* out) {
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
memcpy(&state_[state_length_], in, length * sizeof(*in));
|
||||
|
||||
// Convolves the input signal |in| with the filter kernel |coefficients_|
|
||||
// taking into account the previous state.
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
float* in_ptr = &state_[i];
|
||||
float* coef_ptr = coefficients_.get();
|
||||
|
||||
__m256 m_sum = _mm256_setzero_ps();
|
||||
__m256 m_in;
|
||||
|
||||
// Depending on if the pointer is aligned with 32 bytes or not it is loaded
|
||||
// differently.
|
||||
if (reinterpret_cast<uintptr_t>(in_ptr) & 0x1F) {
|
||||
for (size_t j = 0; j < coefficients_length_; j += 8) {
|
||||
m_in = _mm256_loadu_ps(in_ptr + j);
|
||||
m_sum = _mm256_fmadd_ps(m_in, _mm256_load_ps(coef_ptr + j), m_sum);
|
||||
}
|
||||
} else {
|
||||
for (size_t j = 0; j < coefficients_length_; j += 8) {
|
||||
m_in = _mm256_load_ps(in_ptr + j);
|
||||
m_sum = _mm256_fmadd_ps(m_in, _mm256_load_ps(coef_ptr + j), m_sum);
|
||||
}
|
||||
}
|
||||
__m128 m128_sum = _mm_add_ps(_mm256_extractf128_ps(m_sum, 0),
|
||||
_mm256_extractf128_ps(m_sum, 1));
|
||||
m128_sum = _mm_add_ps(_mm_movehl_ps(m128_sum, m128_sum), m128_sum);
|
||||
_mm_store_ss(out + i,
|
||||
_mm_add_ss(m128_sum, _mm_shuffle_ps(m128_sum, m128_sum, 1)));
|
||||
}
|
||||
|
||||
// Update current state.
|
||||
memmove(state_.get(), &state_[length], state_length_ * sizeof(state_[0]));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
41
webrtc/common_audio/fir_filter_avx2.h
Normal file
41
webrtc/common_audio/fir_filter_avx2.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_AUDIO_FIR_FILTER_AVX2_H_
|
||||
#define COMMON_AUDIO_FIR_FILTER_AVX2_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common_audio/fir_filter.h"
|
||||
#include "rtc_base/memory/aligned_malloc.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class FIRFilterAVX2 : public FIRFilter {
|
||||
public:
|
||||
FIRFilterAVX2(const float* coefficients,
|
||||
size_t coefficients_length,
|
||||
size_t max_input_length);
|
||||
~FIRFilterAVX2() override;
|
||||
|
||||
void Filter(const float* in, size_t length, float* out) override;
|
||||
|
||||
private:
|
||||
const size_t coefficients_length_;
|
||||
const size_t state_length_;
|
||||
std::unique_ptr<float[], AlignedFreeDeleter> coefficients_;
|
||||
std::unique_ptr<float[], AlignedFreeDeleter> state_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // COMMON_AUDIO_FIR_FILTER_AVX2_H_
|
61
webrtc/common_audio/fir_filter_c.cc
Normal file
61
webrtc/common_audio/fir_filter_c.cc
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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 "common_audio/fir_filter_c.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
FIRFilterC::~FIRFilterC() {}
|
||||
|
||||
FIRFilterC::FIRFilterC(const float* coefficients, size_t coefficients_length)
|
||||
: coefficients_length_(coefficients_length),
|
||||
state_length_(coefficients_length - 1),
|
||||
coefficients_(new float[coefficients_length_]),
|
||||
state_(new float[state_length_]) {
|
||||
for (size_t i = 0; i < coefficients_length_; ++i) {
|
||||
coefficients_[i] = coefficients[coefficients_length_ - i - 1];
|
||||
}
|
||||
memset(state_.get(), 0, state_length_ * sizeof(state_[0]));
|
||||
}
|
||||
|
||||
void FIRFilterC::Filter(const float* in, size_t length, float* out) {
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
// Convolves the input signal |in| with the filter kernel |coefficients_|
|
||||
// taking into account the previous state.
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
out[i] = 0.f;
|
||||
size_t j;
|
||||
for (j = 0; state_length_ > i && j < state_length_ - i; ++j) {
|
||||
out[i] += state_[i + j] * coefficients_[j];
|
||||
}
|
||||
for (; j < coefficients_length_; ++j) {
|
||||
out[i] += in[j + i - state_length_] * coefficients_[j];
|
||||
}
|
||||
}
|
||||
|
||||
// Update current state.
|
||||
if (length >= state_length_) {
|
||||
memcpy(state_.get(), &in[length - state_length_],
|
||||
state_length_ * sizeof(*in));
|
||||
} else {
|
||||
memmove(state_.get(), &state_[length],
|
||||
(state_length_ - length) * sizeof(state_[0]));
|
||||
memcpy(&state_[state_length_ - length], in, length * sizeof(*in));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
38
webrtc/common_audio/fir_filter_c.h
Normal file
38
webrtc/common_audio/fir_filter_c.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_AUDIO_FIR_FILTER_C_H_
|
||||
#define COMMON_AUDIO_FIR_FILTER_C_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common_audio/fir_filter.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class FIRFilterC : public FIRFilter {
|
||||
public:
|
||||
FIRFilterC(const float* coefficients, size_t coefficients_length);
|
||||
~FIRFilterC() override;
|
||||
|
||||
void Filter(const float* in, size_t length, float* out) override;
|
||||
|
||||
private:
|
||||
size_t coefficients_length_;
|
||||
size_t state_length_;
|
||||
std::unique_ptr<float[]> coefficients_;
|
||||
std::unique_ptr<float[]> state_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // COMMON_AUDIO_FIR_FILTER_C_H_
|
58
webrtc/common_audio/fir_filter_factory.cc
Normal file
58
webrtc/common_audio/fir_filter_factory.cc
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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 "common_audio/fir_filter_factory.h"
|
||||
|
||||
#include "common_audio/fir_filter_c.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/system/arch.h"
|
||||
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
#include "common_audio/fir_filter_neon.h"
|
||||
#elif defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
#include "common_audio/fir_filter_avx2.h"
|
||||
#include "common_audio/fir_filter_sse.h"
|
||||
#include "system_wrappers/include/cpu_features_wrapper.h" // kSSE2, WebRtc_G...
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
FIRFilter* CreateFirFilter(const float* coefficients,
|
||||
size_t coefficients_length,
|
||||
size_t max_input_length) {
|
||||
if (!coefficients || coefficients_length <= 0 || max_input_length <= 0) {
|
||||
RTC_NOTREACHED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FIRFilter* filter = nullptr;
|
||||
// If we know the minimum architecture at compile time, avoid CPU detection.
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
// x86 CPU detection required.
|
||||
if (GetCPUInfo(kAVX2)) {
|
||||
filter =
|
||||
new FIRFilterAVX2(coefficients, coefficients_length, max_input_length);
|
||||
} else if (GetCPUInfo(kSSE2)) {
|
||||
filter =
|
||||
new FIRFilterSSE2(coefficients, coefficients_length, max_input_length);
|
||||
} else {
|
||||
filter = new FIRFilterC(coefficients, coefficients_length);
|
||||
}
|
||||
#elif defined(WEBRTC_HAS_NEON)
|
||||
filter =
|
||||
new FIRFilterNEON(coefficients, coefficients_length, max_input_length);
|
||||
#else
|
||||
filter = new FIRFilterC(coefficients, coefficients_length);
|
||||
#endif
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
32
webrtc/common_audio/fir_filter_factory.h
Normal file
32
webrtc/common_audio/fir_filter_factory.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_AUDIO_FIR_FILTER_FACTORY_H_
|
||||
#define COMMON_AUDIO_FIR_FILTER_FACTORY_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class FIRFilter;
|
||||
|
||||
// Creates a filter with the given coefficients. All initial state values will
|
||||
// be zeros.
|
||||
// The length of the chunks fed to the filter should never be greater than
|
||||
// |max_input_length|. This is needed because, when vectorizing it is
|
||||
// necessary to concatenate the input after the state, and resizing this array
|
||||
// dynamically is expensive.
|
||||
FIRFilter* CreateFirFilter(const float* coefficients,
|
||||
size_t coefficients_length,
|
||||
size_t max_input_length);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // COMMON_AUDIO_FIR_FILTER_FACTORY_H_
|
@ -8,16 +8,18 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/fir_filter_neon.h"
|
||||
#include "common_audio/fir_filter_neon.h"
|
||||
|
||||
#include <arm_neon.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "webrtc/system_wrappers/include/aligned_malloc.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/memory/aligned_malloc.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
FIRFilterNEON::~FIRFilterNEON() {}
|
||||
|
||||
FIRFilterNEON::FIRFilterNEON(const float* coefficients,
|
||||
size_t coefficients_length,
|
||||
size_t max_input_length)
|
||||
@ -37,13 +39,12 @@ FIRFilterNEON::FIRFilterNEON(const float* coefficients,
|
||||
for (size_t i = 0; i < coefficients_length; ++i) {
|
||||
coefficients_[i + padding] = coefficients[coefficients_length - i - 1];
|
||||
}
|
||||
memset(state_.get(),
|
||||
0.f,
|
||||
memset(state_.get(), 0.f,
|
||||
(max_input_length + state_length_) * sizeof(state_[0]));
|
||||
}
|
||||
|
||||
void FIRFilterNEON::Filter(const float* in, size_t length, float* out) {
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
memcpy(&state_[state_length_], in, length * sizeof(*in));
|
||||
|
||||
@ -57,8 +58,8 @@ void FIRFilterNEON::Filter(const float* in, size_t length, float* out) {
|
||||
float32x4_t m_in;
|
||||
|
||||
for (size_t j = 0; j < coefficients_length_; j += 4) {
|
||||
m_in = vld1q_f32(in_ptr + j);
|
||||
m_sum = vmlaq_f32(m_sum, m_in, vld1q_f32(coef_ptr + j));
|
||||
m_in = vld1q_f32(in_ptr + j);
|
||||
m_sum = vmlaq_f32(m_sum, m_in, vld1q_f32(coef_ptr + j));
|
||||
}
|
||||
|
||||
float32x2_t m_half = vadd_f32(vget_high_f32(m_sum), vget_low_f32(m_sum));
|
||||
|
@ -8,12 +8,13 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_FIR_FILTER_NEON_H_
|
||||
#define WEBRTC_COMMON_AUDIO_FIR_FILTER_NEON_H_
|
||||
#ifndef COMMON_AUDIO_FIR_FILTER_NEON_H_
|
||||
#define COMMON_AUDIO_FIR_FILTER_NEON_H_
|
||||
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/common_audio/fir_filter.h"
|
||||
#include "webrtc/system_wrappers/include/aligned_malloc.h"
|
||||
#include <memory>
|
||||
|
||||
#include "common_audio/fir_filter.h"
|
||||
#include "rtc_base/memory/aligned_malloc.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -22,16 +23,17 @@ class FIRFilterNEON : public FIRFilter {
|
||||
FIRFilterNEON(const float* coefficients,
|
||||
size_t coefficients_length,
|
||||
size_t max_input_length);
|
||||
~FIRFilterNEON() override;
|
||||
|
||||
void Filter(const float* in, size_t length, float* out) override;
|
||||
|
||||
private:
|
||||
size_t coefficients_length_;
|
||||
size_t state_length_;
|
||||
rtc::scoped_ptr<float[], AlignedFreeDeleter> coefficients_;
|
||||
rtc::scoped_ptr<float[], AlignedFreeDeleter> state_;
|
||||
std::unique_ptr<float[], AlignedFreeDeleter> coefficients_;
|
||||
std::unique_ptr<float[], AlignedFreeDeleter> state_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_FIR_FILTER_NEON_H_
|
||||
#endif // COMMON_AUDIO_FIR_FILTER_NEON_H_
|
||||
|
@ -8,16 +8,19 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/fir_filter_sse.h"
|
||||
#include "common_audio/fir_filter_sse.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#include "webrtc/system_wrappers/include/aligned_malloc.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/memory/aligned_malloc.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
FIRFilterSSE2::~FIRFilterSSE2() {}
|
||||
|
||||
FIRFilterSSE2::FIRFilterSSE2(const float* coefficients,
|
||||
size_t coefficients_length,
|
||||
size_t max_input_length)
|
||||
@ -37,13 +40,12 @@ FIRFilterSSE2::FIRFilterSSE2(const float* coefficients,
|
||||
for (size_t i = 0; i < coefficients_length; ++i) {
|
||||
coefficients_[i + padding] = coefficients[coefficients_length - i - 1];
|
||||
}
|
||||
memset(state_.get(),
|
||||
0,
|
||||
memset(state_.get(), 0,
|
||||
(max_input_length + state_length_) * sizeof(state_[0]));
|
||||
}
|
||||
|
||||
void FIRFilterSSE2::Filter(const float* in, size_t length, float* out) {
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
memcpy(&state_[state_length_], in, length * sizeof(*in));
|
||||
|
||||
|
@ -8,12 +8,15 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_FIR_FILTER_SSE_H_
|
||||
#define WEBRTC_COMMON_AUDIO_FIR_FILTER_SSE_H_
|
||||
#ifndef COMMON_AUDIO_FIR_FILTER_SSE_H_
|
||||
#define COMMON_AUDIO_FIR_FILTER_SSE_H_
|
||||
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/common_audio/fir_filter.h"
|
||||
#include "webrtc/system_wrappers/include/aligned_malloc.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common_audio/fir_filter.h"
|
||||
#include "rtc_base/memory/aligned_malloc.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -22,16 +25,17 @@ class FIRFilterSSE2 : public FIRFilter {
|
||||
FIRFilterSSE2(const float* coefficients,
|
||||
size_t coefficients_length,
|
||||
size_t max_input_length);
|
||||
~FIRFilterSSE2() override;
|
||||
|
||||
void Filter(const float* in, size_t length, float* out) override;
|
||||
|
||||
private:
|
||||
size_t coefficients_length_;
|
||||
size_t state_length_;
|
||||
rtc::scoped_ptr<float[], AlignedFreeDeleter> coefficients_;
|
||||
rtc::scoped_ptr<float[], AlignedFreeDeleter> state_;
|
||||
std::unique_ptr<float[], AlignedFreeDeleter> coefficients_;
|
||||
std::unique_ptr<float[], AlignedFreeDeleter> state_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_FIR_FILTER_SSE_H_
|
||||
#endif // COMMON_AUDIO_FIR_FILTER_SSE_H_
|
||||
|
@ -8,15 +8,17 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
|
||||
#define WEBRTC_COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
|
||||
#ifndef COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
|
||||
#define COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
|
||||
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -25,46 +27,70 @@ typedef std::numeric_limits<int16_t> limits_int16;
|
||||
// The conversion functions use the following naming convention:
|
||||
// S16: int16_t [-32768, 32767]
|
||||
// Float: float [-1.0, 1.0]
|
||||
// FloatS16: float [-32768.0, 32767.0]
|
||||
static inline int16_t FloatToS16(float v) {
|
||||
if (v > 0)
|
||||
return v >= 1 ? limits_int16::max()
|
||||
: static_cast<int16_t>(v * limits_int16::max() + 0.5f);
|
||||
return v <= -1 ? limits_int16::min()
|
||||
: static_cast<int16_t>(-v * limits_int16::min() - 0.5f);
|
||||
}
|
||||
|
||||
// FloatS16: float [-32768.0, 32768.0]
|
||||
// Dbfs: float [-20.0*log(10, 32768), 0] = [-90.3, 0]
|
||||
// The ratio conversion functions use this naming convention:
|
||||
// Ratio: float (0, +inf)
|
||||
// Db: float (-inf, +inf)
|
||||
static inline float S16ToFloat(int16_t v) {
|
||||
static const float kMaxInt16Inverse = 1.f / limits_int16::max();
|
||||
static const float kMinInt16Inverse = 1.f / limits_int16::min();
|
||||
return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
|
||||
constexpr float kScaling = 1.f / 32768.f;
|
||||
return v * kScaling;
|
||||
}
|
||||
|
||||
static inline int16_t FloatS16ToS16(float v) {
|
||||
static const float kMaxRound = limits_int16::max() - 0.5f;
|
||||
static const float kMinRound = limits_int16::min() + 0.5f;
|
||||
if (v > 0)
|
||||
return v >= kMaxRound ? limits_int16::max()
|
||||
: static_cast<int16_t>(v + 0.5f);
|
||||
return v <= kMinRound ? limits_int16::min() : static_cast<int16_t>(v - 0.5f);
|
||||
v = std::min(v, 32767.f);
|
||||
v = std::max(v, -32768.f);
|
||||
return static_cast<int16_t>(v + std::copysign(0.5f, v));
|
||||
}
|
||||
|
||||
static inline int16_t FloatToS16(float v) {
|
||||
v *= 32768.f;
|
||||
v = std::min(v, 32767.f);
|
||||
v = std::max(v, -32768.f);
|
||||
return static_cast<int16_t>(v + std::copysign(0.5f, v));
|
||||
}
|
||||
|
||||
static inline float FloatToFloatS16(float v) {
|
||||
return v * (v > 0 ? limits_int16::max() : -limits_int16::min());
|
||||
v = std::min(v, 1.f);
|
||||
v = std::max(v, -1.f);
|
||||
return v * 32768.f;
|
||||
}
|
||||
|
||||
static inline float FloatS16ToFloat(float v) {
|
||||
static const float kMaxInt16Inverse = 1.f / limits_int16::max();
|
||||
static const float kMinInt16Inverse = 1.f / limits_int16::min();
|
||||
return v * (v > 0 ? kMaxInt16Inverse : -kMinInt16Inverse);
|
||||
v = std::min(v, 32768.f);
|
||||
v = std::max(v, -32768.f);
|
||||
constexpr float kScaling = 1.f / 32768.f;
|
||||
return v * kScaling;
|
||||
}
|
||||
|
||||
void FloatToS16(const float* src, size_t size, int16_t* dest);
|
||||
void S16ToFloat(const int16_t* src, size_t size, float* dest);
|
||||
void S16ToFloatS16(const int16_t* src, size_t size, float* dest);
|
||||
void FloatS16ToS16(const float* src, size_t size, int16_t* dest);
|
||||
void FloatToFloatS16(const float* src, size_t size, float* dest);
|
||||
void FloatS16ToFloat(const float* src, size_t size, float* dest);
|
||||
|
||||
inline float DbToRatio(float v) {
|
||||
return std::pow(10.0f, v / 20.0f);
|
||||
}
|
||||
|
||||
inline float DbfsToFloatS16(float v) {
|
||||
static constexpr float kMaximumAbsFloatS16 = -limits_int16::min();
|
||||
return DbToRatio(v) * kMaximumAbsFloatS16;
|
||||
}
|
||||
|
||||
inline float FloatS16ToDbfs(float v) {
|
||||
RTC_DCHECK_GE(v, 0);
|
||||
|
||||
// kMinDbfs is equal to -20.0 * log10(-limits_int16::min())
|
||||
static constexpr float kMinDbfs = -90.30899869919436f;
|
||||
if (v <= 1.0f) {
|
||||
return kMinDbfs;
|
||||
}
|
||||
// Equal to 20 * log10(v / (-limits_int16::min()))
|
||||
return 20.0f * std::log10(v) + kMinDbfs;
|
||||
}
|
||||
|
||||
// Copy audio from |src| channels to |dest| channels unless |src| and |dest|
|
||||
// point to the same address. |src| and |dest| must have the same number of
|
||||
// channels, and there must be sufficient space allocated in |dest|.
|
||||
@ -87,11 +113,11 @@ void CopyAudioIfNeeded(const T* const* src,
|
||||
template <typename T>
|
||||
void Deinterleave(const T* interleaved,
|
||||
size_t samples_per_channel,
|
||||
int num_channels,
|
||||
size_t num_channels,
|
||||
T* const* deinterleaved) {
|
||||
for (int i = 0; i < num_channels; ++i) {
|
||||
for (size_t i = 0; i < num_channels; ++i) {
|
||||
T* channel = deinterleaved[i];
|
||||
int interleaved_idx = i;
|
||||
size_t interleaved_idx = i;
|
||||
for (size_t j = 0; j < samples_per_channel; ++j) {
|
||||
channel[j] = interleaved[interleaved_idx];
|
||||
interleaved_idx += num_channels;
|
||||
@ -105,11 +131,11 @@ void Deinterleave(const T* interleaved,
|
||||
template <typename T>
|
||||
void Interleave(const T* const* deinterleaved,
|
||||
size_t samples_per_channel,
|
||||
int num_channels,
|
||||
size_t num_channels,
|
||||
T* interleaved) {
|
||||
for (int i = 0; i < num_channels; ++i) {
|
||||
for (size_t i = 0; i < num_channels; ++i) {
|
||||
const T* channel = deinterleaved[i];
|
||||
int interleaved_idx = i;
|
||||
size_t interleaved_idx = i;
|
||||
for (size_t j = 0; j < samples_per_channel; ++j) {
|
||||
interleaved[interleaved_idx] = channel[j];
|
||||
interleaved_idx += num_channels;
|
||||
@ -155,7 +181,7 @@ void DownmixInterleavedToMonoImpl(const T* interleaved,
|
||||
int num_channels,
|
||||
T* deinterleaved) {
|
||||
RTC_DCHECK_GT(num_channels, 0);
|
||||
RTC_DCHECK_GT(num_frames, 0u);
|
||||
RTC_DCHECK_GT(num_frames, 0);
|
||||
|
||||
const T* const end = interleaved + num_frames * num_channels;
|
||||
|
||||
@ -185,4 +211,4 @@ void DownmixInterleavedToMono<int16_t>(const int16_t* interleaved,
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
|
||||
#endif // COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
|
||||
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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 "webrtc/common_audio/lapped_transform.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/common_audio/real_fourier.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
void LappedTransform::BlockThunk::ProcessBlock(const float* const* input,
|
||||
size_t num_frames,
|
||||
int num_input_channels,
|
||||
int num_output_channels,
|
||||
float* const* output) {
|
||||
RTC_CHECK_EQ(num_input_channels, parent_->num_in_channels_);
|
||||
RTC_CHECK_EQ(num_output_channels, parent_->num_out_channels_);
|
||||
RTC_CHECK_EQ(parent_->block_length_, num_frames);
|
||||
|
||||
for (int i = 0; i < num_input_channels; ++i) {
|
||||
memcpy(parent_->real_buf_.Row(i), input[i],
|
||||
num_frames * sizeof(*input[0]));
|
||||
parent_->fft_->Forward(parent_->real_buf_.Row(i),
|
||||
parent_->cplx_pre_.Row(i));
|
||||
}
|
||||
|
||||
size_t block_length = RealFourier::ComplexLength(
|
||||
RealFourier::FftOrder(num_frames));
|
||||
RTC_CHECK_EQ(parent_->cplx_length_, block_length);
|
||||
parent_->block_processor_->ProcessAudioBlock(parent_->cplx_pre_.Array(),
|
||||
num_input_channels,
|
||||
parent_->cplx_length_,
|
||||
num_output_channels,
|
||||
parent_->cplx_post_.Array());
|
||||
|
||||
for (int i = 0; i < num_output_channels; ++i) {
|
||||
parent_->fft_->Inverse(parent_->cplx_post_.Row(i),
|
||||
parent_->real_buf_.Row(i));
|
||||
memcpy(output[i], parent_->real_buf_.Row(i),
|
||||
num_frames * sizeof(*input[0]));
|
||||
}
|
||||
}
|
||||
|
||||
LappedTransform::LappedTransform(int num_in_channels,
|
||||
int num_out_channels,
|
||||
size_t chunk_length,
|
||||
const float* window,
|
||||
size_t block_length,
|
||||
size_t shift_amount,
|
||||
Callback* callback)
|
||||
: blocker_callback_(this),
|
||||
num_in_channels_(num_in_channels),
|
||||
num_out_channels_(num_out_channels),
|
||||
block_length_(block_length),
|
||||
chunk_length_(chunk_length),
|
||||
block_processor_(callback),
|
||||
blocker_(chunk_length_,
|
||||
block_length_,
|
||||
num_in_channels_,
|
||||
num_out_channels_,
|
||||
window,
|
||||
shift_amount,
|
||||
&blocker_callback_),
|
||||
fft_(RealFourier::Create(RealFourier::FftOrder(block_length_))),
|
||||
cplx_length_(RealFourier::ComplexLength(fft_->order())),
|
||||
real_buf_(num_in_channels,
|
||||
block_length_,
|
||||
RealFourier::kFftBufferAlignment),
|
||||
cplx_pre_(num_in_channels,
|
||||
cplx_length_,
|
||||
RealFourier::kFftBufferAlignment),
|
||||
cplx_post_(num_out_channels,
|
||||
cplx_length_,
|
||||
RealFourier::kFftBufferAlignment) {
|
||||
RTC_CHECK(num_in_channels_ > 0 && num_out_channels_ > 0);
|
||||
RTC_CHECK_GT(block_length_, 0u);
|
||||
RTC_CHECK_GT(chunk_length_, 0u);
|
||||
RTC_CHECK(block_processor_);
|
||||
|
||||
// block_length_ power of 2?
|
||||
RTC_CHECK_EQ(0u, block_length_ & (block_length_ - 1));
|
||||
}
|
||||
|
||||
void LappedTransform::ProcessChunk(const float* const* in_chunk,
|
||||
float* const* out_chunk) {
|
||||
blocker_.ProcessChunk(in_chunk, chunk_length_, num_in_channels_,
|
||||
num_out_channels_, out_chunk);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_LAPPED_TRANSFORM_H_
|
||||
#define WEBRTC_COMMON_AUDIO_LAPPED_TRANSFORM_H_
|
||||
|
||||
#include <complex>
|
||||
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/common_audio/blocker.h"
|
||||
#include "webrtc/common_audio/real_fourier.h"
|
||||
#include "webrtc/system_wrappers/include/aligned_array.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Helper class for audio processing modules which operate on frequency domain
|
||||
// input derived from the windowed time domain audio stream.
|
||||
//
|
||||
// The input audio chunk is sliced into possibly overlapping blocks, multiplied
|
||||
// by a window and transformed with an FFT implementation. The transformed data
|
||||
// is supplied to the given callback for processing. The processed output is
|
||||
// then inverse transformed into the time domain and spliced back into a chunk
|
||||
// which constitutes the final output of this processing module.
|
||||
class LappedTransform {
|
||||
public:
|
||||
class Callback {
|
||||
public:
|
||||
virtual ~Callback() {}
|
||||
|
||||
virtual void ProcessAudioBlock(const std::complex<float>* const* in_block,
|
||||
int num_in_channels, size_t frames,
|
||||
int num_out_channels,
|
||||
std::complex<float>* const* out_block) = 0;
|
||||
};
|
||||
|
||||
// Construct a transform instance. |chunk_length| is the number of samples in
|
||||
// each channel. |window| defines the window, owned by the caller (a copy is
|
||||
// made internally); |window| should have length equal to |block_length|.
|
||||
// |block_length| defines the length of a block, in samples.
|
||||
// |shift_amount| is in samples. |callback| is the caller-owned audio
|
||||
// processing function called for each block of the input chunk.
|
||||
LappedTransform(int num_in_channels,
|
||||
int num_out_channels,
|
||||
size_t chunk_length,
|
||||
const float* window,
|
||||
size_t block_length,
|
||||
size_t shift_amount,
|
||||
Callback* callback);
|
||||
~LappedTransform() {}
|
||||
|
||||
// Main audio processing helper method. Internally slices |in_chunk| into
|
||||
// blocks, transforms them to frequency domain, calls the callback for each
|
||||
// block and returns a de-blocked time domain chunk of audio through
|
||||
// |out_chunk|. Both buffers are caller-owned.
|
||||
void ProcessChunk(const float* const* in_chunk, float* const* out_chunk);
|
||||
|
||||
// Get the chunk length.
|
||||
//
|
||||
// The chunk length is the number of samples per channel that must be passed
|
||||
// to ProcessChunk via the parameter in_chunk.
|
||||
//
|
||||
// Returns the same chunk_length passed to the LappedTransform constructor.
|
||||
size_t chunk_length() const { return chunk_length_; }
|
||||
|
||||
// Get the number of input channels.
|
||||
//
|
||||
// This is the number of arrays that must be passed to ProcessChunk via
|
||||
// in_chunk.
|
||||
//
|
||||
// Returns the same num_in_channels passed to the LappedTransform constructor.
|
||||
int num_in_channels() const { return num_in_channels_; }
|
||||
|
||||
// Get the number of output channels.
|
||||
//
|
||||
// This is the number of arrays that must be passed to ProcessChunk via
|
||||
// out_chunk.
|
||||
//
|
||||
// Returns the same num_out_channels passed to the LappedTransform
|
||||
// constructor.
|
||||
int num_out_channels() const { return num_out_channels_; }
|
||||
|
||||
private:
|
||||
// Internal middleware callback, given to the blocker. Transforms each block
|
||||
// and hands it over to the processing method given at construction time.
|
||||
class BlockThunk : public BlockerCallback {
|
||||
public:
|
||||
explicit BlockThunk(LappedTransform* parent) : parent_(parent) {}
|
||||
|
||||
virtual void ProcessBlock(const float* const* input, size_t num_frames,
|
||||
int num_input_channels, int num_output_channels,
|
||||
float* const* output);
|
||||
|
||||
private:
|
||||
LappedTransform* const parent_;
|
||||
} blocker_callback_;
|
||||
|
||||
const int num_in_channels_;
|
||||
const int num_out_channels_;
|
||||
|
||||
const size_t block_length_;
|
||||
const size_t chunk_length_;
|
||||
|
||||
Callback* const block_processor_;
|
||||
Blocker blocker_;
|
||||
|
||||
rtc::scoped_ptr<RealFourier> fft_;
|
||||
const size_t cplx_length_;
|
||||
AlignedArray<float> real_buf_;
|
||||
AlignedArray<std::complex<float> > cplx_pre_;
|
||||
AlignedArray<std::complex<float> > cplx_post_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_LAPPED_TRANSFORM_H_
|
||||
|
@ -1,19 +1,29 @@
|
||||
common_audio_sources = [
|
||||
'audio_converter.cc',
|
||||
'audio_util.cc',
|
||||
'channel_buffer.cc',
|
||||
'fir_filter_c.cc',
|
||||
'fir_filter_factory.cc',
|
||||
'real_fourier.cc',
|
||||
'real_fourier_ooura.cc',
|
||||
'resampler/push_resampler.cc',
|
||||
'resampler/push_sinc_resampler.cc',
|
||||
'resampler/resampler.cc',
|
||||
'resampler/sinc_resampler.cc',
|
||||
'resampler/sinusoidal_linear_chirp_source.cc',
|
||||
'signal_processing/auto_corr_to_refl_coef.c',
|
||||
'ring_buffer.c',
|
||||
'signal_processing/auto_correlation.c',
|
||||
'signal_processing/auto_corr_to_refl_coef.c',
|
||||
'signal_processing/complex_bit_reverse.c',
|
||||
'signal_processing/complex_fft.c',
|
||||
'signal_processing/copy_set_operations.c',
|
||||
'signal_processing/cross_correlation.c',
|
||||
'signal_processing/division_operations.c',
|
||||
'signal_processing/dot_product_with_scale.c',
|
||||
'signal_processing/dot_product_with_scale.cc',
|
||||
'signal_processing/downsample_fast.c',
|
||||
'signal_processing/energy.c',
|
||||
'signal_processing/filter_ar.c',
|
||||
'signal_processing/filter_ar_fast_q12.c',
|
||||
'signal_processing/energy.c',
|
||||
'signal_processing/filter_ma_fast_q12.c',
|
||||
'signal_processing/get_hanning_window.c',
|
||||
'signal_processing/get_scaling_square.c',
|
||||
@ -24,34 +34,27 @@ common_audio_sources = [
|
||||
'signal_processing/randomization_functions.c',
|
||||
'signal_processing/real_fft.c',
|
||||
'signal_processing/refl_coef_to_lpc.c',
|
||||
'signal_processing/resample.c',
|
||||
'signal_processing/resample_48khz.c',
|
||||
'signal_processing/resample_by_2.c',
|
||||
'signal_processing/resample_by_2_internal.c',
|
||||
'signal_processing/resample.c',
|
||||
'signal_processing/resample_fractional.c',
|
||||
'signal_processing/spl_init.c',
|
||||
'signal_processing/spl_sqrt.c',
|
||||
'signal_processing/spl_inl.c',
|
||||
'signal_processing/splitting_filter.c',
|
||||
'signal_processing/spl_sqrt.c',
|
||||
'signal_processing/sqrt_of_one_minus_x_squared.c',
|
||||
'signal_processing/vector_scaling_operations.c',
|
||||
'smoothing_filter.cc',
|
||||
'third_party/ooura/fft_size_128/ooura_fft.cc',
|
||||
'third_party/ooura/fft_size_256/fft4g.cc',
|
||||
'third_party/spl_sqrt_floor/spl_sqrt_floor.c',
|
||||
'vad/vad.cc',
|
||||
'vad/vad_core.c',
|
||||
'vad/vad_filterbank.c',
|
||||
'vad/vad_gmm.c',
|
||||
'vad/vad_sp.c',
|
||||
'vad/webrtc_vad.c',
|
||||
'audio_converter.cc',
|
||||
'audio_ring_buffer.cc',
|
||||
'audio_util.cc',
|
||||
'blocker.cc',
|
||||
'channel_buffer.cc',
|
||||
'fft4g.c',
|
||||
'fir_filter.cc',
|
||||
'lapped_transform.cc',
|
||||
'real_fourier.cc',
|
||||
'real_fourier_ooura.cc',
|
||||
'ring_buffer.c',
|
||||
'sparse_fir_filter.cc',
|
||||
'wav_file.cc',
|
||||
'wav_header.cc',
|
||||
'window_generator.cc',
|
||||
@ -59,18 +62,52 @@ common_audio_sources = [
|
||||
|
||||
arch_libs = []
|
||||
if have_x86
|
||||
arch_libs += [static_library('common_audio_sse2',
|
||||
['resampler/sinc_resampler_sse.cc', 'fir_filter_sse.cc'],
|
||||
dependencies: common_deps,
|
||||
include_directories: webrtc_inc,
|
||||
c_args: common_cflags + ['-msse2'],
|
||||
cpp_args: common_cxxflags + ['-msse2'])]
|
||||
arch_libs += [
|
||||
static_library('common_audio_sse2',
|
||||
[
|
||||
'fir_filter_sse.cc',
|
||||
'resampler/sinc_resampler_sse.cc',
|
||||
'third_party/ooura/fft_size_128/ooura_fft_sse2.cc',
|
||||
],
|
||||
dependencies: common_deps,
|
||||
include_directories: webrtc_inc,
|
||||
c_args: common_cflags + ['-msse2'],
|
||||
cpp_args: common_cxxflags + ['-msse2']
|
||||
)
|
||||
]
|
||||
arch_libs += [
|
||||
static_library('common_audio_avx',
|
||||
[
|
||||
'fir_filter_avx2.cc',
|
||||
'resampler/sinc_resampler_avx2.cc',
|
||||
],
|
||||
dependencies: common_deps,
|
||||
include_directories: webrtc_inc,
|
||||
c_args: common_cflags + ['-mavx2', '-mfma'],
|
||||
cpp_args: common_cxxflags + ['-mavx2', '-mfma']
|
||||
)
|
||||
]
|
||||
endif
|
||||
|
||||
if have_mips
|
||||
common_audio_sources += [
|
||||
'signal_processing/complex_bit_reverse_mips.c',
|
||||
'signal_processing/complex_fft_mips.c',
|
||||
'signal_processing/cross_correlation_mips.c',
|
||||
'signal_processing/downsample_fast_mips.c',
|
||||
'signal_processing/filter_ar_fast_q12_mips.c',
|
||||
'signal_processing/min_max_operations_mips.c',
|
||||
'signal_processing/resample_by_2_mips.c',
|
||||
'signal_processing/vector_scaling_operations_mips.c',
|
||||
'third_party/ooura/fft_size_128/ooura_fft_mips.c',
|
||||
'third_party/spl_sqrt_floor/spl_sqrt_floor_mips.c',
|
||||
]
|
||||
endif
|
||||
|
||||
if have_arm
|
||||
common_audio_sources += [
|
||||
'signal_processing/complex_bit_reverse_arm.S',
|
||||
'signal_processing/spl_sqrt_floor_arm.S',
|
||||
'third_party/spl_sqrt_floor/spl_sqrt_floor_arm.S',
|
||||
]
|
||||
endif
|
||||
|
||||
@ -82,11 +119,12 @@ endif
|
||||
|
||||
if have_neon
|
||||
common_audio_sources += [
|
||||
'fir_filter_neon.cc',
|
||||
'resampler/sinc_resampler_neon.cc',
|
||||
'signal_processing/cross_correlation_neon.c',
|
||||
'signal_processing/downsample_fast_neon.c',
|
||||
'signal_processing/min_max_operations_neon.c',
|
||||
'fir_filter_neon.cc',
|
||||
'third_party/ooura/fft_size_128/ooura_fft_neon.c',
|
||||
]
|
||||
endif
|
||||
|
||||
@ -94,7 +132,6 @@ if not have_arm
|
||||
common_audio_sources += [
|
||||
'signal_processing/complex_bit_reverse.c',
|
||||
'signal_processing/filter_ar_fast_q12.c',
|
||||
'signal_processing/spl_sqrt_floor.c',
|
||||
]
|
||||
endif
|
||||
|
||||
|
@ -8,25 +8,20 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/real_fourier.h"
|
||||
#include "common_audio/real_fourier.h"
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/common_audio/real_fourier_ooura.h"
|
||||
#include "webrtc/common_audio/real_fourier_openmax.h"
|
||||
#include "webrtc/common_audio/signal_processing/include/spl_inl.h"
|
||||
#include "common_audio/real_fourier_ooura.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
using std::complex;
|
||||
|
||||
const int RealFourier::kFftBufferAlignment = 32;
|
||||
const size_t RealFourier::kFftBufferAlignment = 32;
|
||||
|
||||
rtc::scoped_ptr<RealFourier> RealFourier::Create(int fft_order) {
|
||||
#if defined(RTC_USE_OPENMAX_DL)
|
||||
return rtc::scoped_ptr<RealFourier>(new RealFourierOpenmax(fft_order));
|
||||
#else
|
||||
return rtc::scoped_ptr<RealFourier>(new RealFourierOoura(fft_order));
|
||||
#endif
|
||||
std::unique_ptr<RealFourier> RealFourier::Create(int fft_order) {
|
||||
return std::unique_ptr<RealFourier>(new RealFourierOoura(fft_order));
|
||||
}
|
||||
|
||||
int RealFourier::FftOrder(size_t length) {
|
||||
@ -36,7 +31,7 @@ int RealFourier::FftOrder(size_t length) {
|
||||
|
||||
size_t RealFourier::FftLength(int order) {
|
||||
RTC_CHECK_GE(order, 0);
|
||||
return static_cast<size_t>(1 << order);
|
||||
return size_t{1} << order;
|
||||
}
|
||||
|
||||
size_t RealFourier::ComplexLength(int order) {
|
||||
@ -54,4 +49,3 @@ RealFourier::fft_cplx_scoper RealFourier::AllocCplxBuffer(int count) {
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
|
@ -8,13 +8,15 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_REAL_FOURIER_H_
|
||||
#define WEBRTC_COMMON_AUDIO_REAL_FOURIER_H_
|
||||
#ifndef COMMON_AUDIO_REAL_FOURIER_H_
|
||||
#define COMMON_AUDIO_REAL_FOURIER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <complex>
|
||||
#include <memory>
|
||||
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/system_wrappers/include/aligned_malloc.h"
|
||||
#include "rtc_base/memory/aligned_malloc.h"
|
||||
|
||||
// Uniform interface class for the real DFT and its inverse, for power-of-2
|
||||
// input lengths. Also contains helper functions for buffer allocation, taking
|
||||
@ -25,17 +27,17 @@ namespace webrtc {
|
||||
class RealFourier {
|
||||
public:
|
||||
// Shorthand typenames for the scopers used by the buffer allocation helpers.
|
||||
typedef rtc::scoped_ptr<float[], AlignedFreeDeleter> fft_real_scoper;
|
||||
typedef rtc::scoped_ptr<std::complex<float>[], AlignedFreeDeleter>
|
||||
typedef std::unique_ptr<float[], AlignedFreeDeleter> fft_real_scoper;
|
||||
typedef std::unique_ptr<std::complex<float>[], AlignedFreeDeleter>
|
||||
fft_cplx_scoper;
|
||||
|
||||
// The alignment required for all input and output buffers, in bytes.
|
||||
static const int kFftBufferAlignment;
|
||||
static const size_t kFftBufferAlignment;
|
||||
|
||||
// Construct a wrapper instance for the given input order, which must be
|
||||
// between 1 and kMaxFftOrder, inclusively.
|
||||
static rtc::scoped_ptr<RealFourier> Create(int fft_order);
|
||||
virtual ~RealFourier() {};
|
||||
static std::unique_ptr<RealFourier> Create(int fft_order);
|
||||
virtual ~RealFourier() {}
|
||||
|
||||
// Helper to compute the smallest FFT order (a power of 2) which will contain
|
||||
// the given input length.
|
||||
@ -71,5 +73,4 @@ class RealFourier {
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_REAL_FOURIER_H_
|
||||
|
||||
#endif // COMMON_AUDIO_REAL_FOURIER_H_
|
||||
|
@ -8,13 +8,13 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/real_fourier_ooura.h"
|
||||
#include "common_audio/real_fourier_ooura.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/common_audio/fft4g.h"
|
||||
#include "common_audio/third_party/ooura/fft_size_256/fft4g.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -28,8 +28,8 @@ void Conjugate(complex<float>* array, size_t complex_length) {
|
||||
}
|
||||
|
||||
size_t ComputeWorkIpSize(size_t fft_length) {
|
||||
return static_cast<size_t>(2 + std::ceil(std::sqrt(
|
||||
static_cast<float>(fft_length))));
|
||||
return static_cast<size_t>(
|
||||
2 + std::ceil(std::sqrt(static_cast<float>(fft_length))));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -45,11 +45,13 @@ RealFourierOoura::RealFourierOoura(int fft_order)
|
||||
RTC_CHECK_GE(fft_order, 1);
|
||||
}
|
||||
|
||||
RealFourierOoura::~RealFourierOoura() = default;
|
||||
|
||||
void RealFourierOoura::Forward(const float* src, complex<float>* dest) const {
|
||||
{
|
||||
// This cast is well-defined since C++11. See "Non-static data members" at:
|
||||
// http://en.cppreference.com/w/cpp/numeric/complex
|
||||
auto dest_float = reinterpret_cast<float*>(dest);
|
||||
auto* dest_float = reinterpret_cast<float*>(dest);
|
||||
std::copy(src, src + length_, dest_float);
|
||||
WebRtc_rdft(length_, 1, dest_float, work_ip_.get(), work_w_.get());
|
||||
}
|
||||
@ -63,7 +65,7 @@ void RealFourierOoura::Forward(const float* src, complex<float>* dest) const {
|
||||
|
||||
void RealFourierOoura::Inverse(const complex<float>* src, float* dest) const {
|
||||
{
|
||||
auto dest_complex = reinterpret_cast<complex<float>*>(dest);
|
||||
auto* dest_complex = reinterpret_cast<complex<float>*>(dest);
|
||||
// The real output array is shorter than the input complex array by one
|
||||
// complex element.
|
||||
const size_t dest_complex_length = complex_length_ - 1;
|
||||
@ -71,8 +73,8 @@ void RealFourierOoura::Inverse(const complex<float>* src, float* dest) const {
|
||||
// Restore Ooura's conjugate definition.
|
||||
Conjugate(dest_complex, dest_complex_length);
|
||||
// Restore real[n/2] to imag[0].
|
||||
dest_complex[0] = complex<float>(dest_complex[0].real(),
|
||||
src[complex_length_ - 1].real());
|
||||
dest_complex[0] =
|
||||
complex<float>(dest_complex[0].real(), src[complex_length_ - 1].real());
|
||||
}
|
||||
|
||||
WebRtc_rdft(length_, -1, dest, work_ip_.get(), work_w_.get());
|
||||
@ -82,4 +84,8 @@ void RealFourierOoura::Inverse(const complex<float>* src, float* dest) const {
|
||||
std::for_each(dest, dest + length_, [scale](float& v) { v *= scale; });
|
||||
}
|
||||
|
||||
int RealFourierOoura::order() const {
|
||||
return order_;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -8,38 +8,38 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_REAL_FOURIER_OOURA_H_
|
||||
#define WEBRTC_COMMON_AUDIO_REAL_FOURIER_OOURA_H_
|
||||
#ifndef COMMON_AUDIO_REAL_FOURIER_OOURA_H_
|
||||
#define COMMON_AUDIO_REAL_FOURIER_OOURA_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <complex>
|
||||
#include <memory>
|
||||
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/common_audio/real_fourier.h"
|
||||
#include "common_audio/real_fourier.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RealFourierOoura : public RealFourier {
|
||||
public:
|
||||
explicit RealFourierOoura(int fft_order);
|
||||
~RealFourierOoura() override;
|
||||
|
||||
void Forward(const float* src, std::complex<float>* dest) const override;
|
||||
void Inverse(const std::complex<float>* src, float* dest) const override;
|
||||
|
||||
int order() const override {
|
||||
return order_;
|
||||
}
|
||||
int order() const override;
|
||||
|
||||
private:
|
||||
const int order_;
|
||||
const size_t length_;
|
||||
const size_t complex_length_;
|
||||
// These are work arrays for Ooura. The names are based on the comments in
|
||||
// fft4g.c.
|
||||
const rtc::scoped_ptr<size_t[]> work_ip_;
|
||||
const rtc::scoped_ptr<float[]> work_w_;
|
||||
// common_audio/third_party/ooura/fft_size_256/fft4g.cc.
|
||||
const std::unique_ptr<size_t[]> work_ip_;
|
||||
const std::unique_ptr<float[]> work_w_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_REAL_FOURIER_OOURA_H_
|
||||
|
||||
#endif // COMMON_AUDIO_REAL_FOURIER_OOURA_H_
|
||||
|
@ -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_
|
||||
|
@ -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_
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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
@ -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
|
||||
|
@ -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_
|
||||
|
66
webrtc/common_audio/resampler/sinc_resampler_avx2.cc
Normal file
66
webrtc/common_audio/resampler/sinc_resampler_avx2.cc
Normal 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
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -11,26 +11,12 @@
|
||||
// A ring buffer to hold arbitrary data. Provides no thread safety. Unless
|
||||
// otherwise specified, functions return 0 on success and -1 on error.
|
||||
|
||||
#include "webrtc/common_audio/ring_buffer.h"
|
||||
#include "common_audio/ring_buffer.h"
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
enum Wrap {
|
||||
SAME_WRAP,
|
||||
DIFF_WRAP
|
||||
};
|
||||
|
||||
struct RingBuffer {
|
||||
size_t read_pos;
|
||||
size_t write_pos;
|
||||
size_t element_count;
|
||||
size_t element_size;
|
||||
enum Wrap rw_wrap;
|
||||
char* data;
|
||||
};
|
||||
|
||||
// Get address of region(s) from which we can read data.
|
||||
// If the region is contiguous, |data_ptr_bytes_2| will be zero.
|
||||
// If non-contiguous, |data_ptr_bytes_2| will be the size in bytes of the second
|
||||
@ -132,7 +118,6 @@ size_t WebRtc_ReadBuffer(RingBuffer* self,
|
||||
&buf_ptr_bytes_1,
|
||||
&buf_ptr_2,
|
||||
&buf_ptr_bytes_2);
|
||||
|
||||
if (buf_ptr_bytes_2 > 0) {
|
||||
// We have a wrap around when reading the buffer. Copy the buffer data to
|
||||
// |data| and point to it.
|
||||
@ -145,7 +130,7 @@ size_t WebRtc_ReadBuffer(RingBuffer* self,
|
||||
}
|
||||
if (data_ptr) {
|
||||
// |buf_ptr_1| == |data| in the case of a wrap.
|
||||
*data_ptr = buf_ptr_1;
|
||||
*data_ptr = read_count == 0 ? NULL : buf_ptr_1;
|
||||
}
|
||||
|
||||
// Update read position
|
||||
|
@ -11,8 +11,10 @@
|
||||
// A ring buffer to hold arbitrary data. Provides no thread safety. Unless
|
||||
// otherwise specified, functions return 0 on success and -1 on error.
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_RING_BUFFER_H_
|
||||
#define WEBRTC_COMMON_AUDIO_RING_BUFFER_H_
|
||||
#ifndef COMMON_AUDIO_RING_BUFFER_H_
|
||||
#define COMMON_AUDIO_RING_BUFFER_H_
|
||||
|
||||
// TODO(alessiob): Used by AEC, AECm and AudioRingBuffer. Remove when possible.
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -20,21 +22,31 @@ extern "C" {
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
typedef struct RingBuffer RingBuffer;
|
||||
enum Wrap { SAME_WRAP, DIFF_WRAP };
|
||||
|
||||
// Creates and initializes the buffer. Returns NULL on failure.
|
||||
typedef struct RingBuffer {
|
||||
size_t read_pos;
|
||||
size_t write_pos;
|
||||
size_t element_count;
|
||||
size_t element_size;
|
||||
enum Wrap rw_wrap;
|
||||
char* data;
|
||||
} RingBuffer;
|
||||
|
||||
// Creates and initializes the buffer. Returns null on failure.
|
||||
RingBuffer* WebRtc_CreateBuffer(size_t element_count, size_t element_size);
|
||||
void WebRtc_InitBuffer(RingBuffer* handle);
|
||||
void WebRtc_FreeBuffer(void* handle);
|
||||
|
||||
// Reads data from the buffer. The |data_ptr| will point to the address where
|
||||
// it is located. If all |element_count| data are feasible to read without
|
||||
// buffer wrap around |data_ptr| will point to the location in the buffer.
|
||||
// Otherwise, the data will be copied to |data| (memory allocation done by the
|
||||
// user) and |data_ptr| points to the address of |data|. |data_ptr| is only
|
||||
// guaranteed to be valid until the next call to WebRtc_WriteBuffer().
|
||||
// Reads data from the buffer. Returns the number of elements that were read.
|
||||
// The |data_ptr| will point to the address where the read data is located.
|
||||
// If no data can be read, |data_ptr| is set to |NULL|. If all data can be read
|
||||
// without buffer wrap around then |data_ptr| will point to the location in the
|
||||
// buffer. Otherwise, the data will be copied to |data| (memory allocation done
|
||||
// by the user) and |data_ptr| points to the address of |data|. |data_ptr| is
|
||||
// only guaranteed to be valid until the next call to WebRtc_WriteBuffer().
|
||||
//
|
||||
// To force a copying to |data|, pass a NULL |data_ptr|.
|
||||
// To force a copying to |data|, pass a null |data_ptr|.
|
||||
//
|
||||
// Returns number of elements read.
|
||||
size_t WebRtc_ReadBuffer(RingBuffer* handle,
|
||||
@ -43,7 +55,8 @@ size_t WebRtc_ReadBuffer(RingBuffer* handle,
|
||||
size_t element_count);
|
||||
|
||||
// Writes |data| to buffer and returns the number of elements written.
|
||||
size_t WebRtc_WriteBuffer(RingBuffer* handle, const void* data,
|
||||
size_t WebRtc_WriteBuffer(RingBuffer* handle,
|
||||
const void* data,
|
||||
size_t element_count);
|
||||
|
||||
// Moves the buffer read position and returns the number of elements moved.
|
||||
@ -63,4 +76,4 @@ size_t WebRtc_available_write(const RingBuffer* handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_RING_BUFFER_H_
|
||||
#endif // COMMON_AUDIO_RING_BUFFER_H_
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
void WebRtcSpl_AutoCorrToReflCoef(const int32_t *R, int use_order, int16_t *K)
|
||||
{
|
||||
|
@ -8,9 +8,9 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
size_t WebRtcSpl_AutoCorrelation(const int16_t* in_vector,
|
||||
size_t in_vector_length,
|
||||
@ -22,7 +22,7 @@ size_t WebRtcSpl_AutoCorrelation(const int16_t* in_vector,
|
||||
int16_t smax = 0;
|
||||
int scaling = 0;
|
||||
|
||||
assert(order <= in_vector_length);
|
||||
RTC_DCHECK_LE(order, in_vector_length);
|
||||
|
||||
// Find the maximum absolute value of the samples.
|
||||
smax = WebRtcSpl_MaxAbsValueW16(in_vector, in_vector_length);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
/* Tables for data buffer indexes that are bit reversed and thus need to be
|
||||
* swapped. Note that, index_7[{0, 2, 4, ...}] are for the left side of the swap
|
||||
|
@ -12,7 +12,7 @@
|
||||
@ for ARMv5 platforms.
|
||||
@ Reference C code is in file complex_bit_reverse.c. Bit-exact.
|
||||
|
||||
#include "webrtc/system_wrappers/include/asm_defines.h"
|
||||
#include "rtc_base/system/asm_defines.h"
|
||||
|
||||
GLOBAL_FUNCTION WebRtcSpl_ComplexBitReverse
|
||||
.align 2
|
||||
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
static int16_t coefTable_7[] = {
|
||||
4, 256, 8, 128, 12, 384, 16, 64,
|
||||
|
@ -15,8 +15,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/complex_fft_tables.h"
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/complex_fft_tables.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "rtc_base/system/arch.h"
|
||||
|
||||
#define CFFTSFT 14
|
||||
#define CFFTRND 1
|
||||
@ -134,8 +135,8 @@ int WebRtcSpl_ComplexFFT(int16_t frfi[], int stages, int mode)
|
||||
tr32 >>= 15 - CFFTSFT;
|
||||
ti32 >>= 15 - CFFTSFT;
|
||||
|
||||
qr32 = ((int32_t)frfi[2 * i]) << CFFTSFT;
|
||||
qi32 = ((int32_t)frfi[2 * i + 1]) << CFFTSFT;
|
||||
qr32 = ((int32_t)frfi[2 * i]) * (1 << CFFTSFT);
|
||||
qi32 = ((int32_t)frfi[2 * i + 1]) * (1 << CFFTSFT);
|
||||
|
||||
frfi[2 * j] = (int16_t)(
|
||||
(qr32 - tr32 + CFFTRND2) >> (1 + CFFTSFT));
|
||||
@ -166,7 +167,7 @@ int WebRtcSpl_ComplexIFFT(int16_t frfi[], int stages, int mode)
|
||||
/* The 1024-value is a constant given from the size of kSinTable1024[],
|
||||
* and should not be changed depending on the input parameter 'stages'
|
||||
*/
|
||||
n = 1 << stages;
|
||||
n = ((size_t)1) << stages;
|
||||
if (n > 1024)
|
||||
return -1;
|
||||
|
||||
@ -276,8 +277,8 @@ int WebRtcSpl_ComplexIFFT(int16_t frfi[], int stages, int mode)
|
||||
tr32 >>= 15 - CIFFTSFT;
|
||||
ti32 >>= 15 - CIFFTSFT;
|
||||
|
||||
qr32 = ((int32_t)frfi[2 * i]) << CIFFTSFT;
|
||||
qi32 = ((int32_t)frfi[2 * i + 1]) << CIFFTSFT;
|
||||
qr32 = ((int32_t)frfi[2 * i]) * (1 << CIFFTSFT);
|
||||
qi32 = ((int32_t)frfi[2 * i + 1]) * (1 << CIFFTSFT);
|
||||
|
||||
frfi[2 * j] = (int16_t)(
|
||||
(qr32 - tr32 + round2) >> (shift + CIFFTSFT));
|
||||
|
@ -9,8 +9,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/complex_fft_tables.h"
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/complex_fft_tables.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
#define CFFTSFT 14
|
||||
#define CFFTRND 1
|
||||
|
@ -8,141 +8,125 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_AUDIO_SIGNAL_PROCESSING_COMPLEX_FFT_TABLES_H_
|
||||
#define COMMON_AUDIO_SIGNAL_PROCESSING_COMPLEX_FFT_TABLES_H_
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_COMPLEX_FFT_TABLES_H_
|
||||
#define WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_COMPLEX_FFT_TABLES_H_
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
#include <stdint.h>
|
||||
|
||||
static const int16_t kSinTable1024[] = {
|
||||
0, 201, 402, 603, 804, 1005, 1206, 1406,
|
||||
1607, 1808, 2009, 2209, 2410, 2610, 2811, 3011,
|
||||
3211, 3411, 3611, 3811, 4011, 4210, 4409, 4608,
|
||||
4807, 5006, 5205, 5403, 5601, 5799, 5997, 6195,
|
||||
6392, 6589, 6786, 6982, 7179, 7375, 7571, 7766,
|
||||
7961, 8156, 8351, 8545, 8739, 8932, 9126, 9319,
|
||||
9511, 9703, 9895, 10087, 10278, 10469, 10659, 10849,
|
||||
11038, 11227, 11416, 11604, 11792, 11980, 12166, 12353,
|
||||
12539, 12724, 12909, 13094, 13278, 13462, 13645, 13827,
|
||||
14009, 14191, 14372, 14552, 14732, 14911, 15090, 15268,
|
||||
15446, 15623, 15799, 15975, 16150, 16325, 16499, 16672,
|
||||
16845, 17017, 17189, 17360, 17530, 17699, 17868, 18036,
|
||||
18204, 18371, 18537, 18702, 18867, 19031, 19194, 19357,
|
||||
19519, 19680, 19840, 20000, 20159, 20317, 20474, 20631,
|
||||
20787, 20942, 21096, 21249, 21402, 21554, 21705, 21855,
|
||||
22004, 22153, 22301, 22448, 22594, 22739, 22883, 23027,
|
||||
23169, 23311, 23452, 23592, 23731, 23869, 24006, 24143,
|
||||
24278, 24413, 24546, 24679, 24811, 24942, 25072, 25201,
|
||||
25329, 25456, 25582, 25707, 25831, 25954, 26077, 26198,
|
||||
26318, 26437, 26556, 26673, 26789, 26905, 27019, 27132,
|
||||
27244, 27355, 27466, 27575, 27683, 27790, 27896, 28001,
|
||||
28105, 28208, 28309, 28410, 28510, 28608, 28706, 28802,
|
||||
28897, 28992, 29085, 29177, 29268, 29358, 29446, 29534,
|
||||
29621, 29706, 29790, 29873, 29955, 30036, 30116, 30195,
|
||||
30272, 30349, 30424, 30498, 30571, 30643, 30713, 30783,
|
||||
30851, 30918, 30984, 31049, 31113, 31175, 31236, 31297,
|
||||
31356, 31413, 31470, 31525, 31580, 31633, 31684, 31735,
|
||||
31785, 31833, 31880, 31926, 31970, 32014, 32056, 32097,
|
||||
32137, 32176, 32213, 32249, 32284, 32318, 32350, 32382,
|
||||
32412, 32441, 32468, 32495, 32520, 32544, 32567, 32588,
|
||||
32609, 32628, 32646, 32662, 32678, 32692, 32705, 32717,
|
||||
32727, 32736, 32744, 32751, 32757, 32761, 32764, 32766,
|
||||
32767, 32766, 32764, 32761, 32757, 32751, 32744, 32736,
|
||||
32727, 32717, 32705, 32692, 32678, 32662, 32646, 32628,
|
||||
32609, 32588, 32567, 32544, 32520, 32495, 32468, 32441,
|
||||
32412, 32382, 32350, 32318, 32284, 32249, 32213, 32176,
|
||||
32137, 32097, 32056, 32014, 31970, 31926, 31880, 31833,
|
||||
31785, 31735, 31684, 31633, 31580, 31525, 31470, 31413,
|
||||
31356, 31297, 31236, 31175, 31113, 31049, 30984, 30918,
|
||||
30851, 30783, 30713, 30643, 30571, 30498, 30424, 30349,
|
||||
30272, 30195, 30116, 30036, 29955, 29873, 29790, 29706,
|
||||
29621, 29534, 29446, 29358, 29268, 29177, 29085, 28992,
|
||||
28897, 28802, 28706, 28608, 28510, 28410, 28309, 28208,
|
||||
28105, 28001, 27896, 27790, 27683, 27575, 27466, 27355,
|
||||
27244, 27132, 27019, 26905, 26789, 26673, 26556, 26437,
|
||||
26318, 26198, 26077, 25954, 25831, 25707, 25582, 25456,
|
||||
25329, 25201, 25072, 24942, 24811, 24679, 24546, 24413,
|
||||
24278, 24143, 24006, 23869, 23731, 23592, 23452, 23311,
|
||||
23169, 23027, 22883, 22739, 22594, 22448, 22301, 22153,
|
||||
22004, 21855, 21705, 21554, 21402, 21249, 21096, 20942,
|
||||
20787, 20631, 20474, 20317, 20159, 20000, 19840, 19680,
|
||||
19519, 19357, 19194, 19031, 18867, 18702, 18537, 18371,
|
||||
18204, 18036, 17868, 17699, 17530, 17360, 17189, 17017,
|
||||
16845, 16672, 16499, 16325, 16150, 15975, 15799, 15623,
|
||||
15446, 15268, 15090, 14911, 14732, 14552, 14372, 14191,
|
||||
14009, 13827, 13645, 13462, 13278, 13094, 12909, 12724,
|
||||
12539, 12353, 12166, 11980, 11792, 11604, 11416, 11227,
|
||||
11038, 10849, 10659, 10469, 10278, 10087, 9895, 9703,
|
||||
9511, 9319, 9126, 8932, 8739, 8545, 8351, 8156,
|
||||
7961, 7766, 7571, 7375, 7179, 6982, 6786, 6589,
|
||||
6392, 6195, 5997, 5799, 5601, 5403, 5205, 5006,
|
||||
4807, 4608, 4409, 4210, 4011, 3811, 3611, 3411,
|
||||
3211, 3011, 2811, 2610, 2410, 2209, 2009, 1808,
|
||||
1607, 1406, 1206, 1005, 804, 603, 402, 201,
|
||||
0, -201, -402, -603, -804, -1005, -1206, -1406,
|
||||
-1607, -1808, -2009, -2209, -2410, -2610, -2811, -3011,
|
||||
-3211, -3411, -3611, -3811, -4011, -4210, -4409, -4608,
|
||||
-4807, -5006, -5205, -5403, -5601, -5799, -5997, -6195,
|
||||
-6392, -6589, -6786, -6982, -7179, -7375, -7571, -7766,
|
||||
-7961, -8156, -8351, -8545, -8739, -8932, -9126, -9319,
|
||||
-9511, -9703, -9895, -10087, -10278, -10469, -10659, -10849,
|
||||
-11038, -11227, -11416, -11604, -11792, -11980, -12166, -12353,
|
||||
-12539, -12724, -12909, -13094, -13278, -13462, -13645, -13827,
|
||||
-14009, -14191, -14372, -14552, -14732, -14911, -15090, -15268,
|
||||
-15446, -15623, -15799, -15975, -16150, -16325, -16499, -16672,
|
||||
-16845, -17017, -17189, -17360, -17530, -17699, -17868, -18036,
|
||||
-18204, -18371, -18537, -18702, -18867, -19031, -19194, -19357,
|
||||
-19519, -19680, -19840, -20000, -20159, -20317, -20474, -20631,
|
||||
-20787, -20942, -21096, -21249, -21402, -21554, -21705, -21855,
|
||||
-22004, -22153, -22301, -22448, -22594, -22739, -22883, -23027,
|
||||
-23169, -23311, -23452, -23592, -23731, -23869, -24006, -24143,
|
||||
-24278, -24413, -24546, -24679, -24811, -24942, -25072, -25201,
|
||||
-25329, -25456, -25582, -25707, -25831, -25954, -26077, -26198,
|
||||
-26318, -26437, -26556, -26673, -26789, -26905, -27019, -27132,
|
||||
-27244, -27355, -27466, -27575, -27683, -27790, -27896, -28001,
|
||||
-28105, -28208, -28309, -28410, -28510, -28608, -28706, -28802,
|
||||
-28897, -28992, -29085, -29177, -29268, -29358, -29446, -29534,
|
||||
-29621, -29706, -29790, -29873, -29955, -30036, -30116, -30195,
|
||||
-30272, -30349, -30424, -30498, -30571, -30643, -30713, -30783,
|
||||
-30851, -30918, -30984, -31049, -31113, -31175, -31236, -31297,
|
||||
-31356, -31413, -31470, -31525, -31580, -31633, -31684, -31735,
|
||||
-31785, -31833, -31880, -31926, -31970, -32014, -32056, -32097,
|
||||
-32137, -32176, -32213, -32249, -32284, -32318, -32350, -32382,
|
||||
-32412, -32441, -32468, -32495, -32520, -32544, -32567, -32588,
|
||||
-32609, -32628, -32646, -32662, -32678, -32692, -32705, -32717,
|
||||
-32727, -32736, -32744, -32751, -32757, -32761, -32764, -32766,
|
||||
-32767, -32766, -32764, -32761, -32757, -32751, -32744, -32736,
|
||||
-32727, -32717, -32705, -32692, -32678, -32662, -32646, -32628,
|
||||
-32609, -32588, -32567, -32544, -32520, -32495, -32468, -32441,
|
||||
-32412, -32382, -32350, -32318, -32284, -32249, -32213, -32176,
|
||||
-32137, -32097, -32056, -32014, -31970, -31926, -31880, -31833,
|
||||
-31785, -31735, -31684, -31633, -31580, -31525, -31470, -31413,
|
||||
-31356, -31297, -31236, -31175, -31113, -31049, -30984, -30918,
|
||||
-30851, -30783, -30713, -30643, -30571, -30498, -30424, -30349,
|
||||
-30272, -30195, -30116, -30036, -29955, -29873, -29790, -29706,
|
||||
-29621, -29534, -29446, -29358, -29268, -29177, -29085, -28992,
|
||||
-28897, -28802, -28706, -28608, -28510, -28410, -28309, -28208,
|
||||
-28105, -28001, -27896, -27790, -27683, -27575, -27466, -27355,
|
||||
-27244, -27132, -27019, -26905, -26789, -26673, -26556, -26437,
|
||||
-26318, -26198, -26077, -25954, -25831, -25707, -25582, -25456,
|
||||
-25329, -25201, -25072, -24942, -24811, -24679, -24546, -24413,
|
||||
-24278, -24143, -24006, -23869, -23731, -23592, -23452, -23311,
|
||||
-23169, -23027, -22883, -22739, -22594, -22448, -22301, -22153,
|
||||
-22004, -21855, -21705, -21554, -21402, -21249, -21096, -20942,
|
||||
-20787, -20631, -20474, -20317, -20159, -20000, -19840, -19680,
|
||||
-19519, -19357, -19194, -19031, -18867, -18702, -18537, -18371,
|
||||
-18204, -18036, -17868, -17699, -17530, -17360, -17189, -17017,
|
||||
-16845, -16672, -16499, -16325, -16150, -15975, -15799, -15623,
|
||||
-15446, -15268, -15090, -14911, -14732, -14552, -14372, -14191,
|
||||
-14009, -13827, -13645, -13462, -13278, -13094, -12909, -12724,
|
||||
-12539, -12353, -12166, -11980, -11792, -11604, -11416, -11227,
|
||||
-11038, -10849, -10659, -10469, -10278, -10087, -9895, -9703,
|
||||
-9511, -9319, -9126, -8932, -8739, -8545, -8351, -8156,
|
||||
-7961, -7766, -7571, -7375, -7179, -6982, -6786, -6589,
|
||||
-6392, -6195, -5997, -5799, -5601, -5403, -5205, -5006,
|
||||
-4807, -4608, -4409, -4210, -4011, -3811, -3611, -3411,
|
||||
-3211, -3011, -2811, -2610, -2410, -2209, -2009, -1808,
|
||||
-1607, -1406, -1206, -1005, -804, -603, -402, -201
|
||||
};
|
||||
0, 201, 402, 603, 804, 1005, 1206, 1406, 1607,
|
||||
1808, 2009, 2209, 2410, 2610, 2811, 3011, 3211, 3411,
|
||||
3611, 3811, 4011, 4210, 4409, 4608, 4807, 5006, 5205,
|
||||
5403, 5601, 5799, 5997, 6195, 6392, 6589, 6786, 6982,
|
||||
7179, 7375, 7571, 7766, 7961, 8156, 8351, 8545, 8739,
|
||||
8932, 9126, 9319, 9511, 9703, 9895, 10087, 10278, 10469,
|
||||
10659, 10849, 11038, 11227, 11416, 11604, 11792, 11980, 12166,
|
||||
12353, 12539, 12724, 12909, 13094, 13278, 13462, 13645, 13827,
|
||||
14009, 14191, 14372, 14552, 14732, 14911, 15090, 15268, 15446,
|
||||
15623, 15799, 15975, 16150, 16325, 16499, 16672, 16845, 17017,
|
||||
17189, 17360, 17530, 17699, 17868, 18036, 18204, 18371, 18537,
|
||||
18702, 18867, 19031, 19194, 19357, 19519, 19680, 19840, 20000,
|
||||
20159, 20317, 20474, 20631, 20787, 20942, 21096, 21249, 21402,
|
||||
21554, 21705, 21855, 22004, 22153, 22301, 22448, 22594, 22739,
|
||||
22883, 23027, 23169, 23311, 23452, 23592, 23731, 23869, 24006,
|
||||
24143, 24278, 24413, 24546, 24679, 24811, 24942, 25072, 25201,
|
||||
25329, 25456, 25582, 25707, 25831, 25954, 26077, 26198, 26318,
|
||||
26437, 26556, 26673, 26789, 26905, 27019, 27132, 27244, 27355,
|
||||
27466, 27575, 27683, 27790, 27896, 28001, 28105, 28208, 28309,
|
||||
28410, 28510, 28608, 28706, 28802, 28897, 28992, 29085, 29177,
|
||||
29268, 29358, 29446, 29534, 29621, 29706, 29790, 29873, 29955,
|
||||
30036, 30116, 30195, 30272, 30349, 30424, 30498, 30571, 30643,
|
||||
30713, 30783, 30851, 30918, 30984, 31049, 31113, 31175, 31236,
|
||||
31297, 31356, 31413, 31470, 31525, 31580, 31633, 31684, 31735,
|
||||
31785, 31833, 31880, 31926, 31970, 32014, 32056, 32097, 32137,
|
||||
32176, 32213, 32249, 32284, 32318, 32350, 32382, 32412, 32441,
|
||||
32468, 32495, 32520, 32544, 32567, 32588, 32609, 32628, 32646,
|
||||
32662, 32678, 32692, 32705, 32717, 32727, 32736, 32744, 32751,
|
||||
32757, 32761, 32764, 32766, 32767, 32766, 32764, 32761, 32757,
|
||||
32751, 32744, 32736, 32727, 32717, 32705, 32692, 32678, 32662,
|
||||
32646, 32628, 32609, 32588, 32567, 32544, 32520, 32495, 32468,
|
||||
32441, 32412, 32382, 32350, 32318, 32284, 32249, 32213, 32176,
|
||||
32137, 32097, 32056, 32014, 31970, 31926, 31880, 31833, 31785,
|
||||
31735, 31684, 31633, 31580, 31525, 31470, 31413, 31356, 31297,
|
||||
31236, 31175, 31113, 31049, 30984, 30918, 30851, 30783, 30713,
|
||||
30643, 30571, 30498, 30424, 30349, 30272, 30195, 30116, 30036,
|
||||
29955, 29873, 29790, 29706, 29621, 29534, 29446, 29358, 29268,
|
||||
29177, 29085, 28992, 28897, 28802, 28706, 28608, 28510, 28410,
|
||||
28309, 28208, 28105, 28001, 27896, 27790, 27683, 27575, 27466,
|
||||
27355, 27244, 27132, 27019, 26905, 26789, 26673, 26556, 26437,
|
||||
26318, 26198, 26077, 25954, 25831, 25707, 25582, 25456, 25329,
|
||||
25201, 25072, 24942, 24811, 24679, 24546, 24413, 24278, 24143,
|
||||
24006, 23869, 23731, 23592, 23452, 23311, 23169, 23027, 22883,
|
||||
22739, 22594, 22448, 22301, 22153, 22004, 21855, 21705, 21554,
|
||||
21402, 21249, 21096, 20942, 20787, 20631, 20474, 20317, 20159,
|
||||
20000, 19840, 19680, 19519, 19357, 19194, 19031, 18867, 18702,
|
||||
18537, 18371, 18204, 18036, 17868, 17699, 17530, 17360, 17189,
|
||||
17017, 16845, 16672, 16499, 16325, 16150, 15975, 15799, 15623,
|
||||
15446, 15268, 15090, 14911, 14732, 14552, 14372, 14191, 14009,
|
||||
13827, 13645, 13462, 13278, 13094, 12909, 12724, 12539, 12353,
|
||||
12166, 11980, 11792, 11604, 11416, 11227, 11038, 10849, 10659,
|
||||
10469, 10278, 10087, 9895, 9703, 9511, 9319, 9126, 8932,
|
||||
8739, 8545, 8351, 8156, 7961, 7766, 7571, 7375, 7179,
|
||||
6982, 6786, 6589, 6392, 6195, 5997, 5799, 5601, 5403,
|
||||
5205, 5006, 4807, 4608, 4409, 4210, 4011, 3811, 3611,
|
||||
3411, 3211, 3011, 2811, 2610, 2410, 2209, 2009, 1808,
|
||||
1607, 1406, 1206, 1005, 804, 603, 402, 201, 0,
|
||||
-201, -402, -603, -804, -1005, -1206, -1406, -1607, -1808,
|
||||
-2009, -2209, -2410, -2610, -2811, -3011, -3211, -3411, -3611,
|
||||
-3811, -4011, -4210, -4409, -4608, -4807, -5006, -5205, -5403,
|
||||
-5601, -5799, -5997, -6195, -6392, -6589, -6786, -6982, -7179,
|
||||
-7375, -7571, -7766, -7961, -8156, -8351, -8545, -8739, -8932,
|
||||
-9126, -9319, -9511, -9703, -9895, -10087, -10278, -10469, -10659,
|
||||
-10849, -11038, -11227, -11416, -11604, -11792, -11980, -12166, -12353,
|
||||
-12539, -12724, -12909, -13094, -13278, -13462, -13645, -13827, -14009,
|
||||
-14191, -14372, -14552, -14732, -14911, -15090, -15268, -15446, -15623,
|
||||
-15799, -15975, -16150, -16325, -16499, -16672, -16845, -17017, -17189,
|
||||
-17360, -17530, -17699, -17868, -18036, -18204, -18371, -18537, -18702,
|
||||
-18867, -19031, -19194, -19357, -19519, -19680, -19840, -20000, -20159,
|
||||
-20317, -20474, -20631, -20787, -20942, -21096, -21249, -21402, -21554,
|
||||
-21705, -21855, -22004, -22153, -22301, -22448, -22594, -22739, -22883,
|
||||
-23027, -23169, -23311, -23452, -23592, -23731, -23869, -24006, -24143,
|
||||
-24278, -24413, -24546, -24679, -24811, -24942, -25072, -25201, -25329,
|
||||
-25456, -25582, -25707, -25831, -25954, -26077, -26198, -26318, -26437,
|
||||
-26556, -26673, -26789, -26905, -27019, -27132, -27244, -27355, -27466,
|
||||
-27575, -27683, -27790, -27896, -28001, -28105, -28208, -28309, -28410,
|
||||
-28510, -28608, -28706, -28802, -28897, -28992, -29085, -29177, -29268,
|
||||
-29358, -29446, -29534, -29621, -29706, -29790, -29873, -29955, -30036,
|
||||
-30116, -30195, -30272, -30349, -30424, -30498, -30571, -30643, -30713,
|
||||
-30783, -30851, -30918, -30984, -31049, -31113, -31175, -31236, -31297,
|
||||
-31356, -31413, -31470, -31525, -31580, -31633, -31684, -31735, -31785,
|
||||
-31833, -31880, -31926, -31970, -32014, -32056, -32097, -32137, -32176,
|
||||
-32213, -32249, -32284, -32318, -32350, -32382, -32412, -32441, -32468,
|
||||
-32495, -32520, -32544, -32567, -32588, -32609, -32628, -32646, -32662,
|
||||
-32678, -32692, -32705, -32717, -32727, -32736, -32744, -32751, -32757,
|
||||
-32761, -32764, -32766, -32767, -32766, -32764, -32761, -32757, -32751,
|
||||
-32744, -32736, -32727, -32717, -32705, -32692, -32678, -32662, -32646,
|
||||
-32628, -32609, -32588, -32567, -32544, -32520, -32495, -32468, -32441,
|
||||
-32412, -32382, -32350, -32318, -32284, -32249, -32213, -32176, -32137,
|
||||
-32097, -32056, -32014, -31970, -31926, -31880, -31833, -31785, -31735,
|
||||
-31684, -31633, -31580, -31525, -31470, -31413, -31356, -31297, -31236,
|
||||
-31175, -31113, -31049, -30984, -30918, -30851, -30783, -30713, -30643,
|
||||
-30571, -30498, -30424, -30349, -30272, -30195, -30116, -30036, -29955,
|
||||
-29873, -29790, -29706, -29621, -29534, -29446, -29358, -29268, -29177,
|
||||
-29085, -28992, -28897, -28802, -28706, -28608, -28510, -28410, -28309,
|
||||
-28208, -28105, -28001, -27896, -27790, -27683, -27575, -27466, -27355,
|
||||
-27244, -27132, -27019, -26905, -26789, -26673, -26556, -26437, -26318,
|
||||
-26198, -26077, -25954, -25831, -25707, -25582, -25456, -25329, -25201,
|
||||
-25072, -24942, -24811, -24679, -24546, -24413, -24278, -24143, -24006,
|
||||
-23869, -23731, -23592, -23452, -23311, -23169, -23027, -22883, -22739,
|
||||
-22594, -22448, -22301, -22153, -22004, -21855, -21705, -21554, -21402,
|
||||
-21249, -21096, -20942, -20787, -20631, -20474, -20317, -20159, -20000,
|
||||
-19840, -19680, -19519, -19357, -19194, -19031, -18867, -18702, -18537,
|
||||
-18371, -18204, -18036, -17868, -17699, -17530, -17360, -17189, -17017,
|
||||
-16845, -16672, -16499, -16325, -16150, -15975, -15799, -15623, -15446,
|
||||
-15268, -15090, -14911, -14732, -14552, -14372, -14191, -14009, -13827,
|
||||
-13645, -13462, -13278, -13094, -12909, -12724, -12539, -12353, -12166,
|
||||
-11980, -11792, -11604, -11416, -11227, -11038, -10849, -10659, -10469,
|
||||
-10278, -10087, -9895, -9703, -9511, -9319, -9126, -8932, -8739,
|
||||
-8545, -8351, -8156, -7961, -7766, -7571, -7375, -7179, -6982,
|
||||
-6786, -6589, -6392, -6195, -5997, -5799, -5601, -5403, -5205,
|
||||
-5006, -4807, -4608, -4409, -4210, -4011, -3811, -3611, -3411,
|
||||
-3211, -3011, -2811, -2610, -2410, -2209, -2009, -1808, -1607,
|
||||
-1406, -1206, -1005, -804, -603, -402, -201};
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_COMPLEX_FFT_TABLES_H_
|
||||
#endif // COMMON_AUDIO_SIGNAL_PROCESSING_COMPLEX_FFT_TABLES_H_
|
||||
|
@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
|
||||
void WebRtcSpl_MemSetW16(int16_t *ptr, int16_t set_value, size_t length)
|
||||
|
@ -8,7 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
/* C version of WebRtcSpl_CrossCorrelation() for generic platforms. */
|
||||
void WebRtcSpl_CrossCorrelationC(int32_t* cross_correlation,
|
||||
|
@ -8,7 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
void WebRtcSpl_CrossCorrelation_mips(int32_t* cross_correlation,
|
||||
const int16_t* seq1,
|
||||
|
@ -8,7 +8,8 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "rtc_base/system/arch.h"
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
|
@ -21,7 +21,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "rtc_base/sanitizer.h"
|
||||
|
||||
uint32_t WebRtcSpl_DivU32U16(uint32_t num, uint16_t den)
|
||||
{
|
||||
@ -97,7 +98,8 @@ int32_t WebRtcSpl_DivResultInQ31(int32_t num, int32_t den)
|
||||
return div;
|
||||
}
|
||||
|
||||
int32_t WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low)
|
||||
int32_t RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486
|
||||
WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low)
|
||||
{
|
||||
int16_t approx, tmp_hi, tmp_low, num_hi, num_low;
|
||||
int32_t tmpW32;
|
||||
@ -110,6 +112,7 @@ int32_t WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low)
|
||||
// tmpW32 = den * approx
|
||||
|
||||
tmpW32 = (int32_t)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx))
|
||||
// UBSan: 2147483647 - -2 cannot be represented in type 'int'
|
||||
|
||||
// Store tmpW32 in hi and low format
|
||||
tmp_hi = (int16_t)(tmpW32 >> 16);
|
||||
|
@ -8,13 +8,15 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/dot_product_with_scale.h"
|
||||
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
int32_t WebRtcSpl_DotProductWithScale(const int16_t* vector1,
|
||||
const int16_t* vector2,
|
||||
size_t length,
|
||||
int scaling) {
|
||||
int32_t sum = 0;
|
||||
int64_t sum = 0;
|
||||
size_t i = 0;
|
||||
|
||||
/* Unroll the loop to improve performance. */
|
||||
@ -28,5 +30,5 @@ int32_t WebRtcSpl_DotProductWithScale(const int16_t* vector1,
|
||||
sum += (vector1[i] * vector2[i]) >> scaling;
|
||||
}
|
||||
|
||||
return sum;
|
||||
return rtc::saturated_cast<int32_t>(sum);
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_AUDIO_SIGNAL_PROCESSING_DOT_PRODUCT_WITH_SCALE_H_
|
||||
#define COMMON_AUDIO_SIGNAL_PROCESSING_DOT_PRODUCT_WITH_SCALE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Calculates the dot product between two (int16_t) vectors.
|
||||
//
|
||||
// Input:
|
||||
// - vector1 : Vector 1
|
||||
// - vector2 : Vector 2
|
||||
// - vector_length : Number of samples used in the dot product
|
||||
// - scaling : The number of right bit shifts to apply on each term
|
||||
// during calculation to avoid overflow, i.e., the
|
||||
// output will be in Q(-|scaling|)
|
||||
//
|
||||
// Return value : The dot product in Q(-scaling)
|
||||
int32_t WebRtcSpl_DotProductWithScale(const int16_t* vector1,
|
||||
const int16_t* vector2,
|
||||
size_t length,
|
||||
int scaling);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // COMMON_AUDIO_SIGNAL_PROCESSING_DOT_PRODUCT_WITH_SCALE_H_
|
@ -8,7 +8,10 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/sanitizer.h"
|
||||
|
||||
// TODO(Bjornv): Change the function parameter order to WebRTC code style.
|
||||
// C version of WebRtcSpl_DownsampleFast() for generic platforms.
|
||||
@ -20,6 +23,7 @@ int WebRtcSpl_DownsampleFastC(const int16_t* data_in,
|
||||
size_t coefficients_length,
|
||||
int factor,
|
||||
size_t delay) {
|
||||
int16_t* const original_data_out = data_out;
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
int32_t out_s32 = 0;
|
||||
@ -31,11 +35,20 @@ int WebRtcSpl_DownsampleFastC(const int16_t* data_in,
|
||||
return -1;
|
||||
}
|
||||
|
||||
rtc_MsanCheckInitialized(coefficients, sizeof(coefficients[0]),
|
||||
coefficients_length);
|
||||
|
||||
for (i = delay; i < endpos; i += factor) {
|
||||
out_s32 = 2048; // Round value, 0.5 in Q12.
|
||||
|
||||
for (j = 0; j < coefficients_length; j++) {
|
||||
out_s32 += coefficients[j] * data_in[i - j]; // Q12.
|
||||
// Negative overflow is permitted here, because this is
|
||||
// auto-regressive filters, and the state for each batch run is
|
||||
// stored in the "negative" positions of the output vector.
|
||||
rtc_MsanCheckInitialized(&data_in[(ptrdiff_t) i - (ptrdiff_t) j],
|
||||
sizeof(data_in[0]), 1);
|
||||
// out_s32 is in Q12 domain.
|
||||
out_s32 += coefficients[j] * data_in[(ptrdiff_t) i - (ptrdiff_t) j];
|
||||
}
|
||||
|
||||
out_s32 >>= 12; // Q0.
|
||||
@ -44,5 +57,9 @@ int WebRtcSpl_DownsampleFastC(const int16_t* data_in,
|
||||
*data_out++ = WebRtcSpl_SatW32ToW16(out_s32);
|
||||
}
|
||||
|
||||
RTC_DCHECK_EQ(original_data_out + data_out_length, data_out);
|
||||
rtc_MsanCheckInitialized(original_data_out, sizeof(original_data_out[0]),
|
||||
data_out_length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
// Version of WebRtcSpl_DownsampleFast() for MIPS platforms.
|
||||
int WebRtcSpl_DownsampleFast_mips(const int16_t* data_in,
|
||||
|
@ -8,7 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
int32_t WebRtcSpl_Energy(int16_t* vector,
|
||||
size_t vector_length,
|
||||
|
@ -15,7 +15,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
size_t WebRtcSpl_FilterAR(const int16_t* a,
|
||||
size_t a_length,
|
||||
@ -29,7 +31,7 @@ size_t WebRtcSpl_FilterAR(const int16_t* a,
|
||||
int16_t* filtered_low,
|
||||
size_t filtered_low_length)
|
||||
{
|
||||
int32_t o;
|
||||
int64_t o;
|
||||
int32_t oLOW;
|
||||
size_t i, j, stop;
|
||||
const int16_t* x_ptr = &x[0];
|
||||
@ -40,19 +42,23 @@ size_t WebRtcSpl_FilterAR(const int16_t* a,
|
||||
{
|
||||
// Calculate filtered[i] and filtered_low[i]
|
||||
const int16_t* a_ptr = &a[1];
|
||||
int16_t* filtered_ptr = &filtered[i - 1];
|
||||
int16_t* filtered_low_ptr = &filtered_low[i - 1];
|
||||
// The index can become negative, but the arrays will never be indexed
|
||||
// with it when negative. Nevertheless, the index cannot be a size_t
|
||||
// because of this.
|
||||
int filtered_ix = (int)i - 1;
|
||||
int16_t* state_ptr = &state[state_length - 1];
|
||||
int16_t* state_low_ptr = &state_low[state_length - 1];
|
||||
|
||||
o = (int32_t)(*x_ptr++) << 12;
|
||||
o = (int32_t)(*x_ptr++) * (1 << 12);
|
||||
oLOW = (int32_t)0;
|
||||
|
||||
stop = (i < a_length) ? i + 1 : a_length;
|
||||
for (j = 1; j < stop; j++)
|
||||
{
|
||||
o -= *a_ptr * *filtered_ptr--;
|
||||
oLOW -= *a_ptr++ * *filtered_low_ptr--;
|
||||
RTC_DCHECK_GE(filtered_ix, 0);
|
||||
o -= *a_ptr * filtered[filtered_ix];
|
||||
oLOW -= *a_ptr++ * filtered_low[filtered_ix];
|
||||
--filtered_ix;
|
||||
}
|
||||
for (j = i + 1; j < a_length; j++)
|
||||
{
|
||||
@ -62,8 +68,8 @@ size_t WebRtcSpl_FilterAR(const int16_t* a,
|
||||
|
||||
o += (oLOW >> 12);
|
||||
*filteredFINAL_ptr = (int16_t)((o + (int32_t)2048) >> 12);
|
||||
*filteredFINAL_LOW_ptr++ = (int16_t)(o - ((int32_t)(*filteredFINAL_ptr++)
|
||||
<< 12));
|
||||
*filteredFINAL_LOW_ptr++ =
|
||||
(int16_t)(o - ((int32_t)(*filteredFINAL_ptr++) * (1 << 12)));
|
||||
}
|
||||
|
||||
// Save the filter state
|
||||
@ -81,7 +87,7 @@ size_t WebRtcSpl_FilterAR(const int16_t* a,
|
||||
for (i = 0; i < x_length; i++)
|
||||
{
|
||||
state[state_length - x_length + i] = filtered[i];
|
||||
state[state_length - x_length + i] = filtered_low[i];
|
||||
state_low[state_length - x_length + i] = filtered_low[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,11 @@
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#include <assert.h>
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "stddef.h"
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
// TODO(bjornv): Change the return type to report errors.
|
||||
|
||||
@ -21,15 +23,18 @@ void WebRtcSpl_FilterARFastQ12(const int16_t* data_in,
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
|
||||
assert(data_length > 0);
|
||||
assert(coefficients_length > 1);
|
||||
RTC_DCHECK_GT(data_length, 0);
|
||||
RTC_DCHECK_GT(coefficients_length, 1);
|
||||
|
||||
for (i = 0; i < data_length; i++) {
|
||||
int32_t output = 0;
|
||||
int32_t sum = 0;
|
||||
int64_t output = 0;
|
||||
int64_t sum = 0;
|
||||
|
||||
for (j = coefficients_length - 1; j > 0; j--) {
|
||||
sum += coefficients[j] * data_out[i - j];
|
||||
// Negative overflow is permitted here, because this is
|
||||
// auto-regressive filters, and the state for each batch run is
|
||||
// stored in the "negative" positions of the output vector.
|
||||
sum += coefficients[j] * data_out[(ptrdiff_t) i - (ptrdiff_t) j];
|
||||
}
|
||||
|
||||
output = coefficients[0] * data_in[i];
|
||||
|
@ -35,7 +35,7 @@
|
||||
@ r11: Scratch
|
||||
@ r12: &coefficients[j]
|
||||
|
||||
#include "webrtc/system_wrappers/include/asm_defines.h"
|
||||
#include "rtc_base/system/asm_defines.h"
|
||||
|
||||
GLOBAL_FUNCTION WebRtcSpl_FilterARFastQ12
|
||||
.align 2
|
||||
|
@ -7,9 +7,9 @@
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#include <assert.h>
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
void WebRtcSpl_FilterARFastQ12(const int16_t* data_in,
|
||||
int16_t* data_out,
|
||||
@ -25,8 +25,8 @@ void WebRtcSpl_FilterARFastQ12(const int16_t* data_in,
|
||||
int min16 = 0xFFFF8000;
|
||||
#endif // #if !defined(MIPS_DSP_R1_LE)
|
||||
|
||||
assert(data_length > 0);
|
||||
assert(coefficients_length > 1);
|
||||
RTC_DCHECK_GT(data_length, 0);
|
||||
RTC_DCHECK_GT(coefficients_length, 1);
|
||||
|
||||
__asm __volatile (
|
||||
".set push \n\t"
|
||||
|
@ -15,7 +15,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
#include "rtc_base/sanitizer.h"
|
||||
|
||||
void WebRtcSpl_FilterMAFastQ12(const int16_t* in_ptr,
|
||||
int16_t* out_ptr,
|
||||
@ -24,13 +26,21 @@ void WebRtcSpl_FilterMAFastQ12(const int16_t* in_ptr,
|
||||
size_t length)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
rtc_MsanCheckInitialized(B, sizeof(B[0]), B_length);
|
||||
rtc_MsanCheckInitialized(in_ptr - B_length + 1, sizeof(in_ptr[0]),
|
||||
B_length + length - 1);
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
int32_t o = 0;
|
||||
|
||||
for (j = 0; j < B_length; j++)
|
||||
{
|
||||
o += B[j] * in_ptr[i - j];
|
||||
// Negative overflow is permitted here, because this is
|
||||
// auto-regressive filters, and the state for each batch run is
|
||||
// stored in the "negative" positions of the output vector.
|
||||
o += B[j] * in_ptr[(ptrdiff_t) i - (ptrdiff_t) j];
|
||||
}
|
||||
|
||||
// If output is higher than 32768, saturate it. Same with negative side
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
// Hanning table with 256 entries
|
||||
static const int16_t kHanningTable[] = {
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
int16_t WebRtcSpl_GetScalingSquare(int16_t* in_vector,
|
||||
size_t in_vector_length,
|
||||
|
@ -19,7 +19,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
void WebRtcSpl_ReverseOrderMultArrayElements(int16_t *out, const int16_t *in,
|
||||
const int16_t *win,
|
||||
@ -64,7 +64,7 @@ void WebRtcSpl_AddVectorsAndShift(int16_t *out, const int16_t *in1,
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcSpl_AddAffineVectorToVector(int16_t *out, int16_t *in,
|
||||
void WebRtcSpl_AddAffineVectorToVector(int16_t *out, const int16_t *in,
|
||||
int16_t gain, int32_t add_constant,
|
||||
int16_t right_shifts,
|
||||
size_t vector_length)
|
||||
@ -77,7 +77,7 @@ void WebRtcSpl_AddAffineVectorToVector(int16_t *out, int16_t *in,
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcSpl_AffineTransformVector(int16_t *out, int16_t *in,
|
||||
void WebRtcSpl_AffineTransformVector(int16_t *out, const int16_t *in,
|
||||
int16_t gain, int32_t add_constant,
|
||||
int16_t right_shifts, size_t vector_length)
|
||||
{
|
||||
|
@ -8,15 +8,14 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_
|
||||
#define WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_
|
||||
#ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_
|
||||
#define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// For ComplexFFT(), the maximum fft order is 10;
|
||||
// for OpenMax FFT in ARM, it is 12;
|
||||
// WebRTC APM uses orders of only 7 and 8.
|
||||
enum {kMaxFFTOrder = 10};
|
||||
enum { kMaxFFTOrder = 10 };
|
||||
|
||||
struct RealFFT;
|
||||
|
||||
@ -57,7 +56,7 @@ void WebRtcSpl_FreeRealFFT(struct RealFFT* self);
|
||||
//
|
||||
// Return Value:
|
||||
// 0 - FFT calculation is successful.
|
||||
// -1 - Error with bad arguments (NULL pointers).
|
||||
// -1 - Error with bad arguments (null pointers).
|
||||
int WebRtcSpl_RealForwardFFT(struct RealFFT* self,
|
||||
const int16_t* real_data_in,
|
||||
int16_t* complex_data_out);
|
||||
@ -85,7 +84,7 @@ int WebRtcSpl_RealForwardFFT(struct RealFFT* self,
|
||||
// 0 or a positive number - a value that the elements in the |real_data_out|
|
||||
// should be shifted left with in order to get
|
||||
// correct physical values.
|
||||
// -1 - Error with bad arguments (NULL pointers).
|
||||
// -1 - Error with bad arguments (null pointers).
|
||||
int WebRtcSpl_RealInverseFFT(struct RealFFT* self,
|
||||
const int16_t* complex_data_in,
|
||||
int16_t* real_data_out);
|
||||
@ -94,4 +93,4 @@ int WebRtcSpl_RealInverseFFT(struct RealFFT* self,
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_
|
||||
#endif // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_
|
||||
|
@ -8,91 +8,84 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This header file includes all of the fix point signal processing library (SPL) function
|
||||
* descriptions and declarations.
|
||||
* For specific function calls, see bottom of file.
|
||||
* This header file includes all of the fix point signal processing library
|
||||
* (SPL) function descriptions and declarations. For specific function calls,
|
||||
* see bottom of file.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SPL_SIGNAL_PROCESSING_LIBRARY_H_
|
||||
#define WEBRTC_SPL_SIGNAL_PROCESSING_LIBRARY_H_
|
||||
#ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SIGNAL_PROCESSING_LIBRARY_H_
|
||||
#define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SIGNAL_PROCESSING_LIBRARY_H_
|
||||
|
||||
#include <string.h>
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
#include "common_audio/signal_processing/dot_product_with_scale.h"
|
||||
|
||||
// Macros specific for the fixed point implementation
|
||||
#define WEBRTC_SPL_WORD16_MAX 32767
|
||||
#define WEBRTC_SPL_WORD16_MIN -32768
|
||||
#define WEBRTC_SPL_WORD32_MAX (int32_t)0x7fffffff
|
||||
#define WEBRTC_SPL_WORD32_MIN (int32_t)0x80000000
|
||||
#define WEBRTC_SPL_MAX_LPC_ORDER 14
|
||||
#define WEBRTC_SPL_MIN(A, B) (A < B ? A : B) // Get min value
|
||||
#define WEBRTC_SPL_MAX(A, B) (A > B ? A : B) // Get max value
|
||||
#define WEBRTC_SPL_WORD16_MAX 32767
|
||||
#define WEBRTC_SPL_WORD16_MIN -32768
|
||||
#define WEBRTC_SPL_WORD32_MAX (int32_t)0x7fffffff
|
||||
#define WEBRTC_SPL_WORD32_MIN (int32_t)0x80000000
|
||||
#define WEBRTC_SPL_MAX_LPC_ORDER 14
|
||||
#define WEBRTC_SPL_MIN(A, B) (A < B ? A : B) // Get min value
|
||||
#define WEBRTC_SPL_MAX(A, B) (A > B ? A : B) // Get max value
|
||||
// TODO(kma/bjorn): For the next two macros, investigate how to correct the code
|
||||
// for inputs of a = WEBRTC_SPL_WORD16_MIN or WEBRTC_SPL_WORD32_MIN.
|
||||
#define WEBRTC_SPL_ABS_W16(a) \
|
||||
(((int16_t)a >= 0) ? ((int16_t)a) : -((int16_t)a))
|
||||
#define WEBRTC_SPL_ABS_W32(a) \
|
||||
(((int32_t)a >= 0) ? ((int32_t)a) : -((int32_t)a))
|
||||
#define WEBRTC_SPL_ABS_W16(a) (((int16_t)a >= 0) ? ((int16_t)a) : -((int16_t)a))
|
||||
#define WEBRTC_SPL_ABS_W32(a) (((int32_t)a >= 0) ? ((int32_t)a) : -((int32_t)a))
|
||||
|
||||
#define WEBRTC_SPL_MUL(a, b) \
|
||||
((int32_t) ((int32_t)(a) * (int32_t)(b)))
|
||||
#define WEBRTC_SPL_UMUL(a, b) \
|
||||
((uint32_t) ((uint32_t)(a) * (uint32_t)(b)))
|
||||
#define WEBRTC_SPL_UMUL_32_16(a, b) \
|
||||
((uint32_t) ((uint32_t)(a) * (uint16_t)(b)))
|
||||
#define WEBRTC_SPL_MUL_16_U16(a, b) \
|
||||
((int32_t)(int16_t)(a) * (uint16_t)(b))
|
||||
#define WEBRTC_SPL_MUL(a, b) ((int32_t)((int32_t)(a) * (int32_t)(b)))
|
||||
#define WEBRTC_SPL_UMUL(a, b) ((uint32_t)((uint32_t)(a) * (uint32_t)(b)))
|
||||
#define WEBRTC_SPL_UMUL_32_16(a, b) ((uint32_t)((uint32_t)(a) * (uint16_t)(b)))
|
||||
#define WEBRTC_SPL_MUL_16_U16(a, b) ((int32_t)(int16_t)(a) * (uint16_t)(b))
|
||||
|
||||
// clang-format off
|
||||
// clang-format would choose some identation
|
||||
// leading to presubmit error (cpplint.py)
|
||||
#ifndef WEBRTC_ARCH_ARM_V7
|
||||
// For ARMv7 platforms, these are inline functions in spl_inl_armv7.h
|
||||
#ifndef MIPS32_LE
|
||||
// For MIPS platforms, these are inline functions in spl_inl_mips.h
|
||||
#define WEBRTC_SPL_MUL_16_16(a, b) \
|
||||
((int32_t) (((int16_t)(a)) * ((int16_t)(b))))
|
||||
#define WEBRTC_SPL_MUL_16_16(a, b) ((int32_t)(((int16_t)(a)) * ((int16_t)(b))))
|
||||
#define WEBRTC_SPL_MUL_16_32_RSFT16(a, b) \
|
||||
(WEBRTC_SPL_MUL_16_16(a, b >> 16) \
|
||||
+ ((WEBRTC_SPL_MUL_16_16(a, (b & 0xffff) >> 1) + 0x4000) >> 15))
|
||||
(WEBRTC_SPL_MUL_16_16(a, b >> 16) + \
|
||||
((WEBRTC_SPL_MUL_16_16(a, (b & 0xffff) >> 1) + 0x4000) >> 15))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define WEBRTC_SPL_MUL_16_32_RSFT11(a, b) \
|
||||
((WEBRTC_SPL_MUL_16_16(a, (b) >> 16) << 5) \
|
||||
+ (((WEBRTC_SPL_MUL_16_U16(a, (uint16_t)(b)) >> 1) + 0x0200) >> 10))
|
||||
#define WEBRTC_SPL_MUL_16_32_RSFT14(a, b) \
|
||||
((WEBRTC_SPL_MUL_16_16(a, (b) >> 16) << 2) \
|
||||
+ (((WEBRTC_SPL_MUL_16_U16(a, (uint16_t)(b)) >> 1) + 0x1000) >> 13))
|
||||
#define WEBRTC_SPL_MUL_16_32_RSFT15(a, b) \
|
||||
((WEBRTC_SPL_MUL_16_16(a, (b) >> 16) << 1) \
|
||||
+ (((WEBRTC_SPL_MUL_16_U16(a, (uint16_t)(b)) >> 1) + 0x2000) >> 14))
|
||||
#define WEBRTC_SPL_MUL_16_32_RSFT11(a, b) \
|
||||
(WEBRTC_SPL_MUL_16_16(a, (b) >> 16) * (1 << 5) + \
|
||||
(((WEBRTC_SPL_MUL_16_U16(a, (uint16_t)(b)) >> 1) + 0x0200) >> 10))
|
||||
#define WEBRTC_SPL_MUL_16_32_RSFT14(a, b) \
|
||||
(WEBRTC_SPL_MUL_16_16(a, (b) >> 16) * (1 << 2) + \
|
||||
(((WEBRTC_SPL_MUL_16_U16(a, (uint16_t)(b)) >> 1) + 0x1000) >> 13))
|
||||
#define WEBRTC_SPL_MUL_16_32_RSFT15(a, b) \
|
||||
((WEBRTC_SPL_MUL_16_16(a, (b) >> 16) * (1 << 1)) + \
|
||||
(((WEBRTC_SPL_MUL_16_U16(a, (uint16_t)(b)) >> 1) + 0x2000) >> 14))
|
||||
// clang-format on
|
||||
|
||||
#define WEBRTC_SPL_MUL_16_16_RSFT(a, b, c) \
|
||||
(WEBRTC_SPL_MUL_16_16(a, b) >> (c))
|
||||
#define WEBRTC_SPL_MUL_16_16_RSFT(a, b, c) (WEBRTC_SPL_MUL_16_16(a, b) >> (c))
|
||||
|
||||
#define WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(a, b, c) \
|
||||
((WEBRTC_SPL_MUL_16_16(a, b) + ((int32_t) \
|
||||
(((int32_t)1) << ((c) - 1)))) >> (c))
|
||||
((WEBRTC_SPL_MUL_16_16(a, b) + ((int32_t)(((int32_t)1) << ((c)-1)))) >> (c))
|
||||
|
||||
// C + the 32 most significant bits of A * B
|
||||
#define WEBRTC_SPL_SCALEDIFF32(A, B, C) \
|
||||
(C + (B >> 16) * A + (((uint32_t)(0x0000FFFF & B) * A) >> 16))
|
||||
(C + (B >> 16) * A + (((uint32_t)(B & 0x0000FFFF) * A) >> 16))
|
||||
|
||||
#define WEBRTC_SPL_SAT(a, b, c) (b > a ? a : b < c ? c : b)
|
||||
#define WEBRTC_SPL_SAT(a, b, c) (b > a ? a : b < c ? c : b)
|
||||
|
||||
// Shifting with negative numbers allowed
|
||||
// Positive means left shift
|
||||
#define WEBRTC_SPL_SHIFT_W32(x, c) \
|
||||
(((c) >= 0) ? ((x) << (c)) : ((x) >> (-(c))))
|
||||
#define WEBRTC_SPL_SHIFT_W32(x, c) ((c) >= 0 ? (x) * (1 << (c)) : (x) >> -(c))
|
||||
|
||||
// Shifting with negative numbers not allowed
|
||||
// We cannot do casting here due to signed/unsigned problem
|
||||
#define WEBRTC_SPL_LSHIFT_W32(x, c) ((x) << (c))
|
||||
#define WEBRTC_SPL_LSHIFT_W32(x, c) ((x) << (c))
|
||||
|
||||
#define WEBRTC_SPL_RSHIFT_U32(x, c) ((uint32_t)(x) >> (c))
|
||||
#define WEBRTC_SPL_RSHIFT_U32(x, c) ((uint32_t)(x) >> (c))
|
||||
|
||||
#define WEBRTC_SPL_RAND(a) \
|
||||
((int16_t)((((int16_t)a * 18816) >> 7) & 0x00007fff))
|
||||
#define WEBRTC_SPL_RAND(a) ((int16_t)((((int16_t)a * 18816) >> 7) & 0x00007fff))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -102,17 +95,10 @@ extern "C" {
|
||||
memcpy(v1, v2, (length) * sizeof(int16_t))
|
||||
|
||||
// inline functions:
|
||||
#include "webrtc/common_audio/signal_processing/include/spl_inl.h"
|
||||
#include "common_audio/signal_processing/include/spl_inl.h"
|
||||
|
||||
// Initialize SPL. Currently it contains only function pointer initialization.
|
||||
// If the underlying platform is known to be ARM-Neon (WEBRTC_HAS_NEON defined),
|
||||
// the pointers will be assigned to code optimized for Neon; otherwise
|
||||
// if run-time Neon detection (WEBRTC_DETECT_NEON) is enabled, the pointers
|
||||
// will be assigned to either Neon code or generic C code; otherwise, generic C
|
||||
// code will be assigned.
|
||||
// Note that this function MUST be called in any application that uses SPL
|
||||
// functions.
|
||||
void WebRtcSpl_Init();
|
||||
// third party math functions
|
||||
#include "common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.h"
|
||||
|
||||
int16_t WebRtcSpl_GetScalingSquare(int16_t* in_vector,
|
||||
size_t in_vector_length,
|
||||
@ -133,13 +119,10 @@ void WebRtcSpl_CopyFromEndW16(const int16_t* in_vector,
|
||||
size_t in_vector_length,
|
||||
size_t samples,
|
||||
int16_t* out_vector);
|
||||
void WebRtcSpl_ZerosArrayW16(int16_t* vector,
|
||||
size_t vector_length);
|
||||
void WebRtcSpl_ZerosArrayW32(int32_t* vector,
|
||||
size_t vector_length);
|
||||
void WebRtcSpl_ZerosArrayW16(int16_t* vector, size_t vector_length);
|
||||
void WebRtcSpl_ZerosArrayW32(int32_t* vector, size_t vector_length);
|
||||
// End: Copy and set operations.
|
||||
|
||||
|
||||
// Minimum and maximum operation functions and their pointers.
|
||||
// Implementation in min_max_operations.c.
|
||||
|
||||
@ -151,9 +134,9 @@ void WebRtcSpl_ZerosArrayW32(int32_t* vector,
|
||||
//
|
||||
// Return value : Maximum absolute value in vector.
|
||||
typedef int16_t (*MaxAbsValueW16)(const int16_t* vector, size_t length);
|
||||
extern MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16;
|
||||
extern const MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16;
|
||||
int16_t WebRtcSpl_MaxAbsValueW16C(const int16_t* vector, size_t length);
|
||||
#if (defined WEBRTC_DETECT_NEON) || (defined WEBRTC_HAS_NEON)
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
int16_t WebRtcSpl_MaxAbsValueW16Neon(const int16_t* vector, size_t length);
|
||||
#endif
|
||||
#if defined(MIPS32_LE)
|
||||
@ -168,9 +151,9 @@ int16_t WebRtcSpl_MaxAbsValueW16_mips(const int16_t* vector, size_t length);
|
||||
//
|
||||
// Return value : Maximum absolute value in vector.
|
||||
typedef int32_t (*MaxAbsValueW32)(const int32_t* vector, size_t length);
|
||||
extern MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32;
|
||||
extern const MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32;
|
||||
int32_t WebRtcSpl_MaxAbsValueW32C(const int32_t* vector, size_t length);
|
||||
#if (defined WEBRTC_DETECT_NEON) || (defined WEBRTC_HAS_NEON)
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
int32_t WebRtcSpl_MaxAbsValueW32Neon(const int32_t* vector, size_t length);
|
||||
#endif
|
||||
#if defined(MIPS_DSP_R1_LE)
|
||||
@ -185,9 +168,9 @@ int32_t WebRtcSpl_MaxAbsValueW32_mips(const int32_t* vector, size_t length);
|
||||
//
|
||||
// Return value : Maximum sample value in |vector|.
|
||||
typedef int16_t (*MaxValueW16)(const int16_t* vector, size_t length);
|
||||
extern MaxValueW16 WebRtcSpl_MaxValueW16;
|
||||
extern const MaxValueW16 WebRtcSpl_MaxValueW16;
|
||||
int16_t WebRtcSpl_MaxValueW16C(const int16_t* vector, size_t length);
|
||||
#if (defined WEBRTC_DETECT_NEON) || (defined WEBRTC_HAS_NEON)
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
int16_t WebRtcSpl_MaxValueW16Neon(const int16_t* vector, size_t length);
|
||||
#endif
|
||||
#if defined(MIPS32_LE)
|
||||
@ -202,9 +185,9 @@ int16_t WebRtcSpl_MaxValueW16_mips(const int16_t* vector, size_t length);
|
||||
//
|
||||
// Return value : Maximum sample value in |vector|.
|
||||
typedef int32_t (*MaxValueW32)(const int32_t* vector, size_t length);
|
||||
extern MaxValueW32 WebRtcSpl_MaxValueW32;
|
||||
extern const MaxValueW32 WebRtcSpl_MaxValueW32;
|
||||
int32_t WebRtcSpl_MaxValueW32C(const int32_t* vector, size_t length);
|
||||
#if (defined WEBRTC_DETECT_NEON) || (defined WEBRTC_HAS_NEON)
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
int32_t WebRtcSpl_MaxValueW32Neon(const int32_t* vector, size_t length);
|
||||
#endif
|
||||
#if defined(MIPS32_LE)
|
||||
@ -219,9 +202,9 @@ int32_t WebRtcSpl_MaxValueW32_mips(const int32_t* vector, size_t length);
|
||||
//
|
||||
// Return value : Minimum sample value in |vector|.
|
||||
typedef int16_t (*MinValueW16)(const int16_t* vector, size_t length);
|
||||
extern MinValueW16 WebRtcSpl_MinValueW16;
|
||||
extern const MinValueW16 WebRtcSpl_MinValueW16;
|
||||
int16_t WebRtcSpl_MinValueW16C(const int16_t* vector, size_t length);
|
||||
#if (defined WEBRTC_DETECT_NEON) || (defined WEBRTC_HAS_NEON)
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
int16_t WebRtcSpl_MinValueW16Neon(const int16_t* vector, size_t length);
|
||||
#endif
|
||||
#if defined(MIPS32_LE)
|
||||
@ -236,9 +219,9 @@ int16_t WebRtcSpl_MinValueW16_mips(const int16_t* vector, size_t length);
|
||||
//
|
||||
// Return value : Minimum sample value in |vector|.
|
||||
typedef int32_t (*MinValueW32)(const int32_t* vector, size_t length);
|
||||
extern MinValueW32 WebRtcSpl_MinValueW32;
|
||||
extern const MinValueW32 WebRtcSpl_MinValueW32;
|
||||
int32_t WebRtcSpl_MinValueW32C(const int32_t* vector, size_t length);
|
||||
#if (defined WEBRTC_DETECT_NEON) || (defined WEBRTC_HAS_NEON)
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
int32_t WebRtcSpl_MinValueW32Neon(const int32_t* vector, size_t length);
|
||||
#endif
|
||||
#if defined(MIPS32_LE)
|
||||
@ -299,7 +282,6 @@ size_t WebRtcSpl_MinIndexW32(const int32_t* vector, size_t length);
|
||||
|
||||
// End: Minimum and maximum operations.
|
||||
|
||||
|
||||
// Vector scaling operations. Implementation in vector_scaling_operations.c.
|
||||
// Description at bottom of file.
|
||||
void WebRtcSpl_VectorBitShiftW16(int16_t* out_vector,
|
||||
@ -325,9 +307,11 @@ void WebRtcSpl_ScaleVectorWithSat(const int16_t* in_vector,
|
||||
size_t vector_length,
|
||||
int16_t right_shifts);
|
||||
void WebRtcSpl_ScaleAndAddVectors(const int16_t* in_vector1,
|
||||
int16_t gain1, int right_shifts1,
|
||||
int16_t gain1,
|
||||
int right_shifts1,
|
||||
const int16_t* in_vector2,
|
||||
int16_t gain2, int right_shifts2,
|
||||
int16_t gain2,
|
||||
int right_shifts2,
|
||||
int16_t* out_vector,
|
||||
size_t vector_length);
|
||||
|
||||
@ -346,8 +330,8 @@ void WebRtcSpl_ScaleAndAddVectors(const int16_t* in_vector1,
|
||||
//
|
||||
// Output:
|
||||
// - out_vector : Output vector
|
||||
// Return value : 0 if OK, -1 if (in_vector1 == NULL
|
||||
// || in_vector2 == NULL || out_vector == NULL
|
||||
// Return value : 0 if OK, -1 if (in_vector1 == null
|
||||
// || in_vector2 == null || out_vector == null
|
||||
// || length <= 0 || right_shift < 0).
|
||||
typedef int (*ScaleAndAddVectorsWithRound)(const int16_t* in_vector1,
|
||||
int16_t in_vector1_scale,
|
||||
@ -356,7 +340,7 @@ typedef int (*ScaleAndAddVectorsWithRound)(const int16_t* in_vector1,
|
||||
int right_shifts,
|
||||
int16_t* out_vector,
|
||||
size_t length);
|
||||
extern ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound;
|
||||
extern const ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound;
|
||||
int WebRtcSpl_ScaleAndAddVectorsWithRoundC(const int16_t* in_vector1,
|
||||
int16_t in_vector1_scale,
|
||||
const int16_t* in_vector2,
|
||||
@ -393,13 +377,13 @@ void WebRtcSpl_AddVectorsAndShift(int16_t* out_vector,
|
||||
size_t vector_length,
|
||||
int16_t right_shifts);
|
||||
void WebRtcSpl_AddAffineVectorToVector(int16_t* out_vector,
|
||||
int16_t* in_vector,
|
||||
const int16_t* in_vector,
|
||||
int16_t gain,
|
||||
int32_t add_constant,
|
||||
int16_t right_shifts,
|
||||
size_t vector_length);
|
||||
void WebRtcSpl_AffineTransformVector(int16_t* out_vector,
|
||||
int16_t* in_vector,
|
||||
const int16_t* in_vector,
|
||||
int16_t gain,
|
||||
int32_t add_constant,
|
||||
int16_t right_shifts,
|
||||
@ -523,7 +507,7 @@ typedef void (*CrossCorrelation)(int32_t* cross_correlation,
|
||||
size_t dim_cross_correlation,
|
||||
int right_shifts,
|
||||
int step_seq2);
|
||||
extern CrossCorrelation WebRtcSpl_CrossCorrelation;
|
||||
extern const CrossCorrelation WebRtcSpl_CrossCorrelation;
|
||||
void WebRtcSpl_CrossCorrelationC(int32_t* cross_correlation,
|
||||
const int16_t* seq1,
|
||||
const int16_t* seq2,
|
||||
@ -531,7 +515,7 @@ void WebRtcSpl_CrossCorrelationC(int32_t* cross_correlation,
|
||||
size_t dim_cross_correlation,
|
||||
int right_shifts,
|
||||
int step_seq2);
|
||||
#if (defined WEBRTC_DETECT_NEON) || (defined WEBRTC_HAS_NEON)
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
void WebRtcSpl_CrossCorrelationNeon(int32_t* cross_correlation,
|
||||
const int16_t* seq1,
|
||||
const int16_t* seq2,
|
||||
@ -585,7 +569,6 @@ int16_t WebRtcSpl_RandUArray(int16_t* vector,
|
||||
|
||||
// Math functions
|
||||
int32_t WebRtcSpl_Sqrt(int32_t value);
|
||||
int32_t WebRtcSpl_SqrtFloor(int32_t value);
|
||||
|
||||
// Divisions. Implementations collected in division_operations.c and
|
||||
// descriptions at bottom of this file.
|
||||
@ -600,22 +583,6 @@ int32_t WebRtcSpl_Energy(int16_t* vector,
|
||||
size_t vector_length,
|
||||
int* scale_factor);
|
||||
|
||||
// Calculates the dot product between two (int16_t) vectors.
|
||||
//
|
||||
// Input:
|
||||
// - vector1 : Vector 1
|
||||
// - vector2 : Vector 2
|
||||
// - vector_length : Number of samples used in the dot product
|
||||
// - scaling : The number of right bit shifts to apply on each term
|
||||
// during calculation to avoid overflow, i.e., the
|
||||
// output will be in Q(-|scaling|)
|
||||
//
|
||||
// Return value : The dot product in Q(-scaling)
|
||||
int32_t WebRtcSpl_DotProductWithScale(const int16_t* vector1,
|
||||
const int16_t* vector2,
|
||||
size_t length,
|
||||
int scaling);
|
||||
|
||||
// Filter operations.
|
||||
size_t WebRtcSpl_FilterAR(const int16_t* ar_coef,
|
||||
size_t ar_coef_length,
|
||||
@ -689,7 +656,7 @@ typedef int (*DownsampleFast)(const int16_t* data_in,
|
||||
size_t coefficients_length,
|
||||
int factor,
|
||||
size_t delay);
|
||||
extern DownsampleFast WebRtcSpl_DownsampleFast;
|
||||
extern const DownsampleFast WebRtcSpl_DownsampleFast;
|
||||
int WebRtcSpl_DownsampleFastC(const int16_t* data_in,
|
||||
size_t data_in_length,
|
||||
int16_t* data_out,
|
||||
@ -698,7 +665,7 @@ int WebRtcSpl_DownsampleFastC(const int16_t* data_in,
|
||||
size_t coefficients_length,
|
||||
int factor,
|
||||
size_t delay);
|
||||
#if (defined WEBRTC_DETECT_NEON) || (defined WEBRTC_HAS_NEON)
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
int WebRtcSpl_DownsampleFastNeon(const int16_t* data_in,
|
||||
size_t data_in_length,
|
||||
int16_t* data_out,
|
||||
@ -795,7 +762,8 @@ typedef struct {
|
||||
int32_t S_16_8[8];
|
||||
} WebRtcSpl_State22khzTo8khz;
|
||||
|
||||
void WebRtcSpl_Resample22khzTo8khz(const int16_t* in, int16_t* out,
|
||||
void WebRtcSpl_Resample22khzTo8khz(const int16_t* in,
|
||||
int16_t* out,
|
||||
WebRtcSpl_State22khzTo8khz* state,
|
||||
int32_t* tmpmem);
|
||||
|
||||
@ -808,7 +776,8 @@ typedef struct {
|
||||
int32_t S_11_22[8];
|
||||
} WebRtcSpl_State8khzTo22khz;
|
||||
|
||||
void WebRtcSpl_Resample8khzTo22khz(const int16_t* in, int16_t* out,
|
||||
void WebRtcSpl_Resample8khzTo22khz(const int16_t* in,
|
||||
int16_t* out,
|
||||
WebRtcSpl_State8khzTo22khz* state,
|
||||
int32_t* tmpmem);
|
||||
|
||||
@ -848,7 +817,8 @@ typedef struct {
|
||||
int32_t S_32_16[8];
|
||||
} WebRtcSpl_State48khzTo16khz;
|
||||
|
||||
void WebRtcSpl_Resample48khzTo16khz(const int16_t* in, int16_t* out,
|
||||
void WebRtcSpl_Resample48khzTo16khz(const int16_t* in,
|
||||
int16_t* out,
|
||||
WebRtcSpl_State48khzTo16khz* state,
|
||||
int32_t* tmpmem);
|
||||
|
||||
@ -860,7 +830,8 @@ typedef struct {
|
||||
int32_t S_24_48[8];
|
||||
} WebRtcSpl_State16khzTo48khz;
|
||||
|
||||
void WebRtcSpl_Resample16khzTo48khz(const int16_t* in, int16_t* out,
|
||||
void WebRtcSpl_Resample16khzTo48khz(const int16_t* in,
|
||||
int16_t* out,
|
||||
WebRtcSpl_State16khzTo48khz* state,
|
||||
int32_t* tmpmem);
|
||||
|
||||
@ -873,7 +844,8 @@ typedef struct {
|
||||
int32_t S_16_8[8];
|
||||
} WebRtcSpl_State48khzTo8khz;
|
||||
|
||||
void WebRtcSpl_Resample48khzTo8khz(const int16_t* in, int16_t* out,
|
||||
void WebRtcSpl_Resample48khzTo8khz(const int16_t* in,
|
||||
int16_t* out,
|
||||
WebRtcSpl_State48khzTo8khz* state,
|
||||
int32_t* tmpmem);
|
||||
|
||||
@ -886,7 +858,8 @@ typedef struct {
|
||||
int32_t S_24_48[8];
|
||||
} WebRtcSpl_State8khzTo48khz;
|
||||
|
||||
void WebRtcSpl_Resample8khzTo48khz(const int16_t* in, int16_t* out,
|
||||
void WebRtcSpl_Resample8khzTo48khz(const int16_t* in,
|
||||
int16_t* out,
|
||||
WebRtcSpl_State8khzTo48khz* state,
|
||||
int32_t* tmpmem);
|
||||
|
||||
@ -899,11 +872,15 @@ void WebRtcSpl_ResetResample8khzTo48khz(WebRtcSpl_State8khzTo48khz* state);
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
void WebRtcSpl_DownsampleBy2(const int16_t* in, size_t len,
|
||||
int16_t* out, int32_t* filtState);
|
||||
void WebRtcSpl_DownsampleBy2(const int16_t* in,
|
||||
size_t len,
|
||||
int16_t* out,
|
||||
int32_t* filtState);
|
||||
|
||||
void WebRtcSpl_UpsampleBy2(const int16_t* in, size_t len,
|
||||
int16_t* out, int32_t* filtState);
|
||||
void WebRtcSpl_UpsampleBy2(const int16_t* in,
|
||||
size_t len,
|
||||
int16_t* out,
|
||||
int32_t* filtState);
|
||||
|
||||
/************************************************************
|
||||
* END OF RESAMPLING FUNCTIONS
|
||||
@ -924,7 +901,7 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // WEBRTC_SPL_SIGNAL_PROCESSING_LIBRARY_H_
|
||||
#endif // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SIGNAL_PROCESSING_LIBRARY_H_
|
||||
|
||||
//
|
||||
// WebRtcSpl_AddSatW16(...)
|
||||
@ -1352,23 +1329,6 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band,
|
||||
// Return value : Result of the sqrt calculation
|
||||
//
|
||||
|
||||
//
|
||||
// WebRtcSpl_SqrtFloor(...)
|
||||
//
|
||||
// Returns the square root of the input value |value|. The precision of this
|
||||
// function is rounding down integer precision, i.e., sqrt(8) gives 2 as answer.
|
||||
// If |value| is a negative number then 0 is returned.
|
||||
//
|
||||
// Algorithm:
|
||||
//
|
||||
// An iterative 4 cylce/bit routine
|
||||
//
|
||||
// Input:
|
||||
// - value : Value to calculate sqrt of
|
||||
//
|
||||
// Return value : Result of the sqrt calculation
|
||||
//
|
||||
|
||||
//
|
||||
// WebRtcSpl_DivU32U16(...)
|
||||
//
|
||||
|
@ -8,24 +8,71 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
// This header file includes the inline functions in
|
||||
// the fix point signal processing library.
|
||||
|
||||
#ifndef WEBRTC_SPL_SPL_INL_H_
|
||||
#define WEBRTC_SPL_SPL_INL_H_
|
||||
#ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_H_
|
||||
#define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_H_
|
||||
|
||||
#include "rtc_base/compile_assert_c.h"
|
||||
|
||||
extern const int8_t kWebRtcSpl_CountLeadingZeros32_Table[64];
|
||||
|
||||
// Don't call this directly except in tests!
|
||||
static __inline int WebRtcSpl_CountLeadingZeros32_NotBuiltin(uint32_t n) {
|
||||
// Normalize n by rounding up to the nearest number that is a sequence of 0
|
||||
// bits followed by a sequence of 1 bits. This number has the same number of
|
||||
// leading zeros as the original n. There are exactly 33 such values.
|
||||
n |= n >> 1;
|
||||
n |= n >> 2;
|
||||
n |= n >> 4;
|
||||
n |= n >> 8;
|
||||
n |= n >> 16;
|
||||
|
||||
// Multiply the modified n with a constant selected (by exhaustive search)
|
||||
// such that each of the 33 possible values of n give a product whose 6 most
|
||||
// significant bits are unique. Then look up the answer in the table.
|
||||
return kWebRtcSpl_CountLeadingZeros32_Table[(n * 0x8c0b2891) >> 26];
|
||||
}
|
||||
|
||||
// Don't call this directly except in tests!
|
||||
static __inline int WebRtcSpl_CountLeadingZeros64_NotBuiltin(uint64_t n) {
|
||||
const int leading_zeros = n >> 32 == 0 ? 32 : 0;
|
||||
return leading_zeros + WebRtcSpl_CountLeadingZeros32_NotBuiltin(
|
||||
(uint32_t)(n >> (32 - leading_zeros)));
|
||||
}
|
||||
|
||||
// Returns the number of leading zero bits in the argument.
|
||||
static __inline int WebRtcSpl_CountLeadingZeros32(uint32_t n) {
|
||||
#ifdef __GNUC__
|
||||
RTC_COMPILE_ASSERT(sizeof(unsigned int) == sizeof(uint32_t));
|
||||
return n == 0 ? 32 : __builtin_clz(n);
|
||||
#else
|
||||
return WebRtcSpl_CountLeadingZeros32_NotBuiltin(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns the number of leading zero bits in the argument.
|
||||
static __inline int WebRtcSpl_CountLeadingZeros64(uint64_t n) {
|
||||
#ifdef __GNUC__
|
||||
RTC_COMPILE_ASSERT(sizeof(unsigned long long) == sizeof(uint64_t)); // NOLINT
|
||||
return n == 0 ? 64 : __builtin_clzll(n);
|
||||
#else
|
||||
return WebRtcSpl_CountLeadingZeros64_NotBuiltin(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WEBRTC_ARCH_ARM_V7
|
||||
#include "webrtc/common_audio/signal_processing/include/spl_inl_armv7.h"
|
||||
#include "common_audio/signal_processing/include/spl_inl_armv7.h"
|
||||
#else
|
||||
|
||||
#if defined(MIPS32_LE)
|
||||
#include "webrtc/common_audio/signal_processing/include/spl_inl_mips.h"
|
||||
#include "common_audio/signal_processing/include/spl_inl_mips.h"
|
||||
#endif
|
||||
|
||||
#if !defined(MIPS_DSP_R1_LE)
|
||||
static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) {
|
||||
int16_t out16 = (int16_t) value32;
|
||||
int16_t out16 = (int16_t)value32;
|
||||
|
||||
if (value32 > 32767)
|
||||
out16 = 32767;
|
||||
@ -35,132 +82,65 @@ static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) {
|
||||
return out16;
|
||||
}
|
||||
|
||||
static __inline int32_t WebRtcSpl_AddSatW32(int32_t l_var1, int32_t l_var2) {
|
||||
int32_t l_sum;
|
||||
static __inline int32_t WebRtcSpl_AddSatW32(int32_t a, int32_t b) {
|
||||
// Do the addition in unsigned numbers, since signed overflow is undefined
|
||||
// behavior.
|
||||
const int32_t sum = (int32_t)((uint32_t)a + (uint32_t)b);
|
||||
|
||||
// Perform long addition
|
||||
l_sum = l_var1 + l_var2;
|
||||
|
||||
if (l_var1 < 0) { // Check for underflow.
|
||||
if ((l_var2 < 0) && (l_sum >= 0)) {
|
||||
l_sum = (int32_t)0x80000000;
|
||||
}
|
||||
} else { // Check for overflow.
|
||||
if ((l_var2 > 0) && (l_sum < 0)) {
|
||||
l_sum = (int32_t)0x7FFFFFFF;
|
||||
}
|
||||
// a + b can't overflow if a and b have different signs. If they have the
|
||||
// same sign, a + b also has the same sign iff it didn't overflow.
|
||||
if ((a < 0) == (b < 0) && (a < 0) != (sum < 0)) {
|
||||
// The direction of the overflow is obvious from the sign of a + b.
|
||||
return sum < 0 ? INT32_MAX : INT32_MIN;
|
||||
}
|
||||
|
||||
return l_sum;
|
||||
return sum;
|
||||
}
|
||||
|
||||
static __inline int32_t WebRtcSpl_SubSatW32(int32_t l_var1, int32_t l_var2) {
|
||||
int32_t l_diff;
|
||||
static __inline int32_t WebRtcSpl_SubSatW32(int32_t a, int32_t b) {
|
||||
// Do the subtraction in unsigned numbers, since signed overflow is undefined
|
||||
// behavior.
|
||||
const int32_t diff = (int32_t)((uint32_t)a - (uint32_t)b);
|
||||
|
||||
// Perform subtraction.
|
||||
l_diff = l_var1 - l_var2;
|
||||
|
||||
if (l_var1 < 0) { // Check for underflow.
|
||||
if ((l_var2 > 0) && (l_diff > 0)) {
|
||||
l_diff = (int32_t)0x80000000;
|
||||
}
|
||||
} else { // Check for overflow.
|
||||
if ((l_var2 < 0) && (l_diff < 0)) {
|
||||
l_diff = (int32_t)0x7FFFFFFF;
|
||||
}
|
||||
// a - b can't overflow if a and b have the same sign. If they have different
|
||||
// signs, a - b has the same sign as a iff it didn't overflow.
|
||||
if ((a < 0) != (b < 0) && (a < 0) != (diff < 0)) {
|
||||
// The direction of the overflow is obvious from the sign of a - b.
|
||||
return diff < 0 ? INT32_MAX : INT32_MIN;
|
||||
}
|
||||
|
||||
return l_diff;
|
||||
return diff;
|
||||
}
|
||||
|
||||
static __inline int16_t WebRtcSpl_AddSatW16(int16_t a, int16_t b) {
|
||||
return WebRtcSpl_SatW32ToW16((int32_t) a + (int32_t) b);
|
||||
return WebRtcSpl_SatW32ToW16((int32_t)a + (int32_t)b);
|
||||
}
|
||||
|
||||
static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) {
|
||||
return WebRtcSpl_SatW32ToW16((int32_t) var1 - (int32_t) var2);
|
||||
return WebRtcSpl_SatW32ToW16((int32_t)var1 - (int32_t)var2);
|
||||
}
|
||||
#endif // #if !defined(MIPS_DSP_R1_LE)
|
||||
|
||||
#if !defined(MIPS32_LE)
|
||||
static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) {
|
||||
int16_t bits;
|
||||
|
||||
if (0xFFFF0000 & n) {
|
||||
bits = 16;
|
||||
} else {
|
||||
bits = 0;
|
||||
}
|
||||
if (0x0000FF00 & (n >> bits)) bits += 8;
|
||||
if (0x000000F0 & (n >> bits)) bits += 4;
|
||||
if (0x0000000C & (n >> bits)) bits += 2;
|
||||
if (0x00000002 & (n >> bits)) bits += 1;
|
||||
if (0x00000001 & (n >> bits)) bits += 1;
|
||||
|
||||
return bits;
|
||||
return 32 - WebRtcSpl_CountLeadingZeros32(n);
|
||||
}
|
||||
|
||||
// Return the number of steps a can be left-shifted without overflow,
|
||||
// or 0 if a == 0.
|
||||
static __inline int16_t WebRtcSpl_NormW32(int32_t a) {
|
||||
int16_t zeros;
|
||||
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
else if (a < 0) {
|
||||
a = ~a;
|
||||
}
|
||||
|
||||
if (!(0xFFFF8000 & a)) {
|
||||
zeros = 16;
|
||||
} else {
|
||||
zeros = 0;
|
||||
}
|
||||
if (!(0xFF800000 & (a << zeros))) zeros += 8;
|
||||
if (!(0xF8000000 & (a << zeros))) zeros += 4;
|
||||
if (!(0xE0000000 & (a << zeros))) zeros += 2;
|
||||
if (!(0xC0000000 & (a << zeros))) zeros += 1;
|
||||
|
||||
return zeros;
|
||||
return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a < 0 ? ~a : a) - 1;
|
||||
}
|
||||
|
||||
// Return the number of steps a can be left-shifted without overflow,
|
||||
// or 0 if a == 0.
|
||||
static __inline int16_t WebRtcSpl_NormU32(uint32_t a) {
|
||||
int16_t zeros;
|
||||
|
||||
if (a == 0) return 0;
|
||||
|
||||
if (!(0xFFFF0000 & a)) {
|
||||
zeros = 16;
|
||||
} else {
|
||||
zeros = 0;
|
||||
}
|
||||
if (!(0xFF000000 & (a << zeros))) zeros += 8;
|
||||
if (!(0xF0000000 & (a << zeros))) zeros += 4;
|
||||
if (!(0xC0000000 & (a << zeros))) zeros += 2;
|
||||
if (!(0x80000000 & (a << zeros))) zeros += 1;
|
||||
|
||||
return zeros;
|
||||
return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a);
|
||||
}
|
||||
|
||||
// Return the number of steps a can be left-shifted without overflow,
|
||||
// or 0 if a == 0.
|
||||
static __inline int16_t WebRtcSpl_NormW16(int16_t a) {
|
||||
int16_t zeros;
|
||||
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
else if (a < 0) {
|
||||
a = ~a;
|
||||
}
|
||||
|
||||
if (!(0xFF80 & a)) {
|
||||
zeros = 8;
|
||||
} else {
|
||||
zeros = 0;
|
||||
}
|
||||
if (!(0xF800 & (a << zeros))) zeros += 4;
|
||||
if (!(0xE000 & (a << zeros))) zeros += 2;
|
||||
if (!(0xC000 & (a << zeros))) zeros += 1;
|
||||
|
||||
return zeros;
|
||||
const int32_t a32 = a;
|
||||
return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a < 0 ? ~a32 : a32) - 17;
|
||||
}
|
||||
|
||||
static __inline int32_t WebRtc_MulAccumW16(int16_t a, int16_t b, int32_t c) {
|
||||
@ -170,4 +150,4 @@ static __inline int32_t WebRtc_MulAccumW16(int16_t a, int16_t b, int32_t c) {
|
||||
|
||||
#endif // WEBRTC_ARCH_ARM_V7
|
||||
|
||||
#endif // WEBRTC_SPL_SPL_INL_H_
|
||||
#endif // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_H_
|
||||
|
@ -8,13 +8,12 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
/* This header file includes the inline functions for ARM processors in
|
||||
* the fix point signal processing library.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SPL_SPL_INL_ARMV7_H_
|
||||
#define WEBRTC_SPL_SPL_INL_ARMV7_H_
|
||||
#ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_ARMV7_H_
|
||||
#define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_ARMV7_H_
|
||||
|
||||
/* TODO(kma): Replace some assembly code with GCC intrinsics
|
||||
* (e.g. __builtin_clz).
|
||||
@ -26,35 +25,37 @@
|
||||
*/
|
||||
static __inline int32_t WEBRTC_SPL_MUL_16_32_RSFT16(int16_t a, int32_t b) {
|
||||
int32_t tmp = 0;
|
||||
__asm __volatile ("smulwb %0, %1, %2":"=r"(tmp):"r"(b), "r"(a));
|
||||
__asm __volatile("smulwb %0, %1, %2" : "=r"(tmp) : "r"(b), "r"(a));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static __inline int32_t WEBRTC_SPL_MUL_16_16(int16_t a, int16_t b) {
|
||||
int32_t tmp = 0;
|
||||
__asm __volatile ("smulbb %0, %1, %2":"=r"(tmp):"r"(a), "r"(b));
|
||||
__asm __volatile("smulbb %0, %1, %2" : "=r"(tmp) : "r"(a), "r"(b));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// TODO(kma): add unit test.
|
||||
static __inline int32_t WebRtc_MulAccumW16(int16_t a, int16_t b, int32_t c) {
|
||||
int32_t tmp = 0;
|
||||
__asm __volatile ("smlabb %0, %1, %2, %3":"=r"(tmp):"r"(a), "r"(b), "r"(c));
|
||||
__asm __volatile("smlabb %0, %1, %2, %3"
|
||||
: "=r"(tmp)
|
||||
: "r"(a), "r"(b), "r"(c));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static __inline int16_t WebRtcSpl_AddSatW16(int16_t a, int16_t b) {
|
||||
int32_t s_sum = 0;
|
||||
|
||||
__asm __volatile ("qadd16 %0, %1, %2":"=r"(s_sum):"r"(a), "r"(b));
|
||||
__asm __volatile("qadd16 %0, %1, %2" : "=r"(s_sum) : "r"(a), "r"(b));
|
||||
|
||||
return (int16_t) s_sum;
|
||||
return (int16_t)s_sum;
|
||||
}
|
||||
|
||||
static __inline int32_t WebRtcSpl_AddSatW32(int32_t l_var1, int32_t l_var2) {
|
||||
int32_t l_sum = 0;
|
||||
|
||||
__asm __volatile ("qadd %0, %1, %2":"=r"(l_sum):"r"(l_var1), "r"(l_var2));
|
||||
__asm __volatile("qadd %0, %1, %2" : "=r"(l_sum) : "r"(l_var1), "r"(l_var2));
|
||||
|
||||
return l_sum;
|
||||
}
|
||||
@ -62,7 +63,7 @@ static __inline int32_t WebRtcSpl_AddSatW32(int32_t l_var1, int32_t l_var2) {
|
||||
static __inline int32_t WebRtcSpl_SubSatW32(int32_t l_var1, int32_t l_var2) {
|
||||
int32_t l_sub = 0;
|
||||
|
||||
__asm __volatile ("qsub %0, %1, %2":"=r"(l_sub):"r"(l_var1), "r"(l_var2));
|
||||
__asm __volatile("qsub %0, %1, %2" : "=r"(l_sub) : "r"(l_var1), "r"(l_var2));
|
||||
|
||||
return l_sub;
|
||||
}
|
||||
@ -70,7 +71,7 @@ static __inline int32_t WebRtcSpl_SubSatW32(int32_t l_var1, int32_t l_var2) {
|
||||
static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) {
|
||||
int32_t s_sub = 0;
|
||||
|
||||
__asm __volatile ("qsub16 %0, %1, %2":"=r"(s_sub):"r"(var1), "r"(var2));
|
||||
__asm __volatile("qsub16 %0, %1, %2" : "=r"(s_sub) : "r"(var1), "r"(var2));
|
||||
|
||||
return (int16_t)s_sub;
|
||||
}
|
||||
@ -78,7 +79,7 @@ static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) {
|
||||
static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) {
|
||||
int32_t tmp = 0;
|
||||
|
||||
__asm __volatile ("clz %0, %1":"=r"(tmp):"r"(n));
|
||||
__asm __volatile("clz %0, %1" : "=r"(tmp) : "r"(n));
|
||||
|
||||
return (int16_t)(32 - tmp);
|
||||
}
|
||||
@ -88,12 +89,11 @@ static __inline int16_t WebRtcSpl_NormW32(int32_t a) {
|
||||
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
else if (a < 0) {
|
||||
} else if (a < 0) {
|
||||
a ^= 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a));
|
||||
__asm __volatile("clz %0, %1" : "=r"(tmp) : "r"(a));
|
||||
|
||||
return (int16_t)(tmp - 1);
|
||||
}
|
||||
@ -101,9 +101,10 @@ static __inline int16_t WebRtcSpl_NormW32(int32_t a) {
|
||||
static __inline int16_t WebRtcSpl_NormU32(uint32_t a) {
|
||||
int tmp = 0;
|
||||
|
||||
if (a == 0) return 0;
|
||||
if (a == 0)
|
||||
return 0;
|
||||
|
||||
__asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a));
|
||||
__asm __volatile("clz %0, %1" : "=r"(tmp) : "r"(a));
|
||||
|
||||
return (int16_t)tmp;
|
||||
}
|
||||
@ -114,12 +115,11 @@ static __inline int16_t WebRtcSpl_NormW16(int16_t a) {
|
||||
|
||||
if (a_32 == 0) {
|
||||
return 0;
|
||||
}
|
||||
else if (a_32 < 0) {
|
||||
} else if (a_32 < 0) {
|
||||
a_32 ^= 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
__asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a_32));
|
||||
__asm __volatile("clz %0, %1" : "=r"(tmp) : "r"(a_32));
|
||||
|
||||
return (int16_t)(tmp - 17);
|
||||
}
|
||||
@ -128,9 +128,9 @@ static __inline int16_t WebRtcSpl_NormW16(int16_t a) {
|
||||
static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) {
|
||||
int32_t out = 0;
|
||||
|
||||
__asm __volatile ("ssat %0, #16, %1" : "=r"(out) : "r"(value32));
|
||||
__asm __volatile("ssat %0, #16, %1" : "=r"(out) : "r"(value32));
|
||||
|
||||
return (int16_t)out;
|
||||
}
|
||||
|
||||
#endif // WEBRTC_SPL_SPL_INL_ARMV7_H_
|
||||
#endif // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_ARMV7_H_
|
||||
|
@ -8,72 +8,65 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
// This header file includes the inline functions in
|
||||
// the fix point signal processing library.
|
||||
|
||||
#ifndef WEBRTC_SPL_SPL_INL_MIPS_H_
|
||||
#define WEBRTC_SPL_SPL_INL_MIPS_H_
|
||||
#ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_MIPS_H_
|
||||
#define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_MIPS_H_
|
||||
|
||||
static __inline int32_t WEBRTC_SPL_MUL_16_16(int32_t a,
|
||||
int32_t b) {
|
||||
static __inline int32_t WEBRTC_SPL_MUL_16_16(int32_t a, int32_t b) {
|
||||
int32_t value32 = 0;
|
||||
int32_t a1 = 0, b1 = 0;
|
||||
|
||||
__asm __volatile(
|
||||
#if defined(MIPS32_R2_LE)
|
||||
"seh %[a1], %[a] \n\t"
|
||||
"seh %[b1], %[b] \n\t"
|
||||
"seh %[a1], %[a] \n\t"
|
||||
"seh %[b1], %[b] \n\t"
|
||||
#else
|
||||
"sll %[a1], %[a], 16 \n\t"
|
||||
"sll %[b1], %[b], 16 \n\t"
|
||||
"sra %[a1], %[a1], 16 \n\t"
|
||||
"sra %[b1], %[b1], 16 \n\t"
|
||||
"sll %[a1], %[a], 16 \n\t"
|
||||
"sll %[b1], %[b], 16 \n\t"
|
||||
"sra %[a1], %[a1], 16 \n\t"
|
||||
"sra %[b1], %[b1], 16 \n\t"
|
||||
#endif
|
||||
"mul %[value32], %[a1], %[b1] \n\t"
|
||||
: [value32] "=r" (value32), [a1] "=&r" (a1), [b1] "=&r" (b1)
|
||||
: [a] "r" (a), [b] "r" (b)
|
||||
: "hi", "lo"
|
||||
);
|
||||
"mul %[value32], %[a1], %[b1] \n\t"
|
||||
: [value32] "=r"(value32), [a1] "=&r"(a1), [b1] "=&r"(b1)
|
||||
: [a] "r"(a), [b] "r"(b)
|
||||
: "hi", "lo");
|
||||
return value32;
|
||||
}
|
||||
|
||||
static __inline int32_t WEBRTC_SPL_MUL_16_32_RSFT16(int16_t a,
|
||||
int32_t b) {
|
||||
static __inline int32_t WEBRTC_SPL_MUL_16_32_RSFT16(int16_t a, int32_t b) {
|
||||
int32_t value32 = 0, b1 = 0, b2 = 0;
|
||||
int32_t a1 = 0;
|
||||
|
||||
__asm __volatile(
|
||||
#if defined(MIPS32_R2_LE)
|
||||
"seh %[a1], %[a] \n\t"
|
||||
"seh %[a1], %[a] \n\t"
|
||||
#else
|
||||
"sll %[a1], %[a], 16 \n\t"
|
||||
"sra %[a1], %[a1], 16 \n\t"
|
||||
"sll %[a1], %[a], 16 \n\t"
|
||||
"sra %[a1], %[a1], 16 \n\t"
|
||||
#endif
|
||||
"andi %[b2], %[b], 0xFFFF \n\t"
|
||||
"sra %[b1], %[b], 16 \n\t"
|
||||
"sra %[b2], %[b2], 1 \n\t"
|
||||
"mul %[value32], %[a1], %[b1] \n\t"
|
||||
"mul %[b2], %[a1], %[b2] \n\t"
|
||||
"addiu %[b2], %[b2], 0x4000 \n\t"
|
||||
"sra %[b2], %[b2], 15 \n\t"
|
||||
"addu %[value32], %[value32], %[b2] \n\t"
|
||||
: [value32] "=&r" (value32), [b1] "=&r" (b1), [b2] "=&r" (b2),
|
||||
[a1] "=&r" (a1)
|
||||
: [a] "r" (a), [b] "r" (b)
|
||||
: "hi", "lo"
|
||||
);
|
||||
"andi %[b2], %[b], 0xFFFF \n\t"
|
||||
"sra %[b1], %[b], 16 \n\t"
|
||||
"sra %[b2], %[b2], 1 \n\t"
|
||||
"mul %[value32], %[a1], %[b1] \n\t"
|
||||
"mul %[b2], %[a1], %[b2] \n\t"
|
||||
"addiu %[b2], %[b2], 0x4000 \n\t"
|
||||
"sra %[b2], %[b2], 15 \n\t"
|
||||
"addu %[value32], %[value32], %[b2] \n\t"
|
||||
: [value32] "=&r"(value32), [b1] "=&r"(b1), [b2] "=&r"(b2), [a1] "=&r"(a1)
|
||||
: [a] "r"(a), [b] "r"(b)
|
||||
: "hi", "lo");
|
||||
return value32;
|
||||
}
|
||||
|
||||
#if defined(MIPS_DSP_R1_LE)
|
||||
static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) {
|
||||
__asm __volatile(
|
||||
"shll_s.w %[value32], %[value32], 16 \n\t"
|
||||
"sra %[value32], %[value32], 16 \n\t"
|
||||
: [value32] "+r" (value32)
|
||||
:
|
||||
);
|
||||
"shll_s.w %[value32], %[value32], 16 \n\t"
|
||||
"sra %[value32], %[value32], 16 \n\t"
|
||||
: [value32] "+r"(value32)
|
||||
:);
|
||||
int16_t out16 = (int16_t)value32;
|
||||
return out16;
|
||||
}
|
||||
@ -81,11 +74,9 @@ static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) {
|
||||
static __inline int16_t WebRtcSpl_AddSatW16(int16_t a, int16_t b) {
|
||||
int32_t value32 = 0;
|
||||
|
||||
__asm __volatile(
|
||||
"addq_s.ph %[value32], %[a], %[b] \n\t"
|
||||
: [value32] "=r" (value32)
|
||||
: [a] "r" (a), [b] "r" (b)
|
||||
);
|
||||
__asm __volatile("addq_s.ph %[value32], %[a], %[b] \n\t"
|
||||
: [value32] "=r"(value32)
|
||||
: [a] "r"(a), [b] "r"(b));
|
||||
return (int16_t)value32;
|
||||
}
|
||||
|
||||
@ -93,10 +84,9 @@ static __inline int32_t WebRtcSpl_AddSatW32(int32_t l_var1, int32_t l_var2) {
|
||||
int32_t l_sum;
|
||||
|
||||
__asm __volatile(
|
||||
"addq_s.w %[l_sum], %[l_var1], %[l_var2] \n\t"
|
||||
: [l_sum] "=r" (l_sum)
|
||||
: [l_var1] "r" (l_var1), [l_var2] "r" (l_var2)
|
||||
);
|
||||
"addq_s.w %[l_sum], %[l_var1], %[l_var2] \n\t"
|
||||
: [l_sum] "=r"(l_sum)
|
||||
: [l_var1] "r"(l_var1), [l_var2] "r"(l_var2));
|
||||
|
||||
return l_sum;
|
||||
}
|
||||
@ -104,11 +94,9 @@ static __inline int32_t WebRtcSpl_AddSatW32(int32_t l_var1, int32_t l_var2) {
|
||||
static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) {
|
||||
int32_t value32;
|
||||
|
||||
__asm __volatile(
|
||||
"subq_s.ph %[value32], %[var1], %[var2] \n\t"
|
||||
: [value32] "=r" (value32)
|
||||
: [var1] "r" (var1), [var2] "r" (var2)
|
||||
);
|
||||
__asm __volatile("subq_s.ph %[value32], %[var1], %[var2] \n\t"
|
||||
: [value32] "=r"(value32)
|
||||
: [var1] "r"(var1), [var2] "r"(var2));
|
||||
|
||||
return (int16_t)value32;
|
||||
}
|
||||
@ -117,10 +105,9 @@ static __inline int32_t WebRtcSpl_SubSatW32(int32_t l_var1, int32_t l_var2) {
|
||||
int32_t l_diff;
|
||||
|
||||
__asm __volatile(
|
||||
"subq_s.w %[l_diff], %[l_var1], %[l_var2] \n\t"
|
||||
: [l_diff] "=r" (l_diff)
|
||||
: [l_var1] "r" (l_var1), [l_var2] "r" (l_var2)
|
||||
);
|
||||
"subq_s.w %[l_diff], %[l_var1], %[l_var2] \n\t"
|
||||
: [l_diff] "=r"(l_diff)
|
||||
: [l_var1] "r"(l_var1), [l_var2] "r"(l_var2));
|
||||
|
||||
return l_diff;
|
||||
}
|
||||
@ -131,11 +118,10 @@ static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) {
|
||||
int i32 = 32;
|
||||
|
||||
__asm __volatile(
|
||||
"clz %[bits], %[n] \n\t"
|
||||
"subu %[bits], %[i32], %[bits] \n\t"
|
||||
: [bits] "=&r" (bits)
|
||||
: [n] "r" (n), [i32] "r" (i32)
|
||||
);
|
||||
"clz %[bits], %[n] \n\t"
|
||||
"subu %[bits], %[i32], %[bits] \n\t"
|
||||
: [bits] "=&r"(bits)
|
||||
: [n] "r"(n), [i32] "r"(i32));
|
||||
|
||||
return (int16_t)bits;
|
||||
}
|
||||
@ -144,21 +130,20 @@ static __inline int16_t WebRtcSpl_NormW32(int32_t a) {
|
||||
int zeros = 0;
|
||||
|
||||
__asm __volatile(
|
||||
".set push \n\t"
|
||||
".set noreorder \n\t"
|
||||
"bnez %[a], 1f \n\t"
|
||||
" sra %[zeros], %[a], 31 \n\t"
|
||||
"b 2f \n\t"
|
||||
" move %[zeros], $zero \n\t"
|
||||
"1: \n\t"
|
||||
"xor %[zeros], %[a], %[zeros] \n\t"
|
||||
"clz %[zeros], %[zeros] \n\t"
|
||||
"addiu %[zeros], %[zeros], -1 \n\t"
|
||||
"2: \n\t"
|
||||
".set pop \n\t"
|
||||
: [zeros]"=&r"(zeros)
|
||||
: [a] "r" (a)
|
||||
);
|
||||
".set push \n\t"
|
||||
".set noreorder \n\t"
|
||||
"bnez %[a], 1f \n\t"
|
||||
" sra %[zeros], %[a], 31 \n\t"
|
||||
"b 2f \n\t"
|
||||
" move %[zeros], $zero \n\t"
|
||||
"1: \n\t"
|
||||
"xor %[zeros], %[a], %[zeros] \n\t"
|
||||
"clz %[zeros], %[zeros] \n\t"
|
||||
"addiu %[zeros], %[zeros], -1 \n\t"
|
||||
"2: \n\t"
|
||||
".set pop \n\t"
|
||||
: [zeros] "=&r"(zeros)
|
||||
: [a] "r"(a));
|
||||
|
||||
return (int16_t)zeros;
|
||||
}
|
||||
@ -166,11 +151,9 @@ static __inline int16_t WebRtcSpl_NormW32(int32_t a) {
|
||||
static __inline int16_t WebRtcSpl_NormU32(uint32_t a) {
|
||||
int zeros = 0;
|
||||
|
||||
__asm __volatile(
|
||||
"clz %[zeros], %[a] \n\t"
|
||||
: [zeros] "=r" (zeros)
|
||||
: [a] "r" (a)
|
||||
);
|
||||
__asm __volatile("clz %[zeros], %[a] \n\t"
|
||||
: [zeros] "=r"(zeros)
|
||||
: [a] "r"(a));
|
||||
|
||||
return (int16_t)(zeros & 0x1f);
|
||||
}
|
||||
@ -180,46 +163,42 @@ static __inline int16_t WebRtcSpl_NormW16(int16_t a) {
|
||||
int a0 = a << 16;
|
||||
|
||||
__asm __volatile(
|
||||
".set push \n\t"
|
||||
".set noreorder \n\t"
|
||||
"bnez %[a0], 1f \n\t"
|
||||
" sra %[zeros], %[a0], 31 \n\t"
|
||||
"b 2f \n\t"
|
||||
" move %[zeros], $zero \n\t"
|
||||
"1: \n\t"
|
||||
"xor %[zeros], %[a0], %[zeros] \n\t"
|
||||
"clz %[zeros], %[zeros] \n\t"
|
||||
"addiu %[zeros], %[zeros], -1 \n\t"
|
||||
"2: \n\t"
|
||||
".set pop \n\t"
|
||||
: [zeros]"=&r"(zeros)
|
||||
: [a0] "r" (a0)
|
||||
);
|
||||
".set push \n\t"
|
||||
".set noreorder \n\t"
|
||||
"bnez %[a0], 1f \n\t"
|
||||
" sra %[zeros], %[a0], 31 \n\t"
|
||||
"b 2f \n\t"
|
||||
" move %[zeros], $zero \n\t"
|
||||
"1: \n\t"
|
||||
"xor %[zeros], %[a0], %[zeros] \n\t"
|
||||
"clz %[zeros], %[zeros] \n\t"
|
||||
"addiu %[zeros], %[zeros], -1 \n\t"
|
||||
"2: \n\t"
|
||||
".set pop \n\t"
|
||||
: [zeros] "=&r"(zeros)
|
||||
: [a0] "r"(a0));
|
||||
|
||||
return (int16_t)zeros;
|
||||
}
|
||||
|
||||
static __inline int32_t WebRtc_MulAccumW16(int16_t a,
|
||||
int16_t b,
|
||||
int32_t c) {
|
||||
static __inline int32_t WebRtc_MulAccumW16(int16_t a, int16_t b, int32_t c) {
|
||||
int32_t res = 0, c1 = 0;
|
||||
__asm __volatile(
|
||||
#if defined(MIPS32_R2_LE)
|
||||
"seh %[a], %[a] \n\t"
|
||||
"seh %[b], %[b] \n\t"
|
||||
"seh %[a], %[a] \n\t"
|
||||
"seh %[b], %[b] \n\t"
|
||||
#else
|
||||
"sll %[a], %[a], 16 \n\t"
|
||||
"sll %[b], %[b], 16 \n\t"
|
||||
"sra %[a], %[a], 16 \n\t"
|
||||
"sra %[b], %[b], 16 \n\t"
|
||||
"sll %[a], %[a], 16 \n\t"
|
||||
"sll %[b], %[b], 16 \n\t"
|
||||
"sra %[a], %[a], 16 \n\t"
|
||||
"sra %[b], %[b], 16 \n\t"
|
||||
#endif
|
||||
"mul %[res], %[a], %[b] \n\t"
|
||||
"addu %[c1], %[c], %[res] \n\t"
|
||||
: [c1] "=r" (c1), [res] "=&r" (res)
|
||||
: [a] "r" (a), [b] "r" (b), [c] "r" (c)
|
||||
: "hi", "lo"
|
||||
);
|
||||
"mul %[res], %[a], %[b] \n\t"
|
||||
"addu %[c1], %[c], %[res] \n\t"
|
||||
: [c1] "=r"(c1), [res] "=&r"(res)
|
||||
: [a] "r"(a), [b] "r"(b), [c] "r"(c)
|
||||
: "hi", "lo");
|
||||
return (c1);
|
||||
}
|
||||
|
||||
#endif // WEBRTC_SPL_SPL_INL_MIPS_H_
|
||||
#endif // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_MIPS_H_
|
||||
|
@ -15,12 +15,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "rtc_base/sanitizer.h"
|
||||
|
||||
#define SPL_LEVINSON_MAXORDER 20
|
||||
|
||||
int16_t WebRtcSpl_LevinsonDurbin(const int32_t* R, int16_t* A, int16_t* K,
|
||||
size_t order)
|
||||
int16_t RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486
|
||||
WebRtcSpl_LevinsonDurbin(const int32_t* R, int16_t* A, int16_t* K,
|
||||
size_t order)
|
||||
{
|
||||
size_t i, j;
|
||||
// Auto-correlation coefficients in high precision
|
||||
@ -43,16 +45,17 @@ int16_t WebRtcSpl_LevinsonDurbin(const int32_t* R, int16_t* A, int16_t* K,
|
||||
|
||||
for (i = 0; i <= order; ++i)
|
||||
{
|
||||
temp1W32 = WEBRTC_SPL_LSHIFT_W32(R[i], norm);
|
||||
temp1W32 = R[i] * (1 << norm);
|
||||
// UBSan: 12 * 268435456 cannot be represented in type 'int'
|
||||
|
||||
// Put R in hi and low format
|
||||
R_hi[i] = (int16_t)(temp1W32 >> 16);
|
||||
R_low[i] = (int16_t)((temp1W32 - ((int32_t)R_hi[i] << 16)) >> 1);
|
||||
R_low[i] = (int16_t)((temp1W32 - ((int32_t)R_hi[i] * 65536)) >> 1);
|
||||
}
|
||||
|
||||
// K = A[1] = -R[1] / R[0]
|
||||
|
||||
temp2W32 = WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[1],16)
|
||||
+ WEBRTC_SPL_LSHIFT_W32((int32_t)R_low[1],1); // R[1] in Q31
|
||||
temp2W32 = R[1] * (1 << norm); // R[1] in Q31
|
||||
temp3W32 = WEBRTC_SPL_ABS_W32(temp2W32); // abs R[1]
|
||||
temp1W32 = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); // abs(R[1])/R[0] in Q31
|
||||
// Put back the sign on R[1]
|
||||
@ -63,7 +66,7 @@ int16_t WebRtcSpl_LevinsonDurbin(const int32_t* R, int16_t* A, int16_t* K,
|
||||
|
||||
// Put K in hi and low format
|
||||
K_hi = (int16_t)(temp1W32 >> 16);
|
||||
K_low = (int16_t)((temp1W32 - ((int32_t)K_hi << 16)) >> 1);
|
||||
K_low = (int16_t)((temp1W32 - ((int32_t)K_hi * 65536)) >> 1);
|
||||
|
||||
// Store first reflection coefficient
|
||||
K[0] = K_hi;
|
||||
@ -72,11 +75,11 @@ int16_t WebRtcSpl_LevinsonDurbin(const int32_t* R, int16_t* A, int16_t* K,
|
||||
|
||||
// Put A[1] in hi and low format
|
||||
A_hi[1] = (int16_t)(temp1W32 >> 16);
|
||||
A_low[1] = (int16_t)((temp1W32 - ((int32_t)A_hi[1] << 16)) >> 1);
|
||||
A_low[1] = (int16_t)((temp1W32 - ((int32_t)A_hi[1] * 65536)) >> 1);
|
||||
|
||||
// Alpha = R[0] * (1-K^2)
|
||||
|
||||
temp1W32 = ((K_hi * K_low >> 14) + K_hi * K_hi) << 1; // = k^2 in Q31
|
||||
temp1W32 = ((K_hi * K_low >> 14) + K_hi * K_hi) * 2; // = k^2 in Q31
|
||||
|
||||
temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); // Guard against <0
|
||||
temp1W32 = (int32_t)0x7fffffffL - temp1W32; // temp1W32 = (1 - K[0]*K[0]) in Q31
|
||||
@ -112,14 +115,14 @@ int16_t WebRtcSpl_LevinsonDurbin(const int32_t* R, int16_t* A, int16_t* K,
|
||||
for (j = 1; j < i; j++)
|
||||
{
|
||||
// temp1W32 is in Q31
|
||||
temp1W32 += (R_hi[j] * A_hi[i - j] << 1) +
|
||||
temp1W32 += (R_hi[j] * A_hi[i - j] * 2) +
|
||||
(((R_hi[j] * A_low[i - j] >> 15) +
|
||||
(R_low[j] * A_hi[i - j] >> 15)) << 1);
|
||||
(R_low[j] * A_hi[i - j] >> 15)) * 2);
|
||||
}
|
||||
|
||||
temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, 4);
|
||||
temp1W32 += (WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[i], 16)
|
||||
+ WEBRTC_SPL_LSHIFT_W32((int32_t)R_low[i], 1));
|
||||
temp1W32 = temp1W32 * 16;
|
||||
temp1W32 += ((int32_t)R_hi[i] * 65536)
|
||||
+ WEBRTC_SPL_LSHIFT_W32((int32_t)R_low[i], 1);
|
||||
|
||||
// K = -temp1W32 / Alpha
|
||||
temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32); // abs(temp1W32)
|
||||
@ -135,7 +138,7 @@ int16_t WebRtcSpl_LevinsonDurbin(const int32_t* R, int16_t* A, int16_t* K,
|
||||
norm = WebRtcSpl_NormW32(temp3W32);
|
||||
if ((Alpha_exp <= norm) || (temp3W32 == 0))
|
||||
{
|
||||
temp3W32 = WEBRTC_SPL_LSHIFT_W32(temp3W32, Alpha_exp);
|
||||
temp3W32 = temp3W32 * (1 << Alpha_exp);
|
||||
} else
|
||||
{
|
||||
if (temp3W32 > 0)
|
||||
@ -149,7 +152,7 @@ int16_t WebRtcSpl_LevinsonDurbin(const int32_t* R, int16_t* A, int16_t* K,
|
||||
|
||||
// Put K on hi and low format
|
||||
K_hi = (int16_t)(temp3W32 >> 16);
|
||||
K_low = (int16_t)((temp3W32 - ((int32_t)K_hi << 16)) >> 1);
|
||||
K_low = (int16_t)((temp3W32 - ((int32_t)K_hi * 65536)) >> 1);
|
||||
|
||||
// Store Reflection coefficient in Q15
|
||||
K[i - 1] = K_hi;
|
||||
@ -171,17 +174,17 @@ int16_t WebRtcSpl_LevinsonDurbin(const int32_t* R, int16_t* A, int16_t* K,
|
||||
for (j = 1; j < i; j++)
|
||||
{
|
||||
// temp1W32 = A[j] in Q27
|
||||
temp1W32 = WEBRTC_SPL_LSHIFT_W32((int32_t)A_hi[j],16)
|
||||
temp1W32 = (int32_t)A_hi[j] * 65536
|
||||
+ WEBRTC_SPL_LSHIFT_W32((int32_t)A_low[j],1);
|
||||
|
||||
// temp1W32 += K*A[i-j] in Q27
|
||||
temp1W32 += (K_hi * A_hi[i - j] + (K_hi * A_low[i - j] >> 15) +
|
||||
(K_low * A_hi[i - j] >> 15)) << 1;
|
||||
(K_low * A_hi[i - j] >> 15)) * 2;
|
||||
|
||||
// Put Anew in hi and low format
|
||||
A_upd_hi[j] = (int16_t)(temp1W32 >> 16);
|
||||
A_upd_low[j] = (int16_t)(
|
||||
(temp1W32 - ((int32_t)A_upd_hi[j] << 16)) >> 1);
|
||||
(temp1W32 - ((int32_t)A_upd_hi[j] * 65536)) >> 1);
|
||||
}
|
||||
|
||||
// temp3W32 = K in Q27 (Convert from Q31 to Q27)
|
||||
@ -190,11 +193,11 @@ int16_t WebRtcSpl_LevinsonDurbin(const int32_t* R, int16_t* A, int16_t* K,
|
||||
// Store Anew in hi and low format
|
||||
A_upd_hi[i] = (int16_t)(temp3W32 >> 16);
|
||||
A_upd_low[i] = (int16_t)(
|
||||
(temp3W32 - ((int32_t)A_upd_hi[i] << 16)) >> 1);
|
||||
(temp3W32 - ((int32_t)A_upd_hi[i] * 65536)) >> 1);
|
||||
|
||||
// Alpha = Alpha * (1-K^2)
|
||||
|
||||
temp1W32 = ((K_hi * K_low >> 14) + K_hi * K_hi) << 1; // K*K in Q31
|
||||
temp1W32 = ((K_hi * K_low >> 14) + K_hi * K_hi) * 2; // K*K in Q31
|
||||
|
||||
temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); // Guard against <0
|
||||
temp1W32 = (int32_t)0x7fffffffL - temp1W32; // 1 - K*K in Q31
|
||||
@ -237,10 +240,10 @@ int16_t WebRtcSpl_LevinsonDurbin(const int32_t* R, int16_t* A, int16_t* K,
|
||||
for (i = 1; i <= order; i++)
|
||||
{
|
||||
// temp1W32 in Q27
|
||||
temp1W32 = WEBRTC_SPL_LSHIFT_W32((int32_t)A_hi[i], 16)
|
||||
temp1W32 = (int32_t)A_hi[i] * 65536
|
||||
+ WEBRTC_SPL_LSHIFT_W32((int32_t)A_low[i], 1);
|
||||
// Round and store upper word
|
||||
A[i] = (int16_t)(((temp1W32 << 1) + 32768) >> 16);
|
||||
A[i] = (int16_t)(((temp1W32 * 2) + 32768) >> 16);
|
||||
}
|
||||
return 1; // Stable filters
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
#define SPL_LPC_TO_REFL_COEF_MAX_AR_MODEL_ORDER 50
|
||||
|
||||
|
@ -24,10 +24,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
// TODO(bjorn/kma): Consolidate function pairs (e.g. combine
|
||||
// WebRtcSpl_MaxAbsValueW16C and WebRtcSpl_MaxAbsIndexW16 into a single one.)
|
||||
@ -38,7 +38,7 @@ int16_t WebRtcSpl_MaxAbsValueW16C(const int16_t* vector, size_t length) {
|
||||
size_t i = 0;
|
||||
int absolute = 0, maximum = 0;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
absolute = abs((int)vector[i]);
|
||||
@ -64,7 +64,7 @@ int32_t WebRtcSpl_MaxAbsValueW32C(const int32_t* vector, size_t length) {
|
||||
uint32_t absolute = 0, maximum = 0;
|
||||
size_t i = 0;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
absolute = abs((int)vector[i]);
|
||||
@ -83,7 +83,7 @@ int16_t WebRtcSpl_MaxValueW16C(const int16_t* vector, size_t length) {
|
||||
int16_t maximum = WEBRTC_SPL_WORD16_MIN;
|
||||
size_t i = 0;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (vector[i] > maximum)
|
||||
@ -97,7 +97,7 @@ int32_t WebRtcSpl_MaxValueW32C(const int32_t* vector, size_t length) {
|
||||
int32_t maximum = WEBRTC_SPL_WORD32_MIN;
|
||||
size_t i = 0;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (vector[i] > maximum)
|
||||
@ -111,7 +111,7 @@ int16_t WebRtcSpl_MinValueW16C(const int16_t* vector, size_t length) {
|
||||
int16_t minimum = WEBRTC_SPL_WORD16_MAX;
|
||||
size_t i = 0;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (vector[i] < minimum)
|
||||
@ -125,7 +125,7 @@ int32_t WebRtcSpl_MinValueW32C(const int32_t* vector, size_t length) {
|
||||
int32_t minimum = WEBRTC_SPL_WORD32_MAX;
|
||||
size_t i = 0;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (vector[i] < minimum)
|
||||
@ -141,7 +141,7 @@ size_t WebRtcSpl_MaxAbsIndexW16(const int16_t* vector, size_t length) {
|
||||
size_t i = 0, index = 0;
|
||||
int absolute = 0, maximum = 0;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
absolute = abs((int)vector[i]);
|
||||
@ -160,7 +160,7 @@ size_t WebRtcSpl_MaxIndexW16(const int16_t* vector, size_t length) {
|
||||
size_t i = 0, index = 0;
|
||||
int16_t maximum = WEBRTC_SPL_WORD16_MIN;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (vector[i] > maximum) {
|
||||
@ -177,7 +177,7 @@ size_t WebRtcSpl_MaxIndexW32(const int32_t* vector, size_t length) {
|
||||
size_t i = 0, index = 0;
|
||||
int32_t maximum = WEBRTC_SPL_WORD32_MIN;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (vector[i] > maximum) {
|
||||
@ -194,7 +194,7 @@ size_t WebRtcSpl_MinIndexW16(const int16_t* vector, size_t length) {
|
||||
size_t i = 0, index = 0;
|
||||
int16_t minimum = WEBRTC_SPL_WORD16_MAX;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (vector[i] < minimum) {
|
||||
@ -211,7 +211,7 @@ size_t WebRtcSpl_MinIndexW32(const int32_t* vector, size_t length) {
|
||||
size_t i = 0, index = 0;
|
||||
int32_t minimum = WEBRTC_SPL_WORD32_MAX;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (vector[i] < minimum) {
|
||||
|
@ -16,9 +16,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
// Maximum absolute value of word16 vector.
|
||||
int16_t WebRtcSpl_MaxAbsValueW16_mips(const int16_t* vector, size_t length) {
|
||||
@ -26,7 +25,7 @@ int16_t WebRtcSpl_MaxAbsValueW16_mips(const int16_t* vector, size_t length) {
|
||||
int32_t tmp32_0, tmp32_1, tmp32_2, tmp32_3;
|
||||
size_t i, loop_size;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
#if defined(MIPS_DSP_R1)
|
||||
const int32_t* tmpvec32 = (int32_t*)vector;
|
||||
@ -230,7 +229,7 @@ int32_t WebRtcSpl_MaxAbsValueW32_mips(const int32_t* vector, size_t length) {
|
||||
uint32_t absolute = 0, maximum = 0;
|
||||
int tmp1 = 0, max_value = 0x7fffffff;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
__asm__ volatile (
|
||||
".set push \n\t"
|
||||
@ -264,7 +263,7 @@ int16_t WebRtcSpl_MaxValueW16_mips(const int16_t* vector, size_t length) {
|
||||
int tmp1;
|
||||
int16_t value;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
__asm__ volatile (
|
||||
".set push \n\t"
|
||||
@ -292,7 +291,7 @@ int32_t WebRtcSpl_MaxValueW32_mips(const int32_t* vector, size_t length) {
|
||||
int32_t maximum = WEBRTC_SPL_WORD32_MIN;
|
||||
int tmp1, value;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
__asm__ volatile (
|
||||
".set push \n\t"
|
||||
@ -322,7 +321,7 @@ int16_t WebRtcSpl_MinValueW16_mips(const int16_t* vector, size_t length) {
|
||||
int tmp1;
|
||||
int16_t value;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
__asm__ volatile (
|
||||
".set push \n\t"
|
||||
@ -351,7 +350,7 @@ int32_t WebRtcSpl_MinValueW32_mips(const int32_t* vector, size_t length) {
|
||||
int32_t minimum = WEBRTC_SPL_WORD32_MAX;
|
||||
int tmp1, value;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
__asm__ volatile (
|
||||
".set push \n\t"
|
||||
|
@ -9,16 +9,16 @@
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
// Maximum absolute value of word16 vector. C version for generic platforms.
|
||||
int16_t WebRtcSpl_MaxAbsValueW16Neon(const int16_t* vector, size_t length) {
|
||||
int absolute = 0, maximum = 0;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
const int16_t* p_start = vector;
|
||||
size_t rest = length & 7;
|
||||
@ -76,7 +76,7 @@ int32_t WebRtcSpl_MaxAbsValueW32Neon(const int32_t* vector, size_t length) {
|
||||
size_t i = 0;
|
||||
size_t residual = length & 0x7;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
const int32_t* p_start = vector;
|
||||
uint32x4_t max32x4_0 = vdupq_n_u32(0);
|
||||
@ -128,7 +128,7 @@ int16_t WebRtcSpl_MaxValueW16Neon(const int16_t* vector, size_t length) {
|
||||
size_t i = 0;
|
||||
size_t residual = length & 0x7;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
const int16_t* p_start = vector;
|
||||
int16x8_t max16x8 = vdupq_n_s16(WEBRTC_SPL_WORD16_MIN);
|
||||
@ -166,7 +166,7 @@ int32_t WebRtcSpl_MaxValueW32Neon(const int32_t* vector, size_t length) {
|
||||
size_t i = 0;
|
||||
size_t residual = length & 0x7;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
const int32_t* p_start = vector;
|
||||
int32x4_t max32x4_0 = vdupq_n_s32(WEBRTC_SPL_WORD32_MIN);
|
||||
@ -208,7 +208,7 @@ int16_t WebRtcSpl_MinValueW16Neon(const int16_t* vector, size_t length) {
|
||||
size_t i = 0;
|
||||
size_t residual = length & 0x7;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
const int16_t* p_start = vector;
|
||||
int16x8_t min16x8 = vdupq_n_s16(WEBRTC_SPL_WORD16_MAX);
|
||||
@ -246,7 +246,7 @@ int32_t WebRtcSpl_MinValueW32Neon(const int32_t* vector, size_t length) {
|
||||
size_t i = 0;
|
||||
size_t residual = length & 0x7;
|
||||
|
||||
assert(length > 0);
|
||||
RTC_DCHECK_GT(length, 0);
|
||||
|
||||
const int32_t* p_start = vector;
|
||||
int32x4_t min32x4_0 = vdupq_n_s32(WEBRTC_SPL_WORD32_MAX);
|
||||
|
@ -19,7 +19,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
static const uint32_t kMaxSeedUsed = 0x80000000;
|
||||
|
||||
|
@ -8,11 +8,11 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/real_fft.h"
|
||||
#include "common_audio/signal_processing/include/real_fft.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
struct RealFFT {
|
||||
int order;
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
void WebRtcSpl_ReflCoefToLpc(const int16_t *k, int use_order, int16_t *a)
|
||||
{
|
||||
|
@ -15,8 +15,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "webrtc/common_audio/signal_processing/resample_by_2_internal.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/resample_by_2_internal.h"
|
||||
|
||||
// Declaration of internally used functions
|
||||
static void WebRtcSpl_32khzTo22khzIntToShort(const int32_t *In, int16_t *Out,
|
||||
|
@ -16,8 +16,8 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "webrtc/common_audio/signal_processing/resample_by_2_internal.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/resample_by_2_internal.h"
|
||||
|
||||
////////////////////////////
|
||||
///// 48 kHz -> 16 kHz /////
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
#ifdef WEBRTC_ARCH_ARM_V7
|
||||
|
||||
@ -83,7 +83,7 @@ void WebRtcSpl_DownsampleBy2(const int16_t* in, size_t len,
|
||||
|
||||
for (i = (len >> 1); i > 0; i--) {
|
||||
// lower allpass filter
|
||||
in32 = (int32_t)(*in++) << 10;
|
||||
in32 = (int32_t)(*in++) * (1 << 10);
|
||||
diff = in32 - state1;
|
||||
tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
|
||||
state0 = in32;
|
||||
@ -95,7 +95,7 @@ void WebRtcSpl_DownsampleBy2(const int16_t* in, size_t len,
|
||||
state2 = tmp2;
|
||||
|
||||
// upper allpass filter
|
||||
in32 = (int32_t)(*in++) << 10;
|
||||
in32 = (int32_t)(*in++) * (1 << 10);
|
||||
diff = in32 - state5;
|
||||
tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
|
||||
state4 = in32;
|
||||
@ -141,7 +141,7 @@ void WebRtcSpl_UpsampleBy2(const int16_t* in, size_t len,
|
||||
|
||||
for (i = len; i > 0; i--) {
|
||||
// lower allpass filter
|
||||
in32 = (int32_t)(*in++) << 10;
|
||||
in32 = (int32_t)(*in++) * (1 << 10);
|
||||
diff = in32 - state1;
|
||||
tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state0);
|
||||
state0 = in32;
|
||||
|
@ -14,7 +14,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/resample_by_2_internal.h"
|
||||
#include "common_audio/signal_processing/resample_by_2_internal.h"
|
||||
#include "rtc_base/sanitizer.h"
|
||||
|
||||
// allpass filter coefficients.
|
||||
static const int16_t kResampleAllpass[2][3] = {
|
||||
@ -28,8 +29,9 @@ static const int16_t kResampleAllpass[2][3] = {
|
||||
// output: int16_t (saturated) (of length len/2)
|
||||
// state: filter state array; length = 8
|
||||
|
||||
void WebRtcSpl_DownBy2IntToShort(int32_t *in, int32_t len, int16_t *out,
|
||||
int32_t *state)
|
||||
void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486
|
||||
WebRtcSpl_DownBy2IntToShort(int32_t *in, int32_t len, int16_t *out,
|
||||
int32_t *state)
|
||||
{
|
||||
int32_t tmp0, tmp1, diff;
|
||||
int32_t i;
|
||||
@ -41,6 +43,8 @@ void WebRtcSpl_DownBy2IntToShort(int32_t *in, int32_t len, int16_t *out,
|
||||
{
|
||||
tmp0 = in[i << 1];
|
||||
diff = tmp0 - state[1];
|
||||
// UBSan: -1771017321 - 999586185 cannot be represented in type 'int'
|
||||
|
||||
// scale down and round
|
||||
diff = (diff + (1 << 13)) >> 14;
|
||||
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
||||
@ -121,10 +125,11 @@ void WebRtcSpl_DownBy2IntToShort(int32_t *in, int32_t len, int16_t *out,
|
||||
// output: int32_t (shifted 15 positions to the left, + offset 16384) (of length len/2)
|
||||
// state: filter state array; length = 8
|
||||
|
||||
void WebRtcSpl_DownBy2ShortToInt(const int16_t *in,
|
||||
int32_t len,
|
||||
int32_t *out,
|
||||
int32_t *state)
|
||||
void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486
|
||||
WebRtcSpl_DownBy2ShortToInt(const int16_t *in,
|
||||
int32_t len,
|
||||
int32_t *out,
|
||||
int32_t *state)
|
||||
{
|
||||
int32_t tmp0, tmp1, diff;
|
||||
int32_t i;
|
||||
@ -141,6 +146,8 @@ void WebRtcSpl_DownBy2ShortToInt(const int16_t *in,
|
||||
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
||||
state[0] = tmp0;
|
||||
diff = tmp1 - state[2];
|
||||
// UBSan: -1379909682 - 834099714 cannot be represented in type 'int'
|
||||
|
||||
// scale down and truncate
|
||||
diff = diff >> 14;
|
||||
if (diff < 0)
|
||||
@ -549,8 +556,9 @@ void WebRtcSpl_LPBy2ShortToInt(const int16_t* in, int32_t len, int32_t* out,
|
||||
// input: int32_t (shifted 15 positions to the left, + offset 16384)
|
||||
// output: int32_t (normalized, not saturated)
|
||||
// state: filter state array; length = 8
|
||||
void WebRtcSpl_LPBy2IntToInt(const int32_t* in, int32_t len, int32_t* out,
|
||||
int32_t* state)
|
||||
void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486
|
||||
WebRtcSpl_LPBy2IntToInt(const int32_t* in, int32_t len, int32_t* out,
|
||||
int32_t* state)
|
||||
{
|
||||
int32_t tmp0, tmp1, diff;
|
||||
int32_t i;
|
||||
@ -594,6 +602,8 @@ void WebRtcSpl_LPBy2IntToInt(const int32_t* in, int32_t len, int32_t* out,
|
||||
{
|
||||
tmp0 = in[i << 1];
|
||||
diff = tmp0 - state[5];
|
||||
// UBSan: -794814117 - 1566149201 cannot be represented in type 'int'
|
||||
|
||||
// scale down and round
|
||||
diff = (diff + (1 << 13)) >> 14;
|
||||
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
||||
|
@ -8,40 +8,53 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This header file contains some internal resampling functions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SPL_RESAMPLE_BY_2_INTERNAL_H_
|
||||
#define WEBRTC_SPL_RESAMPLE_BY_2_INTERNAL_H_
|
||||
#ifndef COMMON_AUDIO_SIGNAL_PROCESSING_RESAMPLE_BY_2_INTERNAL_H_
|
||||
#define COMMON_AUDIO_SIGNAL_PROCESSING_RESAMPLE_BY_2_INTERNAL_H_
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/*******************************************************************
|
||||
* resample_by_2_fast.c
|
||||
* Functions for internal use in the other resample functions
|
||||
******************************************************************/
|
||||
void WebRtcSpl_DownBy2IntToShort(int32_t *in, int32_t len, int16_t *out,
|
||||
int32_t *state);
|
||||
void WebRtcSpl_DownBy2IntToShort(int32_t* in,
|
||||
int32_t len,
|
||||
int16_t* out,
|
||||
int32_t* state);
|
||||
|
||||
void WebRtcSpl_DownBy2ShortToInt(const int16_t *in, int32_t len,
|
||||
int32_t *out, int32_t *state);
|
||||
void WebRtcSpl_DownBy2ShortToInt(const int16_t* in,
|
||||
int32_t len,
|
||||
int32_t* out,
|
||||
int32_t* state);
|
||||
|
||||
void WebRtcSpl_UpBy2ShortToInt(const int16_t *in, int32_t len,
|
||||
int32_t *out, int32_t *state);
|
||||
void WebRtcSpl_UpBy2ShortToInt(const int16_t* in,
|
||||
int32_t len,
|
||||
int32_t* out,
|
||||
int32_t* state);
|
||||
|
||||
void WebRtcSpl_UpBy2IntToInt(const int32_t *in, int32_t len, int32_t *out,
|
||||
int32_t *state);
|
||||
|
||||
void WebRtcSpl_UpBy2IntToShort(const int32_t *in, int32_t len,
|
||||
int16_t *out, int32_t *state);
|
||||
|
||||
void WebRtcSpl_LPBy2ShortToInt(const int16_t* in, int32_t len,
|
||||
int32_t* out, int32_t* state);
|
||||
|
||||
void WebRtcSpl_LPBy2IntToInt(const int32_t* in, int32_t len, int32_t* out,
|
||||
void WebRtcSpl_UpBy2IntToInt(const int32_t* in,
|
||||
int32_t len,
|
||||
int32_t* out,
|
||||
int32_t* state);
|
||||
|
||||
#endif // WEBRTC_SPL_RESAMPLE_BY_2_INTERNAL_H_
|
||||
void WebRtcSpl_UpBy2IntToShort(const int32_t* in,
|
||||
int32_t len,
|
||||
int16_t* out,
|
||||
int32_t* state);
|
||||
|
||||
void WebRtcSpl_LPBy2ShortToInt(const int16_t* in,
|
||||
int32_t len,
|
||||
int32_t* out,
|
||||
int32_t* state);
|
||||
|
||||
void WebRtcSpl_LPBy2IntToInt(const int32_t* in,
|
||||
int32_t len,
|
||||
int32_t* out,
|
||||
int32_t* state);
|
||||
|
||||
#endif // COMMON_AUDIO_SIGNAL_PROCESSING_RESAMPLE_BY_2_INTERNAL_H_
|
||||
|
@ -17,11 +17,13 @@
|
||||
|
||||
#if defined(MIPS32_LE)
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
#if !defined(MIPS_DSP_R2_LE)
|
||||
// allpass filter coefficients.
|
||||
static const uint16_t kResampleAllpass1[3] = {3284, 24441, 49528};
|
||||
static const uint16_t kResampleAllpass2[3] = {12199, 37471, 60255};
|
||||
#endif
|
||||
|
||||
// Multiply a 32-bit value with a 16-bit value and accumulate to another input:
|
||||
#define MUL_ACCUM_1(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
// interpolation coefficients
|
||||
static const int16_t kCoefficients48To32[2][8] = {
|
||||
|
@ -8,133 +8,62 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
/* The global function contained in this file initializes SPL function
|
||||
* pointers, currently only for ARM platforms.
|
||||
*
|
||||
* Some code came from common/rtcd.c in the WebM project.
|
||||
*/
|
||||
// Some code came from common/rtcd.c in the WebM project.
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "webrtc/system_wrappers/include/cpu_features_wrapper.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
/* Declare function pointers. */
|
||||
MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16;
|
||||
MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32;
|
||||
MaxValueW16 WebRtcSpl_MaxValueW16;
|
||||
MaxValueW32 WebRtcSpl_MaxValueW32;
|
||||
MinValueW16 WebRtcSpl_MinValueW16;
|
||||
MinValueW32 WebRtcSpl_MinValueW32;
|
||||
CrossCorrelation WebRtcSpl_CrossCorrelation;
|
||||
DownsampleFast WebRtcSpl_DownsampleFast;
|
||||
ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound;
|
||||
// TODO(bugs.webrtc.org/9553): These function pointers are useless. Refactor
|
||||
// things so that we simply have a bunch of regular functions with different
|
||||
// implementations for different platforms.
|
||||
|
||||
#if (defined(WEBRTC_DETECT_NEON) || !defined(WEBRTC_HAS_NEON)) && \
|
||||
!defined(MIPS32_LE)
|
||||
/* Initialize function pointers to the generic C version. */
|
||||
static void InitPointersToC() {
|
||||
WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16C;
|
||||
WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C;
|
||||
WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16C;
|
||||
WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32C;
|
||||
WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16C;
|
||||
WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32C;
|
||||
WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationC;
|
||||
WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastC;
|
||||
WebRtcSpl_ScaleAndAddVectorsWithRound =
|
||||
WebRtcSpl_ScaleAndAddVectorsWithRoundC;
|
||||
}
|
||||
#endif
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
|
||||
#if defined(WEBRTC_DETECT_NEON) || defined(WEBRTC_HAS_NEON)
|
||||
/* Initialize function pointers to the Neon version. */
|
||||
static void InitPointersToNeon() {
|
||||
WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16Neon;
|
||||
WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32Neon;
|
||||
WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16Neon;
|
||||
WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32Neon;
|
||||
WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16Neon;
|
||||
WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32Neon;
|
||||
WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationNeon;
|
||||
WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastNeon;
|
||||
WebRtcSpl_ScaleAndAddVectorsWithRound =
|
||||
WebRtcSpl_ScaleAndAddVectorsWithRoundC;
|
||||
}
|
||||
#endif
|
||||
const MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16Neon;
|
||||
const MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32Neon;
|
||||
const MaxValueW16 WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16Neon;
|
||||
const MaxValueW32 WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32Neon;
|
||||
const MinValueW16 WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16Neon;
|
||||
const MinValueW32 WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32Neon;
|
||||
const CrossCorrelation WebRtcSpl_CrossCorrelation =
|
||||
WebRtcSpl_CrossCorrelationNeon;
|
||||
const DownsampleFast WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastNeon;
|
||||
const ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound =
|
||||
WebRtcSpl_ScaleAndAddVectorsWithRoundC;
|
||||
|
||||
#if defined(MIPS32_LE)
|
||||
/* Initialize function pointers to the MIPS version. */
|
||||
static void InitPointersToMIPS() {
|
||||
WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16_mips;
|
||||
WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16_mips;
|
||||
WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32_mips;
|
||||
WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16_mips;
|
||||
WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32_mips;
|
||||
WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelation_mips;
|
||||
WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFast_mips;
|
||||
#if defined(MIPS_DSP_R1_LE)
|
||||
WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32_mips;
|
||||
WebRtcSpl_ScaleAndAddVectorsWithRound =
|
||||
WebRtcSpl_ScaleAndAddVectorsWithRound_mips;
|
||||
#else
|
||||
WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C;
|
||||
WebRtcSpl_ScaleAndAddVectorsWithRound =
|
||||
WebRtcSpl_ScaleAndAddVectorsWithRoundC;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void InitFunctionPointers(void) {
|
||||
#if defined(WEBRTC_DETECT_NEON)
|
||||
if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {
|
||||
InitPointersToNeon();
|
||||
} else {
|
||||
InitPointersToC();
|
||||
}
|
||||
#elif defined(WEBRTC_HAS_NEON)
|
||||
InitPointersToNeon();
|
||||
#elif defined(MIPS32_LE)
|
||||
InitPointersToMIPS();
|
||||
|
||||
const MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16_mips;
|
||||
const MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32 =
|
||||
#ifdef MIPS_DSP_R1_LE
|
||||
WebRtcSpl_MaxAbsValueW32_mips;
|
||||
#else
|
||||
InitPointersToC();
|
||||
#endif /* WEBRTC_DETECT_NEON */
|
||||
}
|
||||
WebRtcSpl_MaxAbsValueW32C;
|
||||
#endif
|
||||
const MaxValueW16 WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16_mips;
|
||||
const MaxValueW32 WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32_mips;
|
||||
const MinValueW16 WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16_mips;
|
||||
const MinValueW32 WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32_mips;
|
||||
const CrossCorrelation WebRtcSpl_CrossCorrelation =
|
||||
WebRtcSpl_CrossCorrelation_mips;
|
||||
const DownsampleFast WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFast_mips;
|
||||
const ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound =
|
||||
#ifdef MIPS_DSP_R1_LE
|
||||
WebRtcSpl_ScaleAndAddVectorsWithRound_mips;
|
||||
#else
|
||||
WebRtcSpl_ScaleAndAddVectorsWithRoundC;
|
||||
#endif
|
||||
|
||||
#if defined(WEBRTC_POSIX)
|
||||
#include <pthread.h>
|
||||
#else
|
||||
|
||||
static void once(void (*func)(void)) {
|
||||
static pthread_once_t lock = PTHREAD_ONCE_INIT;
|
||||
pthread_once(&lock, func);
|
||||
}
|
||||
const MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16C;
|
||||
const MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C;
|
||||
const MaxValueW16 WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16C;
|
||||
const MaxValueW32 WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32C;
|
||||
const MinValueW16 WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16C;
|
||||
const MinValueW32 WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32C;
|
||||
const CrossCorrelation WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationC;
|
||||
const DownsampleFast WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastC;
|
||||
const ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound =
|
||||
WebRtcSpl_ScaleAndAddVectorsWithRoundC;
|
||||
|
||||
#elif defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
static void once(void (*func)(void)) {
|
||||
/* Didn't use InitializeCriticalSection() since there's no race-free context
|
||||
* in which to execute it.
|
||||
*
|
||||
* TODO(kma): Change to different implementation (e.g.
|
||||
* InterlockedCompareExchangePointer) to avoid issues similar to
|
||||
* http://code.google.com/p/webm/issues/detail?id=467.
|
||||
*/
|
||||
static CRITICAL_SECTION lock = {(void *)((size_t)-1), -1, 0, 0, 0, 0};
|
||||
static int done = 0;
|
||||
|
||||
EnterCriticalSection(&lock);
|
||||
if (!done) {
|
||||
func();
|
||||
done = 1;
|
||||
}
|
||||
LeaveCriticalSection(&lock);
|
||||
}
|
||||
|
||||
/* There's no fallback version as an #else block here to ensure thread safety.
|
||||
* In case of neither pthread for WEBRTC_POSIX nor _WIN32 is present, build
|
||||
* system should pick it up.
|
||||
*/
|
||||
#endif /* WEBRTC_POSIX */
|
||||
|
||||
void WebRtcSpl_Init() {
|
||||
once(InitFunctionPointers);
|
||||
}
|
||||
#endif
|
||||
|
24
webrtc/common_audio/signal_processing/spl_inl.c
Normal file
24
webrtc/common_audio/signal_processing/spl_inl.c
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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 <stdint.h>
|
||||
|
||||
#include "common_audio/signal_processing/include/spl_inl.h"
|
||||
|
||||
// Table used by WebRtcSpl_CountLeadingZeros32_NotBuiltin. For each uint32_t n
|
||||
// that's a sequence of 0 bits followed by a sequence of 1 bits, the entry at
|
||||
// index (n * 0x8c0b2891) >> 26 in this table gives the number of zero bits in
|
||||
// n.
|
||||
const int8_t kWebRtcSpl_CountLeadingZeros32_Table[64] = {
|
||||
32, 8, 17, -1, -1, 14, -1, -1, -1, 20, -1, -1, -1, 28, -1, 18,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 26, 25, 24,
|
||||
4, 11, 23, 31, 3, 7, 10, 16, 22, 30, -1, -1, 2, 6, 13, 9,
|
||||
-1, 15, -1, 21, -1, 29, 19, -1, -1, -1, -1, -1, 1, 27, 5, 12,
|
||||
};
|
@ -15,9 +15,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "rtc_base/checks.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
int32_t WebRtcSpl_SqrtLocal(int32_t in);
|
||||
|
||||
@ -139,8 +138,19 @@ int32_t WebRtcSpl_Sqrt(int32_t value)
|
||||
|
||||
A = value;
|
||||
|
||||
if (A == 0)
|
||||
return (int32_t)0; // sqrt(0) = 0
|
||||
// The convention in this function is to calculate sqrt(abs(A)). Negate the
|
||||
// input if it is negative.
|
||||
if (A < 0) {
|
||||
if (A == WEBRTC_SPL_WORD32_MIN) {
|
||||
// This number cannot be held in an int32_t after negating.
|
||||
// Map it to the maximum positive value.
|
||||
A = WEBRTC_SPL_WORD32_MAX;
|
||||
} else {
|
||||
A = -A;
|
||||
}
|
||||
} else if (A == 0) {
|
||||
return 0; // sqrt(0) = 0
|
||||
}
|
||||
|
||||
sh = WebRtcSpl_NormW32(A); // # shifts to normalize A
|
||||
A = WEBRTC_SPL_LSHIFT_W32(A, sh); // Normalize A
|
||||
@ -155,7 +165,7 @@ int32_t WebRtcSpl_Sqrt(int32_t value)
|
||||
x_norm = (int16_t)(A >> 16); // x_norm = AH
|
||||
|
||||
nshift = (sh / 2);
|
||||
assert(nshift >= 0);
|
||||
RTC_DCHECK_GE(nshift, 0);
|
||||
|
||||
A = (int32_t)WEBRTC_SPL_LSHIFT_W32((int32_t)x_norm, 16);
|
||||
A = WEBRTC_SPL_ABS_W32(A); // A = abs(x_norm<<16)
|
||||
|
@ -13,9 +13,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "rtc_base/checks.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
// Maximum number of samples in a low/high-band frame.
|
||||
enum
|
||||
@ -136,14 +135,14 @@ void WebRtcSpl_AnalysisQMF(const int16_t* in_data, size_t in_data_length,
|
||||
int32_t filter1[kMaxBandFrameLength];
|
||||
int32_t filter2[kMaxBandFrameLength];
|
||||
const size_t band_length = in_data_length / 2;
|
||||
assert(in_data_length % 2 == 0);
|
||||
assert(band_length <= kMaxBandFrameLength);
|
||||
RTC_DCHECK_EQ(0, in_data_length % 2);
|
||||
RTC_DCHECK_LE(band_length, kMaxBandFrameLength);
|
||||
|
||||
// Split even and odd samples. Also shift them to Q10.
|
||||
for (i = 0, k = 0; i < band_length; i++, k += 2)
|
||||
{
|
||||
half_in2[i] = WEBRTC_SPL_LSHIFT_W32((int32_t)in_data[k], 10);
|
||||
half_in1[i] = WEBRTC_SPL_LSHIFT_W32((int32_t)in_data[k + 1], 10);
|
||||
half_in2[i] = ((int32_t)in_data[k]) * (1 << 10);
|
||||
half_in1[i] = ((int32_t)in_data[k + 1]) * (1 << 10);
|
||||
}
|
||||
|
||||
// All pass filter even and odd samples, independently.
|
||||
@ -175,16 +174,16 @@ void WebRtcSpl_SynthesisQMF(const int16_t* low_band, const int16_t* high_band,
|
||||
int32_t filter2[kMaxBandFrameLength];
|
||||
size_t i;
|
||||
int16_t k;
|
||||
assert(band_length <= kMaxBandFrameLength);
|
||||
RTC_DCHECK_LE(band_length, kMaxBandFrameLength);
|
||||
|
||||
// Obtain the sum and difference channels out of upper and lower-band channels.
|
||||
// Also shift to Q10 domain.
|
||||
for (i = 0; i < band_length; i++)
|
||||
{
|
||||
tmp = (int32_t)low_band[i] + (int32_t)high_band[i];
|
||||
half_in1[i] = WEBRTC_SPL_LSHIFT_W32(tmp, 10);
|
||||
half_in1[i] = tmp * (1 << 10);
|
||||
tmp = (int32_t)low_band[i] - (int32_t)high_band[i];
|
||||
half_in2[i] = WEBRTC_SPL_LSHIFT_W32(tmp, 10);
|
||||
half_in2[i] = tmp * (1 << 10);
|
||||
}
|
||||
|
||||
// all-pass filter the sum and difference channels
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
void WebRtcSpl_SqrtOfOneMinusXSquared(int16_t *xQ15, size_t vector_length,
|
||||
int16_t *yQ15)
|
||||
|
@ -20,7 +20,7 @@
|
||||
* WebRtcSpl_ScaleAndAddVectorsWithRoundC()
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
void WebRtcSpl_VectorBitShiftW16(int16_t *res, size_t length,
|
||||
const int16_t *in, int16_t right_shifts)
|
||||
@ -37,7 +37,7 @@ void WebRtcSpl_VectorBitShiftW16(int16_t *res, size_t length,
|
||||
{
|
||||
for (i = length; i > 0; i--)
|
||||
{
|
||||
(*res++) = ((*in++) << (-right_shifts));
|
||||
(*res++) = ((*in++) * (1 << (-right_shifts)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user