1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "downmix.h"
16 
17 /* coefficient matrix for downmixing */
18 /* usage: [output_channel_layout][input_channel][output_channel*/
19 const uint16_t channelDownmixMatrix[PA_CHANNEL_LAYOUT_COUNT][PA_DOWNMIX_CHANNEL_MAX][PA_DOWNMIX_CHANNEL_MAX] = {
20     /* Downmix matrix for STEREO output */
21     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_FRONT_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 10000,
22     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_FRONT_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 10000,
23     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 7071,
24     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] = 7071,
25     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_REAR_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 7071,
26     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_REAR_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 7071,
27     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 5000,
28     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] = 5000,
29     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_SIDE_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 7071,
30     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_SIDE_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 7071,
31     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 6057,
32     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] = 2509,
33     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 2509,
34     [PA_CHANNEL_LAYOUT_STEREO][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] = 6057,
35     [PA_CHANNEL_LAYOUT_STEREO][PA_DOWNMIX_POSITION_TOP_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 3552,
36     [PA_CHANNEL_LAYOUT_STEREO][PA_DOWNMIX_POSITION_TOP_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] = 3552,
37     [PA_CHANNEL_LAYOUT_STEREO][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 10000,
38     [PA_CHANNEL_LAYOUT_STEREO][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 10000,
39     [PA_CHANNEL_LAYOUT_STEREO][PA_DOWNMIX_POSITION_TOP_FRONT_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 7071,
40     [PA_CHANNEL_LAYOUT_STEREO][PA_DOWNMIX_POSITION_TOP_FRONT_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] = 7071,
41     [PA_CHANNEL_LAYOUT_STEREO][PA_DOWNMIX_POSITION_TOP_REAR_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 7071,
42     [PA_CHANNEL_LAYOUT_STEREO][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 7071,
43     [PA_CHANNEL_LAYOUT_STEREO][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 3544,
44     [PA_CHANNEL_LAYOUT_STEREO][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] = 3544,
45 
46     /* Downmix matrix for 5POINT1 */
47     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_FRONT_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 10000,
48     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_FRONT_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 10000,
49     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_FRONT_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 10000,
50     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_LFE][PA_CHANNEL_POSITION_LFE] = 10000,
51     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_REAR_LEFT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
52     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_REAR_RIGHT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
53     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_SIDE_LEFT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
54     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_SIDE_RIGHT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
55     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 5946,
56     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 7071,
57     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] = 5946,
58     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 7071,
59     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_SIDE_LEFT] = 7071,
60     [PA_CHANNEL_LAYOUT_5POINT1][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_SIDE_RIGHT] = 7071,
61     [PA_CHANNEL_LAYOUT_5POINT1][PA_DOWNMIX_POSITION_TOP_CENTER][PA_CHANNEL_POSITION_SIDE_LEFT] = 5000,
62     [PA_CHANNEL_LAYOUT_5POINT1][PA_DOWNMIX_POSITION_TOP_CENTER][PA_CHANNEL_POSITION_SIDE_RIGHT] = 5000,
63     [PA_CHANNEL_LAYOUT_5POINT1][PA_DOWNMIX_POSITION_TOP_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 5000,
64     [PA_CHANNEL_LAYOUT_5POINT1][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 10000,
65     [PA_CHANNEL_LAYOUT_5POINT1][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 10000,
66     [PA_CHANNEL_LAYOUT_5POINT1][PA_DOWNMIX_POSITION_TOP_FRONT_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 10000,
67     [PA_CHANNEL_LAYOUT_5POINT1][PA_DOWNMIX_POSITION_TOP_REAR_LEFT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
68     [PA_CHANNEL_LAYOUT_5POINT1][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT][PA_CHANNEL_POSITION_SIDE_RIGHT] = 10000,
69     [PA_CHANNEL_LAYOUT_5POINT1][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_CHANNEL_POSITION_SIDE_LEFT] = 7071,
70     [PA_CHANNEL_LAYOUT_5POINT1][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_CHANNEL_POSITION_SIDE_RIGHT] = 7071,
71 
72     /* Downmix table for 5POINT1POINT2 */
73     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_FRONT_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 10000,
74     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_FRONT_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 10000,
75     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_FRONT_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 10000,
76     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_LFE][PA_CHANNEL_POSITION_LFE] = 10000,
77     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_REAR_LEFT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
78     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_REAR_RIGHT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
79     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_SIDE_LEFT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
80     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_SIDE_RIGHT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
81     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 5946,
82     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] =
83         7071,
84     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] =
85         5946,
86     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] =
87         7071,
88     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_SIDE_LEFT] = 7071,
89     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_SIDE_RIGHT] = 7071,
90     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_DOWNMIX_POSITION_TOP_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_LEFT] = 7071,
91     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_DOWNMIX_POSITION_TOP_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT] = 7071,
92     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 10000,
93     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 10000,
94     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_DOWNMIX_POSITION_TOP_FRONT_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 10000,
95     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_DOWNMIX_POSITION_TOP_REAR_LEFT][PA_DOWNMIX_POSITION_TOP_REAR_LEFT] = 10000,
96     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT] = 10000,
97     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_CHANNEL_POSITION_REAR_LEFT] = 7071,
98     [PA_CHANNEL_LAYOUT_5POINT1POINT2][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_CHANNEL_POSITION_REAR_RIGHT] = 7071,
99 
100     /* Downmix table for 5POINT1POINT4 */
101     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_FRONT_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 10000,
102     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_FRONT_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 10000,
103     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_FRONT_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 10000,
104     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_LFE][PA_CHANNEL_POSITION_LFE] = 10000,
105     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_REAR_LEFT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
106     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_REAR_RIGHT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
107     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_SIDE_LEFT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
108     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_SIDE_RIGHT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
109     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 5946,
110     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] =
111         7071,
112     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] =
113         5946,
114     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] =
115         7071,
116     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_SIDE_LEFT] = 7071,
117     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_SIDE_RIGHT] = 7071,
118     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_DOWNMIX_POSITION_TOP_CENTER][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT] = 5000,
119     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_DOWNMIX_POSITION_TOP_CENTER][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT] = 5000,
120     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_DOWNMIX_POSITION_TOP_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_LEFT] = 5000,
121     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_DOWNMIX_POSITION_TOP_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT] = 5000,
122     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT] = 10000,
123     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT] = 10000,
124     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_DOWNMIX_POSITION_TOP_FRONT_CENTER][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT] = 7071,
125     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_DOWNMIX_POSITION_TOP_FRONT_CENTER][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT] = 7071,
126     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_DOWNMIX_POSITION_TOP_REAR_LEFT][PA_DOWNMIX_POSITION_TOP_REAR_LEFT] = 10000,
127     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT] = 10000,
128     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_LEFT] = 7071,
129     [PA_CHANNEL_LAYOUT_5POINT1POINT4][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT] = 7071,
130 
131     /* Downmix table for 7POINT1 */
132     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_FRONT_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 10000,
133     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_FRONT_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 10000,
134     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_FRONT_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 10000,
135     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_LFE][PA_CHANNEL_POSITION_LFE] = 10000,
136     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_REAR_LEFT][PA_CHANNEL_POSITION_REAR_LEFT] = 10000,
137     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_REAR_RIGHT][PA_CHANNEL_POSITION_REAR_RIGHT] = 10000,
138     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_SIDE_RIGHT][PA_CHANNEL_POSITION_SIDE_RIGHT] = 10000,
139     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_SIDE_LEFT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
140     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 5946,
141     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 7071,
142     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] = 5946,
143     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 7071,
144     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_REAR_LEFT] = 7071,
145     [PA_CHANNEL_LAYOUT_7POINT1][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_REAR_RIGHT] = 7071,
146     [PA_CHANNEL_LAYOUT_7POINT1][PA_DOWNMIX_POSITION_TOP_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 5000,
147     [PA_CHANNEL_LAYOUT_7POINT1][PA_DOWNMIX_POSITION_TOP_CENTER][PA_CHANNEL_POSITION_SIDE_LEFT] = 5000,
148     [PA_CHANNEL_LAYOUT_7POINT1][PA_DOWNMIX_POSITION_TOP_CENTER][PA_CHANNEL_POSITION_SIDE_RIGHT] = 5000,
149     [PA_CHANNEL_LAYOUT_7POINT1][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 10000,
150     [PA_CHANNEL_LAYOUT_7POINT1][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 10000,
151     [PA_CHANNEL_LAYOUT_7POINT1][PA_DOWNMIX_POSITION_TOP_FRONT_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 10000,
152     [PA_CHANNEL_LAYOUT_7POINT1][PA_DOWNMIX_POSITION_TOP_REAR_LEFT][PA_CHANNEL_POSITION_REAR_LEFT] = 10000,
153     [PA_CHANNEL_LAYOUT_7POINT1][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT][PA_CHANNEL_POSITION_REAR_RIGHT] = 10000,
154     [PA_CHANNEL_LAYOUT_7POINT1][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_CHANNEL_POSITION_REAR_LEFT] = 7071,
155     [PA_CHANNEL_LAYOUT_7POINT1][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_CHANNEL_POSITION_REAR_RIGHT] = 7071,
156 
157     /* downmix table for 7POINT1POINT2 */
158     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_FRONT_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 10000,
159     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_FRONT_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 10000,
160     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_FRONT_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 10000,
161     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_LFE][PA_CHANNEL_POSITION_LFE] = 10000,
162     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_REAR_LEFT][PA_CHANNEL_POSITION_REAR_LEFT] = 10000,
163     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_REAR_RIGHT][PA_CHANNEL_POSITION_REAR_RIGHT] = 10000,
164     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_SIDE_RIGHT][PA_CHANNEL_POSITION_SIDE_RIGHT] = 10000,
165     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_SIDE_LEFT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
166     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 5946,
167     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] =
168         7071,
169     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] =
170         5946,
171     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] =
172         7071,
173     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_REAR_LEFT] = 7071,
174     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_REAR_RIGHT] = 7071,
175     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_DOWNMIX_POSITION_TOP_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_LEFT] = 7071,
176     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_DOWNMIX_POSITION_TOP_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT] = 7071,
177     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 10000,
178     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 10000,
179     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_DOWNMIX_POSITION_TOP_FRONT_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 10000,
180     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_DOWNMIX_POSITION_TOP_REAR_LEFT][PA_DOWNMIX_POSITION_TOP_REAR_LEFT] = 10000,
181     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT] = 10000,
182     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_LEFT] = 7071,
183     [PA_CHANNEL_LAYOUT_7POINT1POINT2][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT] = 7071,
184 
185     /* downmix table for 7POINT1POINT4*/
186     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_FRONT_LEFT][PA_CHANNEL_POSITION_FRONT_LEFT] = 10000,
187     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_FRONT_RIGHT][PA_CHANNEL_POSITION_FRONT_RIGHT] = 10000,
188     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_FRONT_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] = 10000,
189     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_LFE][PA_CHANNEL_POSITION_LFE] = 10000,
190     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_REAR_LEFT][PA_CHANNEL_POSITION_REAR_LEFT] = 10000,
191     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_REAR_RIGHT][PA_CHANNEL_POSITION_REAR_RIGHT] = 10000,
192     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_SIDE_RIGHT][PA_CHANNEL_POSITION_SIDE_RIGHT] = 10000,
193     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_SIDE_LEFT][PA_CHANNEL_POSITION_SIDE_LEFT] = 10000,
194     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_LEFT] = 5946,
195     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] =
196         7071,
197     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_RIGHT] =
198         5946,
199     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER][PA_CHANNEL_POSITION_FRONT_CENTER] =
200         7071,
201     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_REAR_LEFT] = 7071,
202     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_CHANNEL_POSITION_REAR_CENTER][PA_CHANNEL_POSITION_REAR_RIGHT] = 7071,
203     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_DOWNMIX_POSITION_TOP_CENTER][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT] = 5000,
204     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_DOWNMIX_POSITION_TOP_CENTER][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT] = 5000,
205     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_DOWNMIX_POSITION_TOP_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_LEFT] = 5000,
206     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_DOWNMIX_POSITION_TOP_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT] = 5000,
207     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT] = 10000,
208     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT] = 10000,
209     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_DOWNMIX_POSITION_TOP_FRONT_CENTER][PA_DOWNMIX_POSITION_TOP_FRONT_LEFT] = 7071,
210     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_DOWNMIX_POSITION_TOP_FRONT_CENTER][PA_DOWNMIX_POSITION_TOP_FRONT_RIGHT] = 7071,
211     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_DOWNMIX_POSITION_TOP_REAR_LEFT][PA_DOWNMIX_POSITION_TOP_REAR_LEFT] = 10000,
212     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT] = 10000,
213     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_LEFT] = 7071,
214     [PA_CHANNEL_LAYOUT_7POINT1POINT4][PA_DOWNMIX_POSITION_TOP_REAR_CENTER][PA_DOWNMIX_POSITION_TOP_REAR_RIGHT] = 7071,
215 };
216 
pa_channel_map_to_index(const pa_channel_map *map)217 pa_channel_layout_index_t pa_channel_map_to_index(const pa_channel_map *map)
218 {
219     pa_bitset_t in_map[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX)];
220     unsigned c;
221 
222     pa_assert(map);
223 
224     pa_return_val_if_fail(pa_channel_map_valid(map), PA_CHANNEL_LAYOUT_OTHER);
225 
226     memset(in_map, 0, sizeof(in_map));
227 
228     for (c = 0; c < map->channels; c++) { pa_bitset_set(in_map, map->map[c], true); }
229 
230     if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, -1)) {
231         return PA_CHANNEL_LAYOUT_STEREO;
232     }
233 
234     if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, PA_CHANNEL_POSITION_FRONT_LEFT,
235         PA_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT,
236         PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, -1)) { return PA_CHANNEL_LAYOUT_5POINT1; }
237 
238     if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, PA_CHANNEL_POSITION_FRONT_LEFT,
239         PA_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT,
240         PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, PA_CHANNEL_POSITION_TOP_REAR_LEFT,
241         PA_CHANNEL_POSITION_TOP_REAR_RIGHT, -1)) { return PA_CHANNEL_LAYOUT_5POINT1POINT2; }
242 
243     if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, PA_CHANNEL_POSITION_FRONT_LEFT,
244         PA_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT,
245         PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, PA_CHANNEL_POSITION_TOP_REAR_LEFT,
246         PA_CHANNEL_POSITION_TOP_REAR_RIGHT, PA_CHANNEL_POSITION_TOP_FRONT_LEFT,
247         PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, -1)) { return PA_CHANNEL_LAYOUT_5POINT1POINT4; }
248 
249     if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, PA_CHANNEL_POSITION_FRONT_LEFT,
250         PA_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT,
251         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_FRONT_CENTER,
252         PA_CHANNEL_POSITION_LFE, -1)) { return PA_CHANNEL_LAYOUT_7POINT1; }
253 
254     if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, PA_CHANNEL_POSITION_FRONT_LEFT,
255         PA_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT,
256         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_FRONT_CENTER,
257         PA_CHANNEL_POSITION_LFE, PA_CHANNEL_POSITION_TOP_REAR_LEFT,  PA_CHANNEL_POSITION_TOP_REAR_RIGHT, -1)) {
258         return PA_CHANNEL_LAYOUT_7POINT1POINT2;
259     }
260     if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, PA_CHANNEL_POSITION_FRONT_LEFT,
261         PA_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT,
262         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_FRONT_CENTER,
263         PA_CHANNEL_POSITION_LFE, PA_CHANNEL_POSITION_TOP_REAR_LEFT,  PA_CHANNEL_POSITION_TOP_REAR_RIGHT,
264         PA_CHANNEL_POSITION_TOP_FRONT_LEFT, PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, -1)) {
265         return PA_CHANNEL_LAYOUT_7POINT1POINT4;
266     }
267     return PA_CHANNEL_LAYOUT_OTHER;
268 }
269 
pa_to_downmix_position(const pa_channel_position_t channel_position)270 int pa_to_downmix_position(const pa_channel_position_t channel_position)
271 {
272     if (channel_position < PA_CHANNEL_POSITION_AUX0) {
273         return channel_position;
274     } else if (channel_position > PA_CHANNEL_POSITION_AUX31) { /* skip AUX0 - AUX31 */
275         return channel_position - SKIPPED_CHANNEL_COUNT;
276     } else {
277     /* AUX0 - AUX31, which are not in use now */
278     /* do nothing to map table */
279         return 0;
280     }
281 }