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
*, size_t);
30 static int aifcwriteheader(sox_format_t
*, size_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;
45 unsigned short bits
= 0;
48 uint32_t blocksize
= 0;
49 int foundcomm
= 0, foundmark
= 0, foundinstr
= 0, is_sowt
= 0;
55 unsigned short looptype
;
57 unsigned short nmarks
= 0;
58 unsigned short sustainLoopBegin
= 0, sustainLoopEnd
= 0,
59 releaseLoopBegin
= 0, releaseLoopEnd
= 0;
75 if (lsx_reads(ft
, buf
, (size_t)4) == SOX_EOF
|| strncmp(buf
, "FORM", (size_t)4) != 0) {
76 lsx_fail_errno(ft
,SOX_EHDR
,"AIFF header does not begin with magic word `FORM'");
79 lsx_readdw(ft
, &totalsize
);
80 if (lsx_reads(ft
, buf
, (size_t)4) == SOX_EOF
|| (strncmp(buf
, "AIFF", (size_t)4) != 0 &&
81 strncmp(buf
, "AIFC", (size_t)4) != 0)) {
82 lsx_fail_errno(ft
,SOX_EHDR
,"AIFF `FORM' chunk does not specify `AIFF' or `AIFC' as type");
87 /* Skip everything but the COMM chunk and the SSND chunk */
88 /* The SSND chunk must be the last in the file */
90 if (lsx_reads(ft
, buf
, (size_t)4) == SOX_EOF
) {
94 lsx_fail_errno(ft
,SOX_EHDR
,"Missing SSND chunk in AIFF file");
98 if (strncmp(buf
, "COMM", (size_t)4) == 0) {
100 lsx_readdw(ft
, &chunksize
);
101 lsx_readw(ft
, &channels
);
102 lsx_readdw(ft
, &frames
);
103 lsx_readw(ft
, &bits
);
104 rate
= read_ieee_extended(ft
);
107 lsx_reads(ft
, buf
, (size_t)4);
109 if (strncmp(buf
, "sowt", (size_t)4) == 0) {
110 /* CD audio as read on Mac OS machines */
111 /* Need to endian swap all the data */
114 else if (strncmp(buf
, "NONE", (size_t)4) != 0 &&
115 strncmp(buf
, "twos", (size_t)4) != 0) {
117 lsx_fail_errno(ft
,SOX_EHDR
,"AIFC files that contain compressed data are not supported: %s",buf
);
121 while(chunksize
-- > 0)
122 lsx_readb(ft
, &trash8
);
125 else if (strncmp(buf
, "SSND", (size_t)4) == 0) {
127 lsx_readdw(ft
, &chunksize
);
128 lsx_readdw(ft
, &offset
);
129 lsx_readdw(ft
, &blocksize
);
131 ssndsize
= chunksize
;
132 /* word-align chunksize in case it wasn't
133 * done by writing application already.
135 chunksize
+= (chunksize
% 2);
136 /* if can't seek, just do sound now */
139 /* else, seek to end of sound and hunt for more */
140 seekto
= lsx_tell(ft
);
141 lsx_seeki(ft
, (off_t
)chunksize
, SEEK_CUR
);
143 else if (strncmp(buf
, "MARK", (size_t)4) == 0) {
145 lsx_readdw(ft
, &chunksize
);
146 if (chunksize
>= sizeof(nmarks
)) {
147 lsx_readw(ft
, &nmarks
);
148 chunksize
-= sizeof(nmarks
);
152 /* Some programs like to always have a MARK chunk
153 * but will set number of marks to 0 and force
154 * software to detect and ignore it.
161 /* Make sure its not larger then we support */
165 for(i
= 0; i
< nmarks
&& chunksize
; i
++) {
166 unsigned char len
, read_len
, tmp_c
;
170 lsx_readw(ft
, &(marks
[i
].id
));
171 lsx_readdw(ft
, &(marks
[i
].position
));
173 /* If error reading length then
174 * don't try to read more bytes
175 * based on that value.
177 if (lsx_readb(ft
, &len
) != SOX_SUCCESS
)
185 for(j
= 0; j
< len
&& chunksize
; j
++) {
186 lsx_readb(ft
, &tmp_c
);
188 marks
[i
].name
[j
] = tmp_c
;
191 marks
[i
].name
[read_len
] = 0;
192 if ((len
& 1) == 0 && chunksize
) {
194 lsx_readb(ft
, &trash8
);
197 /* HA HA! Sound Designer (and others) makes */
198 /* bogus files. It spits out bogus chunksize */
200 while(chunksize
-- > 0)
201 lsx_readb(ft
, &trash8
);
203 else if (strncmp(buf
, "INST", (size_t)4) == 0) {
205 lsx_readdw(ft
, &chunksize
);
206 lsx_readsb(ft
, &(ft
->oob
.instr
.MIDInote
));
207 lsx_readb(ft
, &trash8
);
208 lsx_readsb(ft
, &(ft
->oob
.instr
.MIDIlow
));
209 lsx_readsb(ft
, &(ft
->oob
.instr
.MIDIhi
));
211 lsx_readb(ft
, &trash8
);
213 lsx_readb(ft
, &trash8
);
214 lsx_readw(ft
, &trash16
);/* gain */
215 lsx_readw(ft
, &looptype
); /* sustain loop */
216 ft
->oob
.loops
[0].type
= looptype
;
217 lsx_readw(ft
, &sustainLoopBegin
); /* begin marker */
218 lsx_readw(ft
, &sustainLoopEnd
); /* end marker */
219 lsx_readw(ft
, &looptype
); /* release loop */
220 ft
->oob
.loops
[1].type
= looptype
;
221 lsx_readw(ft
, &releaseLoopBegin
); /* begin marker */
222 lsx_readw(ft
, &releaseLoopEnd
); /* end marker */
226 else if (strncmp(buf
, "APPL", (size_t)4) == 0) {
227 lsx_readdw(ft
, &chunksize
);
228 /* word-align chunksize in case it wasn't
229 * done by writing application already.
231 chunksize
+= (chunksize
% 2);
232 while(chunksize
-- > 0)
233 lsx_readb(ft
, &trash8
);
235 else if (strncmp(buf
, "ALCH", (size_t)4) == 0) {
236 /* I think this is bogus and gets grabbed by APPL */
238 lsx_readdw(ft
, &trash32
); /* ENVS - jeez! */
239 lsx_readdw(ft
, &chunksize
);
240 while(chunksize
-- > 0)
241 lsx_readb(ft
, &trash8
);
243 else if (strncmp(buf
, "ANNO", (size_t)4) == 0) {
244 rc
= textChunk(&annotation
, "Annotation:", ft
);
246 /* Fail already called in function */
250 sox_append_comments(&ft
->oob
.comments
, annotation
);
253 else if (strncmp(buf
, "COMT", (size_t)4) == 0) {
254 rc
= commentChunk(&comment
, "Comment:", ft
);
256 /* Fail already called in function */
260 sox_append_comments(&ft
->oob
.comments
, comment
);
263 else if (strncmp(buf
, "AUTH", (size_t)4) == 0) {
265 rc
= textChunk(&author
, "Author:", ft
);
267 /* Fail already called in function */
272 else if (strncmp(buf
, "NAME", (size_t)4) == 0) {
274 rc
= textChunk(&nametext
, "Name:", ft
);
276 /* Fail already called in function */
281 else if (strncmp(buf
, "(c) ", (size_t)4) == 0) {
282 /* Copyright chunk */
283 rc
= textChunk(©right
, "Copyright:", ft
);
285 /* Fail already called in function */
294 lsx_debug("AIFFstartread: ignoring `%s' chunk", buf
);
295 lsx_readdw(ft
, &chunksize
);
298 /* Skip the chunk using lsx_readb() so we may read
300 while (chunksize
-- > 0) {
301 if (lsx_readb(ft
, &trash8
) == SOX_EOF
)
310 * if a pipe, we lose all chunks after sound.
311 * Like, say, instrument loops.
315 lsx_seeki(ft
, seekto
, SEEK_SET
);
317 lsx_fail_errno(ft
,SOX_EOF
,"AIFF: no sound data on input file");
321 /* SSND chunk just read */
323 lsx_warn("AIFF header has invalid blocksize. Ignoring but expect a premature EOF");
326 while (offset
-- > 0) {
327 if (lsx_readb(ft
, &trash8
) == SOX_EOF
) {
328 lsx_fail_errno(ft
,errno
,"unexpected EOF while skipping AIFF offset");
334 if (ft
->encoding
.encoding
!= SOX_ENCODING_UNKNOWN
&& ft
->encoding
.encoding
!= SOX_ENCODING_SIGN2
)
335 lsx_report("AIFF only supports signed data. Forcing to signed.");
336 ft
->encoding
.encoding
= SOX_ENCODING_SIGN2
;
337 if (bits
<= 8) bits
= 8;
338 else if (bits
<= 16) bits
= 16;
339 else if (bits
<= 24) bits
= 24;
340 else if (bits
<= 32) bits
= 32;
342 lsx_fail_errno(ft
,SOX_EFMT
,"unsupported sample size in AIFF header: %d", bits
);
346 if ((ft
->signal
.channels
== SOX_UNSPEC
)
347 || (ft
->signal
.rate
== SOX_UNSPEC
)
348 || (ft
->encoding
.encoding
== SOX_ENCODING_UNKNOWN
)
349 || (ft
->encoding
.bits_per_sample
== 0)) {
350 lsx_report("You must specify # channels, sample rate, signed/unsigned,");
351 lsx_report("and 8/16 on the command line.");
352 lsx_fail_errno(ft
,SOX_EFMT
,"Bogus AIFF file: no COMM section.");
357 ssndsize
/= bits
>> 3;
359 /* Cope with 'sowt' CD tracks as read on Macs */
361 ft
->encoding
.reverse_bytes
= !ft
->encoding
.reverse_bytes
;
363 if (foundmark
&& !foundinstr
) {
364 lsx_debug("Ignoring MARK chunk since no INSTR found.");
367 if (!foundmark
&& foundinstr
) {
368 lsx_debug("Ignoring INSTR chunk since no MARK found.");
371 if (foundmark
&& foundinstr
) {
373 int slbIndex
= 0, sleIndex
= 0;
374 int rlbIndex
= 0, rleIndex
= 0;
376 /* find our loop markers and save their marker indexes */
377 for(i
= 0; i
< nmarks
; i
++) {
378 if(marks
[i
].id
== sustainLoopBegin
)
380 if(marks
[i
].id
== sustainLoopEnd
)
382 if(marks
[i
].id
== releaseLoopBegin
)
384 if(marks
[i
].id
== releaseLoopEnd
)
388 ft
->oob
.instr
.nloops
= 0;
389 if (ft
->oob
.loops
[0].type
!= 0) {
390 ft
->oob
.loops
[0].start
= marks
[slbIndex
].position
;
391 ft
->oob
.loops
[0].length
=
392 marks
[sleIndex
].position
- marks
[slbIndex
].position
;
393 /* really the loop count should be infinite */
394 ft
->oob
.loops
[0].count
= 1;
395 ft
->oob
.instr
.loopmode
= SOX_LOOP_SUSTAIN_DECAY
| ft
->oob
.loops
[0].type
;
396 ft
->oob
.instr
.nloops
++;
398 if (ft
->oob
.loops
[1].type
!= 0) {
399 ft
->oob
.loops
[1].start
= marks
[rlbIndex
].position
;
400 ft
->oob
.loops
[1].length
=
401 marks
[rleIndex
].position
- marks
[rlbIndex
].position
;
402 /* really the loop count should be infinite */
403 ft
->oob
.loops
[1].count
= 1;
404 ft
->oob
.instr
.loopmode
= SOX_LOOP_SUSTAIN_DECAY
| ft
->oob
.loops
[1].type
;
405 ft
->oob
.instr
.nloops
++;
408 reportInstrument(ft
);
410 return lsx_check_read_params(
411 ft
, channels
, rate
, SOX_ENCODING_SIGN2
, bits
, (off_t
)ssndsize
, sox_false
);
414 /* print out the MIDI key allocations, loop points, directions etc */
415 static void reportInstrument(sox_format_t
* ft
)
419 if(ft
->oob
.instr
.nloops
> 0)
420 lsx_report("AIFF Loop markers:");
421 for(loopNum
= 0; loopNum
< ft
->oob
.instr
.nloops
; loopNum
++) {
422 if (ft
->oob
.loops
[loopNum
].count
) {
423 lsx_report("Loop %d: start: %6lu", loopNum
, (unsigned long)ft
->oob
.loops
[loopNum
].start
);
424 lsx_report(" end: %6lu",
425 (unsigned long)(ft
->oob
.loops
[loopNum
].start
+ ft
->oob
.loops
[loopNum
].length
));
426 lsx_report(" count: %6d", ft
->oob
.loops
[loopNum
].count
);
427 lsx_report(" type: ");
428 switch(ft
->oob
.loops
[loopNum
].type
& ~SOX_LOOP_SUSTAIN_DECAY
) {
429 case 0: lsx_report("off"); break;
430 case 1: lsx_report("forward"); break;
431 case 2: lsx_report("forward/backward"); break;
435 lsx_report("Unity MIDI Note: %d", ft
->oob
.instr
.MIDInote
);
436 lsx_report("Low MIDI Note: %d", ft
->oob
.instr
.MIDIlow
);
437 lsx_report("High MIDI Note: %d", ft
->oob
.instr
.MIDIhi
);
440 /* Process a text chunk, allocate memory, display it if verbose and return */
441 static int textChunk(char **text
, char *chunkDescription
, sox_format_t
* ft
)
444 lsx_readdw(ft
, &chunksize
);
445 /* allocate enough memory to hold the text including a terminating \0 */
446 *text
= lsx_malloc((size_t) chunksize
+ 1);
447 if (lsx_readbuf(ft
, *text
, (size_t) chunksize
) != chunksize
)
449 lsx_fail_errno(ft
,SOX_EOF
,"AIFF: Unexpected EOF in %s header", chunkDescription
);
452 *(*text
+ chunksize
) = '\0';
455 /* Read past pad byte */
457 if (lsx_readbuf(ft
, &c
, (size_t)1) != 1)
459 lsx_fail_errno(ft
,SOX_EOF
,"AIFF: Unexpected EOF in %s header", chunkDescription
);
463 lsx_debug("%-10s \"%s\"", chunkDescription
, *text
);
467 /* Comment lengths are words, not double words, and we can have several, so
468 we use a special function, not textChunk().;
470 static int commentChunk(char **text
, char *chunkDescription
, sox_format_t
* ft
)
473 unsigned short numComments
;
475 unsigned short markerId
;
476 unsigned short totalCommentLength
= 0;
477 unsigned int totalReadLength
= 0;
478 unsigned int commentIndex
;
480 lsx_readdw(ft
, &chunksize
);
481 lsx_readw(ft
, &numComments
);
482 totalReadLength
+= 2; /* chunksize doesn't count */
483 for(commentIndex
= 0; commentIndex
< numComments
; commentIndex
++) {
484 unsigned short commentLength
;
486 lsx_readdw(ft
, &timeStamp
);
487 lsx_readw(ft
, &markerId
);
488 lsx_readw(ft
, &commentLength
);
489 if (((size_t)totalCommentLength
) + commentLength
> USHRT_MAX
) {
490 lsx_fail_errno(ft
,SOX_EOF
,"AIFF: Comment too long in %s header", chunkDescription
);
493 totalCommentLength
+= commentLength
;
494 /* allocate enough memory to hold the text including a terminating \0 */
495 if(commentIndex
== 0) {
496 *text
= lsx_malloc((size_t) totalCommentLength
+ 1);
499 *text
= lsx_realloc(*text
, (size_t) totalCommentLength
+ 1);
502 if (lsx_readbuf(ft
, *text
+ totalCommentLength
- commentLength
, (size_t) commentLength
) != commentLength
) {
503 lsx_fail_errno(ft
,SOX_EOF
,"AIFF: Unexpected EOF in %s header", chunkDescription
);
506 *(*text
+ totalCommentLength
) = '\0';
507 totalReadLength
+= totalCommentLength
+ 4 + 2 + 2; /* include header */
508 if (commentLength
% 2) {
509 /* Read past pad byte */
511 if (lsx_readbuf(ft
, &c
, (size_t)1) != 1) {
512 lsx_fail_errno(ft
,SOX_EOF
,"AIFF: Unexpected EOF in %s header", chunkDescription
);
515 totalReadLength
+= 1;
518 lsx_debug("%-10s \"%s\"", chunkDescription
, *text
);
519 /* make sure we read the whole chunk */
520 if (totalReadLength
< chunksize
) {
523 for (i
=0; i
< chunksize
- totalReadLength
; i
++ )
524 lsx_readbuf(ft
, &c
, (size_t)1);
529 int lsx_aiffstopread(sox_format_t
* ft
)
537 while (! lsx_eof(ft
))
539 if (lsx_readbuf(ft
, buf
, (size_t)4) != 4)
542 lsx_readdw(ft
, &chunksize
);
546 lsx_warn("Ignoring AIFF tail chunk: `%s', %u bytes long",
548 if (! strcmp(buf
, "MARK") || ! strcmp(buf
, "INST"))
549 lsx_warn(" You're stripping MIDI/loop info!");
550 while (chunksize
-- > 0)
552 if (lsx_readb(ft
, &trash
) == SOX_EOF
)
560 /* When writing, the header is supposed to contain the number of
561 samples and data bytes written.
562 Since we don't know how many samples there are until we're done,
563 we first write the header with an very large number,
564 and at the end we rewind the file and write the header again
565 with the right number. This only works if the file is seekable;
566 if it is not, the very large size remains in the header.
567 Strictly spoken this is not legal, but the playaiff utility
568 will still be able to play the resulting file. */
570 int lsx_aiffstartwrite(sox_format_t
* ft
)
574 /* Needed because lsx_rawwrite() */
575 rc
= lsx_rawstartwrite(ft
);
579 /* Compute the "very large number" so that a maximum number
580 of samples can be transmitted through a pipe without the
581 risk of causing overflow when calculating the number of bytes.
582 At 48 kHz, 16 bits stereo, this gives ~3 hours of audio.
583 Sorry, the AIFF format does not provide for an indefinite
584 number of samples. */
585 return(aiffwriteheader(ft
, (size_t) 0x7f000000 / ((ft
->encoding
.bits_per_sample
>>3)*ft
->signal
.channels
)));
588 int lsx_aiffstopwrite(sox_format_t
* ft
)
590 /* If we've written an odd number of bytes, write a padding
592 if (ft
->olength
% 2 == 1 && ft
->encoding
.bits_per_sample
== 8 && ft
->signal
.channels
== 1)
594 sox_sample_t buf
= 0;
595 lsx_rawwrite(ft
, &buf
, (size_t) 1);
600 lsx_fail_errno(ft
,SOX_EOF
,"Non-seekable file.");
603 if (lsx_seeki(ft
, (off_t
)0, SEEK_SET
) != 0)
605 lsx_fail_errno(ft
,errno
,"can't rewind output file to rewrite AIFF header");
608 return(aiffwriteheader(ft
, ft
->olength
/ ft
->signal
.channels
));
611 static int aiffwriteheader(sox_format_t
* ft
, size_t nframes
)
614 8 /*COMM hdr*/ + 18 /*COMM chunk*/ +
615 8 /*SSND hdr*/ + 12 /*SSND chunk*/;
618 size_t padded_comment_size
= 0, comment_size
= 0;
619 size_t comment_chunk_size
= 0;
620 char * comment
= lsx_cat_comments(ft
->oob
.comments
);
622 /* MARK and INST chunks */
623 if (ft
->oob
.instr
.nloops
) {
624 hsize
+= 8 /* MARK hdr */ + 2 + 16*ft
->oob
.instr
.nloops
;
625 hsize
+= 8 /* INST hdr */ + 20; /* INST chunk */
628 if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
629 ft
->encoding
.bits_per_sample
== 8)
631 else if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
632 ft
->encoding
.bits_per_sample
== 16)
634 else if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
635 ft
->encoding
.bits_per_sample
== 24)
637 else if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
638 ft
->encoding
.bits_per_sample
== 32)
642 lsx_fail_errno(ft
,SOX_EFMT
,"unsupported output encoding/size for AIFF header");
646 /* COMT comment chunk -- holds comments text with a timestamp and marker id */
647 /* We calculate the comment_chunk_size if we will be writing a comment */
648 if (ft
->oob
.comments
)
650 comment_size
= strlen(comment
);
651 /* Must put an even number of characters out.
652 * True 68k processors OS's seem to require this.
654 padded_comment_size
= ((comment_size
% 2) == 0) ?
655 comment_size
: comment_size
+ 1;
656 /* one comment, timestamp, marker ID and text count */
657 comment_chunk_size
= (2 + 4 + 2 + 2 + padded_comment_size
);
658 hsize
+= 8 /* COMT hdr */ + comment_chunk_size
;
661 lsx_writes(ft
, "FORM"); /* IFF header */
663 lsx_writedw(ft
, (unsigned) (hsize
+ nframes
* (ft
->encoding
.bits_per_sample
>> 3) * ft
->signal
.channels
));
664 lsx_writes(ft
, "AIFF"); /* File type */
666 /* Now we write the COMT comment chunk using the precomputed sizes */
667 if (ft
->oob
.comments
)
669 lsx_writes(ft
, "COMT");
670 lsx_writedw(ft
, (unsigned) comment_chunk_size
);
675 /* time stamp of comment, Unix knows of time from 1/1/1970,
676 Apple knows time from 1/1/1904 */
677 lsx_writedw(ft
, (unsigned)((sox_globals
.repeatable
? 0 : time(NULL
)) + 2082844800));
679 /* A marker ID of 0 indicates the comment is not associated
683 /* now write the count and the bytes of text */
684 lsx_writew(ft
, (unsigned) padded_comment_size
);
685 lsx_writes(ft
, comment
);
686 if (comment_size
!= padded_comment_size
)
691 /* COMM chunk -- describes encoding (and #frames) */
692 lsx_writes(ft
, "COMM");
693 lsx_writedw(ft
, 18); /* COMM chunk size */
694 lsx_writew(ft
, ft
->signal
.channels
); /* nchannels */
695 lsx_writedw(ft
, (unsigned) nframes
); /* number of frames */
696 lsx_writew(ft
, bits
); /* sample width, in bits */
697 write_ieee_extended(ft
, (double)ft
->signal
.rate
);
699 /* MARK chunk -- set markers */
700 if (ft
->oob
.instr
.nloops
) {
701 lsx_writes(ft
, "MARK");
702 if (ft
->oob
.instr
.nloops
> 2)
703 ft
->oob
.instr
.nloops
= 2;
704 lsx_writedw(ft
, 2 + 16u*ft
->oob
.instr
.nloops
);
705 lsx_writew(ft
, ft
->oob
.instr
.nloops
);
707 for(i
= 0; i
< ft
->oob
.instr
.nloops
; i
++) {
708 lsx_writew(ft
, i
+ 1);
709 lsx_writedw(ft
, (unsigned) ft
->oob
.loops
[i
].start
);
712 lsx_writew(ft
, i
*2 + 1);
713 lsx_writedw(ft
, (unsigned) (ft
->oob
.loops
[i
].start
+ ft
->oob
.loops
[i
].length
));
718 lsx_writes(ft
, "INST");
720 /* random MIDI shit that we default on */
721 lsx_writeb(ft
, (uint8_t)ft
->oob
.instr
.MIDInote
);
722 lsx_writeb(ft
, 0); /* detune */
723 lsx_writeb(ft
, (uint8_t)ft
->oob
.instr
.MIDIlow
);
724 lsx_writeb(ft
, (uint8_t)ft
->oob
.instr
.MIDIhi
);
725 lsx_writeb(ft
, 1); /* low velocity */
726 lsx_writeb(ft
, 127); /* hi velocity */
727 lsx_writew(ft
, 0); /* gain */
730 lsx_writew(ft
, ft
->oob
.loops
[0].type
);
731 lsx_writew(ft
, 1); /* marker 1 */
732 lsx_writew(ft
, 3); /* marker 3 */
733 /* release loop, if there */
734 if (ft
->oob
.instr
.nloops
== 2) {
735 lsx_writew(ft
, ft
->oob
.loops
[1].type
);
736 lsx_writew(ft
, 2); /* marker 2 */
737 lsx_writew(ft
, 4); /* marker 4 */
739 lsx_writew(ft
, 0); /* no release loop */
745 /* SSND chunk -- describes data */
746 lsx_writes(ft
, "SSND");
748 lsx_writedw(ft
, (unsigned) (8 + nframes
* ft
->signal
.channels
* (ft
->encoding
.bits_per_sample
>> 3)));
749 lsx_writedw(ft
, 0); /* offset */
750 lsx_writedw(ft
, 0); /* block size */
754 int lsx_aifcstartwrite(sox_format_t
* ft
)
758 /* Needed because lsx_rawwrite() */
759 rc
= lsx_rawstartwrite(ft
);
763 /* Compute the "very large number" so that a maximum number
764 of samples can be transmitted through a pipe without the
765 risk of causing overflow when calculating the number of bytes.
766 At 48 kHz, 16 bits stereo, this gives ~3 hours of music.
767 Sorry, the AIFC format does not provide for an "infinite"
768 number of samples. */
769 return(aifcwriteheader(ft
, (size_t) 0x7f000000 / ((ft
->encoding
.bits_per_sample
>> 3)*ft
->signal
.channels
)));
772 int lsx_aifcstopwrite(sox_format_t
* ft
)
774 /* If we've written an odd number of bytes, write a padding
776 if (ft
->olength
% 2 == 1 && ft
->encoding
.bits_per_sample
== 8 && ft
->signal
.channels
== 1)
778 sox_sample_t buf
= 0;
779 lsx_rawwrite(ft
, &buf
, (size_t) 1);
784 lsx_fail_errno(ft
,SOX_EOF
,"Non-seekable file.");
787 if (lsx_seeki(ft
, (off_t
)0, SEEK_SET
) != 0)
789 lsx_fail_errno(ft
,errno
,"can't rewind output file to rewrite AIFC header");
792 return(aifcwriteheader(ft
, ft
->olength
/ ft
->signal
.channels
));
795 static int aifcwriteheader(sox_format_t
* ft
, size_t nframes
)
798 12 /*FVER*/ + 8 /*COMM hdr*/ + 18+4+1+15 /*COMM chunk*/ +
799 8 /*SSND hdr*/ + 12 /*SSND chunk*/;
802 if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
803 ft
->encoding
.bits_per_sample
== 8)
805 else if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
806 ft
->encoding
.bits_per_sample
== 16)
808 else if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
809 ft
->encoding
.bits_per_sample
== 24)
811 else if (ft
->encoding
.encoding
== SOX_ENCODING_SIGN2
&&
812 ft
->encoding
.bits_per_sample
== 32)
816 lsx_fail_errno(ft
,SOX_EFMT
,"unsupported output encoding/size for AIFC header");
820 lsx_writes(ft
, "FORM"); /* IFF header */
822 lsx_writedw(ft
, (unsigned) (hsize
+ nframes
* (ft
->encoding
.bits_per_sample
>> 3) * ft
->signal
.channels
));
823 lsx_writes(ft
, "AIFC"); /* File type */
826 lsx_writes(ft
, "FVER");
827 lsx_writedw(ft
, 4); /* FVER chunk size */
828 lsx_writedw(ft
, 0xa2805140); /* version_date(May23,1990,2:40pm) */
830 /* COMM chunk -- describes encoding (and #frames) */
831 lsx_writes(ft
, "COMM");
832 lsx_writedw(ft
, 18+4+1+15); /* COMM chunk size */
833 lsx_writew(ft
, ft
->signal
.channels
); /* nchannels */
834 lsx_writedw(ft
, (unsigned) nframes
); /* number of frames */
835 lsx_writew(ft
, bits
); /* sample width, in bits */
836 write_ieee_extended(ft
, (double)ft
->signal
.rate
);
838 lsx_writes(ft
, "NONE"); /*compression_type*/
840 lsx_writes(ft
, "not compressed");
843 /* SSND chunk -- describes data */
844 lsx_writes(ft
, "SSND");
846 lsx_writedw(ft
, (unsigned) (8 + nframes
* ft
->signal
.channels
* (ft
->encoding
.bits_per_sample
>> 3)));
847 lsx_writedw(ft
, 0); /* offset */
848 lsx_writedw(ft
, 0); /* block size */
850 /* Any Private chunks shall appear after the required chunks (FORM,FVER,COMM,SSND) */
854 static double read_ieee_extended(sox_format_t
* ft
)
856 unsigned char buf
[10];
857 if (lsx_readbuf(ft
, buf
, (size_t)10) != 10)
859 lsx_fail_errno(ft
,SOX_EOF
,"EOF while reading IEEE extended number");
862 return ConvertFromIeeeExtended(buf
);
865 static void write_ieee_extended(sox_format_t
* ft
, double x
)
868 ConvertToIeeeExtended(x
, buf
);
869 lsx_debug_more("converted %g to %o %o %o %o %o %o %o %o %o %o",
871 buf
[0], buf
[1], buf
[2], buf
[3], buf
[4],
872 buf
[5], buf
[6], buf
[7], buf
[8], buf
[9]);
873 (void)lsx_writebuf(ft
, buf
, (size_t) 10);
878 * C O N V E R T T O I E E E E X T E N D E D
881 /* Copyright (C) 1988-1991 Apple Computer, Inc.
882 * All rights reserved.
884 * Machine-independent I/O routines for IEEE floating-point numbers.
886 * NaN's and infinities are converted to HUGE_VAL, which
887 * happens to be infinity on IEEE machines. Unfortunately, it is
888 * impossible to preserve NaN's in a machine-independent way.
889 * Infinities are, however, preserved on IEEE machines.
891 * These routines have been tested on the following machines:
892 * Apple Macintosh, MPW 3.1 C compiler
893 * Apple Macintosh, THINK C compiler
894 * Silicon Graphics IRIS, MIPS compiler
896 * Digital Equipment VAX
899 * Implemented by Malcolm Slaney and Ken Turkowski.
901 * Malcolm Slaney contributions during 1988-1990 include big- and little-
902 * endian file I/O, conversion to and from Motorola's extended 80-bit
903 * floating-point format, and conversions to and from IEEE single-
904 * precision floating-point format.
906 * In 1991, Ken Turkowski implemented the conversions to and from
907 * IEEE double-precision format, added more precision to the extended
908 * conversions, and accommodated conversions involving +/- infinity,
909 * NaN's, and denormalized numbers.
912 #define FloatToUnsigned(f) ((uint32_t)(((int32_t)(f - 2147483648.0)) + 2147483647) + 1)
914 static void ConvertToIeeeExtended(double num
, char *bytes
)
918 double fMant
, fsMant
;
919 uint32_t hiMant
, loMant
;
929 expon
= 0; hiMant
= 0; loMant
= 0;
932 fMant
= frexp(num
, &expon
);
933 if ((expon
> 16384) || !(fMant
< 1)) { /* Infinity or NaN */
934 expon
= sign
|0x7FFF; hiMant
= 0; loMant
= 0; /* infinity */
938 if (expon
< 0) { /* denormalized */
939 fMant
= ldexp(fMant
, expon
);
943 fMant
= ldexp(fMant
, 32);
944 fsMant
= floor(fMant
);
945 hiMant
= FloatToUnsigned(fsMant
);
946 fMant
= ldexp(fMant
- fsMant
, 32);
947 fsMant
= floor(fMant
);
948 loMant
= FloatToUnsigned(fsMant
);
952 bytes
[0] = expon
>> 8;
954 bytes
[2] = hiMant
>> 24;
955 bytes
[3] = hiMant
>> 16;
956 bytes
[4] = hiMant
>> 8;
958 bytes
[6] = loMant
>> 24;
959 bytes
[7] = loMant
>> 16;
960 bytes
[8] = loMant
>> 8;
966 * C O N V E R T F R O M I E E E E X T E N D E D
970 * Copyright (C) 1988-1991 Apple Computer, Inc.
971 * All rights reserved.
973 * Machine-independent I/O routines for IEEE floating-point numbers.
975 * NaN's and infinities are converted to HUGE_VAL, which
976 * happens to be infinity on IEEE machines. Unfortunately, it is
977 * impossible to preserve NaN's in a machine-independent way.
978 * Infinities are, however, preserved on IEEE machines.
980 * These routines have been tested on the following machines:
981 * Apple Macintosh, MPW 3.1 C compiler
982 * Apple Macintosh, THINK C compiler
983 * Silicon Graphics IRIS, MIPS compiler
985 * Digital Equipment VAX
988 * Implemented by Malcolm Slaney and Ken Turkowski.
990 * Malcolm Slaney contributions during 1988-1990 include big- and little-
991 * endian file I/O, conversion to and from Motorola's extended 80-bit
992 * floating-point format, and conversions to and from IEEE single-
993 * precision floating-point format.
995 * In 1991, Ken Turkowski implemented the conversions to and from
996 * IEEE double-precision format, added more precision to the extended
997 * conversions, and accommodated conversions involving +/- infinity,
998 * NaN's, and denormalized numbers.
1001 #define UnsignedToFloat(u) (((double)((int32_t)(u - 2147483647 - 1))) + 2147483648.0)
1003 /****************************************************************
1004 * Extended precision IEEE floating-point conversion routine.
1005 ****************************************************************/
1007 static double ConvertFromIeeeExtended(unsigned char *bytes
)
1011 uint32_t hiMant
, loMant
;
1013 expon
= ((bytes
[0] & 0x7F) << 8) | (bytes
[1] & 0xFF);
1014 hiMant
= ((uint32_t)(bytes
[2] & 0xFF) << 24)
1015 | ((uint32_t)(bytes
[3] & 0xFF) << 16)
1016 | ((uint32_t)(bytes
[4] & 0xFF) << 8)
1017 | ((uint32_t)(bytes
[5] & 0xFF));
1018 loMant
= ((uint32_t)(bytes
[6] & 0xFF) << 24)
1019 | ((uint32_t)(bytes
[7] & 0xFF) << 16)
1020 | ((uint32_t)(bytes
[8] & 0xFF) << 8)
1021 | ((uint32_t)(bytes
[9] & 0xFF));
1023 if (expon
== 0 && hiMant
== 0 && loMant
== 0) {
1027 if (expon
== 0x7FFF) { /* Infinity or NaN */
1032 f
= ldexp(UnsignedToFloat(hiMant
), expon
-=31);
1033 f
+= ldexp(UnsignedToFloat(loMant
), expon
-=32);
1037 if (bytes
[0] & 0x80)