• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
aiff_caf_find_channel_layout_tag(const int * chan_map,int channels)227 aiff_caf_find_channel_layout_tag (const int *chan_map, int channels)
228 {	const AIFF_CAF_CHANNEL_MAP * curr_map ;
229 	unsigned k, len ;
230 
231 	if (channels < 1 || channels >= ARRAY_LEN (map))
232 		return 0 ;
233 
234 	curr_map = map [channels].map ;
235 	len = map [channels].len ;
236 
237 	for (k = 0 ; k < len ; k++)
238 		if (curr_map [k].channel_map != NULL)
239 			if (memcmp (chan_map, curr_map [k].channel_map, channels * sizeof (chan_map [0])) == 0)
240 				return curr_map [k].channel_layout_tag ;
241 
242 	return 0 ;
243 } /* aiff_caf_find_channel_layout_tag */
244 
245 const AIFF_CAF_CHANNEL_MAP *
aiff_caf_of_channel_layout_tag(int tag)246 aiff_caf_of_channel_layout_tag (int tag)
247 {	const AIFF_CAF_CHANNEL_MAP * curr_map ;
248 	unsigned k, len ;
249 	int channels = tag & 0xffff ;
250 
251 	if (channels < 0 || channels >= ARRAY_LEN (map))
252 		return NULL ;
253 
254 	curr_map = map [channels].map ;
255 	len = map [channels].len ;
256 
257 	for (k = 0 ; k < len ; k++)
258 		if (curr_map [k].channel_layout_tag == tag)
259 			return curr_map + k ;
260 
261 	return NULL ;
262 } /* aiff_caf_of_channel_layout_tag */
263