Coverage Report

Created: 2025-12-20 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libsndfile/src/chanmap.c
Line
Count
Source
1
/*
2
** Copyright (C) 2009-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
3
**
4
** This program is free software; you can redistribute it and/or modify
5
** it under the terms of the GNU Lesser General Public License as published by
6
** the Free Software Foundation; either version 2.1 of the License, or
7
** (at your option) any later version.
8
**
9
** This program is distributed in the hope that it will be useful,
10
** but WITHOUT ANY WARRANTY; without even the implied warranty of
11
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
** GNU Lesser General Public License for more details.
13
**
14
** You should have received a copy of the GNU Lesser General Public License
15
** along with this program; if not, write to the Free Software
16
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
*/
18
19
/*
20
**  Mostly from "Apple Core Audio Format Specification 1.0":
21
**
22
**    http://developer.apple.com/documentation/MusicAudio/Reference/CAFSpec/CAFSpec.pdf
23
*/
24
25
#include "sfconfig.h"
26
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <string.h>
30
31
#include "sndfile.h"
32
#include "common.h"
33
#include "chanmap.h"
34
35
36
static const AIFF_CAF_CHANNEL_MAP zero_chan [] =
37
{ { (0 << 16) | 0, NULL, "Use channel descriptions." },
38
  { (1 << 16) | 0, NULL, "Use channel bitmap." }
39
} ; /* zero_chan */
40
41
42
static const int one_chan_mono [1] = {  SF_CHANNEL_MAP_MONO } ;
43
44
static const AIFF_CAF_CHANNEL_MAP one_chan [] =
45
{ { (100 << 16) | 1, one_chan_mono, "mono" }
46
} ; /* one_chan */
47
48
49
static const int two_channel_stereo [2] = { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT } ;
50
51
static const AIFF_CAF_CHANNEL_MAP two_chan [] =
52
{ { (101 << 16) | 2, two_channel_stereo, "stereo (L, R)" },
53
  { (102 << 16) | 2, two_channel_stereo, "stereo headphones (L, R)" },
54
#if 0
55
  { (103 << 16) | 2, NULL, "matrix stereo (Lt, Rt)" },
56
  { (104 << 16) | 2, NULL, "2 channels (mid, side)" },
57
  { (105 << 16) | 2, NULL, "coincident mic pair" },
58
  { (106 << 16) | 2, NULL, "binaural stereo (L, R)"
59
    }
60
#endif
61
} ; /* two_chan */
62
63
64
static const int three_channel_mpeg_30a [3] =
65
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER } ;
66
static const int three_channel_mpeg_30b [3] =
67
  { SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT } ;
68
static const int three_channel_itu_21 [3] =
69
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_CENTER } ;
70
static const int three_channel_dvd_4 [3] =
71
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_LFE } ;
72
73
static const AIFF_CAF_CHANNEL_MAP three_chan [] =
74
{ { (113 << 16) | 3, three_channel_mpeg_30a, "MPEG 3 0 A (L, R, C)" },
75
  { (114 << 16) | 3, three_channel_mpeg_30b, "MPEG 3 0 B (C, L, R)" },
76
  { (131 << 16) | 3, three_channel_itu_21, "ITU 2.1 (L, R, Cs)" },
77
  { (133 << 16) | 3, three_channel_dvd_4, "DVD 4 (L, R, LFE)" }
78
} ; /* three_chan */
79
80
81
static const int four_channel_ambisonc_b [4] =
82
  { SF_CHANNEL_MAP_AMBISONIC_B_W, SF_CHANNEL_MAP_AMBISONIC_B_X, SF_CHANNEL_MAP_AMBISONIC_B_Y, SF_CHANNEL_MAP_AMBISONIC_B_Z } ;
83
static const int four_channel_quad [4] =
84
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
85
static const int four_channel_mpeg_40a [4] =
86
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_REAR_CENTER } ;
87
static const int four_channel_mpeg_40b [4] =
88
  { SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_CENTER } ;
89
static const int four_channel_itu_23 [4] =
90
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
91
static const int four_channel_dvd_5 [4] =
92
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_CENTER } ;
93
static const int four_channel_dvd_10 [4] =
94
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE } ;
95
96
static const AIFF_CAF_CHANNEL_MAP four_chan [] =
97
{ { (107 << 16) | 4, four_channel_ambisonc_b, "ambisonic B (W,  X, Y, Z)" },
98
  { (108 << 16) | 4, four_channel_quad, "quad (Lfront, Rfront, Lrear, Rrear)" },
99
  { (115 << 16) | 4, four_channel_mpeg_40a, "MPEG 4.0 A (L, R, C, Cs)" },
100
  { (116 << 16) | 4, four_channel_mpeg_40b, "MPEG 4.0 B (C, L, R, Cs)" },
101
  { (132 << 16) | 4, four_channel_itu_23, "ITU 2.3 (L, R, Ls, Rs)" },
102
  { (134 << 16) | 4, four_channel_dvd_5, "DVD 5 (L, R, LFE, Cs)" },
103
  { (136 << 16) | 4, four_channel_dvd_10, "DVD 10 (L, R, C, LFE)" }
104
} ; /* four_chan */
105
106
107
static const int five_channel_pentagonal [5] =
108
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_CENTER } ;
109
static const int five_channel_mpeg_50_a [5] =
110
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
111
static const int five_channel_mpeg_50_b [5] =
112
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_CENTER } ;
113
static const int five_channel_mpeg_50_c [5] =
114
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
115
static const int five_channel_mpeg_50_d [5] =
116
  { SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
117
static const int five_channel_dvd_6 [5] =
118
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
119
static const int five_channel_dvd_11 [5] =
120
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_CENTER } ;
121
static const int five_channel_dvd_18 [5] =
122
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_LFE } ;
123
124
static const AIFF_CAF_CHANNEL_MAP five_chan [] =
125
{ { (109 << 16) | 5, five_channel_pentagonal, "pentagonal (L,  R, Lrear, Rrear, C)" },
126
  { (117 << 16) | 5, five_channel_mpeg_50_a, "MPEG 5.0 A (L, R, C, Ls, Rs)" },
127
  { (118 << 16) | 5, five_channel_mpeg_50_b, "MPEG 5.0 B (L, R, Ls, Rs, C)" },
128
  { (119 << 16) | 5, five_channel_mpeg_50_c, "MPEG 5.0 C (L, C, R, Ls, Rs,)" },
129
  { (120 << 16) | 5, five_channel_mpeg_50_d, "MPEG 5.0 D (C, L, R, Ls, Rs)" },
130
  { (135 << 16) | 5, five_channel_dvd_6, "DVD 6 (L, R, LFE, Ls, Rs)" },
131
  { (137 << 16) | 5, five_channel_dvd_11, "DVD 11 (L, R, C, LFE, Cs)" },
132
  { (138 << 16) | 5, five_channel_dvd_18, "DVD 18 (L, R, Ls, Rs, LFE)" }
133
} ; /* five_chan */
134
135
136
static const int six_channel_mpeg_51_a [6] =
137
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
138
static const int six_channel_mpeg_51_b [6] =
139
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE } ;
140
static const int six_channel_mpeg_51_c [6] =
141
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_LFE } ;
142
static const int six_channel_mpeg_51_d [6] =
143
  { SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_LFE } ;
144
static const int six_channel_audio_unit_60 [6] =
145
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_REAR_CENTER } ;
146
static const int six_channel_aac_60 [6] =
147
  { SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_REAR_CENTER } ;
148
149
static const AIFF_CAF_CHANNEL_MAP six_chan [] =
150
{ { (110 << 16) | 6, NULL, "hexagonal (L, R, Lr, Rr, C, Rear)" },
151
  { (121 << 16) | 6, six_channel_mpeg_51_a, "MPEG 5.1 A (L, R, C, LFE, Ls, Rs)" },
152
  { (122 << 16) | 6, six_channel_mpeg_51_b, "MPEG 5.1 B (L, R, Ls, Rs, C, LFE)" },
153
  { (123 << 16) | 6, six_channel_mpeg_51_c, "MPEG 5.1 C (L, C, R, Ls, Rs, LFE)" },
154
  { (124 << 16) | 6, six_channel_mpeg_51_d, "MPEG 5.1 D (C, L, R, Ls, Rs, LFE)" },
155
  { (139 << 16) | 6, six_channel_audio_unit_60, "AudioUnit 6.0 (L, R, Ls, Rs, C, Cs)" },
156
  { (141 << 16) | 6, six_channel_aac_60, "AAC 6.0 (C, L, R, Ls, Rs, Cs)" }
157
} ; /* six_chan */
158
159
160
static const int six_channel_mpeg_61a [7] =
161
  { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_REAR_CENTER } ;
162
static const int six_channel_aac_61 [7] =
163
  { SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_REAR_CENTER, SF_CHANNEL_MAP_LFE } ;
164
165
static const AIFF_CAF_CHANNEL_MAP seven_chan [] =
166
{ { (125 << 16) | 7, six_channel_mpeg_61a, "MPEG 6.1 A (L, R, C, LFE, Ls, Rs, Cs)" },
167
  { (140 << 16) | 7, NULL, "AudioUnit 7.0 (L, R, Ls, Rs, C, Rls, Rrs)" },
168
  { (142 << 16) | 7, six_channel_aac_61, "AAC 6.1 (C, L, R, Ls, Rs, Cs, Lfe)" },
169
  { (143 << 16) | 7, NULL, "AAC 7.0 (C, L, R, Ls, Rs, Rls, Rrs,)" }
170
} ; /* seven_chan */
171
172
173
static const AIFF_CAF_CHANNEL_MAP eight_chan [] =
174
{ { (111 << 16) | 8, NULL,
175
    // front left, front right, rear left, rear right,
176
    // front center, rear center, side left, side right
177
    "octagonal (Lf, Rf, Lr, Rr, Cf, Cr, Ls, Rs)"
178
    },
179
  { (112 << 16) | 8, NULL,
180
    // left, right, rear left, rear right
181
    // top left, top right, top rear left, top rear right
182
    "cube (L, R, Lrear, Rrear, Ltop, Rtop, Ltoprear, Rtoprear)"
183
    },
184
  { (126 << 16) | 8, NULL, "MPEG 7.1 A (L, R, C, LFE, Ls, Rs, Lc, Rc)" },
185
  { (127 << 16) | 8, NULL, "MPEG 7.1 B (C, Lc, Rc, L, R, Ls, Rs, LFE)" },
186
  { (128 << 16) | 8, NULL, "MPEG 7.1 C (L, R, C, LFE, Ls, R, Rls, Rrs)" },
187
  { (129 << 16) | 8, NULL, "Emagic Default 7.1 (L, R, Ls, Rs, C, LFE, Lc, Rc)" },
188
  { (130 << 16) | 8, NULL,
189
    // (ITU_5_1 plus a matrix encoded stereo mix)
190
    "SMPTE DTV (L, R, C, LFE, Ls, Rs, Lt, Rt)"
191
    },
192
  { (144 << 16) | 8, NULL, "AAC octagonal (C, L, R, Ls, Rs, Rls, Rrs, Cs)" }
193
} ; /* eight_chan */
194
195
196
197
#if 0
198
199
TMH_10_2_std = (145 << 16) | 16,
200
// L R C Vhc Lsd Rsd Ls Rs Vhl Vhr Lw Rw Csd Cs LFE1 LFE2
201
202
TMH_10_2_full = (146 << 16) | 21,
203
// TMH_10_2_std plus: Lc Rc HI VI Haptic
204
205
#endif
206
207
208
typedef struct
209
{ const AIFF_CAF_CHANNEL_MAP * map ;
210
  int len ;
211
} MAP_MAP ;
212
213
static const MAP_MAP map [] =
214
{ { zero_chan,  ARRAY_LEN (zero_chan) },
215
  { one_chan,   ARRAY_LEN (one_chan) },
216
  { two_chan,   ARRAY_LEN (two_chan) },
217
  { three_chan, ARRAY_LEN (three_chan) },
218
  { four_chan,  ARRAY_LEN (four_chan) },
219
  { five_chan,  ARRAY_LEN (five_chan) },
220
  { six_chan,   ARRAY_LEN (six_chan) },
221
  { seven_chan, ARRAY_LEN (seven_chan) },
222
  { eight_chan, ARRAY_LEN (eight_chan) }
223
} ; /* map */
224
225
226
int
227
aiff_caf_find_channel_layout_tag (const int *chan_map, int channels)
228
0
{ const AIFF_CAF_CHANNEL_MAP * curr_map ;
229
0
  unsigned k, len ;
230
231
0
  if (channels < 1 || channels >= ARRAY_LEN (map))
232
0
    return 0 ;
233
234
0
  curr_map = map [channels].map ;
235
0
  len = map [channels].len ;
236
237
0
  for (k = 0 ; k < len ; k++)
238
0
    if (curr_map [k].channel_map != NULL)
239
0
      if (memcmp (chan_map, curr_map [k].channel_map, channels * sizeof (chan_map [0])) == 0)
240
0
        return curr_map [k].channel_layout_tag ;
241
242
0
  return 0 ;
243
0
} /* aiff_caf_find_channel_layout_tag */
244
245
const AIFF_CAF_CHANNEL_MAP *
246
aiff_caf_of_channel_layout_tag (int tag)
247
1.93k
{ const AIFF_CAF_CHANNEL_MAP * curr_map ;
248
1.93k
  unsigned k, len ;
249
1.93k
  int channels = tag & 0xffff ;
250
251
1.93k
  if (channels < 0 || channels >= ARRAY_LEN (map))
252
431
    return NULL ;
253
254
1.50k
  curr_map = map [channels].map ;
255
1.50k
  len = map [channels].len ;
256
257
5.19k
  for (k = 0 ; k < len ; k++)
258
4.40k
    if (curr_map [k].channel_layout_tag == tag)
259
716
      return curr_map + k ;
260
261
785
  return NULL ;
262
1.50k
} /* aiff_caf_of_channel_layout_tag */