Chris@0
|
1 /*
|
Chris@0
|
2 ** Copyright (C) 2005-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
Chris@0
|
3 **
|
Chris@0
|
4 ** This program is free software; you can redistribute it and/or modify
|
Chris@0
|
5 ** it under the terms of the GNU Lesser General Public License as published by
|
Chris@0
|
6 ** the Free Software Foundation; either version 2.1 of the License, or
|
Chris@0
|
7 ** (at your option) any later version.
|
Chris@0
|
8 **
|
Chris@0
|
9 ** This program is distributed in the hope that it will be useful,
|
Chris@0
|
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
Chris@0
|
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Chris@0
|
12 ** GNU Lesser General Public License for more details.
|
Chris@0
|
13 **
|
Chris@0
|
14 ** You should have received a copy of the GNU Lesser General Public License
|
Chris@0
|
15 ** along with this program; if not, write to the Free Software
|
Chris@0
|
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Chris@0
|
17 */
|
Chris@0
|
18
|
Chris@0
|
19 #include "sfconfig.h"
|
Chris@0
|
20
|
Chris@0
|
21 #include <stdio.h>
|
Chris@0
|
22 #include <stdlib.h>
|
Chris@0
|
23 #include <string.h>
|
Chris@0
|
24 #include <ctype.h>
|
Chris@0
|
25 #include <math.h>
|
Chris@0
|
26 #include <inttypes.h>
|
Chris@0
|
27
|
Chris@0
|
28 #include "sndfile.h"
|
Chris@0
|
29 #include "sfendian.h"
|
Chris@0
|
30 #include "common.h"
|
Chris@0
|
31 #include "chanmap.h"
|
Chris@0
|
32
|
Chris@0
|
33 /*------------------------------------------------------------------------------
|
Chris@0
|
34 ** Macros to handle big/little endian issues.
|
Chris@0
|
35 */
|
Chris@0
|
36
|
Chris@0
|
37 #define aac_MARKER MAKE_MARKER ('a', 'a', 'c', ' ')
|
Chris@0
|
38 #define alac_MARKER MAKE_MARKER ('a', 'l', 'a', 'c')
|
Chris@0
|
39 #define alaw_MARKER MAKE_MARKER ('a', 'l', 'a', 'w')
|
Chris@0
|
40 #define caff_MARKER MAKE_MARKER ('c', 'a', 'f', 'f')
|
Chris@0
|
41 #define chan_MARKER MAKE_MARKER ('c', 'h', 'a', 'n')
|
Chris@0
|
42 #define data_MARKER MAKE_MARKER ('d', 'a', 't', 'a')
|
Chris@0
|
43 #define desc_MARKER MAKE_MARKER ('d', 'e', 's', 'c')
|
Chris@0
|
44 #define edct_MARKER MAKE_MARKER ('e', 'd', 'c', 't')
|
Chris@0
|
45 #define free_MARKER MAKE_MARKER ('f', 'r', 'e', 'e')
|
Chris@0
|
46 #define ima4_MARKER MAKE_MARKER ('i', 'm', 'a', '4')
|
Chris@0
|
47 #define info_MARKER MAKE_MARKER ('i', 'n', 'f', 'o')
|
Chris@0
|
48 #define inst_MARKER MAKE_MARKER ('i', 'n', 's', 't')
|
Chris@0
|
49 #define kuki_MARKER MAKE_MARKER ('k', 'u', 'k', 'i')
|
Chris@0
|
50 #define lpcm_MARKER MAKE_MARKER ('l', 'p', 'c', 'm')
|
Chris@0
|
51 #define mark_MARKER MAKE_MARKER ('m', 'a', 'r', 'k')
|
Chris@0
|
52 #define midi_MARKER MAKE_MARKER ('m', 'i', 'd', 'i')
|
Chris@0
|
53 #define mp1_MARKER MAKE_MARKER ('.', 'm', 'p', '1')
|
Chris@0
|
54 #define mp2_MARKER MAKE_MARKER ('.', 'm', 'p', '2')
|
Chris@0
|
55 #define mp3_MARKER MAKE_MARKER ('.', 'm', 'p', '3')
|
Chris@0
|
56 #define ovvw_MARKER MAKE_MARKER ('o', 'v', 'v', 'w')
|
Chris@0
|
57 #define pakt_MARKER MAKE_MARKER ('p', 'a', 'k', 't')
|
Chris@0
|
58 #define peak_MARKER MAKE_MARKER ('p', 'e', 'a', 'k')
|
Chris@0
|
59 #define regn_MARKER MAKE_MARKER ('r', 'e', 'g', 'n')
|
Chris@0
|
60 #define strg_MARKER MAKE_MARKER ('s', 't', 'r', 'g')
|
Chris@0
|
61 #define umid_MARKER MAKE_MARKER ('u', 'm', 'i', 'd')
|
Chris@0
|
62 #define uuid_MARKER MAKE_MARKER ('u', 'u', 'i', 'd')
|
Chris@0
|
63 #define ulaw_MARKER MAKE_MARKER ('u', 'l', 'a', 'w')
|
Chris@0
|
64 #define MAC3_MARKER MAKE_MARKER ('M', 'A', 'C', '3')
|
Chris@0
|
65 #define MAC6_MARKER MAKE_MARKER ('M', 'A', 'C', '6')
|
Chris@0
|
66
|
Chris@0
|
67 #define CAF_PEAK_CHUNK_SIZE(ch) ((int) (sizeof (int) + ch * (sizeof (float) + 8)))
|
Chris@0
|
68
|
Chris@0
|
69 #define SFE_CAF_NOT_CAF 666
|
Chris@0
|
70 #define SFE_CAF_NO_DESC 667
|
Chris@0
|
71 #define SFE_CAF_BAD_PEAK 668
|
Chris@0
|
72
|
Chris@0
|
73 /*------------------------------------------------------------------------------
|
Chris@0
|
74 ** Typedefs.
|
Chris@0
|
75 */
|
Chris@0
|
76
|
Chris@0
|
77 typedef struct
|
Chris@0
|
78 { unsigned char srate [8] ;
|
Chris@0
|
79 unsigned int fmt_id ;
|
Chris@0
|
80 unsigned int fmt_flags ;
|
Chris@0
|
81 unsigned int pkt_bytes ;
|
Chris@0
|
82 unsigned int pkt_frames ;
|
Chris@0
|
83 unsigned int channels_per_frame ;
|
Chris@0
|
84 unsigned int bits_per_chan ;
|
Chris@0
|
85 } DESC_CHUNK ;
|
Chris@0
|
86
|
Chris@0
|
87 typedef struct
|
Chris@0
|
88 { int chanmap_tag ;
|
Chris@0
|
89 } CAF_PRIVATE ;
|
Chris@0
|
90
|
Chris@0
|
91 /*------------------------------------------------------------------------------
|
Chris@0
|
92 ** Private static functions.
|
Chris@0
|
93 */
|
Chris@0
|
94
|
Chris@0
|
95 static int caf_close (SF_PRIVATE *psf) ;
|
Chris@0
|
96 static int caf_read_header (SF_PRIVATE *psf) ;
|
Chris@0
|
97 static int caf_write_header (SF_PRIVATE *psf, int calc_length) ;
|
Chris@0
|
98 static int caf_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
|
Chris@0
|
99 static int caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size) ;
|
Chris@0
|
100
|
Chris@0
|
101 /*------------------------------------------------------------------------------
|
Chris@0
|
102 ** Public function.
|
Chris@0
|
103 */
|
Chris@0
|
104
|
Chris@0
|
105 int
|
Chris@0
|
106 caf_open (SF_PRIVATE *psf)
|
Chris@0
|
107 { int subformat, format, error = 0 ;
|
Chris@0
|
108
|
Chris@0
|
109 if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
Chris@0
|
110 { if ((error = caf_read_header (psf)))
|
Chris@0
|
111 return error ;
|
Chris@0
|
112 } ;
|
Chris@0
|
113
|
Chris@0
|
114 subformat = SF_CODEC (psf->sf.format) ;
|
Chris@0
|
115
|
Chris@0
|
116 if ((psf->container_data = calloc (1, sizeof (CAF_PRIVATE))) == NULL)
|
Chris@0
|
117 return SFE_MALLOC_FAILED ;
|
Chris@0
|
118
|
Chris@0
|
119 if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
Chris@0
|
120 { if (psf->is_pipe)
|
Chris@0
|
121 return SFE_NO_PIPE_WRITE ;
|
Chris@0
|
122
|
Chris@0
|
123 format = SF_CONTAINER (psf->sf.format) ;
|
Chris@0
|
124 if (format != SF_FORMAT_CAF)
|
Chris@0
|
125 return SFE_BAD_OPEN_FORMAT ;
|
Chris@0
|
126
|
Chris@0
|
127 psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
Chris@0
|
128
|
Chris@0
|
129 if (psf->file.mode != SFM_RDWR || psf->filelength < 44)
|
Chris@0
|
130 { psf->filelength = 0 ;
|
Chris@0
|
131 psf->datalength = 0 ;
|
Chris@0
|
132 psf->dataoffset = 0 ;
|
Chris@0
|
133 psf->sf.frames = 0 ;
|
Chris@0
|
134 } ;
|
Chris@0
|
135
|
Chris@0
|
136 psf->str_flags = SF_STR_ALLOW_START ;
|
Chris@0
|
137
|
Chris@0
|
138 /*
|
Chris@0
|
139 ** By default, add the peak chunk to floating point files. Default behaviour
|
Chris@0
|
140 ** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE).
|
Chris@0
|
141 */
|
Chris@0
|
142 if (psf->file.mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE))
|
Chris@0
|
143 { if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
|
Chris@0
|
144 return SFE_MALLOC_FAILED ;
|
Chris@0
|
145 psf->peak_info->peak_loc = SF_PEAK_START ;
|
Chris@0
|
146 } ;
|
Chris@0
|
147
|
Chris@0
|
148 if ((error = caf_write_header (psf, SF_FALSE)) != 0)
|
Chris@0
|
149 return error ;
|
Chris@0
|
150
|
Chris@0
|
151 psf->write_header = caf_write_header ;
|
Chris@0
|
152 } ;
|
Chris@0
|
153
|
Chris@0
|
154 psf->container_close = caf_close ;
|
Chris@0
|
155 psf->command = caf_command ;
|
Chris@0
|
156
|
Chris@0
|
157 switch (subformat)
|
Chris@0
|
158 { case SF_FORMAT_PCM_S8 :
|
Chris@0
|
159 case SF_FORMAT_PCM_16 :
|
Chris@0
|
160 case SF_FORMAT_PCM_24 :
|
Chris@0
|
161 case SF_FORMAT_PCM_32 :
|
Chris@0
|
162 error = pcm_init (psf) ;
|
Chris@0
|
163 break ;
|
Chris@0
|
164
|
Chris@0
|
165 case SF_FORMAT_ULAW :
|
Chris@0
|
166 error = ulaw_init (psf) ;
|
Chris@0
|
167 break ;
|
Chris@0
|
168
|
Chris@0
|
169 case SF_FORMAT_ALAW :
|
Chris@0
|
170 error = alaw_init (psf) ;
|
Chris@0
|
171 break ;
|
Chris@0
|
172
|
Chris@0
|
173 /* Lite remove start */
|
Chris@0
|
174 case SF_FORMAT_FLOAT :
|
Chris@0
|
175 error = float32_init (psf) ;
|
Chris@0
|
176 break ;
|
Chris@0
|
177
|
Chris@0
|
178 case SF_FORMAT_DOUBLE :
|
Chris@0
|
179 error = double64_init (psf) ;
|
Chris@0
|
180 break ;
|
Chris@0
|
181 /* Lite remove end */
|
Chris@0
|
182
|
Chris@0
|
183 default :
|
Chris@0
|
184 return SFE_UNSUPPORTED_ENCODING ;
|
Chris@0
|
185 } ;
|
Chris@0
|
186
|
Chris@0
|
187 return error ;
|
Chris@0
|
188 } /* caf_open */
|
Chris@0
|
189
|
Chris@0
|
190 static int
|
Chris@0
|
191 caf_close (SF_PRIVATE *psf)
|
Chris@0
|
192 {
|
Chris@0
|
193 if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
Chris@0
|
194 caf_write_header (psf, SF_TRUE) ;
|
Chris@0
|
195
|
Chris@0
|
196 return 0 ;
|
Chris@0
|
197 } /* caf_close */
|
Chris@0
|
198
|
Chris@0
|
199 static int
|
Chris@0
|
200 caf_command (SF_PRIVATE * psf, int command, void * UNUSED (data), int UNUSED (datasize))
|
Chris@0
|
201 { CAF_PRIVATE *pcaf ;
|
Chris@0
|
202
|
Chris@0
|
203 if ((pcaf = psf->container_data) == NULL)
|
Chris@0
|
204 return SFE_INTERNAL ;
|
Chris@0
|
205
|
Chris@0
|
206 switch (command)
|
Chris@0
|
207 { case SFC_SET_CHANNEL_MAP_INFO :
|
Chris@0
|
208 pcaf->chanmap_tag = aiff_caf_find_channel_layout_tag (psf->channel_map, psf->sf.channels) ;
|
Chris@0
|
209 return (pcaf->chanmap_tag != 0) ;
|
Chris@0
|
210
|
Chris@0
|
211 default :
|
Chris@0
|
212 break ;
|
Chris@0
|
213 } ;
|
Chris@0
|
214
|
Chris@0
|
215 return 0 ;
|
Chris@0
|
216 } /* caf_command */
|
Chris@0
|
217
|
Chris@0
|
218 /*------------------------------------------------------------------------------
|
Chris@0
|
219 */
|
Chris@0
|
220
|
Chris@0
|
221 static int
|
Chris@0
|
222 decode_desc_chunk (SF_PRIVATE *psf, const DESC_CHUNK *desc)
|
Chris@0
|
223 { int format ;
|
Chris@0
|
224
|
Chris@0
|
225 psf->sf.channels = desc->channels_per_frame ;
|
Chris@0
|
226
|
Chris@0
|
227 format = SF_FORMAT_CAF | (psf->endian == SF_ENDIAN_LITTLE ? SF_ENDIAN_LITTLE : 0) ;
|
Chris@0
|
228
|
Chris@0
|
229 if (desc->fmt_id == lpcm_MARKER && desc->fmt_flags & 1)
|
Chris@0
|
230 { /* Floating point data. */
|
Chris@0
|
231 if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame)
|
Chris@0
|
232 { psf->bytewidth = 4 ;
|
Chris@0
|
233 return format | SF_FORMAT_FLOAT ;
|
Chris@0
|
234 } ;
|
Chris@0
|
235 if (desc->bits_per_chan == 64 && desc->pkt_bytes == 8 * desc->channels_per_frame)
|
Chris@0
|
236 { psf->bytewidth = 8 ;
|
Chris@0
|
237 return format | SF_FORMAT_DOUBLE ;
|
Chris@0
|
238 } ;
|
Chris@0
|
239 } ;
|
Chris@0
|
240
|
Chris@0
|
241 if ((desc->fmt_flags & 1) != 0)
|
Chris@0
|
242 { psf_log_printf (psf, "**** Ooops, 'desc' chunk suggests float data, but other info invalid.\n") ;
|
Chris@0
|
243 return 0 ;
|
Chris@0
|
244 } ;
|
Chris@0
|
245
|
Chris@0
|
246 if (desc->fmt_id == lpcm_MARKER)
|
Chris@0
|
247 { /* Integer data. */
|
Chris@0
|
248 if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame)
|
Chris@0
|
249 { psf->bytewidth = 4 ;
|
Chris@0
|
250 return format | SF_FORMAT_PCM_32 ;
|
Chris@0
|
251 } ;
|
Chris@0
|
252 if (desc->bits_per_chan == 24 && desc->pkt_bytes == 3 * desc->channels_per_frame)
|
Chris@0
|
253 { psf->bytewidth = 3 ;
|
Chris@0
|
254 return format | SF_FORMAT_PCM_24 ;
|
Chris@0
|
255 } ;
|
Chris@0
|
256 if (desc->bits_per_chan == 16 && desc->pkt_bytes == 2 * desc->channels_per_frame)
|
Chris@0
|
257 { psf->bytewidth = 2 ;
|
Chris@0
|
258 return format | SF_FORMAT_PCM_16 ;
|
Chris@0
|
259 } ;
|
Chris@0
|
260 if (desc->bits_per_chan == 8 && desc->pkt_bytes == 1 * desc->channels_per_frame)
|
Chris@0
|
261 { psf->bytewidth = 1 ;
|
Chris@0
|
262 return format | SF_FORMAT_PCM_S8 ;
|
Chris@0
|
263 } ;
|
Chris@0
|
264 } ;
|
Chris@0
|
265
|
Chris@0
|
266 if (desc->fmt_id == alaw_MARKER && desc->bits_per_chan == 8)
|
Chris@0
|
267 { psf->bytewidth = 1 ;
|
Chris@0
|
268 return format | SF_FORMAT_ALAW ;
|
Chris@0
|
269 } ;
|
Chris@0
|
270
|
Chris@0
|
271 if (desc->fmt_id == ulaw_MARKER && desc->bits_per_chan == 8)
|
Chris@0
|
272 { psf->bytewidth = 1 ;
|
Chris@0
|
273 return format | SF_FORMAT_ULAW ;
|
Chris@0
|
274 } ;
|
Chris@0
|
275
|
Chris@0
|
276 return 0 ;
|
Chris@0
|
277 } /* decode_desc_chunk */
|
Chris@0
|
278
|
Chris@0
|
279 static int
|
Chris@0
|
280 caf_read_header (SF_PRIVATE *psf)
|
Chris@0
|
281 { DESC_CHUNK desc ;
|
Chris@0
|
282 sf_count_t chunk_size ;
|
Chris@0
|
283 double srate ;
|
Chris@0
|
284 short version, flags ;
|
Chris@0
|
285 int marker, k, have_data = 0, error ;
|
Chris@0
|
286
|
Chris@0
|
287 memset (&desc, 0, sizeof (desc)) ;
|
Chris@0
|
288
|
Chris@0
|
289 /* Set position to start of file to begin reading header. */
|
Chris@0
|
290 psf_binheader_readf (psf, "pmE2E2", 0, &marker, &version, &flags) ;
|
Chris@0
|
291 psf_log_printf (psf, "%M\n Version : %d\n Flags : %x\n", marker, version, flags) ;
|
Chris@0
|
292 if (marker != caff_MARKER)
|
Chris@0
|
293 return SFE_CAF_NOT_CAF ;
|
Chris@0
|
294
|
Chris@0
|
295 psf_binheader_readf (psf, "mE8b", &marker, &chunk_size, psf->u.ucbuf, 8) ;
|
Chris@0
|
296 srate = double64_be_read (psf->u.ucbuf) ;
|
Chris@0
|
297 snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), "%5.3f", srate) ;
|
Chris@0
|
298 psf_log_printf (psf, "%M : %D\n Sample rate : %s\n", marker, chunk_size, psf->u.cbuf) ;
|
Chris@0
|
299 if (marker != desc_MARKER)
|
Chris@0
|
300 return SFE_CAF_NO_DESC ;
|
Chris@0
|
301
|
Chris@0
|
302 if (chunk_size < SIGNED_SIZEOF (DESC_CHUNK))
|
Chris@0
|
303 { psf_log_printf (psf, "**** Chunk size too small. Should be > 32 bytes.\n") ;
|
Chris@0
|
304 return SFE_MALFORMED_FILE ;
|
Chris@0
|
305 } ;
|
Chris@0
|
306
|
Chris@0
|
307 psf->sf.samplerate = lrint (srate) ;
|
Chris@0
|
308
|
Chris@0
|
309 psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.pkt_frames,
|
Chris@0
|
310 &desc.channels_per_frame, &desc.bits_per_chan) ;
|
Chris@0
|
311 psf_log_printf (psf, " Format id : %M\n Format flags : %x\n Bytes / packet : %u\n"
|
Chris@0
|
312 " Frames / packet : %u\n Channels / frame : %u\n Bits / channel : %u\n",
|
Chris@0
|
313 desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ;
|
Chris@0
|
314
|
Chris@0
|
315 if (desc.channels_per_frame > SF_MAX_CHANNELS)
|
Chris@0
|
316 { psf_log_printf (psf, "**** Bad channels per frame value %u.\n", desc.channels_per_frame) ;
|
Chris@0
|
317 return SFE_MALFORMED_FILE ;
|
Chris@0
|
318 } ;
|
Chris@0
|
319
|
Chris@0
|
320 if (chunk_size > SIGNED_SIZEOF (DESC_CHUNK))
|
Chris@0
|
321 psf_binheader_readf (psf, "j", (int) (chunk_size - sizeof (DESC_CHUNK))) ;
|
Chris@0
|
322
|
Chris@0
|
323 psf->sf.channels = desc.channels_per_frame ;
|
Chris@0
|
324
|
Chris@0
|
325 while (have_data == 0 && psf_ftell (psf) < psf->filelength - SIGNED_SIZEOF (marker))
|
Chris@0
|
326 { psf_binheader_readf (psf, "mE8", &marker, &chunk_size) ;
|
Chris@0
|
327
|
Chris@0
|
328 switch (marker)
|
Chris@0
|
329 { case peak_MARKER :
|
Chris@0
|
330 psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
Chris@0
|
331 if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels))
|
Chris@0
|
332 { psf_binheader_readf (psf, "j", (int) chunk_size) ;
|
Chris@0
|
333 psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
|
Chris@0
|
334 return SFE_CAF_BAD_PEAK ;
|
Chris@0
|
335 } ;
|
Chris@0
|
336
|
Chris@0
|
337 if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
|
Chris@0
|
338 return SFE_MALLOC_FAILED ;
|
Chris@0
|
339
|
Chris@0
|
340 /* read in rest of PEAK chunk. */
|
Chris@0
|
341 psf_binheader_readf (psf, "E4", & (psf->peak_info->edit_number)) ;
|
Chris@0
|
342 psf_log_printf (psf, " edit count : %d\n", psf->peak_info->edit_number) ;
|
Chris@0
|
343
|
Chris@0
|
344 psf_log_printf (psf, " Ch Position Value\n") ;
|
Chris@0
|
345 for (k = 0 ; k < psf->sf.channels ; k++)
|
Chris@0
|
346 { sf_count_t position ;
|
Chris@0
|
347 float value ;
|
Chris@0
|
348
|
Chris@0
|
349 psf_binheader_readf (psf, "Ef8", &value, &position) ;
|
Chris@0
|
350 psf->peak_info->peaks [k].value = value ;
|
Chris@0
|
351 psf->peak_info->peaks [k].position = position ;
|
Chris@0
|
352
|
Chris@0
|
353 snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), " %2d %-12" PRId64 " %g\n", k, position, value) ;
|
Chris@0
|
354 psf_log_printf (psf, psf->u.cbuf) ;
|
Chris@0
|
355 } ;
|
Chris@0
|
356
|
Chris@0
|
357 psf->peak_info->peak_loc = SF_PEAK_START ;
|
Chris@0
|
358 break ;
|
Chris@0
|
359
|
Chris@0
|
360 case chan_MARKER :
|
Chris@0
|
361 if (chunk_size < 12)
|
Chris@0
|
362 { psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ;
|
Chris@0
|
363 psf_binheader_readf (psf, "j", (int) chunk_size) ;
|
Chris@0
|
364 break ;
|
Chris@0
|
365 }
|
Chris@0
|
366
|
Chris@0
|
367 psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
Chris@0
|
368
|
Chris@0
|
369 if ((error = caf_read_chanmap (psf, chunk_size)))
|
Chris@0
|
370 return error ;
|
Chris@0
|
371 break ;
|
Chris@0
|
372
|
Chris@0
|
373 case free_MARKER :
|
Chris@0
|
374 psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
Chris@0
|
375 psf_binheader_readf (psf, "j", (int) chunk_size) ;
|
Chris@0
|
376 break ;
|
Chris@0
|
377
|
Chris@0
|
378 case data_MARKER :
|
Chris@0
|
379 if (psf->filelength > 0 && chunk_size + psf->headindex != psf->filelength)
|
Chris@0
|
380 psf_log_printf (psf, "%M : %D (should be %D)\n", marker, chunk_size, chunk_size + 4) ;
|
Chris@0
|
381 else
|
Chris@0
|
382 psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
Chris@0
|
383 psf_binheader_readf (psf, "E4", &k) ;
|
Chris@0
|
384 psf_log_printf (psf, " edit : %u\n", k) ;
|
Chris@0
|
385 have_data = 1 ;
|
Chris@0
|
386 break ;
|
Chris@0
|
387
|
Chris@0
|
388 default :
|
Chris@0
|
389 psf_log_printf (psf, " %M : %D (skipped)\n", marker, chunk_size) ;
|
Chris@0
|
390 psf_binheader_readf (psf, "j", (int) chunk_size) ;
|
Chris@0
|
391 break ;
|
Chris@0
|
392 } ;
|
Chris@0
|
393 } ;
|
Chris@0
|
394
|
Chris@0
|
395 if (have_data == 0)
|
Chris@0
|
396 { psf_log_printf (psf, "**** Error, could not find 'data' chunk.\n") ;
|
Chris@0
|
397 return SFE_MALFORMED_FILE ;
|
Chris@0
|
398 } ;
|
Chris@0
|
399
|
Chris@0
|
400 psf_log_printf (psf, "End\n") ;
|
Chris@0
|
401
|
Chris@0
|
402 psf->dataoffset = psf_ftell (psf) ;
|
Chris@0
|
403 psf->datalength = psf->filelength - psf->dataoffset ;
|
Chris@0
|
404 psf->endian = (desc.fmt_flags & 2) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ;
|
Chris@0
|
405
|
Chris@0
|
406 if ((psf->sf.format = decode_desc_chunk (psf, &desc)) == 0)
|
Chris@0
|
407 return SFE_UNSUPPORTED_ENCODING ;
|
Chris@0
|
408
|
Chris@0
|
409 if (psf->bytewidth > 0)
|
Chris@0
|
410 psf->sf.frames = psf->datalength / psf->bytewidth ;
|
Chris@0
|
411
|
Chris@0
|
412 return 0 ;
|
Chris@0
|
413 } /* caf_read_header */
|
Chris@0
|
414
|
Chris@0
|
415 /*------------------------------------------------------------------------------
|
Chris@0
|
416 */
|
Chris@0
|
417
|
Chris@0
|
418 static int
|
Chris@0
|
419 caf_write_header (SF_PRIVATE *psf, int calc_length)
|
Chris@0
|
420 { CAF_PRIVATE *pcaf ;
|
Chris@0
|
421 DESC_CHUNK desc ;
|
Chris@0
|
422 sf_count_t current, free_len ;
|
Chris@0
|
423 int subformat ;
|
Chris@0
|
424
|
Chris@0
|
425 if ((pcaf = psf->container_data) == NULL)
|
Chris@0
|
426 return SFE_INTERNAL ;
|
Chris@0
|
427
|
Chris@0
|
428 memset (&desc, 0, sizeof (desc)) ;
|
Chris@0
|
429
|
Chris@0
|
430 current = psf_ftell (psf) ;
|
Chris@0
|
431
|
Chris@0
|
432 if (calc_length)
|
Chris@0
|
433 { psf->filelength = psf_get_filelen (psf) ;
|
Chris@0
|
434
|
Chris@0
|
435 psf->datalength = psf->filelength - psf->dataoffset ;
|
Chris@0
|
436
|
Chris@0
|
437 if (psf->dataend)
|
Chris@0
|
438 psf->datalength -= psf->filelength - psf->dataend ;
|
Chris@0
|
439
|
Chris@0
|
440 if (psf->bytewidth > 0)
|
Chris@0
|
441 psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
|
Chris@0
|
442 } ;
|
Chris@0
|
443
|
Chris@0
|
444 /* Reset the current header length to zero. */
|
Chris@0
|
445 psf->header [0] = 0 ;
|
Chris@0
|
446 psf->headindex = 0 ;
|
Chris@0
|
447 psf_fseek (psf, 0, SEEK_SET) ;
|
Chris@0
|
448
|
Chris@0
|
449 /* 'caff' marker, version and flags. */
|
Chris@0
|
450 psf_binheader_writef (psf, "Em22", caff_MARKER, 1, 0) ;
|
Chris@0
|
451
|
Chris@0
|
452 /* 'desc' marker and chunk size. */
|
Chris@0
|
453 psf_binheader_writef (psf, "Em8", desc_MARKER, (sf_count_t) (sizeof (DESC_CHUNK))) ;
|
Chris@0
|
454
|
Chris@0
|
455 double64_be_write (1.0 * psf->sf.samplerate, psf->u.ucbuf) ;
|
Chris@0
|
456 psf_binheader_writef (psf, "b", psf->u.ucbuf, make_size_t (8)) ;
|
Chris@0
|
457
|
Chris@0
|
458 subformat = SF_CODEC (psf->sf.format) ;
|
Chris@0
|
459
|
Chris@0
|
460 psf->endian = SF_ENDIAN (psf->sf.format) ;
|
Chris@0
|
461
|
Chris@0
|
462 if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU))
|
Chris@0
|
463 psf->endian = SF_ENDIAN_BIG ;
|
Chris@0
|
464 else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_LITTLE || psf->endian == SF_ENDIAN_CPU))
|
Chris@0
|
465 psf->endian = SF_ENDIAN_LITTLE ;
|
Chris@0
|
466
|
Chris@0
|
467 if (psf->endian == SF_ENDIAN_LITTLE)
|
Chris@0
|
468 desc.fmt_flags = 2 ;
|
Chris@0
|
469 else
|
Chris@0
|
470 psf->endian = SF_ENDIAN_BIG ;
|
Chris@0
|
471
|
Chris@0
|
472 /* initial section (same for all, it appears) */
|
Chris@0
|
473 switch (subformat)
|
Chris@0
|
474 { case SF_FORMAT_PCM_S8 :
|
Chris@0
|
475 desc.fmt_id = lpcm_MARKER ;
|
Chris@0
|
476 psf->bytewidth = 1 ;
|
Chris@0
|
477 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
Chris@0
|
478 desc.pkt_frames = 1 ;
|
Chris@0
|
479 desc.channels_per_frame = psf->sf.channels ;
|
Chris@0
|
480 desc.bits_per_chan = 8 ;
|
Chris@0
|
481 break ;
|
Chris@0
|
482
|
Chris@0
|
483 case SF_FORMAT_PCM_16 :
|
Chris@0
|
484 desc.fmt_id = lpcm_MARKER ;
|
Chris@0
|
485 psf->bytewidth = 2 ;
|
Chris@0
|
486 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
Chris@0
|
487 desc.pkt_frames = 1 ;
|
Chris@0
|
488 desc.channels_per_frame = psf->sf.channels ;
|
Chris@0
|
489 desc.bits_per_chan = 16 ;
|
Chris@0
|
490 break ;
|
Chris@0
|
491
|
Chris@0
|
492 case SF_FORMAT_PCM_24 :
|
Chris@0
|
493 psf->bytewidth = 3 ;
|
Chris@0
|
494 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
Chris@0
|
495 desc.pkt_frames = 1 ;
|
Chris@0
|
496 desc.channels_per_frame = psf->sf.channels ;
|
Chris@0
|
497 desc.bits_per_chan = 24 ;
|
Chris@0
|
498 desc.fmt_id = lpcm_MARKER ;
|
Chris@0
|
499 break ;
|
Chris@0
|
500
|
Chris@0
|
501 case SF_FORMAT_PCM_32 :
|
Chris@0
|
502 desc.fmt_id = lpcm_MARKER ;
|
Chris@0
|
503 psf->bytewidth = 4 ;
|
Chris@0
|
504 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
Chris@0
|
505 desc.pkt_frames = 1 ;
|
Chris@0
|
506 desc.channels_per_frame = psf->sf.channels ;
|
Chris@0
|
507 desc.bits_per_chan = 32 ;
|
Chris@0
|
508 break ;
|
Chris@0
|
509
|
Chris@0
|
510 case SF_FORMAT_FLOAT :
|
Chris@0
|
511 desc.fmt_id = lpcm_MARKER ;
|
Chris@0
|
512 desc.fmt_flags |= 1 ;
|
Chris@0
|
513 psf->bytewidth = 4 ;
|
Chris@0
|
514 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
Chris@0
|
515 desc.pkt_frames = 1 ;
|
Chris@0
|
516 desc.channels_per_frame = psf->sf.channels ;
|
Chris@0
|
517 desc.bits_per_chan = 32 ;
|
Chris@0
|
518 break ;
|
Chris@0
|
519
|
Chris@0
|
520 case SF_FORMAT_DOUBLE :
|
Chris@0
|
521 desc.fmt_id = lpcm_MARKER ;
|
Chris@0
|
522 desc.fmt_flags |= 1 ;
|
Chris@0
|
523 psf->bytewidth = 8 ;
|
Chris@0
|
524 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
Chris@0
|
525 desc.pkt_frames = 1 ;
|
Chris@0
|
526 desc.channels_per_frame = psf->sf.channels ;
|
Chris@0
|
527 desc.bits_per_chan = 64 ;
|
Chris@0
|
528 break ;
|
Chris@0
|
529
|
Chris@0
|
530 case SF_FORMAT_ALAW :
|
Chris@0
|
531 desc.fmt_id = alaw_MARKER ;
|
Chris@0
|
532 psf->bytewidth = 1 ;
|
Chris@0
|
533 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
Chris@0
|
534 desc.pkt_frames = 1 ;
|
Chris@0
|
535 desc.channels_per_frame = psf->sf.channels ;
|
Chris@0
|
536 desc.bits_per_chan = 8 ;
|
Chris@0
|
537 break ;
|
Chris@0
|
538
|
Chris@0
|
539 case SF_FORMAT_ULAW :
|
Chris@0
|
540 desc.fmt_id = ulaw_MARKER ;
|
Chris@0
|
541 psf->bytewidth = 1 ;
|
Chris@0
|
542 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
Chris@0
|
543 desc.pkt_frames = 1 ;
|
Chris@0
|
544 desc.channels_per_frame = psf->sf.channels ;
|
Chris@0
|
545 desc.bits_per_chan = 8 ;
|
Chris@0
|
546 break ;
|
Chris@0
|
547
|
Chris@0
|
548 default :
|
Chris@0
|
549 return SFE_UNIMPLEMENTED ;
|
Chris@0
|
550 } ;
|
Chris@0
|
551
|
Chris@0
|
552 psf_binheader_writef (psf, "mE44444", desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ;
|
Chris@0
|
553
|
Chris@0
|
554 #if 0
|
Chris@0
|
555 if (psf->str_flags & SF_STR_LOCATE_START)
|
Chris@0
|
556 caf_write_strings (psf, SF_STR_LOCATE_START) ;
|
Chris@0
|
557 #endif
|
Chris@0
|
558
|
Chris@0
|
559 if (psf->peak_info != NULL)
|
Chris@0
|
560 { int k ;
|
Chris@0
|
561 psf_binheader_writef (psf, "Em84", peak_MARKER, (sf_count_t) CAF_PEAK_CHUNK_SIZE (psf->sf.channels), psf->peak_info->edit_number) ;
|
Chris@0
|
562 for (k = 0 ; k < psf->sf.channels ; k++)
|
Chris@0
|
563 psf_binheader_writef (psf, "Ef8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
|
Chris@0
|
564 } ;
|
Chris@0
|
565
|
Chris@0
|
566 if (psf->channel_map && pcaf->chanmap_tag)
|
Chris@0
|
567 psf_binheader_writef (psf, "Em8444", chan_MARKER, (sf_count_t) 12, pcaf->chanmap_tag, 0, 0) ;
|
Chris@0
|
568
|
Chris@0
|
569 /* Add free chunk so that the actual audio data starts at a multiple 0x1000. */
|
Chris@0
|
570 free_len = 0x1000 - psf->headindex - 16 - 12 ;
|
Chris@0
|
571 while (free_len < 0)
|
Chris@0
|
572 free_len += 0x1000 ;
|
Chris@0
|
573 psf_binheader_writef (psf, "Em8z", free_MARKER, free_len, (int) free_len) ;
|
Chris@0
|
574
|
Chris@0
|
575 psf_binheader_writef (psf, "Em84", data_MARKER, psf->datalength + 4, 0) ;
|
Chris@0
|
576
|
Chris@0
|
577 psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
Chris@0
|
578 if (psf->error)
|
Chris@0
|
579 return psf->error ;
|
Chris@0
|
580
|
Chris@0
|
581 psf->dataoffset = psf->headindex ;
|
Chris@0
|
582 if (current < psf->dataoffset)
|
Chris@0
|
583 psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
Chris@0
|
584 else if (current > 0)
|
Chris@0
|
585 psf_fseek (psf, current, SEEK_SET) ;
|
Chris@0
|
586
|
Chris@0
|
587 return psf->error ;
|
Chris@0
|
588 } /* caf_write_header */
|
Chris@0
|
589
|
Chris@0
|
590 static int
|
Chris@0
|
591 caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size)
|
Chris@0
|
592 { const AIFF_CAF_CHANNEL_MAP * map_info ;
|
Chris@0
|
593 unsigned channel_bitmap, channel_decriptions, bytesread ;
|
Chris@0
|
594 int layout_tag ;
|
Chris@0
|
595
|
Chris@0
|
596 bytesread = psf_binheader_readf (psf, "E444", &layout_tag, &channel_bitmap, &channel_decriptions) ;
|
Chris@0
|
597
|
Chris@0
|
598 map_info = aiff_caf_of_channel_layout_tag (layout_tag) ;
|
Chris@0
|
599
|
Chris@0
|
600 psf_log_printf (psf, " Tag : %x\n", layout_tag) ;
|
Chris@0
|
601 if (map_info)
|
Chris@0
|
602 psf_log_printf (psf, " Layout : %s\n", map_info->name) ;
|
Chris@0
|
603
|
Chris@0
|
604 if (bytesread < chunk_size)
|
Chris@0
|
605 psf_binheader_readf (psf, "j", chunk_size - bytesread) ;
|
Chris@0
|
606
|
Chris@0
|
607 if (map_info->channel_map != NULL)
|
Chris@0
|
608 { size_t chanmap_size = psf->sf.channels * sizeof (psf->channel_map [0]) ;
|
Chris@0
|
609
|
Chris@0
|
610 free (psf->channel_map) ;
|
Chris@0
|
611
|
Chris@0
|
612 if ((psf->channel_map = malloc (chanmap_size)) == NULL)
|
Chris@0
|
613 return SFE_MALLOC_FAILED ;
|
Chris@0
|
614
|
Chris@0
|
615 memcpy (psf->channel_map, map_info->channel_map, chanmap_size) ;
|
Chris@0
|
616 } ;
|
Chris@0
|
617
|
Chris@0
|
618 return 0 ;
|
Chris@0
|
619 } /* caf_read_chanmap */
|
Chris@0
|
620
|