1 /* libSoX SGI/Amiga AIFF format.
2 * Copyright 1991-2007 Guido van Rossum And Sundry Contributors
4 * This source code is freely redistributable and may be used for
5 * any purpose. This copyright notice must be maintained.
6 * Guido van Rossum And Sundry Contributors are not responsible for
7 * the consequences of using this software.
9 * Used by SGI on 4D/35 and Indigo.
10 * This is a subformat of the EA-IFF-85 format.
11 * This is related to the IFF format used by the Amiga.
12 * But, apparently, not the same.
13 * Also AIFF-C format output that is defined in DAVIC 1.4 Part 9 Annex B
14 * (usable for japanese-data-broadcasting, specified by ARIB STD-B24.)
20 #include <time.h> /* for time stamping comments */
27 /* forward declarations */
28 static double read_ieee_extended(sox_format_t
*);
29 static int aiffwriteheader(sox_format_t
*, uint64_t);
30 static int aifcwriteheader(sox_format_t
*, uint64_t);
31 static void write_ieee_extended(sox_format_t
*, double);
32 static double ConvertFromIeeeExtended(unsigned char*);
33 static void ConvertToIeeeExtended(double, char *);
34 static int textChunk(char **text
, char *chunkDescription
, sox_format_t
* ft
);
35 static int commentChunk(char **text
, char *chunkDescription
, sox_format_t
* ft
);
36 static void reportInstrument(sox_format_t
* ft
);
38 int lsx_aiffstartread(sox_format_t
* ft
)
43 unsigned short channels
= 0;
44 sox_encoding_t enc
= SOX_ENCODING_SIGN2
;
46 unsigned short bits
= 0;
49 uint32_t blocksize
= 0;
50 int foundcomm
= 0, foundmark
= 0, foundinstr
= 0, is_sowt
= 0;
56 unsigned short looptype
;
58 unsigned short nmarks
= 0;
59 unsigned short sustainLoopBegin
= 0, sustainLoopEnd
= 0,
60 releaseLoopBegin
= 0, releaseLoopEnd
= 0;
76 if (lsx_reads(ft
, buf
, (size_t)4) == SOX_EOF
|| strncmp(buf
, "FORM", (size_t)4) != 0) {
77 lsx_fail_errno(ft
,SOX_EHDR
,"AIFF header does not begin with magic word `FORM'");
80 lsx_readdw(ft
, &totalsize
);
81 if (lsx_reads(ft
, buf
, (size_t)4) == SOX_EOF
|| (strncmp(buf
, "AIFF", (size_t)4) != 0 &&
82 strncmp(buf
, "AIFC", (size_t)4) != 0)) {
83 lsx_fail_errno(ft
,SOX_EHDR
,"AIFF `FORM' chunk does not specify `AIFF' or `AIFC' as type");
88 /* Skip everything but the COMM chunk and the SSND chunk */
89 /* The SSND chunk must be the last in the file */
91 if (lsx_reads(ft
, buf
, (size_t)4) == SOX_EOF
) {
95 lsx_fail_errno(ft
,SOX_EHDR
,"Missing SSND chunk in AIFF file");
99 if (strncmp(buf
, "COMM", (size_t)4) == 0) {
101 lsx_readdw(ft
, &chunksize
);
102 lsx_readw(ft
, &channels
);
103 lsx_readdw(ft
, &frames
);
104 lsx_readw(ft
, &bits
);
105 rate
= read_ieee_extended(ft
);
108 lsx_reads(ft
, buf
, (size_t)4);
110 if (strncmp(buf
, "sowt", (size_t)4) == 0) {
111 /* CD audio as read on Mac OS machines */
112 /* Need to endian swap all the data */
115 else if (strncmp(buf
, "fl32", (size_t)4) == 0 ||
116 strncmp(buf
, "FL32", (size_t)4) == 0) {
117 enc
= SOX_ENCODING_FLOAT
;
119 lsx_fail_errno(ft
, SOX_EHDR
,
120 "Sample size of %u is not consistent with `fl32' compression type", bits
);
124 else if (strncmp(buf
, "fl64", (size_t)4) == 0 ||
125 strncmp(buf
, "FL64", (size_t)4) == 0) {
126 enc
= SOX_ENCODING_FLOAT
;
128 lsx_fail_errno(ft
, SOX_EHDR
,
129 "Sample size of %u is not consistent with `fl64' compression type", bits
);
133 else if (strncmp(buf
, "NONE", (size_t)4) != 0 &&
134 strncmp(buf
, "twos", (size_t)4) != 0) {
136 lsx_fail_errno(ft
, SOX_EHDR
, "Unsupported AIFC compression type `%s'", buf
);
140 while(chunksize
-- > 0)
141 lsx_readb(ft
, &trash8
);
144 else if (strncmp(buf
, "SSND", (size_t)4) == 0) {
146 lsx_readdw(ft
, &chunksize
);
147 lsx_readdw(ft
, &offset
);
148 lsx_readdw(ft
, &blocksize
);
150 ssndsize
= chunksize
;
151 /* word-align chunksize in case it wasn't
152 * done by writing application already.
154 chunksize
+= (chunksize
% 2);
155 /* if can't seek, just do sound now */
158 /* else, seek to end of sound and hunt for more */
159 seekto
= lsx_tell(ft
);
160 lsx_seeki(ft
, (off_t
)chunksize
, SEEK_CUR
);
162 else if (strncmp(buf
, "MARK", (size_t)4) == 0) {
164 lsx_readdw(ft
, &chunksize
);
165 if (chunksize
>= sizeof(nmarks
)) {
166 lsx_readw(ft
, &nmarks
);
167 chunksize
-= sizeof(nmarks
);
171 /* Some programs like to always have a MARK chunk
172 * but will set number of marks to 0 and force
173 * software to detect and ignore it.
180 /* Make sure its not larger then we support */
184 for(i
= 0; i
< nmarks
&& chunksize
; i
++) {
185 unsigned char len
, read_len
, tmp_c
;
189 lsx_readw(ft
, &(marks
[i
].id
));
190 lsx_readdw(ft
, &(marks
[i
].position
));
192 /* If error reading length then
193 * don't try to read more bytes
194 * based on that value.
196 if (lsx_readb(ft
, &len
) != SOX_SUCCESS
)
204 for(j
= 0; j
< len
&& chunksize
; j
++) {
205 lsx_readb(ft
, &tmp_c
);
207 marks
[i
].name
[j
] = tmp_c
;
210 marks
[i
].name
[read_len
] = 0;
211 if ((len
& 1) == 0 && chunksize
) {
213 lsx_readb(ft
, &trash8
);
216 /* HA HA! Sound Designer (and others) makes */
217 /* bogus files. It spits out bogus chunksize */
219 while(chunksize
-- > 0)
220 lsx_readb(ft
, &trash8
);
222 else if (strncmp(buf
, "INST", (size_t)4) == 0) {
224 lsx_readdw(ft
, &chunksize
);
225 lsx_readsb(ft
, &(ft
->oob
.instr
.MIDInote
));
226 lsx_readb(ft
, &trash8
);
227 lsx_readsb(ft
, &(ft
->oob
.instr
.MIDIlow
));
228 lsx_readsb(ft
, &(ft
->oob
.instr
.MIDIhi
));
230 lsx_readb(ft
, &trash8
);
232 lsx_readb(ft
, &trash8
);
233 lsx_readw(ft
, &trash16
);/* gain */
234 lsx_readw(ft
, &looptype
); /* sustain loop */
235 ft
->oob
.loops
[0].type
= looptype
;
236 lsx_readw(ft
, &sustainLoopBegin
); /* begin marker */
237 lsx_readw(ft
, &sustainLoopEnd
); /* end marker */
238 lsx_readw(ft
, &looptype
); /* release loop */
239 ft
->oob
.loops
[1].type
= looptype
;
240 lsx_readw(ft
, &releaseLoopBegin
); /* begin marker */
241 lsx_readw(ft
, &releaseLoopEnd
); /* end marker */
245 else if (strncmp(buf
, "APPL", (size_t)4) == 0) {
246 lsx_readdw(ft
, &chunksize
);
247 /* word-align chunksize in case it wasn't
248 * done by writing application already.
250 chunksize
+= (chunksize
% 2);
251 while(chunksize
-- > 0)
252 lsx_readb(ft
, &trash8
);
254 else if (strncmp(buf
, "ALCH", (size_t)4) == 0) {
255 /* I think this is bogus and gets grabbed by APPL */
257 lsx_readdw(ft
, &trash32
); /* ENVS - jeez! */
258 lsx_readdw(ft
, &chunksize
);
259 while(chunksize
-- > 0)
260 lsx_readb(ft
, &trash8
);
262 else if (strncmp(buf
, "ANNO", (size_t)4) == 0) {
263 rc
= textChunk(&annotation
, "Annotation:", ft
);
265 /* Fail already called in function */
269 sox_append_comments(&ft
->oob
.comments
, annotation
);
272 else if (strncmp(buf
, "COMT", (size_t)4) == 0) {
273 rc
= commentChunk(&comment
, "Comment:", ft
);
275 /* Fail already called in function */
279 sox_append_comments(&ft
->oob
.comments
, comment
);
282 else if (strncmp(buf
, "AUTH", (size_t)4) == 0) {
284 rc
= textChunk(&author
, "Author:", ft
);
286 /* Fail already called in function */
291 else if (strncmp(buf
, "NAME", (size_t)4) == 0) {
293 rc
= textChunk(&nametext
, "Name:", ft
);
295 /* Fail already called in function */
300 else if (strncmp(buf
, "(c) ", (size_t)4) == 0) {
301 /* Copyright chunk */
302 rc
= textChunk(©right
, "Copyright:", ft
);
304 /* Fail already called in function */
313 lsx_debug("AIFFstartread: ignoring `%s' chunk", buf
);
314 lsx_readdw(ft
, &chunksize
);
317 /* Skip the chunk using lsx_readb() so we may read
319 while (chunksize
-- > 0) {
320 if (lsx_readb(ft
, &trash8
) == SOX_EOF
)
329 * if a pipe, we lose all chunks after sound.
330 * Like, say, instrument loops.
334 lsx_seeki(ft
, seekto
, SEEK_SET
);
336 lsx_fail_errno(ft
,SOX_EOF
,"AIFF: no sound data on input file");
340 /* SSND chunk just read */
342 lsx_warn("AIFF header has invalid blocksize. Ignoring but expect a premature EOF");
345 while (offset
-- > 0) {
346 if (lsx_readb(ft
, &trash8
) == SOX_EOF
) {
347 lsx_fail_errno(ft
,errno
,"unexpected EOF while skipping AIFF offset");
353 if (bits
<= 8) bits
= 8;
354 else if (bits
<= 16) bits
= 16;
355 else if (bits
<= 24) bits
= 24;
356 else if (bits
<= 32) bits
= 32;
357 else if (bits
== 64 && enc
== SOX_ENCODING_FLOAT
) /* no-op */;
359 lsx_fail_errno(ft
,SOX_EFMT
,"unsupported sample size in AIFF header: %d", bits
);
363 if ((ft
->signal
.channels
== SOX_UNSPEC
)
364 || (ft
->signal
.rate
== SOX_UNSPEC
)
365 || (ft
->encoding
.encoding
== SOX_ENCODING_UNKNOWN
)
366 || (ft
->encoding
.bits_per_sample
== 0)) {
367 lsx_report("You must specify # channels, sample rate, signed/unsigned,");
368 lsx_report("and 8/16 on the command line.");
369 lsx_fail_errno(ft
,SOX_EFMT
,"Bogus AIFF file: no COMM section.");
374 ssndsize
/= bits
>> 3;
376 /* Cope with 'sowt' CD tracks as read on Macs */
378 ft
->encoding
.reverse_bytes
= !ft
->encoding
.reverse_bytes
;
380 if (foundmark
&& !foundinstr
) {
381 lsx_debug("Ignoring MARK chunk since no INSTR found.");
384 if (!foundmark
&& foundinstr
) {
385 lsx_debug("Ignoring INSTR chunk since no MARK found.");
388 if (foundmark
&& foundinstr
) {
390 int slbIndex
= 0, sleIndex
= 0;
391 int rlbIndex
= 0, rleIndex
= 0;
393 /* find our loop markers and save their marker indexes */
394 for(i2
= 0; i2
< nmarks
; i2
++) {
395 if(marks
[i2
].id
== sustainLoopBegin
)
397 if(marks
[i2
].id
== sustainLoopEnd
)
399 if(marks
[i2
].id
== releaseLoopBegin
)
401 if(marks
[i2
].id
== releaseLoopEnd
)
405 ft
->oob
.instr
.nloops
= 0;
406 if (ft
->oob
.loops
[0].type
!= 0) {
407 ft
->oob
.loops
[0].start
= marks
[slbIndex
].position
;
408 ft
->oob
.loops
[0].length
=
409 marks
[sleIndex
].position
- marks
[slbIndex
].position
;
410 /* really the loop count should be infinite */
411 ft
->oob
.loops
[0].count
= 1;
412 ft
->oob
.instr
.loopmode
= SOX_LOOP_SUSTAIN_DECAY
| ft
->oob
.loops
[0].type
;
413 ft
->oob
.instr
.nloops
++;
415 if (ft
->oob
.loops
[1].type
!= 0) {
416 ft
->oob
.loops
[1].start
= marks
[rlbIndex
].position
;
417 ft
->oob
.loops
[1].length
=
418 marks
[rleIndex
].position
- marks
[rlbIndex
].position
;
419 /* really the loop count should be infinite */
420 ft
->oob
.loops
[1].count
= 1;
421 ft
->oob
.instr
.loopmode
= SOX_LOOP_SUSTAIN_DECAY
| ft
->oob
.loops
[1].type
;
422 ft
->oob
.instr
.nloops
++;
425 reportInstrument(ft
);
427 return lsx_check_read_params(
428 ft
, channels
, rate
, enc
, bits
, (uint64_t)ssndsize
, sox_false
);
431 /* print out the MIDI key allocations, loop points, directions etc */
432 static void reportInstrument(sox_format_t
* ft
)
436 if(ft
->oob
.instr
.nloops
> 0)
437 lsx_report("AIFF Loop markers:");
438 for(loopNum
= 0; loopNum
< ft
->oob
.instr
.nloops
; loopNum
++) {
439 if (ft
->oob
.loops
[loopNum
].count
) {
440 lsx_report("Loop %d: start: %6lu", loopNum
, (unsigned long)ft
->oob
.loops
[loopNum
].start
);
441 lsx_report(" end: %6lu",
442 (unsigned long)(ft
->oob
.loops
[loopNum
].start
+ ft
->oob
.loops
[loopNum
].length
));
443 lsx_report(" count: %6d", ft
->oob
.loops
[loopNum
].count
);
444 lsx_report(" type: ");
445 switch(ft
->oob
.loops
[loopNum
].type
& ~SOX_LOOP_SUSTAIN_DECAY
) {
446 case 0: lsx_report("off"); break;
447 case 1: lsx_report("forward"); break;
448 case 2: lsx_report("forward/backward"); break;
452 lsx_report("Unity MIDI Note: %d", ft
->oob
.instr
.MIDInote
);
453 lsx_report("Low MIDI Note: %d", ft
->oob
.instr
.MIDIlow
);
454 lsx_report("High MIDI Note: %d", ft
->oob
.instr
.MIDIhi
);
457 /* Process a text chunk, allocate memory, display it if verbose and return */
458 static int textChunk(char **text
, char *chunkDescription
, sox_format_t
* ft
)
462 lsx_readdw(ft
, &chunksize0
);
463 chunksize
= chunksize0
;
465 /* allocate enough memory to hold the text including a terminating \0 */
466 if (chunksize
!= SOX_SIZE_MAX
)
467 *text
= lsx_malloc((size_t)chunksize
+1);
469 *text
= lsx_malloc((size_t)chunksize
);
471 if (lsx_readbuf(ft
, *text
, (size_t) chunksize
) != chunksize
)
473 lsx_fail_errno(ft
,SOX_EOF
,"AIFF: Unexpected EOF in %s header", chunkDescription
);
476 if (chunksize
!= SOX_SIZE_MAX
)
477 *(*text
+ chunksize
) = '\0';
479 *(*text
+ chunksize
-1) = '\0';
482 /* Read past pad byte */
484 if (lsx_readbuf(ft
, &c
, (size_t)1) != 1)
486 lsx_fail_errno(ft
,SOX_EOF
,"AIFF: Unexpected EOF in %s header", chunkDescription
);
490 lsx_debug("%-10s \"%s\"", chunkDescription
, *text
);
494 /* Comment lengths are words, not double words, and we can have several, so
495 we use a special function, not textChunk().;
497 static int commentChunk(char **text
, char *chunkDescription
, sox_format_t
* ft
)
500 unsigned short numComments
;
502 unsigned short markerId
;
503 unsigned short totalCommentLength
= 0;
504 unsigned int totalReadLength
= 0;
505 unsigned int commentIndex
;
507 lsx_readdw(ft
, &chunksize
);
508 lsx_readw(ft
, &numComments
);
509 totalReadLength
+= 2; /* chunksize doesn't count */
510 for(commentIndex
= 0; commentIndex
< numComments
; commentIndex
++) {
511 unsigned short commentLength
;
513 lsx_readdw(ft
, &timeStamp
);
514 lsx_readw(ft
, &markerId
);
515 lsx_readw(ft
, &commentLength
);
516 if (((size_t)totalCommentLength
) + commentLength
> USHRT_MAX
) {
517 lsx_fail_errno(ft
,SOX_EOF
,"AIFF: Comment too long in %s header", chunkDescription
);
520 totalCommentLength
+= commentLength
;
521 /* allocate enough memory to hold the text including a terminating \0 */
522 if(commentIndex
== 0) {
523 *text
= lsx_malloc((size_t) totalCommentLength
+ 1);
526 *text
= lsx_realloc(*text
, (size_t) totalCommentLength
+ 1);
529 if (lsx_readbuf(ft
, *text
+ totalCommentLength
- commentLength
, (size_t) commentLength
) != commentLength
) {
530 lsx_fail_errno(ft
,SOX_EOF
,"AIFF: Unexpected EOF in %s header", chunkDescription
);
533 *(*text
+ totalCommentLength
) = '\0';
534 totalReadLength
+= totalCommentLength
+ 4 + 2 + 2; /* include header */
535 if (commentLength
% 2) {
536 /* Read past pad byte */
538 if (lsx_readbuf(ft
, &c
, (size_t)1) != 1) {
539 lsx_fail_errno(ft
,SOX_EOF
,"AIFF: Unexpected EOF in %s header", chunkDescription
);
542 totalReadLength
+= 1;
545 lsx_debug("%-10s \"%s\"", chunkDescription
, *text
);
546 /* make sure we read the whole chunk */
547 if (totalReadLength
< chunksize
) {
550 for (i
=0; i
< chunksize
- totalReadLength
; i
++ )
551 lsx_readbuf(ft
, &c
, (size_t)1);
556 int lsx_aiffstopread(sox_format_t
* ft
)
564 while (! lsx_eof(ft
))
566 if (lsx_readbuf(ft
, buf
, (size_t)4) != 4)
569 lsx_readdw(ft
, &chunksize
);
573 lsx_warn("Ignoring AIFF tail chunk: `%s', %u bytes long",
575 if (! strcmp(buf
, "MARK") || ! strcmp(buf
, "INST"))
576 lsx_warn(" You're stripping MIDI/loop info!");
577 while (chunksize
-- > 0)
579 if (lsx_readb(ft
, &trash
) == SOX_EOF
)
587 /* When writing, the header is supposed to contain the number of
588 samples and data bytes written.
589 Since we don't know how many samples there are until we're done,
590 we first write the header with an very large number,
591 and at the end we rewind the file and write the header again
592 with the right number. This only works if the file is seekable;
593 if it is not, the very large size remains in the header.
594 Strictly spoken this is not legal, but the playaiff utility
595 will still be able to play the resulting file. */
597 int lsx_aiffstartwrite(sox_format_t
* ft
)
601 /* Needed because lsx_rawwrite() */
602 rc
= lsx_rawstartwrite(ft
);
606 /* Compute the "very large number" so that a maximum number
607 of samples can be transmitted through a pipe without the
608 risk of causing overflow when calculating the number of bytes.
609 At 48 kHz, 16 bits stereo, this gives ~3 hours of audio.
610 Sorry, the AIFF format does not provide for an indefinite
611 number of samples. */
612 return(aiffwriteheader(ft
, (uint64_t) 0x7f000000 / ((ft
->encoding
.bits_per_sample
>>3)*ft
->signal
.channels
)));
615 int lsx_aiffstopwrite(sox_format_t
* ft
)
617 /* If we've written an odd number of bytes, write a padding
619 if (ft
->olength
% 2 == 1 && ft
->encoding
.bits_per_sample
== 8 && ft
->signal
.channels
== 1)
621 sox_sample_t buf
= 0;
622 lsx_rawwrite(ft
, &buf
, (size_t) 1);
627 lsx_fail_errno(ft
,SOX_EOF
,"Non-seekable file.");
630 if (lsx_seeki(ft
, (off_t
)0, SEEK_SET
) != 0)
632 lsx_fail_errno(ft
,errno
,"can't rewind output file to rewrite AIFF header");
635 return(aiffwriteheader(ft
, ft
->olength
/ ft
->signal
.channels
));
638 static int aiffwriteheader(sox_format_t
* ft
, uint64_t nframes
)
641 8 /*COMM hdr*/ + 18 /*COMM chunk*/ +
642 8 /*SSND hdr*/ + 12 /*SSND chunk*/;
646 size_t padded_comment_size
= 0, comment_size
= 0;
647 size_t comment_chunk_size
= 0;
648 char * comment
= lsx_cat_comments(ft
->oob
.comments
);
650 /* MARK and INST chunks */
651 if (ft
->oob
.instr
.nloops
) {
652 hsize
+= 8 /* MARK hdr */ + 2 + 16*ft
->oob
.instr
.nloops
;
653 hsize
+= 8 /* INST hdr */ + 20; /* INST chunk */
656 if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
657 ft
->encoding
.bits_per_sample
== 8)
659 else if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
660 ft
->encoding
.bits_per_sample
== 16)
662 else if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
663 ft
->encoding
.bits_per_sample
== 24)
665 else if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
666 ft
->encoding
.bits_per_sample
== 32)
670 lsx_fail_errno(ft
,SOX_EFMT
,"unsupported output encoding/size for AIFF header");
674 /* COMT comment chunk -- holds comments text with a timestamp and marker id */
675 /* We calculate the comment_chunk_size if we will be writing a comment */
676 if (ft
->oob
.comments
)
678 comment_size
= strlen(comment
);
679 /* Must put an even number of characters out.
680 * True 68k processors OS's seem to require this.
682 padded_comment_size
= ((comment_size
% 2) == 0) ?
683 comment_size
: comment_size
+ 1;
684 /* one comment, timestamp, marker ID and text count */
685 comment_chunk_size
= (2 + 4 + 2 + 2 + padded_comment_size
);
686 hsize
+= 8 /* COMT hdr */ + comment_chunk_size
;
689 lsx_writes(ft
, "FORM"); /* IFF header */
691 size
= hsize
+ nframes
* (ft
->encoding
.bits_per_sample
>> 3) * ft
->signal
.channels
;
694 lsx_warn("file size too big for accurate AIFF header");
697 lsx_writedw(ft
, (unsigned)size
);
698 lsx_writes(ft
, "AIFF"); /* File type */
700 /* Now we write the COMT comment chunk using the precomputed sizes */
701 if (ft
->oob
.comments
)
703 lsx_writes(ft
, "COMT");
704 lsx_writedw(ft
, (unsigned) comment_chunk_size
);
709 /* time stamp of comment, Unix knows of time from 1/1/1970,
710 Apple knows time from 1/1/1904 */
711 lsx_writedw(ft
, (unsigned)((sox_globals
.repeatable
? 0 : time(NULL
)) + 2082844800));
713 /* A marker ID of 0 indicates the comment is not associated
717 /* now write the count and the bytes of text */
718 lsx_writew(ft
, (unsigned) padded_comment_size
);
719 lsx_writes(ft
, comment
);
720 if (comment_size
!= padded_comment_size
)
725 /* COMM chunk -- describes encoding (and #frames) */
726 lsx_writes(ft
, "COMM");
727 lsx_writedw(ft
, 18); /* COMM chunk size */
728 lsx_writew(ft
, ft
->signal
.channels
); /* nchannels */
729 lsx_writedw(ft
, (unsigned) nframes
); /* number of frames */
730 lsx_writew(ft
, bits
); /* sample width, in bits */
731 write_ieee_extended(ft
, (double)ft
->signal
.rate
);
733 /* MARK chunk -- set markers */
734 if (ft
->oob
.instr
.nloops
) {
735 lsx_writes(ft
, "MARK");
736 if (ft
->oob
.instr
.nloops
> 2)
737 ft
->oob
.instr
.nloops
= 2;
738 lsx_writedw(ft
, 2 + 16u*ft
->oob
.instr
.nloops
);
739 lsx_writew(ft
, ft
->oob
.instr
.nloops
);
741 for(i
= 0; i
< ft
->oob
.instr
.nloops
; i
++) {
742 unsigned start
= ft
->oob
.loops
[i
].start
> UINT_MAX
744 : ft
->oob
.loops
[i
].start
;
745 unsigned end
= ft
->oob
.loops
[i
].start
+ ft
->oob
.loops
[i
].length
> UINT_MAX
747 : ft
->oob
.loops
[i
].start
+ ft
->oob
.loops
[i
].length
;
748 lsx_writew(ft
, i
+ 1);
749 lsx_writedw(ft
, start
);
752 lsx_writew(ft
, i
*2 + 1);
753 lsx_writedw(ft
, end
);
758 lsx_writes(ft
, "INST");
760 /* random MIDI shit that we default on */
761 lsx_writeb(ft
, (uint8_t)ft
->oob
.instr
.MIDInote
);
762 lsx_writeb(ft
, 0); /* detune */
763 lsx_writeb(ft
, (uint8_t)ft
->oob
.instr
.MIDIlow
);
764 lsx_writeb(ft
, (uint8_t)ft
->oob
.instr
.MIDIhi
);
765 lsx_writeb(ft
, 1); /* low velocity */
766 lsx_writeb(ft
, 127); /* hi velocity */
767 lsx_writew(ft
, 0); /* gain */
770 lsx_writew(ft
, ft
->oob
.loops
[0].type
);
771 lsx_writew(ft
, 1); /* marker 1 */
772 lsx_writew(ft
, 3); /* marker 3 */
773 /* release loop, if there */
774 if (ft
->oob
.instr
.nloops
== 2) {
775 lsx_writew(ft
, ft
->oob
.loops
[1].type
);
776 lsx_writew(ft
, 2); /* marker 2 */
777 lsx_writew(ft
, 4); /* marker 4 */
779 lsx_writew(ft
, 0); /* no release loop */
785 /* SSND chunk -- describes data */
786 lsx_writes(ft
, "SSND");
788 lsx_writedw(ft
, (unsigned) (8 + nframes
* ft
->signal
.channels
* (ft
->encoding
.bits_per_sample
>> 3)));
789 lsx_writedw(ft
, 0); /* offset */
790 lsx_writedw(ft
, 0); /* block size */
794 int lsx_aifcstartwrite(sox_format_t
* ft
)
798 /* Needed because lsx_rawwrite() */
799 rc
= lsx_rawstartwrite(ft
);
803 /* Compute the "very large number" so that a maximum number
804 of samples can be transmitted through a pipe without the
805 risk of causing overflow when calculating the number of bytes.
806 At 48 kHz, 16 bits stereo, this gives ~3 hours of music.
807 Sorry, the AIFC format does not provide for an "infinite"
808 number of samples. */
809 return(aifcwriteheader(ft
, (uint64_t) 0x7f000000 / ((ft
->encoding
.bits_per_sample
>> 3)*ft
->signal
.channels
)));
812 int lsx_aifcstopwrite(sox_format_t
* ft
)
814 /* If we've written an odd number of bytes, write a padding
816 if (ft
->olength
% 2 == 1 && ft
->encoding
.bits_per_sample
== 8 && ft
->signal
.channels
== 1)
818 sox_sample_t buf
= 0;
819 lsx_rawwrite(ft
, &buf
, (size_t) 1);
824 lsx_fail_errno(ft
,SOX_EOF
,"Non-seekable file.");
827 if (lsx_seeki(ft
, (off_t
)0, SEEK_SET
) != 0)
829 lsx_fail_errno(ft
,errno
,"can't rewind output file to rewrite AIFC header");
832 return(aifcwriteheader(ft
, ft
->olength
/ ft
->signal
.channels
));
835 static int aifcwriteheader(sox_format_t
* ft
, uint64_t nframes
)
840 char *ctype
= NULL
, *cname
= NULL
;
841 unsigned cname_len
= 0, comm_len
= 0, comm_padding
= 0;
843 if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
844 ft
->encoding
.bits_per_sample
== 8)
846 else if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
847 ft
->encoding
.bits_per_sample
== 16)
849 else if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
850 ft
->encoding
.bits_per_sample
== 24)
852 else if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
853 ft
->encoding
.bits_per_sample
== 32)
855 else if (ft
->encoding
.encoding
== SOX_ENCODING_FLOAT
&&
856 ft
->encoding
.bits_per_sample
== 32)
858 else if (ft
->encoding
.encoding
== SOX_ENCODING_FLOAT
&&
859 ft
->encoding
.bits_per_sample
== 64)
863 lsx_fail_errno(ft
,SOX_EFMT
,"unsupported output encoding/size for AIFC header");
867 /* calculate length of COMM chunk (without header) */
868 switch (ft
->encoding
.encoding
) {
869 case SOX_ENCODING_SIGN2
:
871 cname
= "not compressed";
873 case SOX_ENCODING_FLOAT
:
876 cname
= "32-bit floating point";
879 cname
= "64-bit floating point";
882 default: /* can't happen */
885 cname_len
= strlen(cname
);
886 comm_len
= 18+4+1+cname_len
;
887 comm_padding
= comm_len
%2;
889 hsize
= 12 /*FVER*/ + 8 /*COMM hdr*/ + comm_len
+comm_padding
/*COMM chunk*/ +
890 8 /*SSND hdr*/ + 12 /*SSND chunk*/;
892 lsx_writes(ft
, "FORM"); /* IFF header */
894 size
= hsize
+ nframes
* (ft
->encoding
.bits_per_sample
>> 3) * ft
->signal
.channels
;
897 lsx_warn("file size too big for accurate AIFC header");
900 lsx_writedw(ft
, (unsigned)size
);
901 lsx_writes(ft
, "AIFC"); /* File type */
904 lsx_writes(ft
, "FVER");
905 lsx_writedw(ft
, 4); /* FVER chunk size */
906 lsx_writedw(ft
, 0xa2805140); /* version_date(May23,1990,2:40pm) */
908 /* COMM chunk -- describes encoding (and #frames) */
909 lsx_writes(ft
, "COMM");
910 lsx_writedw(ft
, comm_len
+comm_padding
); /* COMM chunk size */
911 lsx_writew(ft
, ft
->signal
.channels
); /* nchannels */
912 lsx_writedw(ft
, (unsigned) nframes
); /* number of frames */
913 lsx_writew(ft
, bits
); /* sample width, in bits */
914 write_ieee_extended(ft
, (double)ft
->signal
.rate
);
916 lsx_writes(ft
, ctype
); /*compression_type*/
917 lsx_writeb(ft
, cname_len
);
918 lsx_writes(ft
, cname
);
922 /* SSND chunk -- describes data */
923 lsx_writes(ft
, "SSND");
925 lsx_writedw(ft
, (unsigned) (8 + nframes
* ft
->signal
.channels
* (ft
->encoding
.bits_per_sample
>> 3)));
926 lsx_writedw(ft
, 0); /* offset */
927 lsx_writedw(ft
, 0); /* block size */
929 /* Any Private chunks shall appear after the required chunks (FORM,FVER,COMM,SSND) */
933 static double read_ieee_extended(sox_format_t
* ft
)
935 unsigned char buf
[10];
936 if (lsx_readbuf(ft
, buf
, (size_t)10) != 10)
938 lsx_fail_errno(ft
,SOX_EOF
,"EOF while reading IEEE extended number");
941 return ConvertFromIeeeExtended(buf
);
944 static void write_ieee_extended(sox_format_t
* ft
, double x
)
947 ConvertToIeeeExtended(x
, buf
);
948 lsx_debug_more("converted %g to %o %o %o %o %o %o %o %o %o %o",
950 buf
[0], buf
[1], buf
[2], buf
[3], buf
[4],
951 buf
[5], buf
[6], buf
[7], buf
[8], buf
[9]);
952 (void)lsx_writebuf(ft
, buf
, (size_t) 10);
957 * C O N V E R T T O I E E E E X T E N D E D
960 /* Copyright (C) 1988-1991 Apple Computer, Inc.
962 * All rights reserved.
964 * Warranty Information
965 * Even though Apple has reviewed this software, Apple makes no warranty
966 * or representation, either express or implied, with respect to this
967 * software, its quality, accuracy, merchantability, or fitness for a
968 * particular purpose. As a result, this software is provided "as is,"
969 * and you, its user, are assuming the entire risk as to its quality
972 * Machine-independent I/O routines for IEEE floating-point numbers.
974 * NaN's and infinities are converted to HUGE_VAL, which
975 * happens to be infinity on IEEE machines. Unfortunately, it is
976 * impossible to preserve NaN's in a machine-independent way.
977 * Infinities are, however, preserved on IEEE machines.
979 * These routines have been tested on the following machines:
980 * Apple Macintosh, MPW 3.1 C compiler
981 * Apple Macintosh, THINK C compiler
982 * Silicon Graphics IRIS, MIPS compiler
984 * Digital Equipment VAX
987 * Implemented by Malcolm Slaney and Ken Turkowski.
989 * Malcolm Slaney contributions during 1988-1990 include big- and little-
990 * endian file I/O, conversion to and from Motorola's extended 80-bit
991 * floating-point format, and conversions to and from IEEE single-
992 * precision floating-point format.
994 * In 1991, Ken Turkowski implemented the conversions to and from
995 * IEEE double-precision format, added more precision to the extended
996 * conversions, and accommodated conversions involving +/- infinity,
997 * NaN's, and denormalized numbers.
1000 #define FloatToUnsigned(f) ((uint32_t)(((int32_t)(f - 2147483648.0)) + 2147483647) + 1)
1002 static void ConvertToIeeeExtended(double num
, char *bytes
)
1006 double fMant
, fsMant
;
1007 uint32_t hiMant
, loMant
;
1017 expon
= 0; hiMant
= 0; loMant
= 0;
1020 fMant
= frexp(num
, &expon
);
1021 if ((expon
> 16384) || !(fMant
< 1)) { /* Infinity or NaN */
1022 expon
= sign
|0x7FFF; hiMant
= 0; loMant
= 0; /* infinity */
1026 if (expon
< 0) { /* denormalized */
1027 fMant
= ldexp(fMant
, expon
);
1031 fMant
= ldexp(fMant
, 32);
1032 fsMant
= floor(fMant
);
1033 hiMant
= FloatToUnsigned(fsMant
);
1034 fMant
= ldexp(fMant
- fsMant
, 32);
1035 fsMant
= floor(fMant
);
1036 loMant
= FloatToUnsigned(fsMant
);
1040 bytes
[0] = expon
>> 8;
1042 bytes
[2] = hiMant
>> 24;
1043 bytes
[3] = hiMant
>> 16;
1044 bytes
[4] = hiMant
>> 8;
1046 bytes
[6] = loMant
>> 24;
1047 bytes
[7] = loMant
>> 16;
1048 bytes
[8] = loMant
>> 8;
1054 * C O N V E R T F R O M I E E E E X T E N D E D
1058 * Copyright (C) 1988-1991 Apple Computer, Inc.
1060 * All rights reserved.
1062 * Warranty Information
1063 * Even though Apple has reviewed this software, Apple makes no warranty
1064 * or representation, either express or implied, with respect to this
1065 * software, its quality, accuracy, merchantability, or fitness for a
1066 * particular purpose. As a result, this software is provided "as is,"
1067 * and you, its user, are assuming the entire risk as to its quality
1070 * This code may be used and freely distributed as long as it includes
1071 * this copyright notice and the above warranty information.
1073 * Machine-independent I/O routines for IEEE floating-point numbers.
1075 * NaN's and infinities are converted to HUGE_VAL, which
1076 * happens to be infinity on IEEE machines. Unfortunately, it is
1077 * impossible to preserve NaN's in a machine-independent way.
1078 * Infinities are, however, preserved on IEEE machines.
1080 * These routines have been tested on the following machines:
1081 * Apple Macintosh, MPW 3.1 C compiler
1082 * Apple Macintosh, THINK C compiler
1083 * Silicon Graphics IRIS, MIPS compiler
1084 * Cray X/MP and Y/MP
1085 * Digital Equipment VAX
1088 * Implemented by Malcolm Slaney and Ken Turkowski.
1090 * Malcolm Slaney contributions during 1988-1990 include big- and little-
1091 * endian file I/O, conversion to and from Motorola's extended 80-bit
1092 * floating-point format, and conversions to and from IEEE single-
1093 * precision floating-point format.
1095 * In 1991, Ken Turkowski implemented the conversions to and from
1096 * IEEE double-precision format, added more precision to the extended
1097 * conversions, and accommodated conversions involving +/- infinity,
1098 * NaN's, and denormalized numbers.
1101 #define UnsignedToFloat(u) (((double)((int32_t)(u - 2147483647 - 1))) + 2147483648.0)
1103 /****************************************************************
1104 * Extended precision IEEE floating-point conversion routine.
1105 ****************************************************************/
1107 static double ConvertFromIeeeExtended(unsigned char *bytes
)
1111 uint32_t hiMant
, loMant
;
1113 expon
= ((bytes
[0] & 0x7F) << 8) | (bytes
[1] & 0xFF);
1114 hiMant
= ((uint32_t)(bytes
[2] & 0xFF) << 24)
1115 | ((uint32_t)(bytes
[3] & 0xFF) << 16)
1116 | ((uint32_t)(bytes
[4] & 0xFF) << 8)
1117 | ((uint32_t)(bytes
[5] & 0xFF));
1118 loMant
= ((uint32_t)(bytes
[6] & 0xFF) << 24)
1119 | ((uint32_t)(bytes
[7] & 0xFF) << 16)
1120 | ((uint32_t)(bytes
[8] & 0xFF) << 8)
1121 | ((uint32_t)(bytes
[9] & 0xFF));
1123 if (expon
== 0 && hiMant
== 0 && loMant
== 0) {
1127 if (expon
== 0x7FFF) { /* Infinity or NaN */
1132 f
= ldexp(UnsignedToFloat(hiMant
), expon
-=31);
1133 f
+= ldexp(UnsignedToFloat(loMant
), expon
-=32);
1137 if (bytes
[0] & 0x80)