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