source: roaraudio/libroardsp/channels.c @ 3543:af952b03e304

Last change on this file since 3543:af952b03e304 was 3543:af952b03e304, checked in by phi, 14 years ago

added names for midi channels

File size: 10.7 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 // general:
34 {ROARDSP_CHAN_NONE,           "NONE",           "NONE"           },
35 // waveform:
36 {ROARDSP_CHAN_FRONT_LEFT,     "FRONT_LEFT",     "FL"             },
37 {ROARDSP_CHAN_FRONT_RIGHT,    "FRONT_RIGHT",    "FR"             },
38 {ROARDSP_CHAN_SIDE_LEFT,      "SIDE_LEFT",      "SL"             },
39 {ROARDSP_CHAN_SIDE_RIGHT,     "SIDE_RIGHT",     "SR"             },
40 {ROARDSP_CHAN_BACK_LEFT,      "BACK_LEFT",      "BL"             },
41 {ROARDSP_CHAN_BACK_RIGHT,     "BACK_RIGHT",     "BR"             },
42 {ROARDSP_CHAN_FRONT_CENTER,   "FRONT_CENTER",   "FC"             },
43 {ROARDSP_CHAN_SIDE_CENTER,    "SIDE_CENTER",    "SC"             },
44 {ROARDSP_CHAN_BACK_CENTER,    "BACK_CENTER",    "BC"             },
45 {ROARDSP_CHAN_LEFT,           "LEFT",           "L"              }, // alias
46 {ROARDSP_CHAN_RIGHT,          "RIGHT",          "R"              }, // alias
47 {ROARDSP_CHAN_CENTER,         "CENTER",         "C"              }, // alias
48 {ROARDSP_CHAN_MONO,           "MONO",           "M"              }, // alias
49 {ROARDSP_CHAN_MS_MID,         "MS_MID",         "MID"            },
50 {ROARDSP_CHAN_MS_SIDE,        "MS_SIDE",        "SIDE"           },
51 {ROARDSP_CHAN_LFE,            "LFE",            "LFE"            },
52 // midi:
53 {ROARDSP_CHAN_MIDI0,           "MIDI0",         NULL             },
54 {ROARDSP_CHAN_MIDI1,           "MIDI1",         NULL             },
55 {ROARDSP_CHAN_MIDI2,           "MIDI2",         NULL             },
56 {ROARDSP_CHAN_MIDI3,           "MIDI3",         NULL             },
57 {ROARDSP_CHAN_MIDI4,           "MIDI4",         NULL             },
58 {ROARDSP_CHAN_MIDI5,           "MIDI5",         NULL             },
59 {ROARDSP_CHAN_MIDI6,           "MIDI6",         NULL             },
60 {ROARDSP_CHAN_MIDI7,           "MIDI7",         NULL             },
61 {ROARDSP_CHAN_MIDI8,           "MIDI8",         NULL             },
62 {ROARDSP_CHAN_MIDI9,           "MIDI9",         NULL             },
63 {ROARDSP_CHAN_MIDI10,          "MIDI10",        NULL             },
64 {ROARDSP_CHAN_MIDI11,          "MIDI11",        NULL             },
65 {ROARDSP_CHAN_MIDI12,          "MIDI12",        NULL             },
66 {ROARDSP_CHAN_MIDI13,          "MIDI13",        NULL             },
67 {ROARDSP_CHAN_MIDI14,          "MIDI14",        NULL             },
68 {ROARDSP_CHAN_MIDI15,          "MIDI15",        NULL             },
69 {ROARDSP_CHAN_EOL, NULL, NULL}
70};
71
72char * roardsp_chan2str (int chan) {
73 int i;
74
75 for (i = 0; _g_chans[i].id != ROARDSP_CHAN_EOL; i++)
76  if ( _g_chans[i].id == chan )
77   return _g_chans[i].name;
78
79 return NULL;
80}
81
82int roardsp_str2chan(char * str) {
83 int i;
84
85 for (i = 0; _g_chans[i].id != ROARDSP_CHAN_EOL; i++)
86  if ( !strcasecmp(_g_chans[i].name, str) ||
87       (_g_chans[i].sn != NULL && !strcasecmp(_g_chans[i].sn, str)) )
88   return _g_chans[i].id;
89
90 return -1;
91}
92
93int    roardsp_chanlist2str(char * list, size_t len, char * str, size_t strlen) {
94 int i;
95
96 if ( list == NULL && len > 0 )
97  return -1;
98
99 if ( (str == NULL || strlen == 0) && len > 0 )
100  return -1;
101
102 if ( len == 0 ) {
103  if ( str != NULL && strlen > 0 )
104   *str = 0;
105
106  return 0;
107 }
108
109 // TODO: FIXME: do not ignore strlen from here
110 *str = 0;
111
112 for (i = 0; i < len; i++) {
113  if ( i != 0 )
114   strcat(str, ",");
115
116  strcat(str, roardsp_chan2str(list[i]));
117 }
118
119 return 0;
120}
121
122int    roardsp_chanlist_init(char * list, int channels, int map) {
123 int i;
124
125 if ( channels == 0 )
126  return 0;
127
128 if ( list == NULL )
129  return -1;
130
131 if ( channels > ROAR_MAX_CHANNELS )
132  return -1;
133
134 if ( map == ROARDSP_CHANLIST_MAP_MIDI ) {
135  for (i = 0; i < channels; i++) {
136   list[i] = i+ROARDSP_CHAN_MIDI0;
137  }
138 }
139
140 // test for common maps:
141 if ( channels == 1 ) {
142  list[0] = ROARDSP_CHAN_MONO;
143  return 0;
144 }
145
146 if ( channels == 2 ) {
147  list[0] = ROARDSP_CHAN_LEFT;
148  list[1] = ROARDSP_CHAN_RIGHT;
149  return 0;
150 }
151
152 // test for specific maps:
153 switch (map) {
154  case ROARDSP_CHANLIST_MAP_ROARAUDIO:
155  case ROARDSP_CHANLIST_MAP_FLAC:
156    if ( map == ROARDSP_CHANLIST_MAP_FLAC && channels > 6 ) {
157     // FLAC only has a fixed mapping for up to 6 channels.
158     return -1;
159    }
160
161    switch (channels) {
162     // FLAC or RoarAudio:
163     case 3:
164       list[0] = ROARDSP_CHAN_LEFT;
165       list[1] = ROARDSP_CHAN_RIGHT;
166       list[2] = ROARDSP_CHAN_CENTER;
167      break;
168     case 4:
169       list[0] = ROARDSP_CHAN_FRONT_LEFT;
170       list[1] = ROARDSP_CHAN_FRONT_RIGHT;
171       list[2] = ROARDSP_CHAN_BACK_LEFT;
172       list[3] = ROARDSP_CHAN_BACK_RIGHT;
173      break;
174     case 5:
175       list[0] = ROARDSP_CHAN_FRONT_LEFT;
176       list[1] = ROARDSP_CHAN_FRONT_RIGHT;
177       list[2] = ROARDSP_CHAN_CENTER;
178       list[3] = ROARDSP_CHAN_BACK_LEFT;
179       list[4] = ROARDSP_CHAN_BACK_RIGHT;
180      break;
181     case 6:
182       list[0] = ROARDSP_CHAN_FRONT_LEFT;
183       list[1] = ROARDSP_CHAN_FRONT_RIGHT;
184       list[2] = ROARDSP_CHAN_CENTER;
185       list[3] = ROARDSP_CHAN_LFE;
186       list[4] = ROARDSP_CHAN_BACK_LEFT;
187       list[5] = ROARDSP_CHAN_BACK_RIGHT;
188      break;
189     // RoarAudio:
190     case 7:
191       list[0] = ROARDSP_CHAN_FRONT_LEFT;
192       list[1] = ROARDSP_CHAN_FRONT_RIGHT;
193       list[2] = ROARDSP_CHAN_CENTER;
194       list[3] = ROARDSP_CHAN_LFE;
195       list[4] = ROARDSP_CHAN_SIDE_LEFT;
196       list[5] = ROARDSP_CHAN_SIDE_RIGHT;
197       list[6] = ROARDSP_CHAN_BACK_CENTER;
198      break;
199     case 8:
200       list[0] = ROARDSP_CHAN_FRONT_LEFT;
201       list[1] = ROARDSP_CHAN_FRONT_RIGHT;
202       list[2] = ROARDSP_CHAN_CENTER;
203       list[3] = ROARDSP_CHAN_LFE;
204       list[4] = ROARDSP_CHAN_SIDE_LEFT;
205       list[5] = ROARDSP_CHAN_SIDE_RIGHT;
206       list[6] = ROARDSP_CHAN_BACK_LEFT;
207       list[7] = ROARDSP_CHAN_BACK_RIGHT;
208      break;
209     default:
210       return -1;
211      break;
212    }
213   break;
214  case ROARDSP_CHANLIST_MAP_VORBIS:
215    switch (channels) {
216     case 3:
217       list[0] = ROARDSP_CHAN_LEFT;
218       list[1] = ROARDSP_CHAN_CENTER;
219       list[2] = ROARDSP_CHAN_RIGHT;
220      break;
221     case 4:
222       list[0] = ROARDSP_CHAN_FRONT_LEFT;
223       list[1] = ROARDSP_CHAN_FRONT_RIGHT;
224       list[2] = ROARDSP_CHAN_BACK_LEFT;
225       list[3] = ROARDSP_CHAN_BACK_RIGHT;
226      break;
227     case 5:
228       list[0] = ROARDSP_CHAN_FRONT_LEFT;
229       list[1] = ROARDSP_CHAN_CENTER;
230       list[2] = ROARDSP_CHAN_FRONT_RIGHT;
231       list[3] = ROARDSP_CHAN_BACK_LEFT;
232       list[4] = ROARDSP_CHAN_BACK_RIGHT;
233      break;
234     case 6:
235       list[0] = ROARDSP_CHAN_FRONT_LEFT;
236       list[1] = ROARDSP_CHAN_CENTER;
237       list[2] = ROARDSP_CHAN_FRONT_RIGHT;
238       list[3] = ROARDSP_CHAN_BACK_LEFT;
239       list[4] = ROARDSP_CHAN_BACK_RIGHT;
240       list[5] = ROARDSP_CHAN_LFE;
241      break;
242     case 7:
243       list[0] = ROARDSP_CHAN_FRONT_LEFT;
244       list[1] = ROARDSP_CHAN_CENTER;
245       list[2] = ROARDSP_CHAN_FRONT_RIGHT;
246       list[3] = ROARDSP_CHAN_SIDE_LEFT;
247       list[4] = ROARDSP_CHAN_SIDE_RIGHT;
248       list[5] = ROARDSP_CHAN_BACK_CENTER;
249       list[6] = ROARDSP_CHAN_LFE;
250      break;
251     case 8:
252       list[0] = ROARDSP_CHAN_FRONT_LEFT;
253       list[1] = ROARDSP_CHAN_CENTER;
254       list[2] = ROARDSP_CHAN_FRONT_RIGHT;
255       list[3] = ROARDSP_CHAN_SIDE_LEFT;
256       list[4] = ROARDSP_CHAN_SIDE_RIGHT;
257       list[5] = ROARDSP_CHAN_BACK_LEFT;
258       list[6] = ROARDSP_CHAN_BACK_RIGHT;
259       list[7] = ROARDSP_CHAN_LFE;
260      break;
261     default:
262       return -1;
263      break;
264    }
265   break;
266  case ROARDSP_CHANLIST_MAP_OSS:
267    switch (channels) {
268     case 8:
269       list[7] = ROARDSP_CHAN_BACK_RIGHT;
270     case 7:
271       list[6] = ROARDSP_CHAN_BACK_LEFT;
272     case 6:
273       list[5] = ROARDSP_CHAN_SIDE_RIGHT;
274     case 5:
275       list[4] = ROARDSP_CHAN_SIDE_LEFT;
276     case 4:
277       list[3] = ROARDSP_CHAN_LFE;
278     case 3:
279       list[2] = ROARDSP_CHAN_CENTER;
280       list[1] = ROARDSP_CHAN_RIGHT;
281       list[0] = ROARDSP_CHAN_LEFT;
282      break;
283     default:
284       return -1;
285      break;
286    }
287   break;
288  case ROARDSP_CHANLIST_MAP_ALSA:
289    // we guess: L,R,BL,BR,C,LFE,SL,SR (really, just guessing, see ALSA plugin of libao)
290    switch (channels) {
291     case 8:
292       list[7] = ROARDSP_CHAN_BACK_RIGHT;
293     case 7:
294       list[6] = ROARDSP_CHAN_BACK_LEFT;
295     case 6:
296       list[5] = ROARDSP_CHAN_LFE;
297     case 5:
298       list[4] = ROARDSP_CHAN_CENTER;
299     case 4:
300       list[3] = ROARDSP_CHAN_BACK_RIGHT;
301     case 3:
302       list[2] = ROARDSP_CHAN_BACK_LEFT;
303       list[1] = ROARDSP_CHAN_RIGHT;
304       list[0] = ROARDSP_CHAN_LEFT;
305      break;
306     default:
307       return -1;
308      break;
309    }
310   break;
311  case ROARDSP_CHANLIST_MAP_RIFF_WAVE:
312    // here we are again, guessing:  L,R,C,LFE,BL,BR,CL,CR,BC,SL,SR
313    // strange, C, LFE on 4 channel file?
314    // return -1 to be sure....
315    switch (channels) {
316     default:
317       return -1;
318      break;
319    }
320   break;
321  default:
322    return -1;
323   break;
324 }
325
326 return 0;
327}
328
329int roardsp_chanmap_calc(struct roardsp_chanmap * map, int what, int err_on_none) {
330 int a, b;
331
332 if ( map == NULL )
333  return -1;
334
335 switch (what) {
336  case ROARDSP_CHANMAP_MAP:
337    memset(map->map, (char)-1, sizeof(map->map));
338
339    for (a = 0; a < ROAR_MAX_CHANNELS; a++) {
340     if ( map->in[a] == ROARDSP_CHAN_NONE )
341      continue;
342
343     for (b = 0; b < ROAR_MAX_CHANNELS; b++) {
344      if ( map->in[a] == map->out[b] ) {
345       map->map[a] = b;
346       break;
347      }
348     }
349     if ( b == ROAR_MAX_CHANNELS ) { // src not found in dest
350      if ( err_on_none )
351       return -1;
352
353      map->map[a] = -1;
354     }
355    }
356   break;
357  case ROARDSP_CHANMAP_INVMAP:
358    memset(map->map, (char)-1, sizeof(map->map));
359
360    for (a = 0; a < ROAR_MAX_CHANNELS; a++) {
361     if ( map->out[a] == ROARDSP_CHAN_NONE )
362      continue;
363
364     for (b = 0; b < ROAR_MAX_CHANNELS; b++) {
365      if ( map->out[a] == map->in[b] ) {
366       map->map[a] = b;
367       break;
368      }
369     }
370     if ( b == ROAR_MAX_CHANNELS ) { // src not found in dest
371      if ( err_on_none )
372       return -1;
373
374      map->map[a] = -1;
375     }
376    }
377   break;
378  case ROARDSP_CHANMAP_IN:
379  case ROARDSP_CHANMAP_OUT:
380  default:
381    return -1;
382   break;
383 }
384
385 return 0;
386}
387
388//ll
Note: See TracBrowser for help on using the repository browser.