├── .github
└── FUNDING.yml
├── CMakeLists.txt
├── LICENSE
├── README.md
├── dr_wav.h
├── main.cc
├── ns
├── aligned_malloc.cc
├── aligned_malloc.h
├── array_view.h
├── audio_buffer.cc
├── audio_buffer.h
├── audio_util.cc
├── audio_util.h
├── channel_buffer.h
├── checks.h
├── constructor_magic.h
├── fast_math.cc
├── fast_math.h
├── fft4g.cc
├── fft4g.h
├── gtest_prod_util.h
├── histograms.cc
├── histograms.h
├── noise_estimator.cc
├── noise_estimator.h
├── noise_suppressor.cc
├── noise_suppressor.h
├── ns_common.h
├── ns_config.h
├── ns_fft.cc
├── ns_fft.h
├── prior_signal_model.cc
├── prior_signal_model.h
├── prior_signal_model_estimator.cc
├── prior_signal_model_estimator.h
├── push_sinc_resampler.cc
├── push_sinc_resampler.h
├── quantile_noise_estimator.cc
├── quantile_noise_estimator.h
├── signal_model.cc
├── signal_model.h
├── signal_model_estimator.cc
├── signal_model_estimator.h
├── sinc_resampler.cc
├── sinc_resampler.h
├── speech_probability_estimator.cc
├── speech_probability_estimator.h
├── splitting_filter.c
├── splitting_filter.cc
├── splitting_filter.h
├── suppression_params.cc
├── suppression_params.h
├── three_band_filter_bank.cc
├── three_band_filter_bank.h
├── type_traits.h
├── wiener_filter.cc
└── wiener_filter.h
└── timing.h
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: https://www.paypal.com/paypalme/cpuimage/
13 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8)
2 | project(webrtc_ns_cpp)
3 | file(GLOB NS_SRC ns/*.cc ns/*.h ns/*.c)
4 | add_executable(webrtc_ns_cpp main.cc ${NS_SRC})
5 |
6 | SET(CMAKE_C_FLAGS_DEBUG "-O3")
7 | SET(CMAKE_C_FLAGS_RELEASE "-O3")
8 | SET(CMAKE_CXX_FLAGS_DEBUG "-O3")
9 | SET(CMAKE_CXX_FLAGS_RELEASE "-O3")
10 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftree-vectorize")
11 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftree-vectorize")
12 | SET(CMAKE_BUILD_TYPE "Release")
13 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
14 |
15 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_DEBUG} -Wall -g -O0 -Wextra")
16 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_RELDEBINFO} -g -O3")
17 |
18 | target_link_libraries(webrtc_ns_cpp -lm)
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011, The WebRTC project authors. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are
5 | met:
6 |
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the
13 | distribution.
14 |
15 | * Neither the name of Google nor the names of its contributors may
16 | be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WebRTC_NS_CPP
2 | Noise Suppression Module Port From WebRTC
3 |
4 | # Donating
5 |
6 | If you found this project useful, consider buying me a coffee
7 |
8 |
9 |
--------------------------------------------------------------------------------
/main.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #include "ns/noise_suppressor.h"
12 |
13 | #include
14 | #include
15 |
16 | #include
17 | #include
18 | #include
19 | #include "timing.h"
20 |
21 | //采用https://github.com/mackron/dr_libs/blob/master/dr_wav.h 解码
22 | #define DR_WAV_IMPLEMENTATION
23 |
24 | #include "dr_wav.h"
25 |
26 | #ifndef nullptr
27 | #define nullptr 0
28 | #endif
29 |
30 | #ifndef MIN
31 | #define MIN(A, B) ((A) < (B) ? (A) : (B))
32 | #endif
33 |
34 | #ifndef MAX
35 | #define MAX(A, B) ((A) > (B) ? (A) : (B))
36 | #endif
37 |
38 | //写wav文件
39 | void wavWrite_s16(char *filename, int16_t *buffer, size_t sampleRate, size_t totalSampleCount, unsigned int channels) {
40 | drwav_data_format format;
41 | format.container = drwav_container_riff; // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64.
42 | format.channels = channels;
43 | format.sampleRate = (drwav_uint32) sampleRate;
44 | format.bitsPerSample = sizeof(*buffer) * 8;
45 | format.format = DR_WAVE_FORMAT_PCM;
46 | drwav wav;
47 | drwav_init_file_write(&wav, filename, &format, NULL);
48 | drwav_uint64 samplesWritten = drwav_write_pcm_frames(&wav, totalSampleCount, buffer);
49 | drwav_uninit(&wav);
50 | if (samplesWritten != totalSampleCount) {
51 | fprintf(stderr, "ERROR\n");
52 | exit(1);
53 |
54 | }
55 | }
56 |
57 | //读取wav文件
58 | short *wavRead_s16(char *filename, uint32_t *sampleRate, uint64_t *totalSampleCount, unsigned int *channels) {
59 | short *buffer = drwav_open_file_and_read_pcm_frames_s16(filename, channels, sampleRate, totalSampleCount, NULL);
60 | if (buffer == NULL) {
61 | printf("ERROR.");
62 | }
63 | return buffer;
64 | }
65 |
66 | //分割路径函数
67 | void splitpath(const char *path, char *drv, char *dir, char *name, char *ext) {
68 | const char *end;
69 | const char *p;
70 | const char *s;
71 | if (path[0] && path[1] == ':') {
72 | if (drv) {
73 | *drv++ = *path++;
74 | *drv++ = *path++;
75 | *drv = '\0';
76 | }
77 | } else if (drv)
78 | *drv = '\0';
79 | for (end = path; *end && *end != ':';)
80 | end++;
81 | for (p = end; p > path && *--p != '\\' && *p != '/';)
82 | if (*p == '.') {
83 | end = p;
84 | break;
85 | }
86 | if (ext)
87 | for (s = end; (*ext = *s++);)
88 | ext++;
89 | for (p = end; p > path;)
90 | if (*--p == '\\' || *p == '/') {
91 | p++;
92 | break;
93 | }
94 | if (name) {
95 | for (s = p; s < end;)
96 | *name++ = *s++;
97 | *name = '\0';
98 | }
99 | if (dir) {
100 | for (s = path; s < p;)
101 | *dir++ = *s++;
102 | *dir = '\0';
103 | }
104 | }
105 |
106 | using namespace webrtc;
107 |
108 | int nsProc(short *input, size_t SampleCount, size_t sampleRate, int num_channels) {
109 | AudioBuffer audio(sampleRate, num_channels, sampleRate, num_channels, sampleRate,
110 | num_channels);
111 | StreamConfig stream_config(sampleRate, num_channels);
112 | NsConfig cfg;
113 | /*
114 | * NsConfig::SuppressionLevel::k6dB
115 | * NsConfig::SuppressionLevel::k12dB
116 | * NsConfig::SuppressionLevel::k18dB
117 | * NsConfig::SuppressionLevel::k21dB
118 | */
119 | // cfg.target_level = NsConfig::SuppressionLevel::k21dB;
120 | NoiseSuppressor ns(cfg, sampleRate, num_channels);
121 | short *buffer = input;
122 | bool split_bands = sampleRate > 16000;
123 | uint64_t frames = (SampleCount / stream_config.num_samples());
124 | for (size_t frame_index = 0; frame_index < frames; ++frame_index) {
125 | audio.CopyFrom(buffer, stream_config);
126 | if (split_bands) {
127 | audio.SplitIntoFrequencyBands();
128 | }
129 | ns.Analyze(audio);
130 | ns.Process(&audio);
131 | if (split_bands) {
132 | audio.MergeFrequencyBands();
133 | }
134 | audio.CopyTo(stream_config, buffer);
135 | buffer += stream_config.num_samples();
136 | }
137 | return 0;
138 | }
139 |
140 | void WebRtc_DeNoise(char *in_file, char *out_file) {
141 | uint32_t sampleRate = 0;
142 | uint64_t nSampleCount = 0;
143 | uint32_t channels = 1;
144 | short *data_in = wavRead_s16(in_file, &sampleRate, &nSampleCount, &channels);
145 | if (data_in != NULL) {
146 | double startTime = now();
147 | short *data_out = (short *) calloc(nSampleCount, sizeof(short));
148 | if (data_out != NULL) {
149 | nsProc(data_in, nSampleCount, sampleRate, channels);
150 | double time_interval = calcElapsed(startTime, now());
151 | printf("time interval: %d ms\n ", (int) (time_interval * 1000));
152 | wavWrite_s16(out_file, data_in, sampleRate, (uint32_t) nSampleCount, channels);
153 | free(data_out);
154 | }
155 | free(data_in);
156 | }
157 | }
158 |
159 |
160 | int main(int argc, char *argv[]) {
161 | printf("webrtc noise suppressor\n");
162 | printf("blog:http://cpuimage.cnblogs.com/\n");
163 | printf("email:gaozhihan@vip.qq.com\n");
164 | if (argc < 2) {
165 | printf("usage:\n");
166 | printf("./webrtc_ns input.wav\n");
167 | printf("or\n");
168 | printf("./webrtc_ns input.wav output.wav\n");
169 | return -1;
170 | }
171 | char *in_file = argv[1];
172 |
173 | if (argc > 2) {
174 | char *out_file = argv[2];
175 | WebRtc_DeNoise(in_file, out_file);
176 | } else {
177 | char drive[3];
178 | char dir[256];
179 | char fname[256];
180 | char ext[256];
181 | char out_file[1024];
182 | splitpath(in_file, drive, dir, fname, ext);
183 | sprintf(out_file, "%s%s%s_out%s", drive, dir, fname, ext);
184 | WebRtc_DeNoise(in_file, out_file);
185 | }
186 | printf("press any key to exit.\n");
187 | getchar();
188 | return 0;
189 | }
190 |
191 |
--------------------------------------------------------------------------------
/ns/aligned_malloc.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #include "aligned_malloc.h"
12 |
13 | #include // for free, malloc
14 | #include // for memcpy
15 |
16 | #include "checks.h"
17 |
18 | #ifdef _WIN32
19 |
20 | #include
21 |
22 | #else
23 | #include
24 | #endif
25 |
26 | // Reference on memory alignment:
27 | // http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me
28 | namespace webrtc {
29 |
30 | uintptr_t GetRightAlign(uintptr_t start_pos, size_t alignment) {
31 | // The pointer should be aligned with |alignment| bytes. The - 1 guarantees
32 | // that it is aligned towards the closest higher (right) address.
33 | return (start_pos + alignment - 1) & ~(alignment - 1);
34 | }
35 |
36 | // Alignment must be an integer power of two.
37 | bool ValidAlignment(size_t alignment) {
38 | if (!alignment) {
39 | return false;
40 | }
41 | return (alignment & (alignment - 1)) == 0;
42 | }
43 |
44 | void *GetRightAlign(const void *pointer, size_t alignment) {
45 | if (!pointer) {
46 | return NULL;
47 | }
48 | if (!ValidAlignment(alignment)) {
49 | return NULL;
50 | }
51 | uintptr_t start_pos = reinterpret_cast(pointer);
52 | return reinterpret_cast(GetRightAlign(start_pos, alignment));
53 | }
54 |
55 | void *AlignedMalloc(size_t size, size_t alignment) {
56 | if (size == 0) {
57 | return NULL;
58 | }
59 | if (!ValidAlignment(alignment)) {
60 | return NULL;
61 | }
62 |
63 | // The memory is aligned towards the lowest address that so only
64 | // alignment - 1 bytes needs to be allocated.
65 | // A pointer to the start of the memory must be stored so that it can be
66 | // retreived for deletion, ergo the sizeof(uintptr_t).
67 | void *memory_pointer = malloc(size + sizeof(uintptr_t) + alignment - 1);
68 | RTC_CHECK(memory_pointer);
69 | if (memory_pointer == NULL)
70 | return NULL;
71 | // Aligning after the sizeof(uintptr_t) bytes will leave room for the header
72 | // in the same memory block.
73 | uintptr_t align_start_pos = reinterpret_cast(memory_pointer);
74 | align_start_pos += sizeof(uintptr_t);
75 | uintptr_t aligned_pos = GetRightAlign(align_start_pos, alignment);
76 | void *aligned_pointer = reinterpret_cast(aligned_pos);
77 |
78 | // Store the address to the beginning of the memory just before the aligned
79 | // memory.
80 | uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
81 | void *header_pointer = reinterpret_cast(header_pos);
82 | uintptr_t memory_start = reinterpret_cast(memory_pointer);
83 | memcpy(header_pointer, &memory_start, sizeof(uintptr_t));
84 |
85 | return aligned_pointer;
86 | }
87 |
88 | void AlignedFree(void *mem_block) {
89 | if (mem_block == NULL) {
90 | return;
91 | }
92 | uintptr_t aligned_pos = reinterpret_cast(mem_block);
93 | uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
94 |
95 | // Read out the address of the AlignedMemory struct from the header.
96 | uintptr_t memory_start_pos = *reinterpret_cast(header_pos);
97 | void *memory_start = reinterpret_cast(memory_start_pos);
98 | free(memory_start);
99 | }
100 |
101 | } // namespace webrtc
102 |
--------------------------------------------------------------------------------
/ns/aligned_malloc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef RTC_BASE_MEMORY_ALIGNED_MALLOC_H_
12 | #define RTC_BASE_MEMORY_ALIGNED_MALLOC_H_
13 |
14 | // The functions declared here
15 | // 1) Allocates block of aligned memory.
16 | // 2) Re-calculates a pointer such that it is aligned to a higher or equal
17 | // address.
18 | // Note: alignment must be a power of two. The alignment is in bytes.
19 |
20 | #include
21 |
22 | namespace webrtc {
23 |
24 | // Returns a pointer to the first boundry of |alignment| bytes following the
25 | // address of |ptr|.
26 | // Note that there is no guarantee that the memory in question is available.
27 | // |ptr| has no requirements other than it can't be NULL.
28 | void *GetRightAlign(const void *ptr, size_t alignment);
29 |
30 | // Allocates memory of |size| bytes aligned on an |alignment| boundry.
31 | // The return value is a pointer to the memory. Note that the memory must
32 | // be de-allocated using AlignedFree.
33 | void *AlignedMalloc(size_t size, size_t alignment);
34 |
35 | // De-allocates memory created using the AlignedMalloc() API.
36 | void AlignedFree(void *mem_block);
37 |
38 | // Templated versions to facilitate usage of aligned malloc without casting
39 | // to and from void*.
40 | template
41 | T *GetRightAlign(const T *ptr, size_t alignment) {
42 | return reinterpret_cast(
43 | GetRightAlign(reinterpret_cast(ptr), alignment));
44 | }
45 |
46 | template
47 | T *AlignedMalloc(size_t size, size_t alignment) {
48 | return reinterpret_cast(AlignedMalloc(size, alignment));
49 | }
50 |
51 | // Deleter for use with unique_ptr. E.g., use as
52 | // std::unique_ptr foo;
53 | struct AlignedFreeDeleter {
54 | inline void operator()(void *ptr) const { AlignedFree(ptr); }
55 | };
56 |
57 | } // namespace webrtc
58 |
59 | #endif // RTC_BASE_MEMORY_ALIGNED_MALLOC_H_
60 |
--------------------------------------------------------------------------------
/ns/array_view.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 The WebRTC Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef API_ARRAY_VIEW_H_
12 | #define API_ARRAY_VIEW_H_
13 |
14 | #include
15 | #include
16 | #include
17 |
18 | #include "checks.h"
19 | #include "type_traits.h"
20 |
21 | namespace rtc {
22 |
23 | // tl;dr: rtc::ArrayView is the same thing as gsl::span from the Guideline
24 | // Support Library.
25 | //
26 | // Many functions read from or write to arrays. The obvious way to do this is
27 | // to use two arguments, a pointer to the first element and an element count:
28 | //
29 | // bool Contains17(const int* arr, size_t size) {
30 | // for (size_t i = 0; i < size; ++i) {
31 | // if (arr[i] == 17)
32 | // return true;
33 | // }
34 | // return false;
35 | // }
36 | //
37 | // This is flexible, since it doesn't matter how the array is stored (C array,
38 | // std::vector, rtc::Buffer, ...), but it's error-prone because the caller has
39 | // to correctly specify the array length:
40 | //
41 | // Contains17(arr, arraysize(arr)); // C array
42 | // Contains17(arr.data(), arr.size()); // std::vector
43 | // Contains17(arr, size); // pointer + size
44 | // ...
45 | //
46 | // It's also kind of messy to have two separate arguments for what is
47 | // conceptually a single thing.
48 | //
49 | // Enter rtc::ArrayView. It contains a T pointer (to an array it doesn't
50 | // own) and a count, and supports the basic things you'd expect, such as
51 | // indexing and iteration. It allows us to write our function like this:
52 | //
53 | // bool Contains17(rtc::ArrayView arr) {
54 | // for (auto e : arr) {
55 | // if (e == 17)
56 | // return true;
57 | // }
58 | // return false;
59 | // }
60 | //
61 | // And even better, because a bunch of things will implicitly convert to
62 | // ArrayView, we can call it like this:
63 | //
64 | // Contains17(arr); // C array
65 | // Contains17(arr); // std::vector
66 | // Contains17(rtc::ArrayView(arr, size)); // pointer + size
67 | // Contains17(nullptr); // nullptr -> empty ArrayView
68 | // ...
69 | //
70 | // ArrayView stores both a pointer and a size, but you may also use
71 | // ArrayView, which has a size that's fixed at compile time (which means
72 | // it only has to store the pointer).
73 | //
74 | // One important point is that ArrayView and ArrayView are
75 | // different types, which allow and don't allow mutation of the array elements,
76 | // respectively. The implicit conversions work just like you'd hope, so that
77 | // e.g. vector will convert to either ArrayView or ArrayView, but const vector will convert only to ArrayView.
79 | // (ArrayView itself can be the source type in such conversions, so
80 | // ArrayView will convert to ArrayView.)
81 | //
82 | // Note: ArrayView is tiny (just a pointer and a count if variable-sized, just
83 | // a pointer if fix-sized) and trivially copyable, so it's probably cheaper to
84 | // pass it by value than by const reference.
85 |
86 | namespace impl {
87 |
88 | // Magic constant for indicating that the size of an ArrayView is variable
89 | // instead of fixed.
90 | enum : std::ptrdiff_t {
91 | kArrayViewVarSize = -4711
92 | };
93 |
94 | // Base class for ArrayViews of fixed nonzero size.
95 | template
96 | class ArrayViewBase {
97 | static_assert(Size > 0, "ArrayView size must be variable or non-negative");
98 |
99 | public:
100 | ArrayViewBase(T *data, size_t size) : data_(data) {}
101 |
102 | static constexpr size_t size() { return Size; }
103 |
104 | static constexpr bool empty() { return false; }
105 |
106 | T *data() const { return data_; }
107 |
108 | protected:
109 | static constexpr bool fixed_size() { return true; }
110 |
111 | private:
112 | T *data_;
113 | };
114 |
115 | // Specialized base class for ArrayViews of fixed zero size.
116 | template
117 | class ArrayViewBase {
118 | public:
119 | explicit ArrayViewBase(T *data, size_t size) {}
120 |
121 | static constexpr size_t size() { return 0; }
122 |
123 | static constexpr bool empty() { return true; }
124 |
125 | T *data() const { return nullptr; }
126 |
127 | protected:
128 | static constexpr bool fixed_size() { return true; }
129 | };
130 |
131 | // Specialized base class for ArrayViews of variable size.
132 | template
133 | class ArrayViewBase {
134 | public:
135 | ArrayViewBase(T *data, size_t size)
136 | : data_(size == 0 ? nullptr : data), size_(size) {}
137 |
138 | size_t size() const { return size_; }
139 |
140 | bool empty() const { return size_ == 0; }
141 |
142 | T *data() const { return data_; }
143 |
144 | protected:
145 | static constexpr bool fixed_size() { return false; }
146 |
147 | private:
148 | T *data_;
149 | size_t size_;
150 | };
151 |
152 | } // namespace impl
153 |
154 | template
155 | class ArrayView final : public impl::ArrayViewBase {
156 | public:
157 | using value_type = T;
158 | using const_iterator = const T *;
159 |
160 | // Construct an ArrayView from a pointer and a length.
161 | template
162 | ArrayView(U *data, size_t size)
163 | : impl::ArrayViewBase::ArrayViewBase(data, size) {
164 | RTC_DCHECK_EQ(size == 0 ? nullptr : data, this->data());
165 | RTC_DCHECK_EQ(size, this->size());
166 | RTC_DCHECK_EQ(!this->data(),
167 | this->size() == 0); // data is null iff size == 0.
168 | }
169 |
170 | // Construct an empty ArrayView. Note that fixed-size ArrayViews of size > 0
171 | // cannot be empty.
172 | ArrayView() : ArrayView(nullptr, 0) {}
173 |
174 | ArrayView(std::nullptr_t) // NOLINT
175 | : ArrayView() {}
176 |
177 | ArrayView(std::nullptr_t, size_t size)
178 | : ArrayView(static_cast(nullptr), size) {
179 | static_assert(Size == 0 || Size == impl::kArrayViewVarSize, "");
180 | RTC_DCHECK_EQ(0, size);
181 | }
182 |
183 | // Construct an ArrayView from a C-style array.
184 | template
185 | ArrayView(U (&array)[N]) // NOLINT
186 | : ArrayView(array, N) {
187 | static_assert(Size == N || Size == impl::kArrayViewVarSize,
188 | "Array size must match ArrayView size");
189 | }
190 |
191 | // (Only if size is fixed.) Construct a fixed size ArrayView from a
192 | // non-const std::array instance. For an ArrayView with variable size, the
193 | // used ctor is ArrayView(U& u) instead.
194 | template(N)>::type * = nullptr>
198 | ArrayView(std::array &u) // NOLINT
199 | : ArrayView(u.data(), u.size()) {}
200 |
201 | // (Only if size is fixed.) Construct a fixed size ArrayView where T is
202 | // const from a const(expr) std::array instance. For an ArrayView with
203 | // variable size, the used ctor is ArrayView(U& u) instead.
204 | template(N)>::type * = nullptr>
208 | ArrayView(const std::array &u) // NOLINT
209 | : ArrayView(u.data(), u.size()) {}
210 |
211 | // (Only if size is fixed.) Construct an ArrayView from any type U that has a
212 | // static constexpr size() method whose return value is equal to Size, and a
213 | // data() method whose return value converts implicitly to T*. In particular,
214 | // this means we allow conversion from ArrayView to ArrayView, but not the other way around. We also don't allow conversion from
216 | // ArrayView to ArrayView, or from ArrayView to ArrayView when M != N.
218 | template<
219 | typename U,
220 | typename std::enable_if::value>::type * = nullptr>
222 | ArrayView(U &u) // NOLINT
223 | : ArrayView(u.data(), u.size()) {
224 | static_assert(U::size() == Size, "Sizes must match exactly");
225 | }
226 |
227 | template<
228 | typename U,
229 | typename std::enable_if::value>::type * = nullptr>
231 | ArrayView(const U &u) // NOLINT(runtime/explicit)
232 | : ArrayView(u.data(), u.size()) {
233 | static_assert(U::size() == Size, "Sizes must match exactly");
234 | }
235 |
236 | // (Only if size is variable.) Construct an ArrayView from any type U that
237 | // has a size() method whose return value converts implicitly to size_t, and
238 | // a data() method whose return value converts implicitly to T*. In
239 | // particular, this means we allow conversion from ArrayView to
240 | // ArrayView, but not the other way around. Other allowed
241 | // conversions include
242 | // ArrayView to ArrayView or ArrayView,
243 | // std::vector to ArrayView or ArrayView,
244 | // const std::vector to ArrayView,
245 | // rtc::Buffer to ArrayView or ArrayView, and
246 | // const rtc::Buffer to ArrayView.
247 | template<
248 | typename U,
249 | typename std::enable_if::value>::type * = nullptr>
251 | ArrayView(U &u) // NOLINT
252 | : ArrayView(u.data(), u.size()) {}
253 |
254 | template<
255 | typename U,
256 | typename std::enable_if::value>::type * = nullptr>
258 | ArrayView(const U &u) // NOLINT(runtime/explicit)
259 | : ArrayView(u.data(), u.size()) {}
260 |
261 | // Indexing and iteration. These allow mutation even if the ArrayView is
262 | // const, because the ArrayView doesn't own the array. (To prevent mutation,
263 | // use a const element type.)
264 | T &operator[](size_t idx) const {
265 | RTC_DCHECK_LT(idx, this->size());
266 | RTC_DCHECK(this->data());
267 | return this->data()[idx];
268 | }
269 |
270 | T *begin() const { return this->data(); }
271 |
272 | T *end() const { return this->data() + this->size(); }
273 |
274 | const T *cbegin() const { return this->data(); }
275 |
276 | const T *cend() const { return this->data() + this->size(); }
277 |
278 | ArrayView subview(size_t offset, size_t size) const {
279 | return offset < this->size()
280 | ? ArrayView(this->data() + offset,
281 | std::min(size, this->size() - offset))
282 | : ArrayView();
283 | }
284 |
285 | ArrayView subview(size_t offset) const {
286 | return subview(offset, this->size());
287 | }
288 | };
289 |
290 | // Comparing two ArrayViews compares their (pointer,size) pairs; it does *not*
291 | // dereference the pointers.
292 | template
293 | bool operator==(const ArrayView &a, const ArrayView &b) {
294 | return a.data() == b.data() && a.size() == b.size();
295 | }
296 |
297 | template
298 | bool operator!=(const ArrayView &a, const ArrayView &b) {
299 | return !(a == b);
300 | }
301 |
302 | // Variable-size ArrayViews are the size of two pointers; fixed-size ArrayViews
303 | // are the size of one pointer. (And as a special case, fixed-size ArrayViews
304 | // of size 0 require no storage.)
305 | static_assert(sizeof(ArrayView) == 2 * sizeof(int *), "");
306 | static_assert(sizeof(ArrayView) == sizeof(int *), "");
307 | static_assert(std::is_empty>::value, "");
308 |
309 | template
310 | inline ArrayView MakeArrayView(T *data, size_t size) {
311 | return ArrayView(data, size);
312 | }
313 |
314 | // Only for primitive types that have the same size and aligment.
315 | // Allow reinterpret cast of the array view to another primitive type of the
316 | // same size.
317 | // Template arguments order is (U, T, Size) to allow deduction of the template
318 | // arguments in client calls: reinterpret_array_view(array_view).
319 | template
320 | inline ArrayView reinterpret_array_view(ArrayView view) {
321 | static_assert(sizeof(U) == sizeof(T) && alignof(U) == alignof(T),
322 | "ArrayView reinterpret_cast is only supported for casting "
323 | "between views that represent the same chunk of memory.");
324 | static_assert(
325 | std::is_fundamental::value && std::is_fundamental::value,
326 | "ArrayView reinterpret_cast is only supported for casting between "
327 | "fundamental types.");
328 | return ArrayView(reinterpret_cast(view.data()), view.size());
329 | }
330 |
331 | } // namespace rtc
332 |
333 | #endif // API_ARRAY_VIEW_H_
334 |
--------------------------------------------------------------------------------
/ns/audio_buffer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef MODULES_AUDIO_PROCESSING_AUDIO_BUFFER_H_
12 | #define MODULES_AUDIO_PROCESSING_AUDIO_BUFFER_H_
13 |
14 | #include
15 | #include
16 |
17 | #include
18 | #include
19 |
20 | #include "channel_buffer.h"
21 | //#include "audio_processing.h"
22 |
23 | namespace webrtc {
24 |
25 | class StreamConfig {
26 | public:
27 | // sample_rate_hz: The sampling rate of the stream.
28 | //
29 | // num_channels: The number of audio channels in the stream, excluding the
30 | // keyboard channel if it is present. When passing a
31 | // StreamConfig with an array of arrays T*[N],
32 | //
33 | // N == {num_channels + 1 if has_keyboard
34 | // {num_channels if !has_keyboard
35 | //
36 | // has_keyboard: True if the stream has a keyboard channel. When has_keyboard
37 | // is true, the last channel in any corresponding list of
38 | // channels is the keyboard channel.
39 | StreamConfig(int sample_rate_hz = 0,
40 | size_t num_channels = 0,
41 | bool has_keyboard = false)
42 | : sample_rate_hz_(sample_rate_hz),
43 | num_channels_(num_channels),
44 | has_keyboard_(has_keyboard),
45 | num_frames_(calculate_frames(sample_rate_hz)) {}
46 |
47 | void set_sample_rate_hz(int value) {
48 | sample_rate_hz_ = value;
49 | num_frames_ = calculate_frames(value);
50 | }
51 |
52 | void set_num_channels(size_t value) { num_channels_ = value; }
53 |
54 | void set_has_keyboard(bool value) { has_keyboard_ = value; }
55 |
56 | int sample_rate_hz() const { return sample_rate_hz_; }
57 |
58 | // The number of channels in the stream, not including the keyboard channel if
59 | // present.
60 | size_t num_channels() const { return num_channels_; }
61 |
62 | bool has_keyboard() const { return has_keyboard_; }
63 |
64 | size_t num_frames() const { return num_frames_; }
65 |
66 | size_t num_samples() const { return num_channels_ * num_frames_; }
67 |
68 | bool operator==(const StreamConfig &other) const {
69 | return sample_rate_hz_ == other.sample_rate_hz_ &&
70 | num_channels_ == other.num_channels_ &&
71 | has_keyboard_ == other.has_keyboard_;
72 | }
73 |
74 | bool operator!=(const StreamConfig &other) const { return !(*this == other); }
75 |
76 | private:
77 |
78 | static const int kChunkSizeMs = 10;
79 |
80 | static size_t calculate_frames(int sample_rate_hz) {
81 | return static_cast( kChunkSizeMs * sample_rate_hz /
82 | 1000);
83 | }
84 |
85 | int sample_rate_hz_;
86 | size_t num_channels_;
87 | bool has_keyboard_;
88 | size_t num_frames_;
89 | };
90 |
91 | class PushSincResampler;
92 |
93 | class SplittingFilter;
94 |
95 | enum Band {
96 | kBand0To8kHz = 0, kBand8To16kHz = 1, kBand16To24kHz = 2
97 | };
98 |
99 | // Stores any audio data in a way that allows the audio processing module to
100 | // operate on it in a controlled manner.
101 | class AudioBuffer {
102 | public:
103 | static const int kSplitBandSize = 160;
104 | static const size_t kMaxSampleRate = 384000;
105 |
106 | AudioBuffer(size_t input_rate,
107 | size_t input_num_channels,
108 | size_t buffer_rate,
109 | size_t buffer_num_channels,
110 | size_t output_rate,
111 | size_t output_num_channels);
112 |
113 | // The constructor below will be deprecated.
114 | AudioBuffer(size_t input_num_frames,
115 | size_t input_num_channels,
116 | size_t buffer_num_frames,
117 | size_t buffer_num_channels,
118 | size_t output_num_frames);
119 |
120 | virtual ~AudioBuffer();
121 |
122 | AudioBuffer(const AudioBuffer &) = delete;
123 |
124 | AudioBuffer &operator=(const AudioBuffer &) = delete;
125 |
126 | // Specify that downmixing should be done by selecting a single channel.
127 | void set_downmixing_to_specific_channel(size_t channel);
128 |
129 | // Specify that downmixing should be done by averaging all channels,.
130 | void set_downmixing_by_averaging();
131 |
132 | // Set the number of channels in the buffer. The specified number of channels
133 | // cannot be larger than the specified buffer_num_channels. The number is also
134 | // reset at each call to CopyFrom or InterleaveFrom.
135 | void set_num_channels(size_t num_channels);
136 |
137 | size_t num_channels() const { return num_channels_; }
138 |
139 | size_t num_frames() const { return buffer_num_frames_; }
140 |
141 | size_t num_frames_per_band() const { return num_split_frames_; }
142 |
143 | size_t num_bands() const { return num_bands_; }
144 |
145 | // Returns pointer arrays to the full-band channels.
146 | // Usage:
147 | // channels()[channel][sample].
148 | // Where:
149 | // 0 <= channel < |buffer_num_channels_|
150 | // 0 <= sample < |buffer_num_frames_|
151 | float *const *channels() { return data_->channels(); }
152 |
153 | const float *const *channels_const() const { return data_->channels(); }
154 |
155 | // Returns pointer arrays to the bands for a specific channel.
156 | // Usage:
157 | // split_bands(channel)[band][sample].
158 | // Where:
159 | // 0 <= channel < |buffer_num_channels_|
160 | // 0 <= band < |num_bands_|
161 | // 0 <= sample < |num_split_frames_|
162 | const float *const *split_bands_const(size_t channel) const {
163 | return split_data_.get() ? split_data_->bands(channel)
164 | : data_->bands(channel);
165 | }
166 |
167 | float *const *split_bands(size_t channel) {
168 | return split_data_.get() ? split_data_->bands(channel)
169 | : data_->bands(channel);
170 | }
171 |
172 | // Returns a pointer array to the channels for a specific band.
173 | // Usage:
174 | // split_channels(band)[channel][sample].
175 | // Where:
176 | // 0 <= band < |num_bands_|
177 | // 0 <= channel < |buffer_num_channels_|
178 | // 0 <= sample < |num_split_frames_|
179 | const float *const *split_channels_const(Band band) const {
180 | if (split_data_.get()) {
181 | return split_data_->channels(band);
182 | } else {
183 | return band == kBand0To8kHz ? data_->channels() : nullptr;
184 | }
185 | }
186 |
187 | // Copies data into the buffer.
188 | void CopyFrom(const int16_t *const interleaved_data,
189 | const StreamConfig &stream_config);
190 |
191 | void CopyFrom(const float *const *stacked_data,
192 | const StreamConfig &stream_config);
193 |
194 | // Copies data from the buffer.
195 | void CopyTo(const StreamConfig &stream_config,
196 | int16_t *const interleaved_data);
197 |
198 | void CopyTo(const StreamConfig &stream_config, float *const *stacked_data);
199 |
200 | void CopyTo(AudioBuffer *buffer) const;
201 |
202 | // Splits the buffer data into frequency bands.
203 | void SplitIntoFrequencyBands();
204 |
205 | // Recombines the frequency bands into a full-band signal.
206 | void MergeFrequencyBands();
207 |
208 | // Copies the split bands data into the integer two-dimensional array.
209 | void ExportSplitChannelData(size_t channel,
210 | int16_t *const *split_band_data) const;
211 |
212 | // Copies the data in the integer two-dimensional array into the split_bands
213 | // data.
214 | void ImportSplitChannelData(size_t channel,
215 | const int16_t *const *split_band_data);
216 |
217 | static const size_t kMaxSplitFrameLength = 160;
218 | static const size_t kMaxNumBands = 3;
219 |
220 | // Deprecated methods, will be removed soon.
221 | float *const *channels_f() { return channels(); }
222 |
223 | const float *const *channels_const_f() const { return channels_const(); }
224 |
225 | const float *const *split_bands_const_f(size_t channel) const {
226 | return split_bands_const(channel);
227 | }
228 |
229 | float *const *split_bands_f(size_t channel) { return split_bands(channel); }
230 |
231 | const float *const *split_channels_const_f(Band band) const {
232 | return split_channels_const(band);
233 | }
234 |
235 | private:
236 | FRIEND_TEST_ALL_PREFIXES(AudioBufferTest,
237 | SetNumChannelsSetsChannelBuffersNumChannels);
238 |
239 | void RestoreNumChannels();
240 |
241 | const size_t input_num_frames_;
242 | const size_t input_num_channels_;
243 | const size_t buffer_num_frames_;
244 | const size_t buffer_num_channels_;
245 | const size_t output_num_frames_;
246 | const size_t output_num_channels_;
247 |
248 | size_t num_channels_;
249 | size_t num_bands_;
250 | size_t num_split_frames_;
251 |
252 | std::unique_ptr> data_;
253 | std::unique_ptr> split_data_;
254 | std::unique_ptr splitting_filter_;
255 | std::vector> input_resamplers_;
256 | std::vector> output_resamplers_;
257 | bool downmix_by_averaging_ = true;
258 | size_t channel_for_downmixing_ = 0;
259 | };
260 |
261 | } // namespace webrtc
262 |
263 | #endif // MODULES_AUDIO_PROCESSING_AUDIO_BUFFER_H_
264 |
--------------------------------------------------------------------------------
/ns/audio_util.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #include "audio_util.h"
12 |
13 | namespace webrtc {
14 |
15 | void FloatToS16(const float *src, size_t size, int16_t *dest) {
16 | for (size_t i = 0; i < size; ++i)
17 | dest[i] = FloatToS16(src[i]);
18 | }
19 |
20 | void S16ToFloat(const int16_t *src, size_t size, float *dest) {
21 | for (size_t i = 0; i < size; ++i)
22 | dest[i] = S16ToFloat(src[i]);
23 | }
24 |
25 | void S16ToFloatS16(const int16_t *src, size_t size, float *dest) {
26 | for (size_t i = 0; i < size; ++i)
27 | dest[i] = src[i];
28 | }
29 |
30 | void FloatS16ToS16(const float *src, size_t size, int16_t *dest) {
31 | for (size_t i = 0; i < size; ++i)
32 | dest[i] = FloatS16ToS16(src[i]);
33 | }
34 |
35 | void FloatToFloatS16(const float *src, size_t size, float *dest) {
36 | for (size_t i = 0; i < size; ++i)
37 | dest[i] = FloatToFloatS16(src[i]);
38 | }
39 |
40 | void FloatS16ToFloat(const float *src, size_t size, float *dest) {
41 | for (size_t i = 0; i < size; ++i)
42 | dest[i] = FloatS16ToFloat(src[i]);
43 | }
44 |
45 | template<>
46 | void DownmixInterleavedToMono(const int16_t *interleaved,
47 | size_t num_frames,
48 | int num_channels,
49 | int16_t *deinterleaved) {
50 | DownmixInterleavedToMonoImpl(interleaved, num_frames,
51 | num_channels, deinterleaved);
52 | }
53 |
54 | } // namespace webrtc
55 |
--------------------------------------------------------------------------------
/ns/audio_util.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
12 | #define COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
13 |
14 | #include
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | #include "checks.h"
22 |
23 | namespace webrtc {
24 |
25 | typedef std::numeric_limits limits_int16;
26 |
27 | // The conversion functions use the following naming convention:
28 | // S16: int16_t [-32768, 32767]
29 | // Float: float [-1.0, 1.0]
30 | // FloatS16: float [-32768.0, 32768.0]
31 | // Dbfs: float [-20.0*log(10, 32768), 0] = [-90.3, 0]
32 | // The ratio conversion functions use this naming convention:
33 | // Ratio: float (0, +inf)
34 | // Db: float (-inf, +inf)
35 | static inline float S16ToFloat(int16_t v) {
36 | constexpr float kScaling = 1.f / 32768.f;
37 | return v * kScaling;
38 | }
39 |
40 | static inline int16_t FloatS16ToS16(float v) {
41 | v = std::min(v, 32767.f);
42 | v = std::max(v, -32768.f);
43 | return static_cast(v + std::copysign(0.5f, v));
44 | }
45 |
46 | static inline int16_t FloatToS16(float v) {
47 | v *= 32768.f;
48 | v = std::min(v, 32767.f);
49 | v = std::max(v, -32768.f);
50 | return static_cast(v + std::copysign(0.5f, v));
51 | }
52 |
53 | static inline float FloatToFloatS16(float v) {
54 | v = std::min(v, 1.f);
55 | v = std::max(v, -1.f);
56 | return v * 32768.f;
57 | }
58 |
59 | static inline float FloatS16ToFloat(float v) {
60 | v = std::min(v, 32768.f);
61 | v = std::max(v, -32768.f);
62 | constexpr float kScaling = 1.f / 32768.f;
63 | return v * kScaling;
64 | }
65 |
66 | void FloatToS16(const float *src, size_t size, int16_t *dest);
67 |
68 | void S16ToFloat(const int16_t *src, size_t size, float *dest);
69 |
70 | void S16ToFloatS16(const int16_t *src, size_t size, float *dest);
71 |
72 | void FloatS16ToS16(const float *src, size_t size, int16_t *dest);
73 |
74 | void FloatToFloatS16(const float *src, size_t size, float *dest);
75 |
76 | void FloatS16ToFloat(const float *src, size_t size, float *dest);
77 |
78 | inline float DbToRatio(float v) {
79 | return std::pow(10.0f, v / 20.0f);
80 | }
81 |
82 | inline float DbfsToFloatS16(float v) {
83 | static constexpr float kMaximumAbsFloatS16 = -limits_int16::min();
84 | return DbToRatio(v) * kMaximumAbsFloatS16;
85 | }
86 |
87 | inline float FloatS16ToDbfs(float v) {
88 | RTC_DCHECK_GE(v, 0);
89 |
90 | // kMinDbfs is equal to -20.0 * log10(-limits_int16::min())
91 | static constexpr float kMinDbfs = -90.30899869919436f;
92 | if (v <= 1.0f) {
93 | return kMinDbfs;
94 | }
95 | // Equal to 20 * log10(v / (-limits_int16::min()))
96 | return 20.0f * std::log10(v) + kMinDbfs;
97 | }
98 |
99 | // Copy audio from |src| channels to |dest| channels unless |src| and |dest|
100 | // point to the same address. |src| and |dest| must have the same number of
101 | // channels, and there must be sufficient space allocated in |dest|.
102 | template
103 | void CopyAudioIfNeeded(const T *const *src,
104 | int num_frames,
105 | int num_channels,
106 | T *const *dest) {
107 | for (int i = 0; i < num_channels; ++i) {
108 | if (src[i] != dest[i]) {
109 | std::copy(src[i], src[i] + num_frames, dest[i]);
110 | }
111 | }
112 | }
113 |
114 | // Deinterleave audio from |interleaved| to the channel buffers pointed to
115 | // by |deinterleaved|. There must be sufficient space allocated in the
116 | // |deinterleaved| buffers (|num_channel| buffers with |samples_per_channel|
117 | // per buffer).
118 | template
119 | void Deinterleave(const T *interleaved,
120 | size_t samples_per_channel,
121 | size_t num_channels,
122 | T *const *deinterleaved) {
123 | for (size_t i = 0; i < num_channels; ++i) {
124 | T *channel = deinterleaved[i];
125 | size_t interleaved_idx = i;
126 | for (size_t j = 0; j < samples_per_channel; ++j) {
127 | channel[j] = interleaved[interleaved_idx];
128 | interleaved_idx += num_channels;
129 | }
130 | }
131 | }
132 |
133 | // Interleave audio from the channel buffers pointed to by |deinterleaved| to
134 | // |interleaved|. There must be sufficient space allocated in |interleaved|
135 | // (|samples_per_channel| * |num_channels|).
136 | template
137 | void Interleave(const T *const *deinterleaved,
138 | size_t samples_per_channel,
139 | size_t num_channels,
140 | T *interleaved) {
141 | for (size_t i = 0; i < num_channels; ++i) {
142 | const T *channel = deinterleaved[i];
143 | size_t interleaved_idx = i;
144 | for (size_t j = 0; j < samples_per_channel; ++j) {
145 | interleaved[interleaved_idx] = channel[j];
146 | interleaved_idx += num_channels;
147 | }
148 | }
149 | }
150 |
151 | // Copies audio from a single channel buffer pointed to by |mono| to each
152 | // channel of |interleaved|. There must be sufficient space allocated in
153 | // |interleaved| (|samples_per_channel| * |num_channels|).
154 | template
155 | void UpmixMonoToInterleaved(const T *mono,
156 | int num_frames,
157 | int num_channels,
158 | T *interleaved) {
159 | int interleaved_idx = 0;
160 | for (int i = 0; i < num_frames; ++i) {
161 | for (int j = 0; j < num_channels; ++j) {
162 | interleaved[interleaved_idx++] = mono[i];
163 | }
164 | }
165 | }
166 |
167 | template
168 | void DownmixToMono(const T *const *input_channels,
169 | size_t num_frames,
170 | int num_channels,
171 | T *out) {
172 | for (size_t i = 0; i < num_frames; ++i) {
173 | Intermediate value = input_channels[0][i];
174 | for (int j = 1; j < num_channels; ++j) {
175 | value += input_channels[j][i];
176 | }
177 | out[i] = value / num_channels;
178 | }
179 | }
180 |
181 | // Downmixes an interleaved multichannel signal to a single channel by averaging
182 | // all channels.
183 | template
184 | void DownmixInterleavedToMonoImpl(const T *interleaved,
185 | size_t num_frames,
186 | int num_channels,
187 | T *deinterleaved) {
188 | RTC_DCHECK_GT(num_channels, 0);
189 | RTC_DCHECK_GT(num_frames, 0);
190 |
191 | const T *const end = interleaved + num_frames * num_channels;
192 |
193 | while (interleaved < end) {
194 | const T *const frame_end = interleaved + num_channels;
195 |
196 | Intermediate value = *interleaved++;
197 | while (interleaved < frame_end) {
198 | value += *interleaved++;
199 | }
200 |
201 | *deinterleaved++ = value / num_channels;
202 | }
203 | }
204 |
205 | template
206 | void DownmixInterleavedToMono(const T *interleaved,
207 | size_t num_frames,
208 | int num_channels,
209 | T *deinterleaved);
210 |
211 | template<>
212 | void DownmixInterleavedToMono(const int16_t *interleaved,
213 | size_t num_frames,
214 | int num_channels,
215 | int16_t *deinterleaved);
216 |
217 | } // namespace webrtc
218 |
219 | #endif // COMMON_AUDIO_INCLUDE_AUDIO_UTIL_H_
220 |
--------------------------------------------------------------------------------
/ns/channel_buffer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef COMMON_AUDIO_CHANNEL_BUFFER_H_
12 | #define COMMON_AUDIO_CHANNEL_BUFFER_H_
13 |
14 | #include
15 |
16 | #include
17 | #include
18 |
19 | #include "array_view.h"
20 | #include "audio_util.h"
21 | #include "checks.h"
22 | #include "gtest_prod_util.h"
23 |
24 | namespace webrtc {
25 |
26 | // Helper to encapsulate a contiguous data buffer, full or split into frequency
27 | // bands, with access to a pointer arrays of the deinterleaved channels and
28 | // bands. The buffer is zero initialized at creation.
29 | //
30 | // The buffer structure is showed below for a 2 channel and 2 bands case:
31 | //
32 | // |data_|:
33 | // { [ --- b1ch1 --- ] [ --- b2ch1 --- ] [ --- b1ch2 --- ] [ --- b2ch2 --- ] }
34 | //
35 | // The pointer arrays for the same example are as follows:
36 | //
37 | // |channels_|:
38 | // { [ b1ch1* ] [ b1ch2* ] [ b2ch1* ] [ b2ch2* ] }
39 | //
40 | // |bands_|:
41 | // { [ b1ch1* ] [ b2ch1* ] [ b1ch2* ] [ b2ch2* ] }
42 | template
43 | class ChannelBuffer {
44 | public:
45 | ChannelBuffer(size_t num_frames, size_t num_channels, size_t num_bands = 1)
46 | : data_(new T[num_frames * num_channels]()),
47 | channels_(new T *[num_channels * num_bands]),
48 | bands_(new T *[num_channels * num_bands]),
49 | num_frames_(num_frames),
50 | num_frames_per_band_(num_frames / num_bands),
51 | num_allocated_channels_(num_channels),
52 | num_channels_(num_channels),
53 | num_bands_(num_bands),
54 | bands_view_(num_allocated_channels_,
55 | std::vector>(num_bands_)),
56 | channels_view_(
57 | num_bands_,
58 | std::vector>(num_allocated_channels_)) {
59 | // Temporarily cast away const_ness to allow populating the array views.
60 | auto *bands_view =
61 | const_cast>> *>(&bands_view_);
62 | auto *channels_view =
63 | const_cast>> *>(
64 | &channels_view_);
65 |
66 | for (size_t ch = 0; ch < num_allocated_channels_; ++ch) {
67 | for (size_t band = 0; band < num_bands_; ++band) {
68 | (*channels_view)[band][ch] = rtc::ArrayView(
69 | &data_[ch * num_frames_ + band * num_frames_per_band_],
70 | num_frames_per_band_);
71 | (*bands_view)[ch][band] = channels_view_[band][ch];
72 | channels_[band * num_allocated_channels_ + ch] =
73 | channels_view_[band][ch].data();
74 | bands_[ch * num_bands_ + band] =
75 | channels_[band * num_allocated_channels_ + ch];
76 | }
77 | }
78 | }
79 |
80 | // Returns a pointer array to the channels.
81 | // If band is explicitly specificed, the channels for a specific band are
82 | // returned and the usage becomes: channels(band)[channel][sample].
83 | // Where:
84 | // 0 <= band < |num_bands_|
85 | // 0 <= channel < |num_allocated_channels_|
86 | // 0 <= sample < |num_frames_per_band_|
87 |
88 | // If band is not explicitly specified, the full-band channels (or lower band
89 | // channels) are returned and the usage becomes: channels()[channel][sample].
90 | // Where:
91 | // 0 <= channel < |num_allocated_channels_|
92 | // 0 <= sample < |num_frames_|
93 | const T *const *channels(size_t band = 0) const {
94 | RTC_DCHECK_LT(band, num_bands_);
95 | return &channels_[band * num_allocated_channels_];
96 | }
97 |
98 | T *const *channels(size_t band = 0) {
99 | const ChannelBuffer *t = this;
100 | return const_cast(t->channels(band));
101 | }
102 |
103 | rtc::ArrayView> channels_view(size_t band = 0) {
104 | return channels_view_[band];
105 | }
106 |
107 | rtc::ArrayView> channels_view(size_t band = 0) const {
108 | return channels_view_[band];
109 | }
110 |
111 | // Returns a pointer array to the bands for a specific channel.
112 | // Usage:
113 | // bands(channel)[band][sample].
114 | // Where:
115 | // 0 <= channel < |num_channels_|
116 | // 0 <= band < |num_bands_|
117 | // 0 <= sample < |num_frames_per_band_|
118 | const T *const *bands(size_t channel) const {
119 | RTC_DCHECK_LT(channel, num_channels_);
120 | RTC_DCHECK_GE(channel, 0);
121 | return &bands_[channel * num_bands_];
122 | }
123 |
124 | T *const *bands(size_t channel) {
125 | const ChannelBuffer *t = this;
126 | return const_cast(t->bands(channel));
127 | }
128 |
129 | rtc::ArrayView> bands_view(size_t channel) {
130 | return bands_view_[channel];
131 | }
132 |
133 | rtc::ArrayView> bands_view(size_t channel) const {
134 | return bands_view_[channel];
135 | }
136 |
137 | // Sets the |slice| pointers to the |start_frame| position for each channel.
138 | // Returns |slice| for convenience.
139 | const T *const *Slice(T **slice, size_t start_frame) const {
140 | RTC_DCHECK_LT(start_frame, num_frames_);
141 | for (size_t i = 0; i < num_channels_; ++i)
142 | slice[i] = &channels_[i][start_frame];
143 | return slice;
144 | }
145 |
146 | T **Slice(T **slice, size_t start_frame) {
147 | const ChannelBuffer *t = this;
148 | return const_cast(t->Slice(slice, start_frame));
149 | }
150 |
151 | size_t num_frames() const { return num_frames_; }
152 |
153 | size_t num_frames_per_band() const { return num_frames_per_band_; }
154 |
155 | size_t num_channels() const { return num_channels_; }
156 |
157 | size_t num_bands() const { return num_bands_; }
158 |
159 | size_t size() const { return num_frames_ * num_allocated_channels_; }
160 |
161 | void set_num_channels(size_t num_channels) {
162 | RTC_DCHECK_LE(num_channels, num_allocated_channels_);
163 | num_channels_ = num_channels;
164 | }
165 |
166 | void SetDataForTesting(const T *data, size_t size) {
167 | RTC_CHECK_EQ(size, this->size());
168 | memcpy(data_.get(), data, size * sizeof(*data));
169 | }
170 |
171 | private:
172 | std::unique_ptr data_;
173 | std::unique_ptr channels_;
174 | std::unique_ptr bands_;
175 | const size_t num_frames_;
176 | const size_t num_frames_per_band_;
177 | // Number of channels the internal buffer holds.
178 | const size_t num_allocated_channels_;
179 | // Number of channels the user sees.
180 | size_t num_channels_;
181 | const size_t num_bands_;
182 | const std::vector>> bands_view_;
183 | const std::vector>> channels_view_;
184 | };
185 |
186 | } // namespace webrtc
187 |
188 | #endif // COMMON_AUDIO_CHANNEL_BUFFER_H_
189 |
--------------------------------------------------------------------------------
/ns/checks.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006 The WebRTC Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef RTC_BASE_CHECKS_H_
12 | #define RTC_BASE_CHECKS_H_
13 |
14 | # include
15 | // If you for some reson need to know if DCHECKs are on, test the value of
16 | // RTC_DCHECK_IS_ON. (Test its value, not if it's defined; it'll always be
17 | // defined, to either a true or a false value.)
18 | #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
19 | #define RTC_DCHECK_IS_ON 1
20 | #else
21 | #define RTC_DCHECK_IS_ON 0
22 | #endif
23 |
24 | // Annotate a function that will not return control flow to the caller.
25 | #if defined(_MSC_VER)
26 | #define RTC_NORETURN __declspec(noreturn)
27 | #elif defined(__GNUC__)
28 | #define RTC_NORETURN __attribute__((__noreturn__))
29 | #else
30 | #define RTC_NORETURN
31 | #endif
32 |
33 | #ifdef RTC_DISABLE_CHECK_MSG
34 | #define RTC_CHECK_MSG_ENABLED 0
35 | #else
36 | #define RTC_CHECK_MSG_ENABLED 1
37 | #endif
38 |
39 | #if RTC_CHECK_MSG_ENABLED
40 | #define RTC_CHECK_EVAL_MESSAGE(message) message
41 | #else
42 | #define RTC_CHECK_EVAL_MESSAGE(message) ""
43 | #endif
44 |
45 | // C version. Lacks many features compared to the C++ version, but usage
46 | // guidelines are the same.
47 | #define rtc_FatalMessage(file, line, msg) printf("[%s:%d]%s \n", file, line, msg)
48 | #define RTC_CHECK(condition) \
49 | do { \
50 | if (!(condition)) { \
51 | rtc_FatalMessage(__FILE__, __LINE__, \
52 | RTC_CHECK_EVAL_MESSAGE("CHECK failed: " #condition)); \
53 | } \
54 | } while (0)
55 |
56 | #define RTC_CHECK_EQ(a, b) RTC_CHECK((a) == (b))
57 | #define RTC_CHECK_NE(a, b) RTC_CHECK((a) != (b))
58 | #define RTC_CHECK_LE(a, b) RTC_CHECK((a) <= (b))
59 | #define RTC_CHECK_LT(a, b) RTC_CHECK((a) < (b))
60 | #define RTC_CHECK_GE(a, b) RTC_CHECK((a) >= (b))
61 | #define RTC_CHECK_GT(a, b) RTC_CHECK((a) > (b))
62 |
63 | #define RTC_DCHECK(condition) \
64 | do { \
65 | if (RTC_DCHECK_IS_ON && !(condition)) { \
66 | rtc_FatalMessage(__FILE__, __LINE__, \
67 | RTC_CHECK_EVAL_MESSAGE("DCHECK failed: " #condition)); \
68 | } \
69 | } while (0)
70 |
71 | #define RTC_DCHECK_EQ(a, b) RTC_DCHECK((a) == (b))
72 | #define RTC_DCHECK_NE(a, b) RTC_DCHECK((a) != (b))
73 | #define RTC_DCHECK_LE(a, b) RTC_DCHECK((a) <= (b))
74 | #define RTC_DCHECK_LT(a, b) RTC_DCHECK((a) < (b))
75 | #define RTC_DCHECK_GE(a, b) RTC_DCHECK((a) >= (b))
76 | #define RTC_DCHECK_GT(a, b) RTC_DCHECK((a) > (b))
77 |
78 | #define RTC_UNREACHABLE_CODE_HIT false
79 | #define RTC_NOTREACHED() RTC_DCHECK(RTC_UNREACHABLE_CODE_HIT)
80 | #endif // RTC_BASE_CHECKS_H_
81 |
--------------------------------------------------------------------------------
/ns/constructor_magic.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef RTC_BASE_CONSTRUCTOR_MAGIC_H_
12 | #define RTC_BASE_CONSTRUCTOR_MAGIC_H_
13 |
14 | // Put this in the declarations for a class to be unassignable.
15 | #define RTC_DISALLOW_ASSIGN(TypeName) \
16 | TypeName& operator=(const TypeName&) = delete
17 |
18 | // A macro to disallow the copy constructor and operator= functions. This should
19 | // be used in the declarations for a class.
20 | #define RTC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
21 | TypeName(const TypeName&) = delete; \
22 | RTC_DISALLOW_ASSIGN(TypeName)
23 |
24 | // A macro to disallow all the implicit constructors, namely the default
25 | // constructor, copy constructor and operator= functions.
26 | //
27 | // This should be used in the declarations for a class that wants to prevent
28 | // anyone from instantiating it. This is especially useful for classes
29 | // containing only static methods.
30 | #define RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
31 | TypeName() = delete; \
32 | RTC_DISALLOW_COPY_AND_ASSIGN(TypeName)
33 |
34 | #endif // RTC_BASE_CONSTRUCTOR_MAGIC_H_
35 |
--------------------------------------------------------------------------------
/ns/fast_math.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #include "fast_math.h"
12 |
13 | #include
14 | #include
15 |
16 | #include "checks.h"
17 |
18 | namespace webrtc {
19 |
20 | namespace {
21 |
22 | float FastLog2f(float in) {
23 | RTC_DCHECK_GT(in, .0f);
24 | // Read and interpret float as uint32_t and then cast to float.
25 | // This is done to extract the exponent (bits 30 - 23).
26 | // "Right shift" of the exponent is then performed by multiplying
27 | // with the constant (1/2^23). Finally, we subtract a constant to
28 | // remove the bias (https://en.wikipedia.org/wiki/Exponent_bias).
29 | union {
30 | float dummy;
31 | uint32_t a;
32 | } x = {in};
33 | float out = x.a;
34 | out *= 1.1920929e-7f; // 1/2^23
35 | out -= 126.942695f; // Remove bias.
36 | return out;
37 | }
38 |
39 | } // namespace
40 |
41 | float SqrtFastApproximation(float f) {
42 | // TODO(peah): Add fast approximate implementation.
43 | return sqrtf(f);
44 | }
45 |
46 | float Pow2Approximation(float p) {
47 | // TODO(peah): Add fast approximate implementation.
48 | return powf(2.f, p);
49 | }
50 |
51 | float PowApproximation(float x, float p) {
52 | return Pow2Approximation(p * FastLog2f(x));
53 | }
54 |
55 | float LogApproximation(float x) {
56 | constexpr float kLogOf2 = 0.69314718056f;
57 | return FastLog2f(x) * kLogOf2;
58 | }
59 |
60 | void LogApproximation(rtc::ArrayView x, rtc::ArrayView y) {
61 | for (size_t k = 0; k < x.size(); ++k) {
62 | y[k] = LogApproximation(x[k]);
63 | }
64 | }
65 |
66 | float ExpApproximation(float x) {
67 | constexpr float kLog10Ofe = 0.4342944819f;
68 | return PowApproximation(10.f, x * kLog10Ofe);
69 | }
70 |
71 | void ExpApproximation(rtc::ArrayView x, rtc::ArrayView y) {
72 | for (size_t k = 0; k < x.size(); ++k) {
73 | y[k] = ExpApproximation(x[k]);
74 | }
75 | }
76 |
77 | void ExpApproximationSignFlip(rtc::ArrayView x,
78 | rtc::ArrayView y) {
79 | for (size_t k = 0; k < x.size(); ++k) {
80 | y[k] = ExpApproximation(-x[k]);
81 | }
82 | }
83 |
84 | } // namespace webrtc
85 |
--------------------------------------------------------------------------------
/ns/fast_math.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef MODULES_AUDIO_PROCESSING_NS_FAST_MATH_H_
12 | #define MODULES_AUDIO_PROCESSING_NS_FAST_MATH_H_
13 |
14 | #include "array_view.h"
15 |
16 | namespace webrtc {
17 |
18 | // Sqrt approximation.
19 | float SqrtFastApproximation(float f);
20 |
21 | // Log base conversion log(x) = log2(x)/log2(e).
22 | float LogApproximation(float x);
23 |
24 | void LogApproximation(rtc::ArrayView x, rtc::ArrayView y);
25 |
26 | // 2^x approximation.
27 | float Pow2Approximation(float p);
28 |
29 | // x^p approximation.
30 | float PowApproximation(float x, float p);
31 |
32 | // e^x approximation.
33 | float ExpApproximation(float x);
34 |
35 | void ExpApproximation(rtc::ArrayView x, rtc::ArrayView y);
36 |
37 | void ExpApproximationSignFlip(rtc::ArrayView x,
38 | rtc::ArrayView y);
39 | } // namespace webrtc
40 |
41 | #endif // MODULES_AUDIO_PROCESSING_NS_FAST_MATH_H_
42 |
--------------------------------------------------------------------------------
/ns/fft4g.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the ../../../LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef COMMON_AUDIO_THIRD_PARTY_OOURA_FFT_SIZE_256_FFT4G_H_
12 | #define COMMON_AUDIO_THIRD_PARTY_OOURA_FFT_SIZE_256_FFT4G_H_
13 |
14 | namespace webrtc {
15 |
16 | // Refer to fft4g.c for documentation.
17 | void WebRtc_rdft(size_t n, int isgn, float *a, size_t *ip, float *w);
18 |
19 | } // namespace webrtc
20 |
21 | #endif // COMMON_AUDIO_THIRD_PARTY_OOURA_FFT_SIZE_256_FFT4G_H_
22 |
--------------------------------------------------------------------------------
/ns/gtest_prod_util.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef RTC_BASE_GTEST_PROD_UTIL_H_
12 | #define RTC_BASE_GTEST_PROD_UTIL_H_
13 |
14 | // Define our own version of FRIEND_TEST here rather than including
15 | // gtest_prod.h to avoid depending on any part of GTest in production code.
16 | #define FRIEND_TEST_WEBRTC(test_case_name, test_name) \
17 | friend class test_case_name##_##test_name##_Test
18 |
19 | // This file is a plain copy of Chromium's base/gtest_prod_util.h.
20 | //
21 | // This is a wrapper for gtest's FRIEND_TEST macro that friends
22 | // test with all possible prefixes. This is very helpful when changing the test
23 | // prefix, because the friend declarations don't need to be updated.
24 | //
25 | // Example usage:
26 | //
27 | // class MyClass {
28 | // private:
29 | // void MyMethod();
30 | // FRIEND_TEST_ALL_PREFIXES(MyClassTest, MyMethod);
31 | // };
32 | #define FRIEND_TEST_ALL_PREFIXES(test_case_name, test_name) \
33 | FRIEND_TEST_WEBRTC(test_case_name, test_name); \
34 | FRIEND_TEST_WEBRTC(test_case_name, DISABLED_##test_name); \
35 | FRIEND_TEST_WEBRTC(test_case_name, FLAKY_##test_name); \
36 | FRIEND_TEST_WEBRTC(test_case_name, FAILS_##test_name)
37 |
38 | #endif // RTC_BASE_GTEST_PROD_UTIL_H_
39 |
--------------------------------------------------------------------------------
/ns/histograms.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #include "histograms.h"
12 |
13 | namespace webrtc {
14 |
15 | Histograms::Histograms() {
16 | Clear();
17 | }
18 |
19 | void Histograms::Clear() {
20 | lrt_.fill(0);
21 | spectral_flatness_.fill(0);
22 | spectral_diff_.fill(0);
23 | }
24 |
25 | void Histograms::Update(const SignalModel &features_) {
26 | // Update the histogram for the LRT.
27 | constexpr float kOneByBinSizeLrt = 1.f / kBinSizeLrt;
28 | if (features_.lrt < kHistogramSize * kBinSizeLrt && features_.lrt >= 0.f) {
29 | ++lrt_[kOneByBinSizeLrt * features_.lrt];
30 | }
31 |
32 | // Update histogram for the spectral flatness.
33 | constexpr float kOneByBinSizeSpecFlat = 1.f / kBinSizeSpecFlat;
34 | if (features_.spectral_flatness < kHistogramSize * kBinSizeSpecFlat &&
35 | features_.spectral_flatness >= 0.f) {
36 | ++spectral_flatness_[features_.spectral_flatness * kOneByBinSizeSpecFlat];
37 | }
38 |
39 | // Update histogram for the spectral difference.
40 | constexpr float kOneByBinSizeSpecDiff = 1.f / kBinSizeSpecDiff;
41 | if (features_.spectral_diff < kHistogramSize * kBinSizeSpecDiff &&
42 | features_.spectral_diff >= 0.f) {
43 | ++spectral_diff_[features_.spectral_diff * kOneByBinSizeSpecDiff];
44 | }
45 | }
46 |
47 | } // namespace webrtc
48 |
--------------------------------------------------------------------------------
/ns/histograms.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef MODULES_AUDIO_PROCESSING_NS_HISTOGRAMS_H_
12 | #define MODULES_AUDIO_PROCESSING_NS_HISTOGRAMS_H_
13 |
14 | #include
15 |
16 | #include "array_view.h"
17 | #include "ns_common.h"
18 | #include "signal_model.h"
19 |
20 | namespace webrtc {
21 |
22 | constexpr int kHistogramSize = 1000;
23 |
24 | // Class for handling the updating of histograms.
25 | class Histograms {
26 | public:
27 | Histograms();
28 |
29 | Histograms(const Histograms &) = delete;
30 |
31 | Histograms &operator=(const Histograms &) = delete;
32 |
33 | // Clears the histograms.
34 | void Clear();
35 |
36 | // Extracts thresholds for feature parameters and updates the corresponding
37 | // histogram.
38 | void Update(const SignalModel &features_);
39 |
40 | // Methods for accessing the histograms.
41 | rtc::ArrayView get_lrt() const { return lrt_; }
42 |
43 | rtc::ArrayView get_spectral_flatness() const {
44 | return spectral_flatness_;
45 | }
46 |
47 | rtc::ArrayView get_spectral_diff() const {
48 | return spectral_diff_;
49 | }
50 |
51 | private:
52 | std::array lrt_{};
53 | std::array spectral_flatness_{};
54 | std::array spectral_diff_{};
55 | };
56 |
57 | } // namespace webrtc
58 |
59 | #endif // MODULES_AUDIO_PROCESSING_NS_HISTOGRAMS_H_
60 |
--------------------------------------------------------------------------------
/ns/noise_estimator.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #include "noise_estimator.h"
12 |
13 | #include
14 |
15 | #include "fast_math.h"
16 | #include "checks.h"
17 |
18 | namespace webrtc {
19 |
20 | namespace {
21 |
22 | // Log(i).
23 | constexpr std::array log_table = {
24 | 0.f, 0.f, 0.f, 0.f, 0.f, 1.609438f, 1.791759f,
25 | 1.945910f, 2.079442f, 2.197225f, 2.302585f, 2.397895f, 2.484907f, 2.564949f,
26 | 2.639057f, 2.708050f, 2.772589f, 2.833213f, 2.890372f, 2.944439f, 2.995732f,
27 | 3.044522f, 3.091043f, 3.135494f, 3.178054f, 3.218876f, 3.258097f, 3.295837f,
28 | 3.332205f, 3.367296f, 3.401197f, 3.433987f, 3.465736f, 3.496507f, 3.526361f,
29 | 3.555348f, 3.583519f, 3.610918f, 3.637586f, 3.663562f, 3.688879f, 3.713572f,
30 | 3.737669f, 3.761200f, 3.784190f, 3.806663f, 3.828641f, 3.850147f, 3.871201f,
31 | 3.891820f, 3.912023f, 3.931826f, 3.951244f, 3.970292f, 3.988984f, 4.007333f,
32 | 4.025352f, 4.043051f, 4.060443f, 4.077538f, 4.094345f, 4.110874f, 4.127134f,
33 | 4.143135f, 4.158883f, 4.174387f, 4.189655f, 4.204693f, 4.219508f, 4.234107f,
34 | 4.248495f, 4.262680f, 4.276666f, 4.290460f, 4.304065f, 4.317488f, 4.330733f,
35 | 4.343805f, 4.356709f, 4.369448f, 4.382027f, 4.394449f, 4.406719f, 4.418841f,
36 | 4.430817f, 4.442651f, 4.454347f, 4.465908f, 4.477337f, 4.488636f, 4.499810f,
37 | 4.510859f, 4.521789f, 4.532599f, 4.543295f, 4.553877f, 4.564348f, 4.574711f,
38 | 4.584968f, 4.595119f, 4.605170f, 4.615121f, 4.624973f, 4.634729f, 4.644391f,
39 | 4.653960f, 4.663439f, 4.672829f, 4.682131f, 4.691348f, 4.700480f, 4.709530f,
40 | 4.718499f, 4.727388f, 4.736198f, 4.744932f, 4.753591f, 4.762174f, 4.770685f,
41 | 4.779124f, 4.787492f, 4.795791f, 4.804021f, 4.812184f, 4.820282f, 4.828314f,
42 | 4.836282f, 4.844187f, 4.852030f};
43 |
44 | } // namespace
45 |
46 | NoiseEstimator::NoiseEstimator(const SuppressionParams &suppression_params)
47 | : suppression_params_(suppression_params) {
48 | noise_spectrum_.fill(0.f);
49 | prev_noise_spectrum_.fill(0.f);
50 | conservative_noise_spectrum_.fill(0.f);
51 | parametric_noise_spectrum_.fill(0.f);
52 | }
53 |
54 | void NoiseEstimator::PrepareAnalysis() {
55 | std::copy(noise_spectrum_.begin(), noise_spectrum_.end(),
56 | prev_noise_spectrum_.begin());
57 | }
58 |
59 | void NoiseEstimator::PreUpdate(
60 | int32_t num_analyzed_frames,
61 | rtc::ArrayView signal_spectrum,
62 | float signal_spectral_sum) {
63 | quantile_noise_estimator_.Estimate(signal_spectrum, noise_spectrum_);
64 |
65 | if (num_analyzed_frames < kShortStartupPhaseBlocks) {
66 | // Compute simplified noise model during startup.
67 | const size_t kStartBand = 5;
68 | float sum_log_i_log_magn = 0.f;
69 | float sum_log_i = 0.f;
70 | float sum_log_i_square = 0.f;
71 | float sum_log_magn = 0.f;
72 | for (size_t i = kStartBand; i < kFftSizeBy2Plus1; ++i) {
73 | float log_i = log_table[i];
74 | sum_log_i += log_i;
75 | sum_log_i_square += log_i * log_i;
76 | float log_signal = LogApproximation(signal_spectrum[i]);
77 | sum_log_magn += log_signal;
78 | sum_log_i_log_magn += log_i * log_signal;
79 | }
80 |
81 | // Estimate the parameter for the level of the white noise.
82 | constexpr float kOneByFftSizeBy2Plus1 = 1.f / kFftSizeBy2Plus1;
83 | white_noise_level_ += signal_spectral_sum * kOneByFftSizeBy2Plus1 *
84 | suppression_params_.over_subtraction_factor;
85 |
86 | // Estimate pink noise parameters.
87 | float denom = sum_log_i_square * (kFftSizeBy2Plus1 - kStartBand) -
88 | sum_log_i * sum_log_i;
89 | float num =
90 | sum_log_i_square * sum_log_magn - sum_log_i * sum_log_i_log_magn;
91 | RTC_DCHECK_NE(denom, 0.f);
92 | float pink_noise_adjustment = num / denom;
93 |
94 | // Constrain the estimated spectrum to be positive.
95 | pink_noise_adjustment = std::max(pink_noise_adjustment, 0.f);
96 | pink_noise_numerator_ += pink_noise_adjustment;
97 | num = sum_log_i * sum_log_magn -
98 | (kFftSizeBy2Plus1 - kStartBand) * sum_log_i_log_magn;
99 | RTC_DCHECK_NE(denom, 0.f);
100 | pink_noise_adjustment = num / denom;
101 |
102 | // Constrain the pink noise power to be in the interval [0, 1].
103 | pink_noise_adjustment = std::max(std::min(pink_noise_adjustment, 1.f), 0.f);
104 |
105 | pink_noise_exp_ += pink_noise_adjustment;
106 |
107 | const float one_by_num_analyzed_frames_plus_1 =
108 | 1.f / (num_analyzed_frames + 1.f);
109 |
110 | // Calculate the frequency-independent parts of parametric noise estimate.
111 | float parametric_exp = 0.f;
112 | float parametric_num = 0.f;
113 | if (pink_noise_exp_ > 0.f) {
114 | // Use pink noise estimate.
115 | parametric_num = ExpApproximation(pink_noise_numerator_ *
116 | one_by_num_analyzed_frames_plus_1);
117 | parametric_num *= num_analyzed_frames + 1.f;
118 | parametric_exp = pink_noise_exp_ * one_by_num_analyzed_frames_plus_1;
119 | }
120 |
121 | constexpr float kOneByShortStartupPhaseBlocks =
122 | 1.f / kShortStartupPhaseBlocks;
123 | for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
124 | // Estimate the background noise using the white and pink noise
125 | // parameters.
126 | if (pink_noise_exp_ == 0.f) {
127 | // Use white noise estimate.
128 | parametric_noise_spectrum_[i] = white_noise_level_;
129 | } else {
130 | // Use pink noise estimate.
131 | float use_band = i < kStartBand ? kStartBand : i;
132 | float denom = PowApproximation(use_band, parametric_exp);
133 | RTC_DCHECK_NE(denom, 0.f);
134 | parametric_noise_spectrum_[i] = parametric_num / denom;
135 | }
136 | }
137 |
138 | // Weight quantile noise with modeled noise.
139 | float w = (kShortStartupPhaseBlocks - num_analyzed_frames);
140 | for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
141 | noise_spectrum_[i] *= num_analyzed_frames;
142 | float tmp = parametric_noise_spectrum_[i] * w;
143 | noise_spectrum_[i] += tmp * one_by_num_analyzed_frames_plus_1;
144 | noise_spectrum_[i] *= kOneByShortStartupPhaseBlocks;
145 | }
146 | }
147 | }
148 |
149 | void NoiseEstimator::PostUpdate(
150 | rtc::ArrayView speech_probability,
151 | rtc::ArrayView signal_spectrum) {
152 | // Time-avg parameter for noise_spectrum update.
153 | constexpr float kNoiseUpdate = 0.9f;
154 |
155 | float gamma = kNoiseUpdate;
156 | for (size_t i = 0; i < kFftSizeBy2Plus1; ++i) {
157 | const float prob_speech = speech_probability[i];
158 | const float prob_non_speech = 1.f - prob_speech;
159 |
160 | // Temporary noise update used for speech frames if update value is less
161 | // than previous.
162 | float noise_update_tmp =
163 | gamma * prev_noise_spectrum_[i] +
164 | (1.f - gamma) * (prob_non_speech * signal_spectrum[i] +
165 | prob_speech * prev_noise_spectrum_[i]);
166 |
167 | // Time-constant based on speech/noise_spectrum state.
168 | float gamma_old = gamma;
169 |
170 | // Increase gamma for frame likely to be seech.
171 | constexpr float kProbRange = .2f;
172 | gamma = prob_speech > kProbRange ? .99f : kNoiseUpdate;
173 |
174 | // Conservative noise_spectrum update.
175 | if (prob_speech < kProbRange) {
176 | conservative_noise_spectrum_[i] +=
177 | 0.05f * (signal_spectrum[i] - conservative_noise_spectrum_[i]);
178 | }
179 |
180 | // Noise_spectrum update.
181 | if (gamma == gamma_old) {
182 | noise_spectrum_[i] = noise_update_tmp;
183 | } else {
184 | noise_spectrum_[i] =
185 | gamma * prev_noise_spectrum_[i] +
186 | (1.f - gamma) * (prob_non_speech * signal_spectrum[i] +
187 | prob_speech * prev_noise_spectrum_[i]);
188 | // Allow for noise_spectrum update downwards: If noise_spectrum update
189 | // decreases the noise_spectrum, it is safe, so allow it to happen.
190 | noise_spectrum_[i] = std::min(noise_spectrum_[i], noise_update_tmp);
191 | }
192 | }
193 | }
194 |
195 | } // namespace webrtc
196 |
--------------------------------------------------------------------------------
/ns/noise_estimator.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef MODULES_AUDIO_PROCESSING_NS_NOISE_ESTIMATOR_H_
12 | #define MODULES_AUDIO_PROCESSING_NS_NOISE_ESTIMATOR_H_
13 |
14 | #include
15 |
16 | #include "array_view.h"
17 | #include "ns_common.h"
18 | #include "quantile_noise_estimator.h"
19 | #include "suppression_params.h"
20 |
21 | namespace webrtc {
22 |
23 | // Class for estimating the spectral characteristics of the noise in an incoming
24 | // signal.
25 | class NoiseEstimator {
26 | public:
27 | explicit NoiseEstimator(const SuppressionParams &suppression_params);
28 |
29 | // Prepare the estimator for analysis of a new frame.
30 | void PrepareAnalysis();
31 |
32 | // Performs the first step of the estimator update.
33 | void PreUpdate(int32_t num_analyzed_frames,
34 | rtc::ArrayView signal_spectrum,
35 | float signal_spectral_sum);
36 |
37 | // Performs the second step of the estimator update.
38 | void PostUpdate(
39 | rtc::ArrayView speech_probability,
40 | rtc::ArrayView signal_spectrum);
41 |
42 | // Returns the noise spectral estimate.
43 | rtc::ArrayView get_noise_spectrum() const {
44 | return noise_spectrum_;
45 | }
46 |
47 | // Returns the noise from the previous frame.
48 | rtc::ArrayView get_prev_noise_spectrum()
49 | const {
50 | return prev_noise_spectrum_;
51 | }
52 |
53 | // Returns a noise spectral estimate based on white and pink noise parameters.
54 | rtc::ArrayView get_parametric_noise_spectrum()
55 | const {
56 | return parametric_noise_spectrum_;
57 | }
58 |
59 | rtc::ArrayView
60 | get_conservative_noise_spectrum() const {
61 | return conservative_noise_spectrum_;
62 | }
63 |
64 | private:
65 | const SuppressionParams &suppression_params_;
66 | float white_noise_level_ = 0.f;
67 | float pink_noise_numerator_ = 0.f;
68 | float pink_noise_exp_ = 0.f;
69 | std::array prev_noise_spectrum_{};
70 | std::array conservative_noise_spectrum_{};
71 | std::array parametric_noise_spectrum_{};
72 | std::array noise_spectrum_{};
73 | QuantileNoiseEstimator quantile_noise_estimator_;
74 | };
75 |
76 | } // namespace webrtc
77 |
78 | #endif // MODULES_AUDIO_PROCESSING_NS_NOISE_ESTIMATOR_H_
79 |
--------------------------------------------------------------------------------
/ns/noise_suppressor.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSOR_H_
12 | #define MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSOR_H_
13 |
14 | #include
15 | #include
16 |
17 | #include "array_view.h"
18 | #include "audio_buffer.h"
19 | #include "noise_estimator.h"
20 | #include "ns_common.h"
21 | #include "ns_config.h"
22 | #include "ns_fft.h"
23 | #include "speech_probability_estimator.h"
24 | #include "wiener_filter.h"
25 |
26 | namespace webrtc {
27 |
28 | // Class for suppressing noise in a signal.
29 | class NoiseSuppressor {
30 | public:
31 | NoiseSuppressor(const NsConfig &config,
32 | size_t sample_rate_hz,
33 | size_t num_channels);
34 |
35 | NoiseSuppressor(const NoiseSuppressor &) = delete;
36 |
37 | NoiseSuppressor &operator=(const NoiseSuppressor &) = delete;
38 |
39 | // Analyses the signal (typically applied before the AEC to avoid analyzing
40 | // any comfort noise signal).
41 | void Analyze(const AudioBuffer &audio);
42 |
43 | // Applies noise suppression.
44 | void Process(AudioBuffer *audio);
45 |
46 | private:
47 | const size_t num_bands_;
48 | const size_t num_channels_;
49 | const SuppressionParams suppression_params_;
50 | int32_t num_analyzed_frames_ = -1;
51 | NrFft fft_;
52 |
53 | struct ChannelState {
54 | ChannelState(const SuppressionParams &suppression_params, size_t num_bands);
55 |
56 | SpeechProbabilityEstimator speech_probability_estimator;
57 | WienerFilter wiener_filter;
58 | NoiseEstimator noise_estimator;
59 | std::array prev_analysis_signal_spectrum{};
60 | std::array analyze_analysis_memory{};
61 | std::array process_analysis_memory{};
62 | std::array process_synthesis_memory{};
63 | std::vector> process_delay_memory;
64 | };
65 |
66 | struct FilterBankState {
67 | std::array real;
68 | std::array imag;
69 | std::array extended_frame;
70 | };
71 |
72 | std::vector filter_bank_states_heap_;
73 | std::vector upper_band_gains_heap_;
74 | std::vector energies_before_filtering_heap_;
75 | std::vector gain_adjustments_heap_;
76 | std::vector> channels_;
77 |
78 | // Aggregates the Wiener filters into a single filter to use.
79 | void AggregateWienerFilters(
80 | rtc::ArrayView filter) const;
81 | };
82 |
83 | } // namespace webrtc
84 |
85 | #endif // MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSOR_H_
86 |
--------------------------------------------------------------------------------
/ns/ns_common.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef MODULES_AUDIO_PROCESSING_NS_NS_COMMON_H_
12 | #define MODULES_AUDIO_PROCESSING_NS_NS_COMMON_H_
13 |
14 | #include
15 |
16 | namespace webrtc {
17 |
18 | constexpr size_t kFftSize = 256;
19 | constexpr size_t kFftSizeBy2Plus1 = kFftSize / 2 + 1;
20 | constexpr size_t kNsFrameSize = 160;
21 | constexpr size_t kOverlapSize = kFftSize - kNsFrameSize;
22 |
23 | constexpr int kShortStartupPhaseBlocks = 50;
24 | constexpr int kLongStartupPhaseBlocks = 200;
25 | constexpr int kFeatureUpdateWindowSize = 500;
26 |
27 | constexpr float kLtrFeatureThr = 0.5f;
28 | constexpr float kBinSizeLrt = 0.1f;
29 | constexpr float kBinSizeSpecFlat = 0.05f;
30 | constexpr float kBinSizeSpecDiff = 0.1f;
31 |
32 | } // namespace webrtc
33 |
34 | #endif // MODULES_AUDIO_PROCESSING_NS_NS_COMMON_H_
35 |
--------------------------------------------------------------------------------
/ns/ns_config.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef MODULES_AUDIO_PROCESSING_NS_NS_CONFIG_H_
12 | #define MODULES_AUDIO_PROCESSING_NS_NS_CONFIG_H_
13 |
14 | namespace webrtc {
15 |
16 | // Config struct for the noise suppressor
17 | struct NsConfig {
18 | enum class SuppressionLevel {
19 | k6dB, k12dB, k18dB, k21dB
20 | };
21 | SuppressionLevel target_level = SuppressionLevel::k12dB;
22 | };
23 |
24 | } // namespace webrtc
25 |
26 | #endif // MODULES_AUDIO_PROCESSING_NS_NS_CONFIG_H_
27 |
--------------------------------------------------------------------------------
/ns/ns_fft.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #include "ns_fft.h"
12 |
13 | #include "fft4g.h"
14 |
15 | namespace webrtc {
16 |
17 | NrFft::NrFft() : bit_reversal_state_(kFftSize / 2), tables_(kFftSize / 2) {
18 | // Initialize WebRtc_rdt (setting (bit_reversal_state_[0] to 0 triggers
19 | // initialization)
20 | bit_reversal_state_[0] = 0.f;
21 | std::array tmp_buffer{};
22 | tmp_buffer.fill(0.f);
23 | WebRtc_rdft(kFftSize, 1, tmp_buffer.data(), bit_reversal_state_.data(),
24 | tables_.data());
25 | }
26 |
27 | void NrFft::Fft(rtc::ArrayView time_data,
28 | rtc::ArrayView real,
29 | rtc::ArrayView imag) {
30 | WebRtc_rdft(kFftSize, 1, time_data.data(), bit_reversal_state_.data(),
31 | tables_.data());
32 |
33 | imag[0] = 0;
34 | real[0] = time_data[0];
35 |
36 | imag[kFftSizeBy2Plus1 - 1] = 0;
37 | real[kFftSizeBy2Plus1 - 1] = time_data[1];
38 |
39 | for (size_t i = 1; i < kFftSizeBy2Plus1 - 1; ++i) {
40 | real[i] = time_data[2 * i];
41 | imag[i] = time_data[2 * i + 1];
42 | }
43 | }
44 |
45 | void NrFft::Ifft(rtc::ArrayView real,
46 | rtc::ArrayView imag,
47 | rtc::ArrayView time_data) {
48 | time_data[0] = real[0];
49 | time_data[1] = real[kFftSizeBy2Plus1 - 1];
50 | for (size_t i = 1; i < kFftSizeBy2Plus1 - 1; ++i) {
51 | time_data[2 * i] = real[i];
52 | time_data[2 * i + 1] = imag[i];
53 | }
54 | WebRtc_rdft(kFftSize, -1, time_data.data(), bit_reversal_state_.data(),
55 | tables_.data());
56 |
57 | // Scale the output
58 | constexpr float kScaling = 2.f / kFftSize;
59 | for (float &d : time_data) {
60 | d *= kScaling;
61 | }
62 | }
63 |
64 | } // namespace webrtc
65 |
--------------------------------------------------------------------------------
/ns/ns_fft.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef MODULES_AUDIO_PROCESSING_NS_NS_FFT_H_
12 | #define MODULES_AUDIO_PROCESSING_NS_NS_FFT_H_
13 |
14 | #include
15 |
16 | #include "array_view.h"
17 | #include "ns_common.h"
18 |
19 | namespace webrtc {
20 |
21 | // Wrapper class providing 256 point FFT functionality.
22 | class NrFft {
23 | public:
24 | NrFft();
25 |
26 | NrFft(const NrFft &) = delete;
27 |
28 | NrFft &operator=(const NrFft &) = delete;
29 |
30 | // Transforms the signal from time to frequency domain.
31 | void Fft(rtc::ArrayView time_data,
32 | rtc::ArrayView real,
33 | rtc::ArrayView imag);
34 |
35 | // Transforms the signal from frequency to time domain.
36 | void Ifft(rtc::ArrayView real,
37 | rtc::ArrayView imag,
38 | rtc::ArrayView time_data);
39 |
40 | private:
41 | std::vector bit_reversal_state_;
42 | std::vector tables_;
43 | };
44 |
45 | } // namespace webrtc
46 |
47 | #endif // MODULES_AUDIO_PROCESSING_NS_NS_FFT_H_
48 |
--------------------------------------------------------------------------------
/ns/prior_signal_model.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #include "prior_signal_model.h"
12 |
13 | namespace webrtc {
14 |
15 | PriorSignalModel::PriorSignalModel(float lrt_initial_value)
16 | : lrt(lrt_initial_value) {}
17 |
18 | } // namespace webrtc
19 |
--------------------------------------------------------------------------------
/ns/prior_signal_model.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef MODULES_AUDIO_PROCESSING_NS_PRIOR_SIGNAL_MODEL_H_
12 | #define MODULES_AUDIO_PROCESSING_NS_PRIOR_SIGNAL_MODEL_H_
13 |
14 | namespace webrtc {
15 |
16 | // Struct for storing the prior signal model parameters.
17 | struct PriorSignalModel {
18 | explicit PriorSignalModel(float lrt_initial_value);
19 |
20 | PriorSignalModel(const PriorSignalModel &) = delete;
21 |
22 | PriorSignalModel &operator=(const PriorSignalModel &) = delete;
23 |
24 | float lrt;
25 | float flatness_threshold = .5f;
26 | float template_diff_threshold = .5f;
27 | float lrt_weighting = 1.f;
28 | float flatness_weighting = 0.f;
29 | float difference_weighting = 0.f;
30 | };
31 |
32 | } // namespace webrtc
33 |
34 | #endif // MODULES_AUDIO_PROCESSING_NS_PRIOR_SIGNAL_MODEL_H_
35 |
--------------------------------------------------------------------------------
/ns/prior_signal_model_estimator.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #include "prior_signal_model_estimator.h"
12 |
13 | #include
14 | #include
15 |
16 | #include "fast_math.h"
17 | #include "checks.h"
18 |
19 | namespace webrtc {
20 |
21 | namespace {
22 |
23 | // Identifies the first of the two largest peaks in the histogram.
24 | void FindFirstOfTwoLargestPeaks(
25 | float bin_size,
26 | rtc::ArrayView spectral_flatness,
27 | float *peak_position,
28 | int *peak_weight) {
29 | RTC_DCHECK(peak_position);
30 | RTC_DCHECK(peak_weight);
31 |
32 | int peak_value = 0;
33 | int secondary_peak_value = 0;
34 | *peak_position = 0.f;
35 | float secondary_peak_position = 0.f;
36 | *peak_weight = 0;
37 | int secondary_peak_weight = 0;
38 |
39 | // Identify the two largest peaks.
40 | for (int i = 0; i < kHistogramSize; ++i) {
41 | const float bin_mid = (i + 0.5f) * bin_size;
42 | if (spectral_flatness[i] > peak_value) {
43 | // Found new "first" peak candidate.
44 | secondary_peak_value = peak_value;
45 | secondary_peak_weight = *peak_weight;
46 | secondary_peak_position = *peak_position;
47 |
48 | peak_value = spectral_flatness[i];
49 | *peak_weight = spectral_flatness[i];
50 | *peak_position = bin_mid;
51 | } else if (spectral_flatness[i] > secondary_peak_value) {
52 | // Found new "second" peak candidate.
53 | secondary_peak_value = spectral_flatness[i];
54 | secondary_peak_weight = spectral_flatness[i];
55 | secondary_peak_position = bin_mid;
56 | }
57 | }
58 |
59 | // Merge the peaks if they are close.
60 | if ((fabs(secondary_peak_position - *peak_position) < 2 * bin_size) &&
61 | (secondary_peak_weight > 0.5f * (*peak_weight))) {
62 | *peak_weight += secondary_peak_weight;
63 | *peak_position = 0.5f * (*peak_position + secondary_peak_position);
64 | }
65 | }
66 |
67 | void UpdateLrt(rtc::ArrayView lrt_histogram,
68 | float *prior_model_lrt,
69 | bool *low_lrt_fluctuations) {
70 | RTC_DCHECK(prior_model_lrt);
71 | RTC_DCHECK(low_lrt_fluctuations);
72 |
73 | float average = 0.f;
74 | float average_compl = 0.f;
75 | float average_squared = 0.f;
76 | int count = 0;
77 |
78 | for (int i = 0; i < 10; ++i) {
79 | float bin_mid = (i + 0.5f) * kBinSizeLrt;
80 | average += lrt_histogram[i] * bin_mid;
81 | count += lrt_histogram[i];
82 | }
83 | if (count > 0) {
84 | average = average / count;
85 | }
86 |
87 | for (int i = 0; i < kHistogramSize; ++i) {
88 | float bin_mid = (i + 0.5f) * kBinSizeLrt;
89 | average_squared += lrt_histogram[i] * bin_mid * bin_mid;
90 | average_compl += lrt_histogram[i] * bin_mid;
91 | }
92 | constexpr float kOneFeatureUpdateWindowSize = 1.f / kFeatureUpdateWindowSize;
93 | average_squared = average_squared * kOneFeatureUpdateWindowSize;
94 | average_compl = average_compl * kOneFeatureUpdateWindowSize;
95 |
96 | // Fluctuation limit of LRT feature.
97 | *low_lrt_fluctuations = average_squared - average * average_compl < 0.05f;
98 |
99 | // Get threshold for LRT feature.
100 | constexpr float kMaxLrt = 1.f;
101 | constexpr float kMinLrt = .2f;
102 | if (*low_lrt_fluctuations) {
103 | // Very low fluctuation, so likely noise.
104 | *prior_model_lrt = kMaxLrt;
105 | } else {
106 | *prior_model_lrt = std::min(kMaxLrt, std::max(kMinLrt, 1.2f * average));
107 | }
108 | }
109 |
110 | } // namespace
111 |
112 | PriorSignalModelEstimator::PriorSignalModelEstimator(float lrt_initial_value)
113 | : prior_model_(lrt_initial_value) {}
114 |
115 | // Extract thresholds for feature parameters and computes the threshold/weights.
116 | void PriorSignalModelEstimator::Update(const Histograms &histograms) {
117 | bool low_lrt_fluctuations;
118 | UpdateLrt(histograms.get_lrt(), &prior_model_.lrt, &low_lrt_fluctuations);
119 |
120 | // For spectral flatness and spectral difference: compute the main peaks of
121 | // the histograms.
122 | float spectral_flatness_peak_position;
123 | int spectral_flatness_peak_weight;
124 | FindFirstOfTwoLargestPeaks(
125 | kBinSizeSpecFlat, histograms.get_spectral_flatness(),
126 | &spectral_flatness_peak_position, &spectral_flatness_peak_weight);
127 |
128 | float spectral_diff_peak_position = 0.f;
129 | int spectral_diff_peak_weight = 0;
130 | FindFirstOfTwoLargestPeaks(kBinSizeSpecDiff, histograms.get_spectral_diff(),
131 | &spectral_diff_peak_position,
132 | &spectral_diff_peak_weight);
133 |
134 | // Reject if weight of peaks is not large enough, or peak value too small.
135 | // Peak limit for spectral flatness (varies between 0 and 1).
136 | const int use_spec_flat = spectral_flatness_peak_weight < 0.3f * 500 ||
137 | spectral_flatness_peak_position < 0.6f
138 | ? 0
139 | : 1;
140 |
141 | // Reject if weight of peaks is not large enough or if fluctuation of the LRT
142 | // feature are very low, indicating a noise state.
143 | const int use_spec_diff =
144 | spectral_diff_peak_weight < 0.3f * 500 || low_lrt_fluctuations ? 0 : 1;
145 |
146 | // Update the model.
147 | prior_model_.template_diff_threshold = 1.2f * spectral_diff_peak_position;
148 | prior_model_.template_diff_threshold =
149 | std::min(1.f, std::max(0.16f, prior_model_.template_diff_threshold));
150 |
151 | float one_by_feature_sum = 1.f / (1.f + use_spec_flat + use_spec_diff);
152 | prior_model_.lrt_weighting = one_by_feature_sum;
153 |
154 | if (use_spec_flat == 1) {
155 | prior_model_.flatness_threshold = 0.9f * spectral_flatness_peak_position;
156 | prior_model_.flatness_threshold =
157 | std::min(.95f, std::max(0.1f, prior_model_.flatness_threshold));
158 | prior_model_.flatness_weighting = one_by_feature_sum;
159 | } else {
160 | prior_model_.flatness_weighting = 0.f;
161 | }
162 |
163 | if (use_spec_diff == 1) {
164 | prior_model_.difference_weighting = one_by_feature_sum;
165 | } else {
166 | prior_model_.difference_weighting = 0.f;
167 | }
168 | }
169 |
170 | } // namespace webrtc
171 |
--------------------------------------------------------------------------------
/ns/prior_signal_model_estimator.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef MODULES_AUDIO_PROCESSING_NS_PRIOR_SIGNAL_MODEL_ESTIMATOR_H_
12 | #define MODULES_AUDIO_PROCESSING_NS_PRIOR_SIGNAL_MODEL_ESTIMATOR_H_
13 |
14 | #include "histograms.h"
15 | #include "prior_signal_model.h"
16 |
17 | namespace webrtc {
18 |
19 | // Estimator of the prior signal model parameters.
20 | class PriorSignalModelEstimator {
21 | public:
22 | explicit PriorSignalModelEstimator(float lrt_initial_value);
23 |
24 | PriorSignalModelEstimator(const PriorSignalModelEstimator &) = delete;
25 |
26 | PriorSignalModelEstimator &operator=(const PriorSignalModelEstimator &) =
27 | delete;
28 |
29 | // Updates the model estimate.
30 | void Update(const Histograms &h);
31 |
32 | // Returns the estimated model.
33 | const PriorSignalModel &get_prior_model() const { return prior_model_; }
34 |
35 | private:
36 | PriorSignalModel prior_model_;
37 | };
38 |
39 | } // namespace webrtc
40 |
41 | #endif // MODULES_AUDIO_PROCESSING_NS_PRIOR_SIGNAL_MODEL_ESTIMATOR_H_
42 |
--------------------------------------------------------------------------------
/ns/push_sinc_resampler.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #include "push_sinc_resampler.h"
12 |
13 | #include
14 |
15 | #include "audio_util.h"
16 |
17 | namespace webrtc {
18 |
19 | PushSincResampler::PushSincResampler(size_t source_frames,
20 | size_t destination_frames)
21 | : resampler_(new SincResampler(source_frames * 1.0 / destination_frames,
22 | source_frames,
23 | this)),
24 | source_ptr_(nullptr),
25 | source_ptr_int_(nullptr),
26 | destination_frames_(destination_frames),
27 | first_pass_(true),
28 | source_available_(0) {}
29 |
30 | PushSincResampler::~PushSincResampler() = default;
31 |
32 | size_t PushSincResampler::Resample(const int16_t *source,
33 | size_t source_length,
34 | int16_t *destination,
35 | size_t destination_capacity) {
36 | if (!float_buffer_)
37 | float_buffer_.reset(new float[destination_frames_]);
38 |
39 | source_ptr_int_ = source;
40 | // Pass nullptr as the float source to have Run() read from the int16 source.
41 | Resample(nullptr, source_length, float_buffer_.get(), destination_frames_);
42 | FloatS16ToS16(float_buffer_.get(), destination_frames_, destination);
43 | source_ptr_int_ = nullptr;
44 | return destination_frames_;
45 | }
46 |
47 | size_t PushSincResampler::Resample(const float *source,
48 | size_t source_length,
49 | float *destination,
50 | size_t destination_capacity) {
51 | RTC_CHECK_EQ(source_length, resampler_->request_frames());
52 | RTC_CHECK_GE(destination_capacity, destination_frames_);
53 | // Cache the source pointer. Calling Resample() will immediately trigger
54 | // the Run() callback whereupon we provide the cached value.
55 | source_ptr_ = source;
56 | source_available_ = source_length;
57 |
58 | // On the first pass, we call Resample() twice. During the first call, we
59 | // provide dummy input and discard the output. This is done to prime the
60 | // SincResampler buffer with the correct delay (half the kernel size), thereby
61 | // ensuring that all later Resample() calls will only result in one input
62 | // request through Run().
63 | //
64 | // If this wasn't done, SincResampler would call Run() twice on the first
65 | // pass, and we'd have to introduce an entire |source_frames| of delay, rather
66 | // than the minimum half kernel.
67 | //
68 | // It works out that ChunkSize() is exactly the amount of output we need to
69 | // request in order to prime the buffer with a single Run() request for
70 | // |source_frames|.
71 | if (first_pass_)
72 | resampler_->Resample(resampler_->ChunkSize(), destination);
73 |
74 | resampler_->Resample(destination_frames_, destination);
75 | source_ptr_ = nullptr;
76 | return destination_frames_;
77 | }
78 |
79 | void PushSincResampler::Run(size_t frames, float *destination) {
80 | // Ensure we are only asked for the available samples. This would fail if
81 | // Run() was triggered more than once per Resample() call.
82 | RTC_CHECK_EQ(source_available_, frames);
83 |
84 | if (first_pass_) {
85 | // Provide dummy input on the first pass, the output of which will be
86 | // discarded, as described in Resample().
87 | std::memset(destination, 0, frames * sizeof(*destination));
88 | first_pass_ = false;
89 | return;
90 | }
91 |
92 | if (source_ptr_) {
93 | std::memcpy(destination, source_ptr_, frames * sizeof(*destination));
94 | } else {
95 | for (size_t i = 0; i < frames; ++i)
96 | destination[i] = static_cast(source_ptr_int_[i]);
97 | }
98 | source_available_ -= frames;
99 | }
100 |
101 | } // namespace webrtc
102 |
--------------------------------------------------------------------------------
/ns/push_sinc_resampler.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef COMMON_AUDIO_RESAMPLER_PUSH_SINC_RESAMPLER_H_
12 | #define COMMON_AUDIO_RESAMPLER_PUSH_SINC_RESAMPLER_H_
13 |
14 | #include
15 | #include
16 |
17 | #include
18 |
19 | #include "sinc_resampler.h"
20 | #include "constructor_magic.h"
21 |
22 | namespace webrtc {
23 |
24 | // A thin wrapper over SincResampler to provide a push-based interface as
25 | // required by WebRTC. SincResampler uses a pull-based interface, and will
26 | // use SincResamplerCallback::Run() to request data upon a call to Resample().
27 | // These Run() calls will happen on the same thread Resample() is called on.
28 | class PushSincResampler : public SincResamplerCallback {
29 | public:
30 | // Provide the size of the source and destination blocks in samples. These
31 | // must correspond to the same time duration (typically 10 ms) as the sample
32 | // ratio is inferred from them.
33 | PushSincResampler(size_t source_frames, size_t destination_frames);
34 |
35 | ~PushSincResampler() override;
36 |
37 | // Perform the resampling. |source_frames| must always equal the
38 | // |source_frames| provided at construction. |destination_capacity| must be
39 | // at least as large as |destination_frames|. Returns the number of samples
40 | // provided in destination (for convenience, since this will always be equal
41 | // to |destination_frames|).
42 | size_t Resample(const int16_t *source,
43 | size_t source_frames,
44 | int16_t *destination,
45 | size_t destination_capacity);
46 |
47 | size_t Resample(const float *source,
48 | size_t source_frames,
49 | float *destination,
50 | size_t destination_capacity);
51 |
52 | // Delay due to the filter kernel. Essentially, the time after which an input
53 | // sample will appear in the resampled output.
54 | static float AlgorithmicDelaySeconds(int source_rate_hz) {
55 | return 1.f / source_rate_hz * SincResampler::kKernelSize / 2;
56 | }
57 |
58 | protected:
59 | // Implements SincResamplerCallback.
60 | void Run(size_t frames, float *destination) override;
61 |
62 | private:
63 | friend class PushSincResamplerTest;
64 |
65 | SincResampler *get_resampler_for_testing() { return resampler_.get(); }
66 |
67 | std::unique_ptr resampler_;
68 | std::unique_ptr float_buffer_;
69 | const float *source_ptr_;
70 | const int16_t *source_ptr_int_;
71 | const size_t destination_frames_;
72 |
73 | // True on the first call to Resample(), to prime the SincResampler buffer.
74 | bool first_pass_;
75 |
76 | // Used to assert we are only requested for as much data as is available.
77 | size_t source_available_;
78 |
79 | RTC_DISALLOW_COPY_AND_ASSIGN(PushSincResampler);
80 | };
81 |
82 | } // namespace webrtc
83 |
84 | #endif // COMMON_AUDIO_RESAMPLER_PUSH_SINC_RESAMPLER_H_
85 |
--------------------------------------------------------------------------------
/ns/quantile_noise_estimator.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #include "quantile_noise_estimator.h"
12 |
13 | #include
14 |
15 | #include "fast_math.h"
16 |
17 | namespace webrtc {
18 |
19 | QuantileNoiseEstimator::QuantileNoiseEstimator() {
20 | quantile_.fill(0.f);
21 | density_.fill(0.3f);
22 | log_quantile_.fill(8.f);
23 |
24 | constexpr float kOneBySimult = 1.f / kSimult;
25 | for (size_t i = 0; i < kSimult; ++i) {
26 | counter_[i] = floor(kLongStartupPhaseBlocks * (i + 1.f) * kOneBySimult);
27 | }
28 | }
29 |
30 | void QuantileNoiseEstimator::Estimate(
31 | rtc::ArrayView signal_spectrum,
32 | rtc::ArrayView noise_spectrum) {
33 | std::array log_spectrum{};
34 | LogApproximation(signal_spectrum, log_spectrum);
35 |
36 | int quantile_index_to_return = -1;
37 | // Loop over simultaneous estimates.
38 | for (int s = 0, k = 0; s < kSimult;
39 | ++s, k += static_cast(kFftSizeBy2Plus1)) {
40 | const float one_by_counter_plus_1 = 1.f / (counter_[s] + 1.f);
41 | for (int i = 0, j = k; i < static_cast(kFftSizeBy2Plus1); ++i, ++j) {
42 | // Update log quantile estimate.
43 | const float delta = density_[j] > 1.f ? 40.f / density_[j] : 40.f;
44 |
45 | const float multiplier = delta * one_by_counter_plus_1;
46 | if (log_spectrum[i] > log_quantile_[j]) {
47 | log_quantile_[j] += 0.25f * multiplier;
48 | } else {
49 | log_quantile_[j] -= 0.75f * multiplier;
50 | }
51 |
52 | // Update density estimate.
53 | constexpr float kWidth = 0.01f;
54 | constexpr float kOneByWidthPlus2 = 1.f / (2.f * kWidth);
55 | if (fabs(log_spectrum[i] - log_quantile_[j]) < kWidth) {
56 | density_[j] = (counter_[s] * density_[j] + kOneByWidthPlus2) *
57 | one_by_counter_plus_1;
58 | }
59 | }
60 |
61 | if (counter_[s] >= kLongStartupPhaseBlocks) {
62 | counter_[s] = 0;
63 | if (num_updates_ >= kLongStartupPhaseBlocks) {
64 | quantile_index_to_return = k;
65 | }
66 | }
67 |
68 | ++counter_[s];
69 | }
70 |
71 | // Sequentially update the noise during startup.
72 | if (num_updates_ < kLongStartupPhaseBlocks) {
73 | // Use the last "s" to get noise during startup that differ from zero.
74 | quantile_index_to_return = kFftSizeBy2Plus1 * (kSimult - 1);
75 | ++num_updates_;
76 | }
77 |
78 | if (quantile_index_to_return >= 0) {
79 | ExpApproximation(
80 | rtc::ArrayView(&log_quantile_[quantile_index_to_return],
81 | kFftSizeBy2Plus1),
82 | quantile_);
83 | }
84 |
85 | std::copy(quantile_.begin(), quantile_.end(), noise_spectrum.begin());
86 | }
87 |
88 | } // namespace webrtc
89 |
--------------------------------------------------------------------------------
/ns/quantile_noise_estimator.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | #ifndef MODULES_AUDIO_PROCESSING_NS_QUANTILE_NOISE_ESTIMATOR_H_
12 | #define MODULES_AUDIO_PROCESSING_NS_QUANTILE_NOISE_ESTIMATOR_H_
13 |
14 | #include
15 | #include
16 |
17 | #include "array_view.h"
18 | #include "ns_common.h"
19 |
20 | namespace webrtc {
21 |
22 | constexpr int kSimult = 3;
23 |
24 | // For quantile noise estimation.
25 | class QuantileNoiseEstimator {
26 | public:
27 | QuantileNoiseEstimator();
28 |
29 | QuantileNoiseEstimator(const QuantileNoiseEstimator &) = delete;
30 |
31 | QuantileNoiseEstimator &operator=(const QuantileNoiseEstimator &) = delete;
32 |
33 | // Estimate noise.
34 | void Estimate(rtc::ArrayView signal_spectrum,
35 | rtc::ArrayView noise_spectrum);
36 |
37 | private:
38 | std::array density_{};
39 | std::array log_quantile_{};
40 | std::array