webrtcvad 0.1.0 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/webrtcvad/extconf.rb +29 -0
- data/ext/webrtcvad/webrtc/common_audio/signal_processing/division_operations.c +141 -0
- data/ext/webrtcvad/webrtc/common_audio/signal_processing/dot_product_with_scale.h +40 -0
- data/ext/webrtcvad/webrtc/common_audio/signal_processing/energy.c +39 -0
- data/ext/webrtcvad/webrtc/common_audio/signal_processing/get_scaling_square.c +46 -0
- data/ext/webrtcvad/webrtc/common_audio/signal_processing/include/signal_processing_library.h +1605 -0
- data/ext/webrtcvad/webrtc/common_audio/signal_processing/include/spl_inl.h +153 -0
- data/ext/webrtcvad/webrtc/common_audio/signal_processing/resample_48khz.c +186 -0
- data/ext/webrtcvad/webrtc/common_audio/signal_processing/resample_by_2_internal.c +689 -0
- data/ext/webrtcvad/webrtc/common_audio/signal_processing/resample_by_2_internal.h +60 -0
- data/ext/webrtcvad/webrtc/common_audio/signal_processing/resample_fractional.c +239 -0
- data/ext/webrtcvad/webrtc/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.c +77 -0
- data/ext/webrtcvad/webrtc/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.h +29 -0
- data/ext/webrtcvad/webrtc/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor_mips.c +207 -0
- data/ext/webrtcvad/webrtc/common_audio/vad/include/webrtc_vad.h +87 -0
- data/ext/webrtcvad/webrtc/common_audio/vad/vad_core.c +685 -0
- data/ext/webrtcvad/webrtc/common_audio/vad/vad_core.h +114 -0
- data/ext/webrtcvad/webrtc/common_audio/vad/vad_filterbank.c +329 -0
- data/ext/webrtcvad/webrtc/common_audio/vad/vad_filterbank.h +45 -0
- data/ext/webrtcvad/webrtc/common_audio/vad/vad_gmm.c +82 -0
- data/ext/webrtcvad/webrtc/common_audio/vad/vad_gmm.h +39 -0
- data/ext/webrtcvad/webrtc/common_audio/vad/vad_sp.c +176 -0
- data/ext/webrtcvad/webrtc/common_audio/vad/vad_sp.h +54 -0
- data/ext/webrtcvad/webrtc/common_audio/vad/webrtc_vad.c +114 -0
- data/ext/webrtcvad/webrtc/rtc_base/checks.cc +207 -0
- data/ext/webrtcvad/webrtc/rtc_base/checks.h +400 -0
- data/ext/webrtcvad/webrtc/rtc_base/compile_assert_c.h +25 -0
- data/ext/webrtcvad/webrtc/rtc_base/numerics/safe_compare.h +176 -0
- data/ext/webrtcvad/webrtc/rtc_base/sanitizer.h +144 -0
- data/ext/webrtcvad/webrtc/rtc_base/system/inline.h +31 -0
- data/ext/webrtcvad/webrtc/rtc_base/system/rtc_export.h +43 -0
- data/ext/webrtcvad/webrtc/rtc_base/type_traits.h +140 -0
- data/ext/webrtcvad/webrtcvad.c +112 -0
- metadata +37 -3
@@ -0,0 +1,153 @@
|
|
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
|
+
// This header file includes the inline functions in
|
12
|
+
// the fix point signal processing library.
|
13
|
+
|
14
|
+
#ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_H_
|
15
|
+
#define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_H_
|
16
|
+
|
17
|
+
#include "rtc_base/compile_assert_c.h"
|
18
|
+
|
19
|
+
extern const int8_t kWebRtcSpl_CountLeadingZeros32_Table[64];
|
20
|
+
|
21
|
+
// Don't call this directly except in tests!
|
22
|
+
static __inline int WebRtcSpl_CountLeadingZeros32_NotBuiltin(uint32_t n) {
|
23
|
+
// Normalize n by rounding up to the nearest number that is a sequence of 0
|
24
|
+
// bits followed by a sequence of 1 bits. This number has the same number of
|
25
|
+
// leading zeros as the original n. There are exactly 33 such values.
|
26
|
+
n |= n >> 1;
|
27
|
+
n |= n >> 2;
|
28
|
+
n |= n >> 4;
|
29
|
+
n |= n >> 8;
|
30
|
+
n |= n >> 16;
|
31
|
+
|
32
|
+
// Multiply the modified n with a constant selected (by exhaustive search)
|
33
|
+
// such that each of the 33 possible values of n give a product whose 6 most
|
34
|
+
// significant bits are unique. Then look up the answer in the table.
|
35
|
+
return kWebRtcSpl_CountLeadingZeros32_Table[(n * 0x8c0b2891) >> 26];
|
36
|
+
}
|
37
|
+
|
38
|
+
// Don't call this directly except in tests!
|
39
|
+
static __inline int WebRtcSpl_CountLeadingZeros64_NotBuiltin(uint64_t n) {
|
40
|
+
const int leading_zeros = n >> 32 == 0 ? 32 : 0;
|
41
|
+
return leading_zeros + WebRtcSpl_CountLeadingZeros32_NotBuiltin(
|
42
|
+
(uint32_t)(n >> (32 - leading_zeros)));
|
43
|
+
}
|
44
|
+
|
45
|
+
// Returns the number of leading zero bits in the argument.
|
46
|
+
static __inline int WebRtcSpl_CountLeadingZeros32(uint32_t n) {
|
47
|
+
#ifdef __GNUC__
|
48
|
+
RTC_COMPILE_ASSERT(sizeof(unsigned int) == sizeof(uint32_t));
|
49
|
+
return n == 0 ? 32 : __builtin_clz(n);
|
50
|
+
#else
|
51
|
+
return WebRtcSpl_CountLeadingZeros32_NotBuiltin(n);
|
52
|
+
#endif
|
53
|
+
}
|
54
|
+
|
55
|
+
// Returns the number of leading zero bits in the argument.
|
56
|
+
static __inline int WebRtcSpl_CountLeadingZeros64(uint64_t n) {
|
57
|
+
#ifdef __GNUC__
|
58
|
+
RTC_COMPILE_ASSERT(sizeof(unsigned long long) == sizeof(uint64_t)); // NOLINT
|
59
|
+
return n == 0 ? 64 : __builtin_clzll(n);
|
60
|
+
#else
|
61
|
+
return WebRtcSpl_CountLeadingZeros64_NotBuiltin(n);
|
62
|
+
#endif
|
63
|
+
}
|
64
|
+
|
65
|
+
#ifdef WEBRTC_ARCH_ARM_V7
|
66
|
+
#include "common_audio/signal_processing/include/spl_inl_armv7.h"
|
67
|
+
#else
|
68
|
+
|
69
|
+
#if defined(MIPS32_LE)
|
70
|
+
#include "common_audio/signal_processing/include/spl_inl_mips.h"
|
71
|
+
#endif
|
72
|
+
|
73
|
+
#if !defined(MIPS_DSP_R1_LE)
|
74
|
+
static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) {
|
75
|
+
int16_t out16 = (int16_t)value32;
|
76
|
+
|
77
|
+
if (value32 > 32767)
|
78
|
+
out16 = 32767;
|
79
|
+
else if (value32 < -32768)
|
80
|
+
out16 = -32768;
|
81
|
+
|
82
|
+
return out16;
|
83
|
+
}
|
84
|
+
|
85
|
+
static __inline int32_t WebRtcSpl_AddSatW32(int32_t a, int32_t b) {
|
86
|
+
// Do the addition in unsigned numbers, since signed overflow is undefined
|
87
|
+
// behavior.
|
88
|
+
const int32_t sum = (int32_t)((uint32_t)a + (uint32_t)b);
|
89
|
+
|
90
|
+
// a + b can't overflow if a and b have different signs. If they have the
|
91
|
+
// same sign, a + b also has the same sign iff it didn't overflow.
|
92
|
+
if ((a < 0) == (b < 0) && (a < 0) != (sum < 0)) {
|
93
|
+
// The direction of the overflow is obvious from the sign of a + b.
|
94
|
+
return sum < 0 ? INT32_MAX : INT32_MIN;
|
95
|
+
}
|
96
|
+
return sum;
|
97
|
+
}
|
98
|
+
|
99
|
+
static __inline int32_t WebRtcSpl_SubSatW32(int32_t a, int32_t b) {
|
100
|
+
// Do the subtraction in unsigned numbers, since signed overflow is undefined
|
101
|
+
// behavior.
|
102
|
+
const int32_t diff = (int32_t)((uint32_t)a - (uint32_t)b);
|
103
|
+
|
104
|
+
// a - b can't overflow if a and b have the same sign. If they have different
|
105
|
+
// signs, a - b has the same sign as a iff it didn't overflow.
|
106
|
+
if ((a < 0) != (b < 0) && (a < 0) != (diff < 0)) {
|
107
|
+
// The direction of the overflow is obvious from the sign of a - b.
|
108
|
+
return diff < 0 ? INT32_MAX : INT32_MIN;
|
109
|
+
}
|
110
|
+
return diff;
|
111
|
+
}
|
112
|
+
|
113
|
+
static __inline int16_t WebRtcSpl_AddSatW16(int16_t a, int16_t b) {
|
114
|
+
return WebRtcSpl_SatW32ToW16((int32_t)a + (int32_t)b);
|
115
|
+
}
|
116
|
+
|
117
|
+
static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) {
|
118
|
+
return WebRtcSpl_SatW32ToW16((int32_t)var1 - (int32_t)var2);
|
119
|
+
}
|
120
|
+
#endif // #if !defined(MIPS_DSP_R1_LE)
|
121
|
+
|
122
|
+
#if !defined(MIPS32_LE)
|
123
|
+
static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) {
|
124
|
+
return 32 - WebRtcSpl_CountLeadingZeros32(n);
|
125
|
+
}
|
126
|
+
|
127
|
+
// Return the number of steps a can be left-shifted without overflow,
|
128
|
+
// or 0 if a == 0.
|
129
|
+
static __inline int16_t WebRtcSpl_NormW32(int32_t a) {
|
130
|
+
return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a < 0 ? ~a : a) - 1;
|
131
|
+
}
|
132
|
+
|
133
|
+
// Return the number of steps a can be left-shifted without overflow,
|
134
|
+
// or 0 if a == 0.
|
135
|
+
static __inline int16_t WebRtcSpl_NormU32(uint32_t a) {
|
136
|
+
return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a);
|
137
|
+
}
|
138
|
+
|
139
|
+
// Return the number of steps a can be left-shifted without overflow,
|
140
|
+
// or 0 if a == 0.
|
141
|
+
static __inline int16_t WebRtcSpl_NormW16(int16_t a) {
|
142
|
+
const int32_t a32 = a;
|
143
|
+
return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a < 0 ? ~a32 : a32) - 17;
|
144
|
+
}
|
145
|
+
|
146
|
+
static __inline int32_t WebRtc_MulAccumW16(int16_t a, int16_t b, int32_t c) {
|
147
|
+
return (a * b + c);
|
148
|
+
}
|
149
|
+
#endif // #if !defined(MIPS32_LE)
|
150
|
+
|
151
|
+
#endif // WEBRTC_ARCH_ARM_V7
|
152
|
+
|
153
|
+
#endif // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_H_
|
@@ -0,0 +1,186 @@
|
|
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
|
+
|
12
|
+
/*
|
13
|
+
* This file contains resampling functions between 48 kHz and nb/wb.
|
14
|
+
* The description header can be found in signal_processing_library.h
|
15
|
+
*
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include <string.h>
|
19
|
+
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
20
|
+
#include "common_audio/signal_processing/resample_by_2_internal.h"
|
21
|
+
|
22
|
+
////////////////////////////
|
23
|
+
///// 48 kHz -> 16 kHz /////
|
24
|
+
////////////////////////////
|
25
|
+
|
26
|
+
// 48 -> 16 resampler
|
27
|
+
void WebRtcSpl_Resample48khzTo16khz(const int16_t* in, int16_t* out,
|
28
|
+
WebRtcSpl_State48khzTo16khz* state, int32_t* tmpmem)
|
29
|
+
{
|
30
|
+
///// 48 --> 48(LP) /////
|
31
|
+
// int16_t in[480]
|
32
|
+
// int32_t out[480]
|
33
|
+
/////
|
34
|
+
WebRtcSpl_LPBy2ShortToInt(in, 480, tmpmem + 16, state->S_48_48);
|
35
|
+
|
36
|
+
///// 48 --> 32 /////
|
37
|
+
// int32_t in[480]
|
38
|
+
// int32_t out[320]
|
39
|
+
/////
|
40
|
+
// copy state to and from input array
|
41
|
+
memcpy(tmpmem + 8, state->S_48_32, 8 * sizeof(int32_t));
|
42
|
+
memcpy(state->S_48_32, tmpmem + 488, 8 * sizeof(int32_t));
|
43
|
+
WebRtcSpl_Resample48khzTo32khz(tmpmem + 8, tmpmem, 160);
|
44
|
+
|
45
|
+
///// 32 --> 16 /////
|
46
|
+
// int32_t in[320]
|
47
|
+
// int16_t out[160]
|
48
|
+
/////
|
49
|
+
WebRtcSpl_DownBy2IntToShort(tmpmem, 320, out, state->S_32_16);
|
50
|
+
}
|
51
|
+
|
52
|
+
// initialize state of 48 -> 16 resampler
|
53
|
+
void WebRtcSpl_ResetResample48khzTo16khz(WebRtcSpl_State48khzTo16khz* state)
|
54
|
+
{
|
55
|
+
memset(state->S_48_48, 0, 16 * sizeof(int32_t));
|
56
|
+
memset(state->S_48_32, 0, 8 * sizeof(int32_t));
|
57
|
+
memset(state->S_32_16, 0, 8 * sizeof(int32_t));
|
58
|
+
}
|
59
|
+
|
60
|
+
////////////////////////////
|
61
|
+
///// 16 kHz -> 48 kHz /////
|
62
|
+
////////////////////////////
|
63
|
+
|
64
|
+
// 16 -> 48 resampler
|
65
|
+
void WebRtcSpl_Resample16khzTo48khz(const int16_t* in, int16_t* out,
|
66
|
+
WebRtcSpl_State16khzTo48khz* state, int32_t* tmpmem)
|
67
|
+
{
|
68
|
+
///// 16 --> 32 /////
|
69
|
+
// int16_t in[160]
|
70
|
+
// int32_t out[320]
|
71
|
+
/////
|
72
|
+
WebRtcSpl_UpBy2ShortToInt(in, 160, tmpmem + 16, state->S_16_32);
|
73
|
+
|
74
|
+
///// 32 --> 24 /////
|
75
|
+
// int32_t in[320]
|
76
|
+
// int32_t out[240]
|
77
|
+
// copy state to and from input array
|
78
|
+
/////
|
79
|
+
memcpy(tmpmem + 8, state->S_32_24, 8 * sizeof(int32_t));
|
80
|
+
memcpy(state->S_32_24, tmpmem + 328, 8 * sizeof(int32_t));
|
81
|
+
WebRtcSpl_Resample32khzTo24khz(tmpmem + 8, tmpmem, 80);
|
82
|
+
|
83
|
+
///// 24 --> 48 /////
|
84
|
+
// int32_t in[240]
|
85
|
+
// int16_t out[480]
|
86
|
+
/////
|
87
|
+
WebRtcSpl_UpBy2IntToShort(tmpmem, 240, out, state->S_24_48);
|
88
|
+
}
|
89
|
+
|
90
|
+
// initialize state of 16 -> 48 resampler
|
91
|
+
void WebRtcSpl_ResetResample16khzTo48khz(WebRtcSpl_State16khzTo48khz* state)
|
92
|
+
{
|
93
|
+
memset(state->S_16_32, 0, 8 * sizeof(int32_t));
|
94
|
+
memset(state->S_32_24, 0, 8 * sizeof(int32_t));
|
95
|
+
memset(state->S_24_48, 0, 8 * sizeof(int32_t));
|
96
|
+
}
|
97
|
+
|
98
|
+
////////////////////////////
|
99
|
+
///// 48 kHz -> 8 kHz /////
|
100
|
+
////////////////////////////
|
101
|
+
|
102
|
+
// 48 -> 8 resampler
|
103
|
+
void WebRtcSpl_Resample48khzTo8khz(const int16_t* in, int16_t* out,
|
104
|
+
WebRtcSpl_State48khzTo8khz* state, int32_t* tmpmem)
|
105
|
+
{
|
106
|
+
///// 48 --> 24 /////
|
107
|
+
// int16_t in[480]
|
108
|
+
// int32_t out[240]
|
109
|
+
/////
|
110
|
+
WebRtcSpl_DownBy2ShortToInt(in, 480, tmpmem + 256, state->S_48_24);
|
111
|
+
|
112
|
+
///// 24 --> 24(LP) /////
|
113
|
+
// int32_t in[240]
|
114
|
+
// int32_t out[240]
|
115
|
+
/////
|
116
|
+
WebRtcSpl_LPBy2IntToInt(tmpmem + 256, 240, tmpmem + 16, state->S_24_24);
|
117
|
+
|
118
|
+
///// 24 --> 16 /////
|
119
|
+
// int32_t in[240]
|
120
|
+
// int32_t out[160]
|
121
|
+
/////
|
122
|
+
// copy state to and from input array
|
123
|
+
memcpy(tmpmem + 8, state->S_24_16, 8 * sizeof(int32_t));
|
124
|
+
memcpy(state->S_24_16, tmpmem + 248, 8 * sizeof(int32_t));
|
125
|
+
WebRtcSpl_Resample48khzTo32khz(tmpmem + 8, tmpmem, 80);
|
126
|
+
|
127
|
+
///// 16 --> 8 /////
|
128
|
+
// int32_t in[160]
|
129
|
+
// int16_t out[80]
|
130
|
+
/////
|
131
|
+
WebRtcSpl_DownBy2IntToShort(tmpmem, 160, out, state->S_16_8);
|
132
|
+
}
|
133
|
+
|
134
|
+
// initialize state of 48 -> 8 resampler
|
135
|
+
void WebRtcSpl_ResetResample48khzTo8khz(WebRtcSpl_State48khzTo8khz* state)
|
136
|
+
{
|
137
|
+
memset(state->S_48_24, 0, 8 * sizeof(int32_t));
|
138
|
+
memset(state->S_24_24, 0, 16 * sizeof(int32_t));
|
139
|
+
memset(state->S_24_16, 0, 8 * sizeof(int32_t));
|
140
|
+
memset(state->S_16_8, 0, 8 * sizeof(int32_t));
|
141
|
+
}
|
142
|
+
|
143
|
+
////////////////////////////
|
144
|
+
///// 8 kHz -> 48 kHz /////
|
145
|
+
////////////////////////////
|
146
|
+
|
147
|
+
// 8 -> 48 resampler
|
148
|
+
void WebRtcSpl_Resample8khzTo48khz(const int16_t* in, int16_t* out,
|
149
|
+
WebRtcSpl_State8khzTo48khz* state, int32_t* tmpmem)
|
150
|
+
{
|
151
|
+
///// 8 --> 16 /////
|
152
|
+
// int16_t in[80]
|
153
|
+
// int32_t out[160]
|
154
|
+
/////
|
155
|
+
WebRtcSpl_UpBy2ShortToInt(in, 80, tmpmem + 264, state->S_8_16);
|
156
|
+
|
157
|
+
///// 16 --> 12 /////
|
158
|
+
// int32_t in[160]
|
159
|
+
// int32_t out[120]
|
160
|
+
/////
|
161
|
+
// copy state to and from input array
|
162
|
+
memcpy(tmpmem + 256, state->S_16_12, 8 * sizeof(int32_t));
|
163
|
+
memcpy(state->S_16_12, tmpmem + 416, 8 * sizeof(int32_t));
|
164
|
+
WebRtcSpl_Resample32khzTo24khz(tmpmem + 256, tmpmem + 240, 40);
|
165
|
+
|
166
|
+
///// 12 --> 24 /////
|
167
|
+
// int32_t in[120]
|
168
|
+
// int16_t out[240]
|
169
|
+
/////
|
170
|
+
WebRtcSpl_UpBy2IntToInt(tmpmem + 240, 120, tmpmem, state->S_12_24);
|
171
|
+
|
172
|
+
///// 24 --> 48 /////
|
173
|
+
// int32_t in[240]
|
174
|
+
// int16_t out[480]
|
175
|
+
/////
|
176
|
+
WebRtcSpl_UpBy2IntToShort(tmpmem, 240, out, state->S_24_48);
|
177
|
+
}
|
178
|
+
|
179
|
+
// initialize state of 8 -> 48 resampler
|
180
|
+
void WebRtcSpl_ResetResample8khzTo48khz(WebRtcSpl_State8khzTo48khz* state)
|
181
|
+
{
|
182
|
+
memset(state->S_8_16, 0, 8 * sizeof(int32_t));
|
183
|
+
memset(state->S_16_12, 0, 8 * sizeof(int32_t));
|
184
|
+
memset(state->S_12_24, 0, 8 * sizeof(int32_t));
|
185
|
+
memset(state->S_24_48, 0, 8 * sizeof(int32_t));
|
186
|
+
}
|
@@ -0,0 +1,689 @@
|
|
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
|
+
|
12
|
+
/*
|
13
|
+
* This header file contains some internal resampling functions.
|
14
|
+
*
|
15
|
+
*/
|
16
|
+
|
17
|
+
#include "common_audio/signal_processing/resample_by_2_internal.h"
|
18
|
+
#include "rtc_base/sanitizer.h"
|
19
|
+
|
20
|
+
// allpass filter coefficients.
|
21
|
+
static const int16_t kResampleAllpass[2][3] = {
|
22
|
+
{821, 6110, 12382},
|
23
|
+
{3050, 9368, 15063}
|
24
|
+
};
|
25
|
+
|
26
|
+
//
|
27
|
+
// decimator
|
28
|
+
// input: int32_t (shifted 15 positions to the left, + offset 16384) OVERWRITTEN!
|
29
|
+
// output: int16_t (saturated) (of length len/2)
|
30
|
+
// state: filter state array; length = 8
|
31
|
+
|
32
|
+
void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486
|
33
|
+
WebRtcSpl_DownBy2IntToShort(int32_t *in, int32_t len, int16_t *out,
|
34
|
+
int32_t *state)
|
35
|
+
{
|
36
|
+
int32_t tmp0, tmp1, diff;
|
37
|
+
int32_t i;
|
38
|
+
|
39
|
+
len >>= 1;
|
40
|
+
|
41
|
+
// lower allpass filter (operates on even input samples)
|
42
|
+
for (i = 0; i < len; i++)
|
43
|
+
{
|
44
|
+
tmp0 = in[i << 1];
|
45
|
+
diff = tmp0 - state[1];
|
46
|
+
// UBSan: -1771017321 - 999586185 cannot be represented in type 'int'
|
47
|
+
|
48
|
+
// scale down and round
|
49
|
+
diff = (diff + (1 << 13)) >> 14;
|
50
|
+
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
51
|
+
state[0] = tmp0;
|
52
|
+
diff = tmp1 - state[2];
|
53
|
+
// scale down and truncate
|
54
|
+
diff = diff >> 14;
|
55
|
+
if (diff < 0)
|
56
|
+
diff += 1;
|
57
|
+
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
58
|
+
state[1] = tmp1;
|
59
|
+
diff = tmp0 - state[3];
|
60
|
+
// scale down and truncate
|
61
|
+
diff = diff >> 14;
|
62
|
+
if (diff < 0)
|
63
|
+
diff += 1;
|
64
|
+
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
65
|
+
state[2] = tmp0;
|
66
|
+
|
67
|
+
// divide by two and store temporarily
|
68
|
+
in[i << 1] = (state[3] >> 1);
|
69
|
+
}
|
70
|
+
|
71
|
+
in++;
|
72
|
+
|
73
|
+
// upper allpass filter (operates on odd input samples)
|
74
|
+
for (i = 0; i < len; i++)
|
75
|
+
{
|
76
|
+
tmp0 = in[i << 1];
|
77
|
+
diff = tmp0 - state[5];
|
78
|
+
// scale down and round
|
79
|
+
diff = (diff + (1 << 13)) >> 14;
|
80
|
+
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
81
|
+
state[4] = tmp0;
|
82
|
+
diff = tmp1 - state[6];
|
83
|
+
// scale down and round
|
84
|
+
diff = diff >> 14;
|
85
|
+
if (diff < 0)
|
86
|
+
diff += 1;
|
87
|
+
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
88
|
+
state[5] = tmp1;
|
89
|
+
diff = tmp0 - state[7];
|
90
|
+
// scale down and truncate
|
91
|
+
diff = diff >> 14;
|
92
|
+
if (diff < 0)
|
93
|
+
diff += 1;
|
94
|
+
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
95
|
+
state[6] = tmp0;
|
96
|
+
|
97
|
+
// divide by two and store temporarily
|
98
|
+
in[i << 1] = (state[7] >> 1);
|
99
|
+
}
|
100
|
+
|
101
|
+
in--;
|
102
|
+
|
103
|
+
// combine allpass outputs
|
104
|
+
for (i = 0; i < len; i += 2)
|
105
|
+
{
|
106
|
+
// divide by two, add both allpass outputs and round
|
107
|
+
tmp0 = (in[i << 1] + in[(i << 1) + 1]) >> 15;
|
108
|
+
tmp1 = (in[(i << 1) + 2] + in[(i << 1) + 3]) >> 15;
|
109
|
+
if (tmp0 > (int32_t)0x00007FFF)
|
110
|
+
tmp0 = 0x00007FFF;
|
111
|
+
if (tmp0 < (int32_t)0xFFFF8000)
|
112
|
+
tmp0 = 0xFFFF8000;
|
113
|
+
out[i] = (int16_t)tmp0;
|
114
|
+
if (tmp1 > (int32_t)0x00007FFF)
|
115
|
+
tmp1 = 0x00007FFF;
|
116
|
+
if (tmp1 < (int32_t)0xFFFF8000)
|
117
|
+
tmp1 = 0xFFFF8000;
|
118
|
+
out[i + 1] = (int16_t)tmp1;
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
//
|
123
|
+
// decimator
|
124
|
+
// input: int16_t
|
125
|
+
// output: int32_t (shifted 15 positions to the left, + offset 16384) (of length len/2)
|
126
|
+
// state: filter state array; length = 8
|
127
|
+
|
128
|
+
void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486
|
129
|
+
WebRtcSpl_DownBy2ShortToInt(const int16_t *in,
|
130
|
+
int32_t len,
|
131
|
+
int32_t *out,
|
132
|
+
int32_t *state)
|
133
|
+
{
|
134
|
+
int32_t tmp0, tmp1, diff;
|
135
|
+
int32_t i;
|
136
|
+
|
137
|
+
len >>= 1;
|
138
|
+
|
139
|
+
// lower allpass filter (operates on even input samples)
|
140
|
+
for (i = 0; i < len; i++)
|
141
|
+
{
|
142
|
+
tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14);
|
143
|
+
diff = tmp0 - state[1];
|
144
|
+
// scale down and round
|
145
|
+
diff = (diff + (1 << 13)) >> 14;
|
146
|
+
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
147
|
+
state[0] = tmp0;
|
148
|
+
diff = tmp1 - state[2];
|
149
|
+
// UBSan: -1379909682 - 834099714 cannot be represented in type 'int'
|
150
|
+
|
151
|
+
// scale down and truncate
|
152
|
+
diff = diff >> 14;
|
153
|
+
if (diff < 0)
|
154
|
+
diff += 1;
|
155
|
+
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
156
|
+
state[1] = tmp1;
|
157
|
+
diff = tmp0 - state[3];
|
158
|
+
// scale down and truncate
|
159
|
+
diff = diff >> 14;
|
160
|
+
if (diff < 0)
|
161
|
+
diff += 1;
|
162
|
+
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
163
|
+
state[2] = tmp0;
|
164
|
+
|
165
|
+
// divide by two and store temporarily
|
166
|
+
out[i] = (state[3] >> 1);
|
167
|
+
}
|
168
|
+
|
169
|
+
in++;
|
170
|
+
|
171
|
+
// upper allpass filter (operates on odd input samples)
|
172
|
+
for (i = 0; i < len; i++)
|
173
|
+
{
|
174
|
+
tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14);
|
175
|
+
diff = tmp0 - state[5];
|
176
|
+
// scale down and round
|
177
|
+
diff = (diff + (1 << 13)) >> 14;
|
178
|
+
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
179
|
+
state[4] = tmp0;
|
180
|
+
diff = tmp1 - state[6];
|
181
|
+
// scale down and round
|
182
|
+
diff = diff >> 14;
|
183
|
+
if (diff < 0)
|
184
|
+
diff += 1;
|
185
|
+
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
186
|
+
state[5] = tmp1;
|
187
|
+
diff = tmp0 - state[7];
|
188
|
+
// scale down and truncate
|
189
|
+
diff = diff >> 14;
|
190
|
+
if (diff < 0)
|
191
|
+
diff += 1;
|
192
|
+
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
193
|
+
state[6] = tmp0;
|
194
|
+
|
195
|
+
// divide by two and store temporarily
|
196
|
+
out[i] += (state[7] >> 1);
|
197
|
+
}
|
198
|
+
|
199
|
+
in--;
|
200
|
+
}
|
201
|
+
|
202
|
+
//
|
203
|
+
// interpolator
|
204
|
+
// input: int16_t
|
205
|
+
// output: int32_t (normalized, not saturated) (of length len*2)
|
206
|
+
// state: filter state array; length = 8
|
207
|
+
void WebRtcSpl_UpBy2ShortToInt(const int16_t *in, int32_t len, int32_t *out,
|
208
|
+
int32_t *state)
|
209
|
+
{
|
210
|
+
int32_t tmp0, tmp1, diff;
|
211
|
+
int32_t i;
|
212
|
+
|
213
|
+
// upper allpass filter (generates odd output samples)
|
214
|
+
for (i = 0; i < len; i++)
|
215
|
+
{
|
216
|
+
tmp0 = ((int32_t)in[i] << 15) + (1 << 14);
|
217
|
+
diff = tmp0 - state[5];
|
218
|
+
// scale down and round
|
219
|
+
diff = (diff + (1 << 13)) >> 14;
|
220
|
+
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
221
|
+
state[4] = tmp0;
|
222
|
+
diff = tmp1 - state[6];
|
223
|
+
// scale down and truncate
|
224
|
+
diff = diff >> 14;
|
225
|
+
if (diff < 0)
|
226
|
+
diff += 1;
|
227
|
+
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
228
|
+
state[5] = tmp1;
|
229
|
+
diff = tmp0 - state[7];
|
230
|
+
// scale down and truncate
|
231
|
+
diff = diff >> 14;
|
232
|
+
if (diff < 0)
|
233
|
+
diff += 1;
|
234
|
+
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
235
|
+
state[6] = tmp0;
|
236
|
+
|
237
|
+
// scale down, round and store
|
238
|
+
out[i << 1] = state[7] >> 15;
|
239
|
+
}
|
240
|
+
|
241
|
+
out++;
|
242
|
+
|
243
|
+
// lower allpass filter (generates even output samples)
|
244
|
+
for (i = 0; i < len; i++)
|
245
|
+
{
|
246
|
+
tmp0 = ((int32_t)in[i] << 15) + (1 << 14);
|
247
|
+
diff = tmp0 - state[1];
|
248
|
+
// scale down and round
|
249
|
+
diff = (diff + (1 << 13)) >> 14;
|
250
|
+
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
251
|
+
state[0] = tmp0;
|
252
|
+
diff = tmp1 - state[2];
|
253
|
+
// scale down and truncate
|
254
|
+
diff = diff >> 14;
|
255
|
+
if (diff < 0)
|
256
|
+
diff += 1;
|
257
|
+
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
258
|
+
state[1] = tmp1;
|
259
|
+
diff = tmp0 - state[3];
|
260
|
+
// scale down and truncate
|
261
|
+
diff = diff >> 14;
|
262
|
+
if (diff < 0)
|
263
|
+
diff += 1;
|
264
|
+
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
265
|
+
state[2] = tmp0;
|
266
|
+
|
267
|
+
// scale down, round and store
|
268
|
+
out[i << 1] = state[3] >> 15;
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
//
|
273
|
+
// interpolator
|
274
|
+
// input: int32_t (shifted 15 positions to the left, + offset 16384)
|
275
|
+
// output: int32_t (shifted 15 positions to the left, + offset 16384) (of length len*2)
|
276
|
+
// state: filter state array; length = 8
|
277
|
+
void WebRtcSpl_UpBy2IntToInt(const int32_t *in, int32_t len, int32_t *out,
|
278
|
+
int32_t *state)
|
279
|
+
{
|
280
|
+
int32_t tmp0, tmp1, diff;
|
281
|
+
int32_t i;
|
282
|
+
|
283
|
+
// upper allpass filter (generates odd output samples)
|
284
|
+
for (i = 0; i < len; i++)
|
285
|
+
{
|
286
|
+
tmp0 = in[i];
|
287
|
+
diff = tmp0 - state[5];
|
288
|
+
// scale down and round
|
289
|
+
diff = (diff + (1 << 13)) >> 14;
|
290
|
+
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
291
|
+
state[4] = tmp0;
|
292
|
+
diff = tmp1 - state[6];
|
293
|
+
// scale down and truncate
|
294
|
+
diff = diff >> 14;
|
295
|
+
if (diff < 0)
|
296
|
+
diff += 1;
|
297
|
+
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
298
|
+
state[5] = tmp1;
|
299
|
+
diff = tmp0 - state[7];
|
300
|
+
// scale down and truncate
|
301
|
+
diff = diff >> 14;
|
302
|
+
if (diff < 0)
|
303
|
+
diff += 1;
|
304
|
+
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
305
|
+
state[6] = tmp0;
|
306
|
+
|
307
|
+
// scale down, round and store
|
308
|
+
out[i << 1] = state[7];
|
309
|
+
}
|
310
|
+
|
311
|
+
out++;
|
312
|
+
|
313
|
+
// lower allpass filter (generates even output samples)
|
314
|
+
for (i = 0; i < len; i++)
|
315
|
+
{
|
316
|
+
tmp0 = in[i];
|
317
|
+
diff = tmp0 - state[1];
|
318
|
+
// scale down and round
|
319
|
+
diff = (diff + (1 << 13)) >> 14;
|
320
|
+
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
321
|
+
state[0] = tmp0;
|
322
|
+
diff = tmp1 - state[2];
|
323
|
+
// scale down and truncate
|
324
|
+
diff = diff >> 14;
|
325
|
+
if (diff < 0)
|
326
|
+
diff += 1;
|
327
|
+
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
328
|
+
state[1] = tmp1;
|
329
|
+
diff = tmp0 - state[3];
|
330
|
+
// scale down and truncate
|
331
|
+
diff = diff >> 14;
|
332
|
+
if (diff < 0)
|
333
|
+
diff += 1;
|
334
|
+
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
335
|
+
state[2] = tmp0;
|
336
|
+
|
337
|
+
// scale down, round and store
|
338
|
+
out[i << 1] = state[3];
|
339
|
+
}
|
340
|
+
}
|
341
|
+
|
342
|
+
//
|
343
|
+
// interpolator
|
344
|
+
// input: int32_t (shifted 15 positions to the left, + offset 16384)
|
345
|
+
// output: int16_t (saturated) (of length len*2)
|
346
|
+
// state: filter state array; length = 8
|
347
|
+
void WebRtcSpl_UpBy2IntToShort(const int32_t *in, int32_t len, int16_t *out,
|
348
|
+
int32_t *state)
|
349
|
+
{
|
350
|
+
int32_t tmp0, tmp1, diff;
|
351
|
+
int32_t i;
|
352
|
+
|
353
|
+
// upper allpass filter (generates odd output samples)
|
354
|
+
for (i = 0; i < len; i++)
|
355
|
+
{
|
356
|
+
tmp0 = in[i];
|
357
|
+
diff = tmp0 - state[5];
|
358
|
+
// scale down and round
|
359
|
+
diff = (diff + (1 << 13)) >> 14;
|
360
|
+
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
361
|
+
state[4] = tmp0;
|
362
|
+
diff = tmp1 - state[6];
|
363
|
+
// scale down and round
|
364
|
+
diff = diff >> 14;
|
365
|
+
if (diff < 0)
|
366
|
+
diff += 1;
|
367
|
+
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
368
|
+
state[5] = tmp1;
|
369
|
+
diff = tmp0 - state[7];
|
370
|
+
// scale down and truncate
|
371
|
+
diff = diff >> 14;
|
372
|
+
if (diff < 0)
|
373
|
+
diff += 1;
|
374
|
+
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
375
|
+
state[6] = tmp0;
|
376
|
+
|
377
|
+
// scale down, saturate and store
|
378
|
+
tmp1 = state[7] >> 15;
|
379
|
+
if (tmp1 > (int32_t)0x00007FFF)
|
380
|
+
tmp1 = 0x00007FFF;
|
381
|
+
if (tmp1 < (int32_t)0xFFFF8000)
|
382
|
+
tmp1 = 0xFFFF8000;
|
383
|
+
out[i << 1] = (int16_t)tmp1;
|
384
|
+
}
|
385
|
+
|
386
|
+
out++;
|
387
|
+
|
388
|
+
// lower allpass filter (generates even output samples)
|
389
|
+
for (i = 0; i < len; i++)
|
390
|
+
{
|
391
|
+
tmp0 = in[i];
|
392
|
+
diff = tmp0 - state[1];
|
393
|
+
// scale down and round
|
394
|
+
diff = (diff + (1 << 13)) >> 14;
|
395
|
+
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
396
|
+
state[0] = tmp0;
|
397
|
+
diff = tmp1 - state[2];
|
398
|
+
// scale down and truncate
|
399
|
+
diff = diff >> 14;
|
400
|
+
if (diff < 0)
|
401
|
+
diff += 1;
|
402
|
+
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
403
|
+
state[1] = tmp1;
|
404
|
+
diff = tmp0 - state[3];
|
405
|
+
// scale down and truncate
|
406
|
+
diff = diff >> 14;
|
407
|
+
if (diff < 0)
|
408
|
+
diff += 1;
|
409
|
+
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
410
|
+
state[2] = tmp0;
|
411
|
+
|
412
|
+
// scale down, saturate and store
|
413
|
+
tmp1 = state[3] >> 15;
|
414
|
+
if (tmp1 > (int32_t)0x00007FFF)
|
415
|
+
tmp1 = 0x00007FFF;
|
416
|
+
if (tmp1 < (int32_t)0xFFFF8000)
|
417
|
+
tmp1 = 0xFFFF8000;
|
418
|
+
out[i << 1] = (int16_t)tmp1;
|
419
|
+
}
|
420
|
+
}
|
421
|
+
|
422
|
+
// lowpass filter
|
423
|
+
// input: int16_t
|
424
|
+
// output: int32_t (normalized, not saturated)
|
425
|
+
// state: filter state array; length = 8
|
426
|
+
void WebRtcSpl_LPBy2ShortToInt(const int16_t* in, int32_t len, int32_t* out,
|
427
|
+
int32_t* state)
|
428
|
+
{
|
429
|
+
int32_t tmp0, tmp1, diff;
|
430
|
+
int32_t i;
|
431
|
+
|
432
|
+
len >>= 1;
|
433
|
+
|
434
|
+
// lower allpass filter: odd input -> even output samples
|
435
|
+
in++;
|
436
|
+
// initial state of polyphase delay element
|
437
|
+
tmp0 = state[12];
|
438
|
+
for (i = 0; i < len; i++)
|
439
|
+
{
|
440
|
+
diff = tmp0 - state[1];
|
441
|
+
// scale down and round
|
442
|
+
diff = (diff + (1 << 13)) >> 14;
|
443
|
+
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
444
|
+
state[0] = tmp0;
|
445
|
+
diff = tmp1 - state[2];
|
446
|
+
// scale down and truncate
|
447
|
+
diff = diff >> 14;
|
448
|
+
if (diff < 0)
|
449
|
+
diff += 1;
|
450
|
+
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
451
|
+
state[1] = tmp1;
|
452
|
+
diff = tmp0 - state[3];
|
453
|
+
// scale down and truncate
|
454
|
+
diff = diff >> 14;
|
455
|
+
if (diff < 0)
|
456
|
+
diff += 1;
|
457
|
+
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
458
|
+
state[2] = tmp0;
|
459
|
+
|
460
|
+
// scale down, round and store
|
461
|
+
out[i << 1] = state[3] >> 1;
|
462
|
+
tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14);
|
463
|
+
}
|
464
|
+
in--;
|
465
|
+
|
466
|
+
// upper allpass filter: even input -> even output samples
|
467
|
+
for (i = 0; i < len; i++)
|
468
|
+
{
|
469
|
+
tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14);
|
470
|
+
diff = tmp0 - state[5];
|
471
|
+
// scale down and round
|
472
|
+
diff = (diff + (1 << 13)) >> 14;
|
473
|
+
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
474
|
+
state[4] = tmp0;
|
475
|
+
diff = tmp1 - state[6];
|
476
|
+
// scale down and round
|
477
|
+
diff = diff >> 14;
|
478
|
+
if (diff < 0)
|
479
|
+
diff += 1;
|
480
|
+
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
481
|
+
state[5] = tmp1;
|
482
|
+
diff = tmp0 - state[7];
|
483
|
+
// scale down and truncate
|
484
|
+
diff = diff >> 14;
|
485
|
+
if (diff < 0)
|
486
|
+
diff += 1;
|
487
|
+
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
488
|
+
state[6] = tmp0;
|
489
|
+
|
490
|
+
// average the two allpass outputs, scale down and store
|
491
|
+
out[i << 1] = (out[i << 1] + (state[7] >> 1)) >> 15;
|
492
|
+
}
|
493
|
+
|
494
|
+
// switch to odd output samples
|
495
|
+
out++;
|
496
|
+
|
497
|
+
// lower allpass filter: even input -> odd output samples
|
498
|
+
for (i = 0; i < len; i++)
|
499
|
+
{
|
500
|
+
tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14);
|
501
|
+
diff = tmp0 - state[9];
|
502
|
+
// scale down and round
|
503
|
+
diff = (diff + (1 << 13)) >> 14;
|
504
|
+
tmp1 = state[8] + diff * kResampleAllpass[1][0];
|
505
|
+
state[8] = tmp0;
|
506
|
+
diff = tmp1 - state[10];
|
507
|
+
// scale down and truncate
|
508
|
+
diff = diff >> 14;
|
509
|
+
if (diff < 0)
|
510
|
+
diff += 1;
|
511
|
+
tmp0 = state[9] + diff * kResampleAllpass[1][1];
|
512
|
+
state[9] = tmp1;
|
513
|
+
diff = tmp0 - state[11];
|
514
|
+
// scale down and truncate
|
515
|
+
diff = diff >> 14;
|
516
|
+
if (diff < 0)
|
517
|
+
diff += 1;
|
518
|
+
state[11] = state[10] + diff * kResampleAllpass[1][2];
|
519
|
+
state[10] = tmp0;
|
520
|
+
|
521
|
+
// scale down, round and store
|
522
|
+
out[i << 1] = state[11] >> 1;
|
523
|
+
}
|
524
|
+
|
525
|
+
// upper allpass filter: odd input -> odd output samples
|
526
|
+
in++;
|
527
|
+
for (i = 0; i < len; i++)
|
528
|
+
{
|
529
|
+
tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14);
|
530
|
+
diff = tmp0 - state[13];
|
531
|
+
// scale down and round
|
532
|
+
diff = (diff + (1 << 13)) >> 14;
|
533
|
+
tmp1 = state[12] + diff * kResampleAllpass[0][0];
|
534
|
+
state[12] = tmp0;
|
535
|
+
diff = tmp1 - state[14];
|
536
|
+
// scale down and round
|
537
|
+
diff = diff >> 14;
|
538
|
+
if (diff < 0)
|
539
|
+
diff += 1;
|
540
|
+
tmp0 = state[13] + diff * kResampleAllpass[0][1];
|
541
|
+
state[13] = tmp1;
|
542
|
+
diff = tmp0 - state[15];
|
543
|
+
// scale down and truncate
|
544
|
+
diff = diff >> 14;
|
545
|
+
if (diff < 0)
|
546
|
+
diff += 1;
|
547
|
+
state[15] = state[14] + diff * kResampleAllpass[0][2];
|
548
|
+
state[14] = tmp0;
|
549
|
+
|
550
|
+
// average the two allpass outputs, scale down and store
|
551
|
+
out[i << 1] = (out[i << 1] + (state[15] >> 1)) >> 15;
|
552
|
+
}
|
553
|
+
}
|
554
|
+
|
555
|
+
// lowpass filter
|
556
|
+
// input: int32_t (shifted 15 positions to the left, + offset 16384)
|
557
|
+
// output: int32_t (normalized, not saturated)
|
558
|
+
// state: filter state array; length = 8
|
559
|
+
void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486
|
560
|
+
WebRtcSpl_LPBy2IntToInt(const int32_t* in, int32_t len, int32_t* out,
|
561
|
+
int32_t* state)
|
562
|
+
{
|
563
|
+
int32_t tmp0, tmp1, diff;
|
564
|
+
int32_t i;
|
565
|
+
|
566
|
+
len >>= 1;
|
567
|
+
|
568
|
+
// lower allpass filter: odd input -> even output samples
|
569
|
+
in++;
|
570
|
+
// initial state of polyphase delay element
|
571
|
+
tmp0 = state[12];
|
572
|
+
for (i = 0; i < len; i++)
|
573
|
+
{
|
574
|
+
diff = tmp0 - state[1];
|
575
|
+
// scale down and round
|
576
|
+
diff = (diff + (1 << 13)) >> 14;
|
577
|
+
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
578
|
+
state[0] = tmp0;
|
579
|
+
diff = tmp1 - state[2];
|
580
|
+
// scale down and truncate
|
581
|
+
diff = diff >> 14;
|
582
|
+
if (diff < 0)
|
583
|
+
diff += 1;
|
584
|
+
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
585
|
+
state[1] = tmp1;
|
586
|
+
diff = tmp0 - state[3];
|
587
|
+
// scale down and truncate
|
588
|
+
diff = diff >> 14;
|
589
|
+
if (diff < 0)
|
590
|
+
diff += 1;
|
591
|
+
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
592
|
+
state[2] = tmp0;
|
593
|
+
|
594
|
+
// scale down, round and store
|
595
|
+
out[i << 1] = state[3] >> 1;
|
596
|
+
tmp0 = in[i << 1];
|
597
|
+
}
|
598
|
+
in--;
|
599
|
+
|
600
|
+
// upper allpass filter: even input -> even output samples
|
601
|
+
for (i = 0; i < len; i++)
|
602
|
+
{
|
603
|
+
tmp0 = in[i << 1];
|
604
|
+
diff = tmp0 - state[5];
|
605
|
+
// UBSan: -794814117 - 1566149201 cannot be represented in type 'int'
|
606
|
+
|
607
|
+
// scale down and round
|
608
|
+
diff = (diff + (1 << 13)) >> 14;
|
609
|
+
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
610
|
+
state[4] = tmp0;
|
611
|
+
diff = tmp1 - state[6];
|
612
|
+
// scale down and round
|
613
|
+
diff = diff >> 14;
|
614
|
+
if (diff < 0)
|
615
|
+
diff += 1;
|
616
|
+
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
617
|
+
state[5] = tmp1;
|
618
|
+
diff = tmp0 - state[7];
|
619
|
+
// scale down and truncate
|
620
|
+
diff = diff >> 14;
|
621
|
+
if (diff < 0)
|
622
|
+
diff += 1;
|
623
|
+
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
624
|
+
state[6] = tmp0;
|
625
|
+
|
626
|
+
// average the two allpass outputs, scale down and store
|
627
|
+
out[i << 1] = (out[i << 1] + (state[7] >> 1)) >> 15;
|
628
|
+
}
|
629
|
+
|
630
|
+
// switch to odd output samples
|
631
|
+
out++;
|
632
|
+
|
633
|
+
// lower allpass filter: even input -> odd output samples
|
634
|
+
for (i = 0; i < len; i++)
|
635
|
+
{
|
636
|
+
tmp0 = in[i << 1];
|
637
|
+
diff = tmp0 - state[9];
|
638
|
+
// scale down and round
|
639
|
+
diff = (diff + (1 << 13)) >> 14;
|
640
|
+
tmp1 = state[8] + diff * kResampleAllpass[1][0];
|
641
|
+
state[8] = tmp0;
|
642
|
+
diff = tmp1 - state[10];
|
643
|
+
// scale down and truncate
|
644
|
+
diff = diff >> 14;
|
645
|
+
if (diff < 0)
|
646
|
+
diff += 1;
|
647
|
+
tmp0 = state[9] + diff * kResampleAllpass[1][1];
|
648
|
+
state[9] = tmp1;
|
649
|
+
diff = tmp0 - state[11];
|
650
|
+
// scale down and truncate
|
651
|
+
diff = diff >> 14;
|
652
|
+
if (diff < 0)
|
653
|
+
diff += 1;
|
654
|
+
state[11] = state[10] + diff * kResampleAllpass[1][2];
|
655
|
+
state[10] = tmp0;
|
656
|
+
|
657
|
+
// scale down, round and store
|
658
|
+
out[i << 1] = state[11] >> 1;
|
659
|
+
}
|
660
|
+
|
661
|
+
// upper allpass filter: odd input -> odd output samples
|
662
|
+
in++;
|
663
|
+
for (i = 0; i < len; i++)
|
664
|
+
{
|
665
|
+
tmp0 = in[i << 1];
|
666
|
+
diff = tmp0 - state[13];
|
667
|
+
// scale down and round
|
668
|
+
diff = (diff + (1 << 13)) >> 14;
|
669
|
+
tmp1 = state[12] + diff * kResampleAllpass[0][0];
|
670
|
+
state[12] = tmp0;
|
671
|
+
diff = tmp1 - state[14];
|
672
|
+
// scale down and round
|
673
|
+
diff = diff >> 14;
|
674
|
+
if (diff < 0)
|
675
|
+
diff += 1;
|
676
|
+
tmp0 = state[13] + diff * kResampleAllpass[0][1];
|
677
|
+
state[13] = tmp1;
|
678
|
+
diff = tmp0 - state[15];
|
679
|
+
// scale down and truncate
|
680
|
+
diff = diff >> 14;
|
681
|
+
if (diff < 0)
|
682
|
+
diff += 1;
|
683
|
+
state[15] = state[14] + diff * kResampleAllpass[0][2];
|
684
|
+
state[14] = tmp0;
|
685
|
+
|
686
|
+
// average the two allpass outputs, scale down and store
|
687
|
+
out[i << 1] = (out[i << 1] + (state[15] >> 1)) >> 15;
|
688
|
+
}
|
689
|
+
}
|