1 /*****************************************************************
2 * gavl - a general purpose audio/video processing library
3 *
4 * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5 * gmerlin-general@lists.sourceforge.net
6 * http://gmerlin.sourceforge.net
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * *****************************************************************/
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <math.h>
25 #include <gavl/gavl.h>
26
27 static const struct
28 {
29 gavl_sample_format_t format;
30 char * name;
31 }
32 sample_format_names[] =
33 {
34 { GAVL_SAMPLE_U8, "Unsigned 8 bit"},
35 { GAVL_SAMPLE_S8, "Signed 8 bit"},
36 { GAVL_SAMPLE_U16, "Unsigned 16 bit"},
37 { GAVL_SAMPLE_S16, "Signed 16 bit"},
38 { GAVL_SAMPLE_S32, "Signed 32 bit"},
39 { GAVL_SAMPLE_FLOAT, "Floating point"},
40 { GAVL_SAMPLE_DOUBLE, "Double precision"},
41 { GAVL_SAMPLE_NONE, "Not specified" },
42 };
43
gavl_sample_format_to_string(gavl_sample_format_t format)44 const char * gavl_sample_format_to_string(gavl_sample_format_t format)
45 {
46 int i;
47 for(i = 0; i < sizeof(sample_format_names)/sizeof(sample_format_names[0]); i++)
48 {
49 if(format == sample_format_names[i].format)
50 return sample_format_names[i].name;
51 }
52 return NULL;
53 }
54
gavl_string_to_sample_format(const char * str)55 gavl_sample_format_t gavl_string_to_sample_format(const char * str)
56 {
57 int i;
58 for(i = 0; i < sizeof(sample_format_names)/sizeof(sample_format_names[0]); i++)
59 {
60 if(!strcmp(str, sample_format_names[i].name))
61 return sample_format_names[i].format;
62 }
63 return GAVL_SAMPLE_NONE;
64 }
65
gavl_num_sample_formats()66 int gavl_num_sample_formats()
67 {
68 return sizeof(sample_format_names)/sizeof(sample_format_names[0])-1;
69 }
70
gavl_get_sample_format(int index)71 gavl_sample_format_t gavl_get_sample_format(int index)
72 {
73 if((index >= 0) &&
74 (index < sizeof(sample_format_names)/sizeof(sample_format_names[0])))
75 return sample_format_names[index].format;
76 return GAVL_SAMPLE_NONE;
77 }
78
79 static const struct
80 {
81 gavl_interleave_mode_t mode;
82 char * name;
83 }
84 interleave_mode_names[] =
85 {
86 { GAVL_INTERLEAVE_NONE, "Not interleaved" },
87 { GAVL_INTERLEAVE_2, "Interleaved channel pairs" },
88 { GAVL_INTERLEAVE_ALL, "All channels interleaved" },
89 };
90
91
gavl_interleave_mode_to_string(gavl_interleave_mode_t mode)92 const char * gavl_interleave_mode_to_string(gavl_interleave_mode_t mode)
93 {
94 int i;
95 for(i = 0;
96 i < sizeof(interleave_mode_names)/sizeof(interleave_mode_names[0]);
97 i++)
98 {
99 if(mode == interleave_mode_names[i].mode)
100 return interleave_mode_names[i].name;
101 }
102 return NULL;
103 }
104
105 static const struct
106 {
107 gavl_channel_id_t id;
108 char * name;
109 }
110 channel_id_names[] =
111 {
112 #if 0
113 GAVL_CHID_NONE = 0, /*!< Undefined */
114 GAVL_CHID_FRONT_CENTER, /*!< For mono */
115 GAVL_CHID_FRONT_LEFT, /*!< Front left */
116 GAVL_CHID_FRONT_RIGHT, /*!< Front right */
117 GAVL_CHID_FRONT_CENTER_LEFT, /*!< Left of Center */
118 GAVL_CHID_FRONT_CENTER_RIGHT, /*!< Right of Center */
119 GAVL_CHID_REAR_LEFT, /*!< Rear left */
120 GAVL_CHID_REAR_RIGHT, /*!< Rear right */
121 GAVL_CHID_REAR_CENTER, /*!< Rear Center */
122 GAVL_CHID_SIDE_LEFT, /*!< Side left */
123 GAVL_CHID_SIDE_RIGHT, /*!< Side right */
124 GAVL_CHID_LFE, /*!< Subwoofer */
125 GAVL_CHID_AUX, /*!< Additional channel (can be more than one) */
126 #endif
127 { GAVL_CHID_NONE, "Unknown channel" },
128 { GAVL_CHID_FRONT_CENTER, "Front C" },
129 { GAVL_CHID_FRONT_LEFT, "Front L" },
130 { GAVL_CHID_FRONT_RIGHT, "Front R" },
131 { GAVL_CHID_FRONT_CENTER_LEFT, "Front CL" },
132 { GAVL_CHID_FRONT_CENTER_RIGHT, "Front CR" },
133 { GAVL_CHID_REAR_CENTER, "Rear C" },
134 { GAVL_CHID_REAR_LEFT, "Rear L" },
135 { GAVL_CHID_REAR_RIGHT, "Rear R" },
136 { GAVL_CHID_SIDE_LEFT, "Side L" },
137 { GAVL_CHID_SIDE_RIGHT, "Side R" },
138 { GAVL_CHID_LFE, "LFE" },
139 { GAVL_CHID_AUX, "AUX" },
140 };
141
gavl_channel_id_to_string(gavl_channel_id_t id)142 const char * gavl_channel_id_to_string(gavl_channel_id_t id)
143 {
144 int i;
145 for(i = 0;
146 i < sizeof(channel_id_names)/sizeof(channel_id_names[0]);
147 i++)
148 {
149 // fprintf(stderr, "ID: %d\n", id);
150 if(id == channel_id_names[i].id)
151 return channel_id_names[i].name;
152 }
153 return NULL;
154 }
155
gavl_audio_format_dump(const gavl_audio_format_t * f)156 void gavl_audio_format_dump(const gavl_audio_format_t * f)
157 {
158 int i;
159 fprintf(stderr, " Channels: %d\n", f->num_channels);
160
161 fprintf(stderr, " Channel order: ");
162 for(i = 0; i < f->num_channels; i++)
163 {
164 fprintf(stderr, "%s", gavl_channel_id_to_string(f->channel_locations[i]));
165 if(i < f->num_channels - 1)
166 fprintf(stderr, ", ");
167 }
168 fprintf(stderr, "\n");
169
170 fprintf(stderr, " Samplerate: %d\n", f->samplerate);
171 fprintf(stderr, " Samples per frame: %d\n", f->samples_per_frame);
172 fprintf(stderr, " Interleave Mode: %s\n",
173 gavl_interleave_mode_to_string(f->interleave_mode));
174 fprintf(stderr, " Sample format: %s\n",
175 gavl_sample_format_to_string(f->sample_format));
176
177 if(gavl_front_channels(f) == 3)
178 {
179 if(f->center_level > 0.0)
180 fprintf(stderr, " Center level: %0.1f dB\n", 20 * log10(f->center_level));
181 else
182 fprintf(stderr, " Center level: Zero\n");
183 }
184 if(gavl_rear_channels(f))
185 {
186 if(f->rear_level > 0.0)
187 fprintf(stderr, " Rear level: %0.1f dB\n", 20 * log10(f->rear_level));
188 else
189 fprintf(stderr, " Rear level: Zero\n");
190 }
191
192
193
194 }
195
gavl_set_channel_setup(gavl_audio_format_t * dst)196 void gavl_set_channel_setup(gavl_audio_format_t * dst)
197 {
198 int i;
199 if(dst->channel_locations[0] == GAVL_CHID_NONE)
200 {
201 switch(dst->num_channels)
202 {
203 case 1:
204 dst->channel_locations[0] = GAVL_CHID_FRONT_CENTER;
205 break;
206 case 2: /* 2 Front channels (Stereo or Dual channels) */
207 dst->channel_locations[0] = GAVL_CHID_FRONT_LEFT;
208 dst->channel_locations[1] = GAVL_CHID_FRONT_RIGHT;
209 break;
210 case 3:
211 dst->channel_locations[0] = GAVL_CHID_FRONT_LEFT;
212 dst->channel_locations[1] = GAVL_CHID_FRONT_RIGHT;
213 dst->channel_locations[2] = GAVL_CHID_FRONT_CENTER;
214 break;
215 case 4:
216 dst->channel_locations[0] = GAVL_CHID_FRONT_LEFT;
217 dst->channel_locations[1] = GAVL_CHID_FRONT_RIGHT;
218 dst->channel_locations[2] = GAVL_CHID_REAR_LEFT;
219 dst->channel_locations[3] = GAVL_CHID_REAR_RIGHT;
220 break;
221 case 5:
222 dst->channel_locations[0] = GAVL_CHID_FRONT_LEFT;
223 dst->channel_locations[1] = GAVL_CHID_FRONT_RIGHT;
224 dst->channel_locations[2] = GAVL_CHID_REAR_LEFT;
225 dst->channel_locations[3] = GAVL_CHID_REAR_RIGHT;
226 dst->channel_locations[4] = GAVL_CHID_FRONT_CENTER;
227 break;
228 case 6:
229 dst->channel_locations[0] = GAVL_CHID_FRONT_LEFT;
230 dst->channel_locations[1] = GAVL_CHID_FRONT_RIGHT;
231 dst->channel_locations[2] = GAVL_CHID_REAR_LEFT;
232 dst->channel_locations[3] = GAVL_CHID_REAR_RIGHT;
233 dst->channel_locations[4] = GAVL_CHID_FRONT_CENTER;
234 dst->channel_locations[5] = GAVL_CHID_LFE;
235 break;
236 default:
237 for(i = 0; i < dst->num_channels; i++)
238 dst->channel_locations[i] = GAVL_CHID_AUX;
239 break;
240 }
241 }
242 }
243
gavl_audio_format_copy(gavl_audio_format_t * dst,const gavl_audio_format_t * src)244 void gavl_audio_format_copy(gavl_audio_format_t * dst,
245 const gavl_audio_format_t * src)
246 {
247 memcpy(dst, src, sizeof(*dst));
248 }
249
gavl_channel_index(const gavl_audio_format_t * f,gavl_channel_id_t id)250 int gavl_channel_index(const gavl_audio_format_t * f, gavl_channel_id_t id)
251 {
252 int i;
253 for(i = 0; i < f->num_channels; i++)
254 {
255 if(f->channel_locations[i] == id)
256 return i;
257 }
258 // fprintf(stderr, "Channel %s not present!!! Format was\n",
259 // gavl_channel_id_to_string(id));
260 // gavl_audio_format_dump(f);
261 return -1;
262 }
263
gavl_front_channels(const gavl_audio_format_t * f)264 int gavl_front_channels(const gavl_audio_format_t * f)
265 {
266 int i;
267 int result = 0;
268 for(i = 0; i < f->num_channels; i++)
269 {
270 switch(f->channel_locations[i])
271 {
272 case GAVL_CHID_FRONT_CENTER:
273 case GAVL_CHID_FRONT_LEFT:
274 case GAVL_CHID_FRONT_RIGHT:
275 case GAVL_CHID_FRONT_CENTER_LEFT:
276 case GAVL_CHID_FRONT_CENTER_RIGHT:
277 result++;
278 break;
279 case GAVL_CHID_NONE:
280 case GAVL_CHID_REAR_LEFT:
281 case GAVL_CHID_REAR_RIGHT:
282 case GAVL_CHID_REAR_CENTER:
283 case GAVL_CHID_SIDE_LEFT:
284 case GAVL_CHID_SIDE_RIGHT:
285 case GAVL_CHID_LFE:
286 case GAVL_CHID_AUX:
287 break;
288 }
289 }
290 return result;
291 }
292
gavl_rear_channels(const gavl_audio_format_t * f)293 int gavl_rear_channels(const gavl_audio_format_t * f)
294 {
295 int i;
296 int result = 0;
297 for(i = 0; i < f->num_channels; i++)
298 {
299 switch(f->channel_locations[i])
300 {
301 case GAVL_CHID_REAR_LEFT:
302 case GAVL_CHID_REAR_RIGHT:
303 case GAVL_CHID_REAR_CENTER:
304 result++;
305 break;
306 case GAVL_CHID_FRONT_CENTER:
307 case GAVL_CHID_FRONT_LEFT:
308 case GAVL_CHID_FRONT_RIGHT:
309 case GAVL_CHID_FRONT_CENTER_LEFT:
310 case GAVL_CHID_FRONT_CENTER_RIGHT:
311 case GAVL_CHID_NONE:
312 case GAVL_CHID_SIDE_LEFT:
313 case GAVL_CHID_SIDE_RIGHT:
314 case GAVL_CHID_LFE:
315 case GAVL_CHID_AUX:
316 break;
317 }
318 }
319 return result;
320 }
321
gavl_side_channels(const gavl_audio_format_t * f)322 int gavl_side_channels(const gavl_audio_format_t * f)
323 {
324 int i;
325 int result = 0;
326 for(i = 0; i < f->num_channels; i++)
327 {
328 switch(f->channel_locations[i])
329 {
330 case GAVL_CHID_SIDE_LEFT:
331 case GAVL_CHID_SIDE_RIGHT:
332 result++;
333 break;
334 case GAVL_CHID_REAR_LEFT:
335 case GAVL_CHID_REAR_RIGHT:
336 case GAVL_CHID_REAR_CENTER:
337 case GAVL_CHID_FRONT_CENTER:
338 case GAVL_CHID_FRONT_LEFT:
339 case GAVL_CHID_FRONT_RIGHT:
340 case GAVL_CHID_FRONT_CENTER_LEFT:
341 case GAVL_CHID_FRONT_CENTER_RIGHT:
342 case GAVL_CHID_NONE:
343 case GAVL_CHID_LFE:
344 case GAVL_CHID_AUX:
345 break;
346 }
347 }
348 return result;
349 }
350
gavl_lfe_channels(const gavl_audio_format_t * f)351 int gavl_lfe_channels(const gavl_audio_format_t * f)
352 {
353 int i;
354 int result = 0;
355 for(i = 0; i < f->num_channels; i++)
356 {
357 switch(f->channel_locations[i])
358 {
359 case GAVL_CHID_LFE:
360 result++;
361 break;
362 case GAVL_CHID_SIDE_LEFT:
363 case GAVL_CHID_SIDE_RIGHT:
364 case GAVL_CHID_REAR_LEFT:
365 case GAVL_CHID_REAR_RIGHT:
366 case GAVL_CHID_REAR_CENTER:
367 case GAVL_CHID_FRONT_CENTER:
368 case GAVL_CHID_FRONT_LEFT:
369 case GAVL_CHID_FRONT_RIGHT:
370 case GAVL_CHID_FRONT_CENTER_LEFT:
371 case GAVL_CHID_FRONT_CENTER_RIGHT:
372 case GAVL_CHID_NONE:
373 case GAVL_CHID_AUX:
374 break;
375 }
376 }
377 return result;
378 }
379
gavl_aux_channels(const gavl_audio_format_t * f)380 int gavl_aux_channels(const gavl_audio_format_t * f)
381 {
382 int i;
383 int result = 0;
384 for(i = 0; i < f->num_channels; i++)
385 {
386 switch(f->channel_locations[i])
387 {
388 case GAVL_CHID_AUX:
389 result++;
390 break;
391 case GAVL_CHID_SIDE_LEFT:
392 case GAVL_CHID_SIDE_RIGHT:
393 case GAVL_CHID_REAR_LEFT:
394 case GAVL_CHID_REAR_RIGHT:
395 case GAVL_CHID_REAR_CENTER:
396 case GAVL_CHID_FRONT_CENTER:
397 case GAVL_CHID_FRONT_LEFT:
398 case GAVL_CHID_FRONT_RIGHT:
399 case GAVL_CHID_FRONT_CENTER_LEFT:
400 case GAVL_CHID_FRONT_CENTER_RIGHT:
401 case GAVL_CHID_NONE:
402 case GAVL_CHID_LFE:
403 break;
404 }
405 }
406 return result;
407 }
408
409
410
gavl_bytes_per_sample(gavl_sample_format_t format)411 int gavl_bytes_per_sample(gavl_sample_format_t format)
412 {
413 switch(format)
414 {
415 case GAVL_SAMPLE_U8:
416 case GAVL_SAMPLE_S8:
417 return 1;
418 break;
419 case GAVL_SAMPLE_U16:
420 case GAVL_SAMPLE_S16:
421 return 2;
422 break;
423 case GAVL_SAMPLE_S32:
424 return 4;
425 break;
426 case GAVL_SAMPLE_FLOAT:
427 return sizeof(float);
428 break;
429 case GAVL_SAMPLE_DOUBLE:
430 return sizeof(double);
431 break;
432 case GAVL_SAMPLE_NONE:
433 return 0;
434 }
435 return 0;
436 }
437
438
gavl_audio_formats_equal(const gavl_audio_format_t * format_1,const gavl_audio_format_t * format_2)439 int gavl_audio_formats_equal(const gavl_audio_format_t * format_1,
440 const gavl_audio_format_t * format_2)
441 {
442 return !memcmp(format_1, format_2, sizeof(*format_1));
443 }
444