1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_AUDIO_CHANNELS_H
18 #define ANDROID_AUDIO_CHANNELS_H
19 
20 #include <system/audio.h>
21 
22 #ifdef __cplusplus
23 
24 // New development in channels namespace.
25 namespace android::audio_utils::channels {
26 
27 /**
28  * Returns a particular side (left, right, center) associated
29  * with a channel position mask bit index.
30  * This is a fixed geometrical constant for a given channel mask.
31  *
32  * For the channel mask spec, see system/media/audio/include/system/audio*.h.
33  *
34  * Special Note: if there are two LFE speakers and bass management is used,
35  * then AUDIO_CHANNEL_OUT_LOW_FREQUENCY speaker is on the left side and receives
36  * all bass from left side speakers that they cannot reproduce,
37  * likewise AUDIO_CHANNEL_OUT_LOW_FREQUENCY_2 is used for the right side
38  * (https://www.itu.int/dms_pub/itu-r/opb/rep/R-REP-BS.2159-4-2012-PDF-E.pdf#page=15).
39  *
40  * For simplicity, both AUDIO_CHANNEL_OUT_LOW_FREQUENCY and
41  * AUDIO_CHANNEL_OUT_LOW_FREQUENCY_2 are assigned to the center channel,
42  * which is a safe approximation given the lack of directionality of LFE.
43  * Specific handling for the presence of two LFE speakers must be handled
44  * elsewhere.
45  *
46  * \param idx index of bit in the channel position mask.
47  * \return    side constant.
48  */
49 enum AUDIO_GEOMETRY_SIDE {
50     AUDIO_GEOMETRY_SIDE_LEFT,
51     AUDIO_GEOMETRY_SIDE_CENTER,
52     AUDIO_GEOMETRY_SIDE_RIGHT,
53 };
54 // static constexpr arrays cannot be declared in block scope.
55 // inline allows multiple definition, single object address.
56 constexpr inline AUDIO_GEOMETRY_SIDE kSideFromChannelIdx[] = {
57     AUDIO_GEOMETRY_SIDE_LEFT,   // AUDIO_CHANNEL_OUT_FRONT_LEFT            = 0x1u,
58     AUDIO_GEOMETRY_SIDE_RIGHT,  // AUDIO_CHANNEL_OUT_FRONT_RIGHT           = 0x2u,
59     AUDIO_GEOMETRY_SIDE_CENTER, // AUDIO_CHANNEL_OUT_FRONT_CENTER          = 0x4u,
60     AUDIO_GEOMETRY_SIDE_CENTER, // AUDIO_CHANNEL_OUT_LOW_FREQUENCY         = 0x8u,
61     AUDIO_GEOMETRY_SIDE_LEFT,   // AUDIO_CHANNEL_OUT_BACK_LEFT             = 0x10u,
62     AUDIO_GEOMETRY_SIDE_RIGHT,  // AUDIO_CHANNEL_OUT_BACK_RIGHT            = 0x20u,
63     AUDIO_GEOMETRY_SIDE_LEFT,   // AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER  = 0x40u,
64     AUDIO_GEOMETRY_SIDE_RIGHT,  // AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80u,
65     AUDIO_GEOMETRY_SIDE_CENTER, // AUDIO_CHANNEL_OUT_BACK_CENTER           = 0x100u,
66     AUDIO_GEOMETRY_SIDE_LEFT,   // AUDIO_CHANNEL_OUT_SIDE_LEFT             = 0x200u,
67     AUDIO_GEOMETRY_SIDE_RIGHT,  // AUDIO_CHANNEL_OUT_SIDE_RIGHT            = 0x400u,
68     AUDIO_GEOMETRY_SIDE_CENTER, // AUDIO_CHANNEL_OUT_TOP_CENTER            = 0x800u,
69     AUDIO_GEOMETRY_SIDE_LEFT,   // AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT        = 0x1000u,
70     AUDIO_GEOMETRY_SIDE_CENTER, // AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER      = 0x2000u,
71     AUDIO_GEOMETRY_SIDE_RIGHT,  // AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT       = 0x4000u,
72     AUDIO_GEOMETRY_SIDE_LEFT,   // AUDIO_CHANNEL_OUT_TOP_BACK_LEFT         = 0x8000u,
73     AUDIO_GEOMETRY_SIDE_CENTER, // AUDIO_CHANNEL_OUT_TOP_BACK_CENTER       = 0x10000u,
74     AUDIO_GEOMETRY_SIDE_RIGHT,  // AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT        = 0x20000u,
75     AUDIO_GEOMETRY_SIDE_LEFT,   // AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT         = 0x40000u,
76     AUDIO_GEOMETRY_SIDE_RIGHT,  // AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT        = 0x80000u,
77     AUDIO_GEOMETRY_SIDE_LEFT,   // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_LEFT     = 0x100000u,
78     AUDIO_GEOMETRY_SIDE_CENTER, // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_CENTER   = 0x200000u,
79     AUDIO_GEOMETRY_SIDE_RIGHT,  // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_RIGHT    = 0x400000u,
80     AUDIO_GEOMETRY_SIDE_CENTER, // AUDIO_CHANNEL_OUT_LOW_FREQUENCY_2       = 0x800000u,
81 };
sideFromChannelIdx(size_t idx)82 constexpr inline AUDIO_GEOMETRY_SIDE sideFromChannelIdx(size_t idx) {
83     static_assert(std::size(kSideFromChannelIdx) == FCC_24);
84     if (idx < std::size(kSideFromChannelIdx)) return kSideFromChannelIdx[idx];
85     return AUDIO_GEOMETRY_SIDE_CENTER;
86 }
87 
88 /**
89  * Returns a particular height (bottom, middle, top) associated
90  * with a channel position mask bit index.
91  * This is a fixed geometrical constant for a given channel mask.
92  *
93  * For the channel mask spec, see system/media/audio/include/system/audio*.h.
94  *
95  * \param idx index of bit in the channel position mask.
96  * \return    height constant.
97  */
98 enum AUDIO_GEOMETRY_HEIGHT {
99     AUDIO_GEOMETRY_HEIGHT_BOTTOM,
100     AUDIO_GEOMETRY_HEIGHT_MIDDLE,
101     AUDIO_GEOMETRY_HEIGHT_TOP,
102 };
103 // static constexpr arrays cannot be declared in block scope.
104 // inline allows multiple definition, single object address.
105 constexpr inline AUDIO_GEOMETRY_HEIGHT kHeightFromChannelIdx [] = {
106     AUDIO_GEOMETRY_HEIGHT_MIDDLE, // AUDIO_CHANNEL_OUT_FRONT_LEFT            = 0x1u,
107     AUDIO_GEOMETRY_HEIGHT_MIDDLE, // AUDIO_CHANNEL_OUT_FRONT_RIGHT           = 0x2u,
108     AUDIO_GEOMETRY_HEIGHT_MIDDLE, // AUDIO_CHANNEL_OUT_FRONT_CENTER          = 0x4u,
109     AUDIO_GEOMETRY_HEIGHT_BOTTOM, // AUDIO_CHANNEL_OUT_LOW_FREQUENCY         = 0x8u,
110     AUDIO_GEOMETRY_HEIGHT_MIDDLE, // AUDIO_CHANNEL_OUT_BACK_LEFT             = 0x10u,
111     AUDIO_GEOMETRY_HEIGHT_MIDDLE, // AUDIO_CHANNEL_OUT_BACK_RIGHT            = 0x20u,
112     AUDIO_GEOMETRY_HEIGHT_MIDDLE, // AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER  = 0x40u,
113     AUDIO_GEOMETRY_HEIGHT_MIDDLE, // AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80u,
114     AUDIO_GEOMETRY_HEIGHT_MIDDLE, // AUDIO_CHANNEL_OUT_BACK_CENTER           = 0x100u,
115     AUDIO_GEOMETRY_HEIGHT_MIDDLE, // AUDIO_CHANNEL_OUT_SIDE_LEFT             = 0x200u,
116     AUDIO_GEOMETRY_HEIGHT_MIDDLE, // AUDIO_CHANNEL_OUT_SIDE_RIGHT            = 0x400u,
117     AUDIO_GEOMETRY_HEIGHT_TOP,    // AUDIO_CHANNEL_OUT_TOP_CENTER            = 0x800u,
118     AUDIO_GEOMETRY_HEIGHT_TOP,    // AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT        = 0x1000u,
119     AUDIO_GEOMETRY_HEIGHT_TOP,    // AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER      = 0x2000u,
120     AUDIO_GEOMETRY_HEIGHT_TOP,    // AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT       = 0x4000u,
121     AUDIO_GEOMETRY_HEIGHT_TOP,    // AUDIO_CHANNEL_OUT_TOP_BACK_LEFT         = 0x8000u,
122     AUDIO_GEOMETRY_HEIGHT_TOP,    // AUDIO_CHANNEL_OUT_TOP_BACK_CENTER       = 0x10000u,
123     AUDIO_GEOMETRY_HEIGHT_TOP,    // AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT        = 0x20000u,
124     AUDIO_GEOMETRY_HEIGHT_TOP,    // AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT         = 0x40000u,
125     AUDIO_GEOMETRY_HEIGHT_TOP,    // AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT        = 0x80000u,
126     AUDIO_GEOMETRY_HEIGHT_BOTTOM, // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_LEFT     = 0x100000u,
127     AUDIO_GEOMETRY_HEIGHT_BOTTOM, // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_CENTER   = 0x200000u,
128     AUDIO_GEOMETRY_HEIGHT_BOTTOM, // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_RIGHT    = 0x400000u,
129     AUDIO_GEOMETRY_HEIGHT_BOTTOM, // AUDIO_CHANNEL_OUT_LOW_FREQUENCY_2       = 0x800000u,
130 };
heightFromChannelIdx(size_t idx)131 constexpr inline AUDIO_GEOMETRY_HEIGHT heightFromChannelIdx(size_t idx) {
132     static_assert(std::size(kHeightFromChannelIdx) == FCC_24);
133     if (idx < std::size(kHeightFromChannelIdx)) return kHeightFromChannelIdx[idx];
134     return AUDIO_GEOMETRY_HEIGHT_MIDDLE;
135 }
136 
137 /**
138  * Returns a particular depth (front, middle (aka side), back) associated
139  * with a channel position mask bit index.
140  * This is a fixed geometrical constant for a given channel mask.
141  *
142  * For the channel mask spec, see system/media/audio/include/system/audio*.h.
143  *
144  * \param idx index of bit in the channel position mask.
145  * \return    depth constant.
146  */
147 enum AUDIO_GEOMETRY_DEPTH {
148     AUDIO_GEOMETRY_DEPTH_FRONT,
149     AUDIO_GEOMETRY_DEPTH_MIDDLE,
150     AUDIO_GEOMETRY_DEPTH_BACK,
151 };
152 // static constexpr arrays cannot be declared in block scope.
153 // inline allows multiple definition, single object address.
154 constexpr inline AUDIO_GEOMETRY_DEPTH kDepthFromChannelIdx[] = {
155     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_FRONT_LEFT            = 0x1u,
156     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_FRONT_RIGHT           = 0x2u,
157     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_FRONT_CENTER          = 0x4u,
158     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_LOW_FREQUENCY         = 0x8u,
159     AUDIO_GEOMETRY_DEPTH_BACK,   // AUDIO_CHANNEL_OUT_BACK_LEFT             = 0x10u,
160     AUDIO_GEOMETRY_DEPTH_BACK,   // AUDIO_CHANNEL_OUT_BACK_RIGHT            = 0x20u,
161     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER  = 0x40u,
162     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80u,
163     AUDIO_GEOMETRY_DEPTH_BACK,   // AUDIO_CHANNEL_OUT_BACK_CENTER           = 0x100u,
164     AUDIO_GEOMETRY_DEPTH_MIDDLE, // AUDIO_CHANNEL_OUT_SIDE_LEFT             = 0x200u,
165     AUDIO_GEOMETRY_DEPTH_MIDDLE, // AUDIO_CHANNEL_OUT_SIDE_RIGHT            = 0x400u,
166     AUDIO_GEOMETRY_DEPTH_MIDDLE, // AUDIO_CHANNEL_OUT_TOP_CENTER            = 0x800u,
167     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT        = 0x1000u,
168     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER      = 0x2000u,
169     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT       = 0x4000u,
170     AUDIO_GEOMETRY_DEPTH_BACK,   // AUDIO_CHANNEL_OUT_TOP_BACK_LEFT         = 0x8000u,
171     AUDIO_GEOMETRY_DEPTH_BACK,   // AUDIO_CHANNEL_OUT_TOP_BACK_CENTER       = 0x10000u,
172     AUDIO_GEOMETRY_DEPTH_BACK,   // AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT        = 0x20000u,
173     AUDIO_GEOMETRY_DEPTH_MIDDLE, // AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT         = 0x40000u,
174     AUDIO_GEOMETRY_DEPTH_MIDDLE, // AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT        = 0x80000u,
175     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_LEFT     = 0x100000u,
176     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_CENTER   = 0x200000u,
177     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_RIGHT    = 0x400000u,
178     AUDIO_GEOMETRY_DEPTH_FRONT,  // AUDIO_CHANNEL_OUT_LOW_FREQUENCY_2       = 0x800000u,
179 };
depthFromChannelIdx(size_t idx)180 constexpr inline AUDIO_GEOMETRY_DEPTH depthFromChannelIdx(size_t idx) {
181     static_assert(std::size(kDepthFromChannelIdx) == FCC_24);
182     if (idx < std::size(kDepthFromChannelIdx)) return kDepthFromChannelIdx[idx];
183     return AUDIO_GEOMETRY_DEPTH_FRONT;
184 }
185 
186 /**
187  * Returns the pair channel position mask bit index as determined by
188  * AUDIO_GEOMETRY_SIDE_LEFT and AUDIO_GEOMETRY_SIDE_RIGHT characteristics.
189  *
190  * For example a bit index of 0 (AUDIO_CHANNEL_OUT_FRONT_LEFT) returns
191  * a pair bit index of 1 (AUDIO_CHANNEL_OUT_FRONT_RIGHT).
192  *
193  * If there is no left/right characteristic, then -1 is returned.
194  * For example, a bit index of 2 (AUDIO_CHANNEL_OUT_FRONT_CENTER) returns
195  * a pair bit index of -1 (doesn't exist).
196  *
197  * For the channel mask spec, see system/media/audio/include/system/audio*.h.
198  *
199  * \param idx index of bit in the channel position mask.
200  * \return    index of bit of the pair if non-negative, or -1 if it doesn't exist.
201  */
202 
203 #pragma push_macro("CHANNEL_ASSOCIATE")
204 #undef CHANNEL_ASSOCIATE
205 #define CHANNEL_ASSOCIATE(x, y) \
206  [__builtin_ctz(x)] = __builtin_ctz(y), [__builtin_ctz(y)] = __builtin_ctz(x),
207 
208 #pragma GCC diagnostic push
209 #pragma GCC diagnostic ignored "-Winitializer-overrides"  // we use override array assignment
210 
211 constexpr inline int kPairIdxFromChannelIdx[FCC_24] = {
212     [ 0 ... 23 ] = -1,  // everything defaults to -1 unless overridden below.
213     CHANNEL_ASSOCIATE(AUDIO_CHANNEL_OUT_FRONT_LEFT, AUDIO_CHANNEL_OUT_FRONT_RIGHT)
214     // AUDIO_CHANNEL_OUT_FRONT_CENTER          = 0x4u,
215     // AUDIO_CHANNEL_OUT_LOW_FREQUENCY         = 0x8u,
216     CHANNEL_ASSOCIATE(AUDIO_CHANNEL_OUT_BACK_LEFT, AUDIO_CHANNEL_OUT_BACK_RIGHT)
217     CHANNEL_ASSOCIATE(
218             AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER, AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER)
219     // AUDIO_CHANNEL_OUT_BACK_CENTER           = 0x100u,
220     CHANNEL_ASSOCIATE(AUDIO_CHANNEL_OUT_SIDE_LEFT, AUDIO_CHANNEL_OUT_SIDE_RIGHT)
221     // AUDIO_CHANNEL_OUT_TOP_CENTER            = 0x800u,
222     CHANNEL_ASSOCIATE(AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT, AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT)
223     // AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER      = 0x2000u,
224     CHANNEL_ASSOCIATE(AUDIO_CHANNEL_OUT_TOP_BACK_LEFT, AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT)
225     // AUDIO_CHANNEL_OUT_TOP_BACK_CENTER       = 0x10000u,
226     CHANNEL_ASSOCIATE(AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT, AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT)
227     CHANNEL_ASSOCIATE(AUDIO_CHANNEL_OUT_BOTTOM_FRONT_LEFT, AUDIO_CHANNEL_OUT_BOTTOM_FRONT_RIGHT)
228     // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_CENTER   = 0x200000u,
229     // AUDIO_CHANNEL_OUT_LOW_FREQUENCY_2       = 0x800000u,
230 };
231 #pragma GCC diagnostic pop
232 #pragma pop_macro("CHANNEL_ASSOCIATE")
233 
pairIdxFromChannelIdx(size_t idx)234 constexpr inline ssize_t pairIdxFromChannelIdx(size_t idx) {
235     static_assert(std::size(kPairIdxFromChannelIdx) == FCC_24);
236     if (idx < std::size(kPairIdxFromChannelIdx)) return kPairIdxFromChannelIdx[idx];
237     return -1;
238 }
239 
240 } // android::audio_utils::channels
241 
242 #endif // __cplusplus
243 
244 /** \cond */
245 __BEGIN_DECLS
246 /** \endcond */
247 
248 /**
249  * Expands or contracts sample data from one interleaved channel format to another.
250  * Expanded channels are filled with zeros and put at the end of each audio frame.
251  * Contracted channels are omitted from the end of each audio frame.
252  *
253  *   \param in_buff              points to the buffer of samples
254  *   \param in_buff_chans        Specifies the number of channels in the input buffer.
255  *   \param out_buff             points to the buffer to receive converted samples.
256  *   \param out_buff_chans       Specifies the number of channels in the output buffer.
257  *   \param sample_size_in_bytes Specifies the number of bytes per sample. 1, 2, 3, 4 are
258  *     currently valid.
259  *   \param num_in_bytes         size of input buffer in bytes
260  *
261  * \return
262  *   the number of bytes of output data or 0 if an error occurs.
263  *
264  * \note
265  *   The out and sums buffers must either be completely separate (non-overlapping), or
266  *   they must both start at the same address. Partially overlapping buffers are not supported.
267  */
268 size_t adjust_channels(const void* in_buff, size_t in_buff_chans,
269                        void* out_buff, size_t out_buff_chans,
270                        unsigned sample_size_in_bytes, size_t num_in_bytes);
271 
272 /**
273  * Expands or contracts sample data from one interleaved channel format to another.
274  * Extra expanded channels are left alone in the output buffer.
275  * Contracted channels are omitted from the end of each audio frame.
276  *
277  *   \param in_buff              points to the buffer of samples
278  *   \param in_buff_chans        Specifies the number of channels in the input buffer.
279  *   \param out_buff             points to the buffer to receive converted samples.
280  *   \param out_buff_chans       Specifies the number of channels in the output buffer.
281  *   \param sample_size_in_bytes Specifies the number of bytes per sample. 1, 2, 3, 4 are
282  *     currently valid.
283  *   \param num_in_bytes         size of input buffer in bytes
284  *
285  * \return
286  *   the number of bytes of output data or 0 if an error occurs.
287  *
288  * \note
289  *   The out and in buffers must either be completely separate (non-overlapping), or
290  *   they must both start at the same address. Partially overlapping buffers are not supported.
291  */
292 size_t adjust_selected_channels(const void* in_buff, size_t in_buff_chans,
293                        void* out_buff, size_t out_buff_chans,
294                        unsigned sample_size_in_bytes, size_t num_in_bytes);
295 
296 /**
297  * Expands or contracts sample data from one interleaved channel format to another.
298  * Extra expanded channels are interleaved in from the end of the input buffer.
299  * Contracted channels are copied to the end of the output buffer.
300  *
301  *   \param in_buff              points to the buffer of samples.
302  *   \param in_buff_chans        Specifies the number of channels in the input buffer.
303  *   \param out_buff             points to the buffer to receive converted samples.
304  *   \param out_buff_chans       Specifies the number of channels in the output buffer.
305  *   \param sample_size_in_bytes Specifies the number of bytes per sample. 1, 2, 3, 4 are
306  *     currently valid.
307  *   \param num_in_bytes         size of input buffer in bytes.
308  *
309  * \return
310  *   the number of bytes of output data or 0 if an error occurs.
311  *
312  * \note
313  *   The out and in buffers must be the same length.
314  *   The out and in buffers must either be completely separate (non-overlapping), or
315  *   they must both start at the same address. Partially overlapping buffers are not supported.
316  */
317 size_t adjust_channels_non_destructive(const void* in_buff, size_t in_buff_chans,
318                        void* out_buff, size_t out_buff_chans,
319                        unsigned sample_size_in_bytes, size_t num_in_bytes);
320 
321 /** \cond */
322 __END_DECLS
323 /** \endcond */
324 
325 #endif  // !ANDROID_AUDIO_CHANNELS_H
326