forked from thesofproject/sof
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwindow.c
More file actions
122 lines (103 loc) · 3.27 KB
/
window.c
File metadata and controls
122 lines (103 loc) · 3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2022 Intel Corporation. All rights reserved.
//
// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
#include <sof/audio/format.h>
#include <sof/math/decibels.h>
#include <sof/math/log.h>
#include <sof/math/trig.h>
#include <sof/math/window.h>
#include <errno.h>
#include <stdint.h>
#define WIN_ONE_Q15 INT16_MAX
#define WIN_ONE_Q31 INT32_MAX
#define WIN_05_Q31 Q_CONVERT_FLOAT(0.5, 31)
#define WIN_TWO_PI_Q28 Q_CONVERT_FLOAT(6.2831853072, 28)
#define WIN_085_Q31 Q_CONVERT_FLOAT(0.85, 31)
#define WIN_LOG_2POW31_Q26 Q_CONVERT_FLOAT(21.4875625974, 26)
/* Exact
* #define WIN_HAMMING_A0_Q30 Q_CONVERT_FLOAT(25.0 / 46.0, 30)
* #define WIN_HAMMING_A1_Q30 Q_CONVERT_FLOAT(1 - 25.0 / 46.0, 30)
*/
/* Common approximations to match e.g. Octave */
#define WIN_HAMMING_A0_Q30 Q_CONVERT_FLOAT(0.54, 30)
#define WIN_HAMMING_A1_Q30 Q_CONVERT_FLOAT(0.46, 30)
/**
* \brief Return rectangular window, simply values of one
* \param[in,out] win Output vector with coefficients
* \param[in] length Length of coefficients vector
*/
void win_rectangular_16b(int16_t *win, int length)
{
int i;
for (i = 0; i < length; i++)
win[i] = WIN_ONE_Q15;
}
/**
* \brief Calculate Blackman window function, reference
* https://en.wikipedia.org/wiki/Window_function#Blackman_window
* \param[in,out] win Output vector with coefficients
* \param[in] length Length of coefficients vector
* \param[in] a0 Parameter for window shape, use e.g. 0.42 as Q1.15
*/
void win_blackman_16b(int16_t win[], int length, int16_t a0)
{
const int32_t a1 = Q_CONVERT_FLOAT(0.5, 31);
int32_t inv_length;
int32_t val;
int32_t a;
int16_t alpha;
int32_t a2;
int32_t c1;
int32_t c2;
int n;
alpha = WIN_ONE_Q15 - 2 * a0; /* Q1.15 */
a2 = alpha << 15; /* Divided by 2 in Q1.31 */
a = WIN_TWO_PI_Q28 / (length - 1); /* Q4.28 */
inv_length = WIN_ONE_Q31 / length;
for (n = 0; n < length; n++) {
c1 = cos_fixed_32b(a * n);
c2 = cos_fixed_32b(2 * n * Q_MULTSR_32X32((int64_t)a, inv_length, 28, 31, 28));
val = a0 - Q_MULTSR_32X32((int64_t)a1, c1, 31, 31, 15) +
Q_MULTSR_32X32((int64_t)a2, c2, 31, 31, 15);
win[n] = sat_int16(val);
}
}
void win_hamming_16b(int16_t win[], int length)
{
int32_t val;
int32_t a;
int n;
a = WIN_TWO_PI_Q28 / (length - 1); /* Q4.28 */
for (n = 0; n < length; n++) {
/* Calculate 0.54 - 0.46 * cos(a * n) */
val = cos_fixed_32b(a * n); /* Q4.28 -> Q1.31 */
val = Q_MULTSR_32X32((int64_t)val, WIN_HAMMING_A1_Q30, 31, 30, 30); /* Q1.30 */
val = WIN_HAMMING_A0_Q30 - val;
/* Convert to Q1.15 */
win[n] = sat_int16(Q_SHIFT_RND(val, 30, 15));
}
}
void win_povey_16b(int16_t win[], int length)
{
int32_t cos_an;
int32_t x1;
int32_t x2;
int32_t x3;
int32_t x4;
int32_t a;
int n;
a = WIN_TWO_PI_Q28 / (length - 1); /* Q4.28 */
for (n = 0; n < length; n++) {
/* Calculate 0.5 - 0.5 * cos(a * n) */
cos_an = cos_fixed_32b(a * n); /* Q4.28 -> Q1.31 */
x1 = WIN_05_Q31 - (cos_an >> 1); /* Q1.31 */
/* Calculate x^0.85 as exp(0.85 * log(x)) */
x2 = (int32_t)(ln_int32((uint32_t)x1) >> 1) - WIN_LOG_2POW31_Q26;
x3 = sat_int32(Q_MULTSR_32X32((int64_t)x2, WIN_085_Q31, 26, 31, 27)); /* Q5.27 */
x4 = exp_fixed(x3); /* Q5.27 -> Q12.20 */
/* Convert to Q1.15 */
win[n] = sat_int16(Q_SHIFT_RND(x4, 20, 15));
}
}