source: roaraudio/libroardsp/channels.c @ 3541:1e63ce5b7951

Last change on this file since 3541:1e63ce5b7951 was 3541:1e63ce5b7951, checked in by phi, 14 years ago

support for inverse channel mapping

File size: 9.5 KB
Line 
1//channels.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
5 *
6 *  This file is part of libroardsp a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroardsp is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "libroardsp.h"
27
28static struct {
29 int id;
30 char * name;
31 char * sn;
32} _g_chans[] = {
33 {ROARDSP_CHAN_NONE,           "NONE",           "NONE"           },
34 {ROARDSP_CHAN_FRONT_LEFT,     "FRONT_LEFT",     "FL"             },
35 {ROARDSP_CHAN_FRONT_RIGHT,    "FRONT_RIGHT",    "FR"             },
36 {ROARDSP_CHAN_SIDE_LEFT,      "SIDE_LEFT",      "SL"             },
37 {ROARDSP_CHAN_SIDE_RIGHT,     "SIDE_RIGHT",     "SR"             },
38 {ROARDSP_CHAN_BACK_LEFT,      "BACK_LEFT",      "BL"             },
39 {ROARDSP_CHAN_BACK_RIGHT,     "BACK_RIGHT",     "BR"             },
40 {ROARDSP_CHAN_FRONT_CENTER,   "FRONT_CENTER",   "FC"             },
41 {ROARDSP_CHAN_SIDE_CENTER,    "SIDE_CENTER",    "SC"             },
42 {ROARDSP_CHAN_BACK_CENTER,    "BACK_CENTER",    "BC"             },
43 {ROARDSP_CHAN_LEFT,           "LEFT",           "L"              }, // alias
44 {ROARDSP_CHAN_RIGHT,          "RIGHT",          "R"              }, // alias
45 {ROARDSP_CHAN_CENTER,         "CENTER",         "C"              }, // alias
46 {ROARDSP_CHAN_MONO,           "MONO",           "M"              }, // alias
47 {ROARDSP_CHAN_MS_MID,         "MS_MID",         "MID"            },
48 {ROARDSP_CHAN_MS_SIDE,        "MS_SIDE",        "SIDE"           },
49 {ROARDSP_CHAN_LFE,            "LFE",            "LFE"            },
50 {ROARDSP_CHAN_EOL, NULL, NULL}
51};
52
53char * roardsp_chan2str (int chan) {
54 int i;
55
56 for (i = 0; _g_chans[i].id != ROARDSP_CHAN_EOL; i++)
57  if ( _g_chans[i].id == chan )
58   return _g_chans[i].name;
59
60 return NULL;
61}
62
63int roardsp_str2chan(char * str) {
64 int i;
65
66 for (i = 0; _g_chans[i].id != ROARDSP_CHAN_EOL; i++)
67  if ( !strcasecmp(_g_chans[i].name, str) || !strcasecmp(_g_chans[i].sn, str) )
68   return _g_chans[i].id;
69
70 return -1;
71}
72
73int    roardsp_chanlist2str(char * list, size_t len, char * str, size_t strlen) {
74 int i;
75
76 if ( list == NULL && len > 0 )
77  return -1;
78
79 if ( (str == NULL || strlen == 0) && len > 0 )
80  return -1;
81
82 if ( len == 0 ) {
83  if ( str != NULL && strlen > 0 )
84   *str = 0;
85
86  return 0;
87 }
88
89 // TODO: FIXME: do not ignore strlen from here
90 *str = 0;
91
92 for (i = 0; i < len; i++) {
93  if ( i != 0 )
94   strcat(str, ",");
95
96  strcat(str, roardsp_chan2str(list[i]));
97 }
98
99 return 0;
100}
101
102int    roardsp_chanlist_init(char * list, int channels, int map) {
103 if ( channels == 0 )
104  return 0;
105
106 if ( list == NULL )
107  return -1;
108
109 if ( channels > ROAR_MAX_CHANNELS )
110  return -1;
111
112 // test for common maps:
113 if ( channels == 1 ) {
114  list[0] = ROARDSP_CHAN_MONO;
115  return 0;
116 }
117
118 if ( channels == 2 ) {
119  list[0] = ROARDSP_CHAN_LEFT;
120  list[1] = ROARDSP_CHAN_RIGHT;
121  return 0;
122 }
123
124 // test for specific maps:
125 switch (map) {
126  case ROARDSP_CHANLIST_MAP_ROARAUDIO:
127  case ROARDSP_CHANLIST_MAP_FLAC:
128    if ( map == ROARDSP_CHANLIST_MAP_FLAC && channels > 6 ) {
129     // FLAC only has a fixed mapping for up to 6 channels.
130     return -1;
131    }
132
133    switch (channels) {
134     // FLAC or RoarAudio:
135     case 3:
136       list[0] = ROARDSP_CHAN_LEFT;
137       list[1] = ROARDSP_CHAN_RIGHT;
138       list[2] = ROARDSP_CHAN_CENTER;
139      break;
140     case 4:
141       list[0] = ROARDSP_CHAN_FRONT_LEFT;
142       list[1] = ROARDSP_CHAN_FRONT_RIGHT;
143       list[2] = ROARDSP_CHAN_BACK_LEFT;
144       list[3] = ROARDSP_CHAN_BACK_RIGHT;
145      break;
146     case 5:
147       list[0] = ROARDSP_CHAN_FRONT_LEFT;
148       list[1] = ROARDSP_CHAN_FRONT_RIGHT;
149       list[2] = ROARDSP_CHAN_CENTER;
150       list[3] = ROARDSP_CHAN_BACK_LEFT;
151       list[4] = ROARDSP_CHAN_BACK_RIGHT;
152      break;
153     case 6:
154       list[0] = ROARDSP_CHAN_FRONT_LEFT;
155       list[1] = ROARDSP_CHAN_FRONT_RIGHT;
156       list[2] = ROARDSP_CHAN_CENTER;
157       list[3] = ROARDSP_CHAN_LFE;
158       list[4] = ROARDSP_CHAN_BACK_LEFT;
159       list[5] = ROARDSP_CHAN_BACK_RIGHT;
160      break;
161     // RoarAudio:
162     case 7:
163       list[0] = ROARDSP_CHAN_FRONT_LEFT;
164       list[1] = ROARDSP_CHAN_FRONT_RIGHT;
165       list[2] = ROARDSP_CHAN_CENTER;
166       list[3] = ROARDSP_CHAN_LFE;
167       list[4] = ROARDSP_CHAN_SIDE_LEFT;
168       list[5] = ROARDSP_CHAN_SIDE_RIGHT;
169       list[6] = ROARDSP_CHAN_BACK_CENTER;
170      break;
171     case 8:
172       list[0] = ROARDSP_CHAN_FRONT_LEFT;
173       list[1] = ROARDSP_CHAN_FRONT_RIGHT;
174       list[2] = ROARDSP_CHAN_CENTER;
175       list[3] = ROARDSP_CHAN_LFE;
176       list[4] = ROARDSP_CHAN_SIDE_LEFT;
177       list[5] = ROARDSP_CHAN_SIDE_RIGHT;
178       list[6] = ROARDSP_CHAN_BACK_LEFT;
179       list[7] = ROARDSP_CHAN_BACK_RIGHT;
180      break;
181     default:
182       return -1;
183      break;
184    }
185   break;
186  case ROARDSP_CHANLIST_MAP_VORBIS:
187    switch (channels) {
188     case 3:
189       list[0] = ROARDSP_CHAN_LEFT;
190       list[1] = ROARDSP_CHAN_CENTER;
191       list[2] = ROARDSP_CHAN_RIGHT;
192      break;
193     case 4:
194       list[0] = ROARDSP_CHAN_FRONT_LEFT;
195       list[1] = ROARDSP_CHAN_FRONT_RIGHT;
196       list[2] = ROARDSP_CHAN_BACK_LEFT;
197       list[3] = ROARDSP_CHAN_BACK_RIGHT;
198      break;
199     case 5:
200       list[0] = ROARDSP_CHAN_FRONT_LEFT;
201       list[1] = ROARDSP_CHAN_CENTER;
202       list[2] = ROARDSP_CHAN_FRONT_RIGHT;
203       list[3] = ROARDSP_CHAN_BACK_LEFT;
204       list[4] = ROARDSP_CHAN_BACK_RIGHT;
205      break;
206     case 6:
207       list[0] = ROARDSP_CHAN_FRONT_LEFT;
208       list[1] = ROARDSP_CHAN_CENTER;
209       list[2] = ROARDSP_CHAN_FRONT_RIGHT;
210       list[3] = ROARDSP_CHAN_BACK_LEFT;
211       list[4] = ROARDSP_CHAN_BACK_RIGHT;
212       list[5] = ROARDSP_CHAN_LFE;
213      break;
214     case 7:
215       list[0] = ROARDSP_CHAN_FRONT_LEFT;
216       list[1] = ROARDSP_CHAN_CENTER;
217       list[2] = ROARDSP_CHAN_FRONT_RIGHT;
218       list[3] = ROARDSP_CHAN_SIDE_LEFT;
219       list[4] = ROARDSP_CHAN_SIDE_RIGHT;
220       list[5] = ROARDSP_CHAN_BACK_CENTER;
221       list[6] = ROARDSP_CHAN_LFE;
222      break;
223     case 8:
224       list[0] = ROARDSP_CHAN_FRONT_LEFT;
225       list[1] = ROARDSP_CHAN_CENTER;
226       list[2] = ROARDSP_CHAN_FRONT_RIGHT;
227       list[3] = ROARDSP_CHAN_SIDE_LEFT;
228       list[4] = ROARDSP_CHAN_SIDE_RIGHT;
229       list[5] = ROARDSP_CHAN_BACK_LEFT;
230       list[6] = ROARDSP_CHAN_BACK_RIGHT;
231       list[7] = ROARDSP_CHAN_LFE;
232      break;
233     default:
234       return -1;
235      break;
236    }
237   break;
238  case ROARDSP_CHANLIST_MAP_OSS:
239    switch (channels) {
240     case 8:
241       list[7] = ROARDSP_CHAN_BACK_RIGHT;
242     case 7:
243       list[6] = ROARDSP_CHAN_BACK_LEFT;
244     case 6:
245       list[5] = ROARDSP_CHAN_SIDE_RIGHT;
246     case 5:
247       list[4] = ROARDSP_CHAN_SIDE_LEFT;
248     case 4:
249       list[3] = ROARDSP_CHAN_LFE;
250     case 3:
251       list[2] = ROARDSP_CHAN_CENTER;
252       list[1] = ROARDSP_CHAN_RIGHT;
253       list[0] = ROARDSP_CHAN_LEFT;
254      break;
255     default:
256       return -1;
257      break;
258    }
259   break;
260  case ROARDSP_CHANLIST_MAP_ALSA:
261    // we guess: L,R,BL,BR,C,LFE,SL,SR (really, just guessing, see ALSA plugin of libao)
262    switch (channels) {
263     case 8:
264       list[7] = ROARDSP_CHAN_BACK_RIGHT;
265     case 7:
266       list[6] = ROARDSP_CHAN_BACK_LEFT;
267     case 6:
268       list[5] = ROARDSP_CHAN_LFE;
269     case 5:
270       list[4] = ROARDSP_CHAN_CENTER;
271     case 4:
272       list[3] = ROARDSP_CHAN_BACK_RIGHT;
273     case 3:
274       list[2] = ROARDSP_CHAN_BACK_LEFT;
275       list[1] = ROARDSP_CHAN_RIGHT;
276       list[0] = ROARDSP_CHAN_LEFT;
277      break;
278     default:
279       return -1;
280      break;
281    }
282   break;
283  case ROARDSP_CHANLIST_MAP_RIFF_WAVE:
284    // here we are again, guessing:  L,R,C,LFE,BL,BR,CL,CR,BC,SL,SR
285    // strange, C, LFE on 4 channel file?
286    // return -1 to be sure....
287    switch (channels) {
288     default:
289       return -1;
290      break;
291    }
292   break;
293  default:
294    return -1;
295   break;
296 }
297
298 return 0;
299}
300
301int roardsp_chanmap_calc(struct roardsp_chanmap * map, int what, int err_on_none) {
302 int a, b;
303
304 if ( map == NULL )
305  return -1;
306
307 switch (what) {
308  case ROARDSP_CHANMAP_MAP:
309    memset(map->map, (char)-1, sizeof(map->map));
310
311    for (a = 0; a < ROAR_MAX_CHANNELS; a++) {
312     if ( map->in[a] == ROARDSP_CHAN_NONE )
313      continue;
314
315     for (b = 0; b < ROAR_MAX_CHANNELS; b++) {
316      if ( map->in[a] == map->out[b] ) {
317       map->map[a] = b;
318       break;
319      }
320     }
321     if ( b == ROAR_MAX_CHANNELS ) { // src not found in dest
322      if ( err_on_none )
323       return -1;
324
325      map->map[a] = -1;
326     }
327    }
328   break;
329  case ROARDSP_CHANMAP_INVMAP:
330    memset(map->map, (char)-1, sizeof(map->map));
331
332    for (a = 0; a < ROAR_MAX_CHANNELS; a++) {
333     if ( map->out[a] == ROARDSP_CHAN_NONE )
334      continue;
335
336     for (b = 0; b < ROAR_MAX_CHANNELS; b++) {
337      if ( map->out[a] == map->in[b] ) {
338       map->map[a] = b;
339       break;
340      }
341     }
342     if ( b == ROAR_MAX_CHANNELS ) { // src not found in dest
343      if ( err_on_none )
344       return -1;
345
346      map->map[a] = -1;
347     }
348    }
349   break;
350  case ROARDSP_CHANMAP_IN:
351  case ROARDSP_CHANMAP_OUT:
352  default:
353    return -1;
354   break;
355 }
356
357 return 0;
358}
359
360//ll
Note: See TracBrowser for help on using the repository browser.