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 #include <assert.h>
18 #include <audio_utils/format.h>
19 #include <audio_utils/primitives.h>
20 
21 void memcpy_by_audio_format(void *dst, audio_format_t dst_format,
22         const void *src, audio_format_t src_format, size_t count)
23 {
24     /* default cases for error falls through to assert(false) below. */
25     if (dst_format == src_format) {
26         switch (dst_format) {
27         case AUDIO_FORMAT_PCM_16_BIT:
28         case AUDIO_FORMAT_PCM_FLOAT:
29         case AUDIO_FORMAT_PCM_8_BIT:
30         case AUDIO_FORMAT_PCM_24_BIT_PACKED:
31         case AUDIO_FORMAT_PCM_32_BIT:
32         case AUDIO_FORMAT_PCM_8_24_BIT:
33             if (dst != src) {
34                 // TODO: should assert if memory regions overlap.
35                 memcpy(dst, src, count * audio_bytes_per_sample(dst_format));
36             }
37             return;
38         default:
39             break;
40         }
41     }
42     switch (dst_format) {
43     case AUDIO_FORMAT_PCM_16_BIT:
44         switch (src_format) {
45         case AUDIO_FORMAT_PCM_FLOAT:
46             memcpy_to_i16_from_float((int16_t*)dst, (float*)src, count);
47             return;
48         case AUDIO_FORMAT_PCM_8_BIT:
49             memcpy_to_i16_from_u8((int16_t*)dst, (uint8_t*)src, count);
50             return;
51         case AUDIO_FORMAT_PCM_24_BIT_PACKED:
52             memcpy_to_i16_from_p24((int16_t*)dst, (uint8_t*)src, count);
53             return;
54         case AUDIO_FORMAT_PCM_32_BIT:
55             memcpy_to_i16_from_i32((int16_t*)dst, (int32_t*)src, count);
56             return;
57         case AUDIO_FORMAT_PCM_8_24_BIT:
58             memcpy_to_i16_from_q8_23((int16_t*)dst, (int32_t*)src, count);
59             return;
60         default:
61             break;
62         }
63         break;
64     case AUDIO_FORMAT_PCM_FLOAT:
65         switch (src_format) {
66         case AUDIO_FORMAT_PCM_16_BIT:
67             memcpy_to_float_from_i16((float*)dst, (int16_t*)src, count);
68             return;
69         case AUDIO_FORMAT_PCM_8_BIT:
70             memcpy_to_float_from_u8((float*)dst, (uint8_t*)src, count);
71             return;
72         case AUDIO_FORMAT_PCM_24_BIT_PACKED:
73             memcpy_to_float_from_p24((float*)dst, (uint8_t*)src, count);
74             return;
75         case AUDIO_FORMAT_PCM_32_BIT:
76             memcpy_to_float_from_i32((float*)dst, (int32_t*)src, count);
77             return;
78         case AUDIO_FORMAT_PCM_8_24_BIT:
79             memcpy_to_float_from_q8_23((float*)dst, (int32_t*)src, count);
80             return;
81         default:
82             break;
83         }
84         break;
85     case AUDIO_FORMAT_PCM_8_BIT:
86         switch (src_format) {
87         case AUDIO_FORMAT_PCM_16_BIT:
88             memcpy_to_u8_from_i16((uint8_t*)dst, (int16_t*)src, count);
89             return;
90         case AUDIO_FORMAT_PCM_FLOAT:
91             memcpy_to_u8_from_float((uint8_t*)dst, (float*)src, count);
92             return;
93         // The following converts HAL to AudioRecord formats.
94         case AUDIO_FORMAT_PCM_24_BIT_PACKED:
95             memcpy_to_u8_from_p24((uint8_t*)dst, (uint8_t*)src, count);
96             return;
97         case AUDIO_FORMAT_PCM_32_BIT:
98             memcpy_to_u8_from_i32((uint8_t*)dst, (int32_t*)src, count);
99             return;
100         case AUDIO_FORMAT_PCM_8_24_BIT:
101             memcpy_to_u8_from_q8_23((uint8_t*)dst, (int32_t*)src, count);
102             return;
103         default:
104             break;
105         }
106         break;
107     case AUDIO_FORMAT_PCM_24_BIT_PACKED:
108         switch (src_format) {
109         case AUDIO_FORMAT_PCM_16_BIT:
110             memcpy_to_p24_from_i16((uint8_t*)dst, (int16_t*)src, count);
111             return;
112         case AUDIO_FORMAT_PCM_FLOAT:
113             memcpy_to_p24_from_float((uint8_t*)dst, (float*)src, count);
114             return;
115         case AUDIO_FORMAT_PCM_32_BIT:
116             memcpy_to_p24_from_i32((uint8_t*)dst, (int32_t*)src, count);
117             return;
118         case AUDIO_FORMAT_PCM_8_24_BIT:
119             memcpy_to_p24_from_q8_23((uint8_t*)dst, (int32_t*)src, count);
120             return;
121         default:
122             break;
123         }
124         break;
125     case AUDIO_FORMAT_PCM_32_BIT:
126         switch (src_format) {
127         case AUDIO_FORMAT_PCM_16_BIT:
128             memcpy_to_i32_from_i16((int32_t*)dst, (int16_t*)src, count);
129             return;
130         case AUDIO_FORMAT_PCM_FLOAT:
131             memcpy_to_i32_from_float((int32_t*)dst, (float*)src, count);
132             return;
133         case AUDIO_FORMAT_PCM_24_BIT_PACKED:
134             memcpy_to_i32_from_p24((int32_t*)dst, (uint8_t *)src, count);
135             return;
136         default:
137             break;
138         }
139         break;
140     case AUDIO_FORMAT_PCM_8_24_BIT:
141         switch (src_format) {
142         case AUDIO_FORMAT_PCM_16_BIT:
143             memcpy_to_q8_23_from_i16((int32_t*)dst, (int16_t*)src, count);
144             return;
145         case AUDIO_FORMAT_PCM_FLOAT:
146             memcpy_to_q8_23_from_float_with_clamp((int32_t*)dst, (float*)src, count);
147             return;
148         case AUDIO_FORMAT_PCM_24_BIT_PACKED: {
149             memcpy_to_q8_23_from_p24((int32_t *)dst, (uint8_t *)src, count);
150             return;
151         }
152         default:
153             break;
154         }
155         break;
156     default:
157         break;
158     }
159     // invalid src format for dst format
160     assert(false);
161 }
162 
163 size_t memcpy_by_index_array_initialization_from_channel_mask(int8_t *idxary, size_t arysize,
164         audio_channel_mask_t dst_channel_mask, audio_channel_mask_t src_channel_mask)
165 {
166     const audio_channel_representation_t src_representation =
167             audio_channel_mask_get_representation(src_channel_mask);
168     const audio_channel_representation_t dst_representation =
169             audio_channel_mask_get_representation(dst_channel_mask);
170     const uint32_t src_bits = audio_channel_mask_get_bits(src_channel_mask);
171     const uint32_t dst_bits = audio_channel_mask_get_bits(dst_channel_mask);
172 
173     switch (src_representation) {
174     case AUDIO_CHANNEL_REPRESENTATION_POSITION:
175         switch (dst_representation) {
176         case AUDIO_CHANNEL_REPRESENTATION_POSITION:
177             return memcpy_by_index_array_initialization(idxary, arysize,
178                     dst_bits, src_bits);
179         case AUDIO_CHANNEL_REPRESENTATION_INDEX:
180             return memcpy_by_index_array_initialization_dst_index(idxary, arysize,
181                     dst_bits, src_bits);
182         default:
183             return 0;
184         }
185         break;
186     case AUDIO_CHANNEL_REPRESENTATION_INDEX:
187         switch (dst_representation) {
188         case AUDIO_CHANNEL_REPRESENTATION_POSITION:
189             return memcpy_by_index_array_initialization_src_index(idxary, arysize,
190                     dst_bits, src_bits);
191         case AUDIO_CHANNEL_REPRESENTATION_INDEX:
192             return memcpy_by_index_array_initialization(idxary, arysize,
193                     dst_bits, src_bits);
194         default:
195             return 0;
196         }
197         break;
198     default:
199         return 0;
200     }
201 }
202 
203 void accumulate_by_audio_format(void *dst, const void *src,
204         audio_format_t format, size_t count) {
205     switch (format) {
206     case AUDIO_FORMAT_PCM_16_BIT:
207         accumulate_i16((int16_t *)dst, (const int16_t *)src, count);
208         return;
209     case AUDIO_FORMAT_PCM_FLOAT:
210         accumulate_float((float *)dst, (const float *)src, count);
211         return;
212     case AUDIO_FORMAT_PCM_8_BIT:
213         accumulate_u8((uint8_t *)dst, (const uint8_t *)src, count);
214         return;
215     case AUDIO_FORMAT_PCM_24_BIT_PACKED:
216         accumulate_p24((uint8_t *)dst, (const uint8_t *)src, count);
217         return;
218     case AUDIO_FORMAT_PCM_32_BIT:
219         accumulate_i32((int32_t *)dst, (const int32_t *)src, count);
220         return;
221     case AUDIO_FORMAT_PCM_8_24_BIT:
222         accumulate_q8_23((int32_t *)dst, (const int32_t *)src, count);
223         return;
224     default:
225         break;
226     }
227     // invalid format
228     assert(false);
229 }
230