1 /* libSoX SGI/Amiga AIFF format.
2  * Copyright 1991-2007 Guido van Rossum And Sundry Contributors
3  *
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.
8  *
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.)
15  */
16 
17 #include "sox_i.h"
18 #include "aiff.h"
19 #include "id3.h"
20 
21 #include <time.h>      /* for time stamping comments */
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <limits.h>
27 
28 /* forward declarations */
29 static double read_ieee_extended(sox_format_t *);
30 static int aiffwriteheader(sox_format_t *, uint64_t);
31 static int aifcwriteheader(sox_format_t *, uint64_t);
32 static void write_ieee_extended(sox_format_t *, double);
33 static double ConvertFromIeeeExtended(unsigned char*);
34 static void ConvertToIeeeExtended(double, char *);
35 static int textChunk(char **text, char *chunkDescription, sox_format_t * ft);
36 static int commentChunk(char **text, char *chunkDescription, sox_format_t * ft);
37 static void reportInstrument(sox_format_t * ft);
38 
lsx_aiffstartread(sox_format_t * ft)39 int lsx_aiffstartread(sox_format_t * ft)
40 {
41   char buf[5];
42   uint32_t totalsize;
43   uint32_t chunksize;
44   unsigned short channels = 0;
45   sox_encoding_t enc = SOX_ENCODING_SIGN2;
46   uint32_t frames;
47   unsigned short bits = 0;
48   double rate = 0.0;
49   uint32_t offset = 0;
50   uint32_t blocksize = 0;
51   int foundcomm = 0, foundmark = 0, foundinstr = 0, is_sowt = 0;
52   struct mark {
53     unsigned short id;
54     uint32_t position;
55     char name[40];
56   } marks[32];
57   unsigned short looptype;
58   int i, j;
59   unsigned short nmarks = 0;
60   unsigned short sustainLoopBegin = 0, sustainLoopEnd = 0,
61                  releaseLoopBegin = 0, releaseLoopEnd = 0;
62   off_t seekto = 0;
63   size_t ssndsize = 0;
64   char *annotation;
65   char *author;
66   char *copyright;
67   char *nametext;
68 
69   uint8_t trash8;
70   uint16_t trash16;
71   uint32_t trash32;
72 
73   int rc;
74 
75   /* FORM chunk */
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'");
78     return(SOX_EOF);
79   }
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");
84     return(SOX_EOF);
85   }
86 
87 
88   /* Skip everything but the COMM chunk and the SSND chunk */
89   /* The SSND chunk must be the last in the file */
90   while (1) {
91     if (lsx_reads(ft, buf, (size_t)4) == SOX_EOF) {
92       if (seekto > 0)
93         break;
94       else {
95         lsx_fail_errno(ft,SOX_EHDR,"Missing SSND chunk in AIFF file");
96         return(SOX_EOF);
97       }
98     }
99     if (strncmp(buf, "COMM", (size_t)4) == 0) {
100       /* COMM chunk */
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);
106       chunksize -= 18;
107       if (chunksize > 0) {
108         lsx_reads(ft, buf, (size_t)4);
109         chunksize -= 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 */
113           is_sowt = 1;
114         }
115         else if (strncmp(buf, "fl32", (size_t)4) == 0 ||
116             strncmp(buf, "FL32", (size_t)4) == 0) {
117           enc = SOX_ENCODING_FLOAT;
118           if (bits != 32) {
119             lsx_fail_errno(ft, SOX_EHDR,
120               "Sample size of %u is not consistent with `fl32' compression type", bits);
121             return SOX_EOF;
122           }
123         }
124         else if (strncmp(buf, "fl64", (size_t)4) == 0 ||
125             strncmp(buf, "FL64", (size_t)4) == 0) {
126           enc = SOX_ENCODING_FLOAT;
127           if (bits != 64) {
128             lsx_fail_errno(ft, SOX_EHDR,
129               "Sample size of %u is not consistent with `fl64' compression type", bits);
130             return SOX_EOF;
131           }
132         }
133         else if (strncmp(buf, "NONE", (size_t)4) != 0 &&
134             strncmp(buf, "twos", (size_t)4) != 0) {
135           buf[4] = 0;
136           lsx_fail_errno(ft, SOX_EHDR, "Unsupported AIFC compression type `%s'", buf);
137           return(SOX_EOF);
138         }
139       }
140       while(chunksize-- > 0)
141         lsx_readb(ft, &trash8);
142       foundcomm = 1;
143     }
144     else if (strncmp(buf, "SSND", (size_t)4) == 0) {
145       /* SSND chunk */
146       lsx_readdw(ft, &chunksize);
147       lsx_readdw(ft, &offset);
148       lsx_readdw(ft, &blocksize);
149       chunksize -= 8;
150       ssndsize = chunksize;
151       /* word-align chunksize in case it wasn't
152        * done by writing application already.
153        */
154       chunksize += (chunksize % 2);
155       /* if can't seek, just do sound now */
156       if (!ft->seekable)
157         break;
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);
161     }
162     else if (strncmp(buf, "MARK", (size_t)4) == 0) {
163       /* MARK chunk */
164       lsx_readdw(ft, &chunksize);
165       if (chunksize >= sizeof(nmarks)) {
166         lsx_readw(ft, &nmarks);
167         chunksize -= sizeof(nmarks);
168       }
169       else nmarks = 0;
170 
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.
174        */
175       if (nmarks == 0)
176         foundmark = 0;
177       else
178         foundmark = 1;
179 
180       /* Make sure its not larger then we support */
181       if (nmarks > 32)
182         nmarks = 32;
183 
184       for(i = 0; i < nmarks && chunksize; i++) {
185         unsigned char len, read_len, tmp_c;
186 
187         if (chunksize < 6)
188           break;
189         lsx_readw(ft, &(marks[i].id));
190         lsx_readdw(ft, &(marks[i].position));
191         chunksize -= 6;
192         /* If error reading length then
193          * don't try to read more bytes
194          * based on that value.
195          */
196         if (lsx_readb(ft, &len) != SOX_SUCCESS)
197           break;
198         --chunksize;
199         if (len > chunksize)
200           len = chunksize;
201         read_len = len;
202         if (read_len > 39)
203           read_len = 39;
204         for(j = 0; j < len && chunksize; j++) {
205           lsx_readb(ft, &tmp_c);
206           if (j < read_len)
207             marks[i].name[j] = tmp_c;
208           chunksize--;
209         }
210         marks[i].name[read_len] = 0;
211         if ((len & 1) == 0 && chunksize) {
212           chunksize--;
213           lsx_readb(ft, &trash8);
214         }
215       }
216       /* HA HA!  Sound Designer (and others) makes */
217       /* bogus files. It spits out bogus chunksize */
218       /* for MARK field */
219       while(chunksize-- > 0)
220         lsx_readb(ft, &trash8);
221     }
222     else if (strncmp(buf, "INST", (size_t)4) == 0) {
223       /* INST chunk */
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));
229       /* Low  velocity */
230       lsx_readb(ft, &trash8);
231       /* Hi  velocity */
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 */
242 
243       foundinstr = 1;
244     }
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.
249        */
250       chunksize += (chunksize % 2);
251       while(chunksize-- > 0)
252         lsx_readb(ft, &trash8);
253     }
254     else if (strncmp(buf, "ALCH", (size_t)4) == 0) {
255       /* I think this is bogus and gets grabbed by APPL */
256       /* INST chunk */
257       lsx_readdw(ft, &trash32);                /* ENVS - jeez! */
258       lsx_readdw(ft, &chunksize);
259       while(chunksize-- > 0)
260         lsx_readb(ft, &trash8);
261     }
262     else if (strncmp(buf, "ANNO", (size_t)4) == 0) {
263       rc = textChunk(&annotation, "Annotation:", ft);
264       if (rc) {
265         /* Fail already called in function */
266         return(SOX_EOF);
267       }
268       if (annotation)
269         sox_append_comments(&ft->oob.comments, annotation);
270       free(annotation);
271     }
272     else if (strncmp(buf, "COMT", (size_t)4) == 0) {
273       char *comment = NULL;
274       rc = commentChunk(&comment, "Comment:", ft);
275       if (rc) {
276         /* Fail already called in function */
277         return(SOX_EOF);
278       }
279       if (comment)
280         sox_append_comments(&ft->oob.comments, comment);
281       free(comment);
282     }
283     else if (strncmp(buf, "AUTH", (size_t)4) == 0) {
284       /* Author chunk */
285       rc = textChunk(&author, "Author:", ft);
286       if (rc) {
287         /* Fail already called in function */
288         return(SOX_EOF);
289       }
290       free(author);
291     }
292     else if (strncmp(buf, "NAME", (size_t)4) == 0) {
293       /* Name chunk */
294       rc = textChunk(&nametext, "Name:", ft);
295       if (rc) {
296         /* Fail already called in function */
297         return(SOX_EOF);
298       }
299       free(nametext);
300     }
301     else if (strncmp(buf, "(c) ", (size_t)4) == 0) {
302       /* Copyright chunk */
303       rc = textChunk(&copyright, "Copyright:", ft);
304       if (rc) {
305         /* Fail already called in function */
306         return(SOX_EOF);
307       }
308       free(copyright);
309     }
310     else if (strncmp(buf, "ID3 ", 4) == 0) {
311       off_t offs;
312       lsx_readdw(ft, &chunksize);
313       offs = lsx_tell(ft);
314       lsx_id3_read_tag(ft, 0);
315       lsx_seeki(ft, offs + chunksize, SEEK_SET);
316     }
317     else {
318       if (lsx_eof(ft))
319         break;
320       buf[4] = 0;
321       lsx_debug("AIFFstartread: ignoring `%s' chunk", buf);
322       lsx_readdw(ft, &chunksize);
323       if (lsx_eof(ft))
324         break;
325       /* account for padding after odd-sized chunks */
326       chunksize += chunksize & 1;
327       /* Skip the chunk using lsx_readb() so we may read
328          from a pipe */
329       while (chunksize-- > 0) {
330         if (lsx_readb(ft, &trash8) == SOX_EOF)
331           break;
332       }
333     }
334     if (lsx_eof(ft))
335       break;
336   }
337 
338   /*
339    * if a pipe, we lose all chunks after sound.
340    * Like, say, instrument loops.
341    */
342   if (ft->seekable) {
343     if (seekto > 0)
344       lsx_seeki(ft, seekto, SEEK_SET);
345     else {
346       lsx_fail_errno(ft,SOX_EOF,"AIFF: no sound data on input file");
347       return(SOX_EOF);
348     }
349   }
350   /* SSND chunk just read */
351   if (blocksize != 0)
352     lsx_warn("AIFF header has invalid blocksize.  Ignoring but expect a premature EOF");
353 
354   ssndsize -= offset;
355   while (offset-- > 0) {
356     if (lsx_readb(ft, &trash8) == SOX_EOF) {
357       lsx_fail_errno(ft,errno,"unexpected EOF while skipping AIFF offset");
358       return(SOX_EOF);
359     }
360   }
361 
362   if (foundcomm) {
363     if      (bits <=  8) bits = 8;
364     else if (bits <= 16) bits = 16;
365     else if (bits <= 24) bits = 24;
366     else if (bits <= 32) bits = 32;
367     else if (bits == 64 && enc == SOX_ENCODING_FLOAT) /* no-op */;
368     else {
369       lsx_fail_errno(ft,SOX_EFMT,"unsupported sample size in AIFF header: %d", bits);
370       return(SOX_EOF);
371     }
372   } else  {
373     if ((ft->signal.channels == SOX_UNSPEC)
374         || (ft->signal.rate == SOX_UNSPEC)
375         || (ft->encoding.encoding == SOX_ENCODING_UNKNOWN)
376         || (ft->encoding.bits_per_sample == 0)) {
377       lsx_report("You must specify # channels, sample rate, signed/unsigned,");
378       lsx_report("and 8/16 on the command line.");
379       lsx_fail_errno(ft,SOX_EFMT,"Bogus AIFF file: no COMM section.");
380       return(SOX_EOF);
381     }
382 
383   }
384   ssndsize /= bits >> 3;
385 
386   /* Cope with 'sowt' CD tracks as read on Macs */
387   if (is_sowt)
388     ft->encoding.reverse_bytes = !ft->encoding.reverse_bytes;
389 
390   if (foundmark && !foundinstr) {
391     lsx_debug("Ignoring MARK chunk since no INSTR found.");
392     foundmark = 0;
393   }
394   if (!foundmark && foundinstr) {
395     lsx_debug("Ignoring INSTR chunk since no MARK found.");
396     foundinstr = 0;
397   }
398   if (foundmark && foundinstr) {
399     int i2;
400     int slbIndex = 0, sleIndex = 0;
401     int rlbIndex = 0, rleIndex = 0;
402 
403     /* find our loop markers and save their marker indexes */
404     for(i2 = 0; i2 < nmarks; i2++) {
405       if(marks[i2].id == sustainLoopBegin)
406         slbIndex = i2;
407       if(marks[i2].id == sustainLoopEnd)
408         sleIndex = i2;
409       if(marks[i2].id == releaseLoopBegin)
410         rlbIndex = i2;
411       if(marks[i2].id == releaseLoopEnd)
412         rleIndex = i2;
413     }
414 
415     ft->oob.instr.nloops = 0;
416     if (ft->oob.loops[0].type != 0) {
417       ft->oob.loops[0].start = marks[slbIndex].position;
418       ft->oob.loops[0].length =
419         marks[sleIndex].position - marks[slbIndex].position;
420       /* really the loop count should be infinite */
421       ft->oob.loops[0].count = 1;
422       ft->oob.instr.loopmode = SOX_LOOP_SUSTAIN_DECAY | ft->oob.loops[0].type;
423       ft->oob.instr.nloops++;
424     }
425     if (ft->oob.loops[1].type != 0) {
426       ft->oob.loops[1].start = marks[rlbIndex].position;
427       ft->oob.loops[1].length =
428         marks[rleIndex].position - marks[rlbIndex].position;
429       /* really the loop count should be infinite */
430       ft->oob.loops[1].count = 1;
431       ft->oob.instr.loopmode = SOX_LOOP_SUSTAIN_DECAY | ft->oob.loops[1].type;
432       ft->oob.instr.nloops++;
433     }
434   }
435   reportInstrument(ft);
436 
437   return lsx_check_read_params(
438       ft, channels, rate, enc, bits, (uint64_t)ssndsize, sox_false);
439 }
440 
441 /* print out the MIDI key allocations, loop points, directions etc */
reportInstrument(sox_format_t * ft)442 static void reportInstrument(sox_format_t * ft)
443 {
444   unsigned loopNum;
445 
446   if(ft->oob.instr.nloops > 0)
447     lsx_report("AIFF Loop markers:");
448   for(loopNum  = 0; loopNum < ft->oob.instr.nloops; loopNum++) {
449     if (ft->oob.loops[loopNum].count) {
450       lsx_report("Loop %d: start: %6lu", loopNum, (unsigned long)ft->oob.loops[loopNum].start);
451       lsx_report(" end:   %6lu",
452               (unsigned long)(ft->oob.loops[loopNum].start + ft->oob.loops[loopNum].length));
453       lsx_report(" count: %6d", ft->oob.loops[loopNum].count);
454       lsx_report(" type:  ");
455       switch(ft->oob.loops[loopNum].type & ~SOX_LOOP_SUSTAIN_DECAY) {
456       case 0: lsx_report("off"); break;
457       case 1: lsx_report("forward"); break;
458       case 2: lsx_report("forward/backward"); break;
459       }
460     }
461   }
462   lsx_report("Unity MIDI Note: %d", ft->oob.instr.MIDInote);
463   lsx_report("Low   MIDI Note: %d", ft->oob.instr.MIDIlow);
464   lsx_report("High  MIDI Note: %d", ft->oob.instr.MIDIhi);
465 }
466 
467 /* Process a text chunk, allocate memory, display it if verbose and return */
textChunk(char ** text,char * chunkDescription,sox_format_t * ft)468 static int textChunk(char **text, char *chunkDescription, sox_format_t * ft)
469 {
470   uint32_t chunksize0;
471   size_t chunksize;
472   lsx_readdw(ft, &chunksize0);
473   chunksize = chunksize0;
474 
475   /* allocate enough memory to hold the text including a terminating \0 */
476   if (chunksize != SOX_SIZE_MAX)
477     *text = lsx_malloc((size_t)chunksize+1);
478   else
479     *text = lsx_malloc((size_t)chunksize);
480 
481   if (lsx_readbuf(ft, *text, (size_t) chunksize) != chunksize)
482   {
483     lsx_fail_errno(ft,SOX_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);
484     return(SOX_EOF);
485   }
486   if (chunksize != SOX_SIZE_MAX)
487     *(*text + chunksize) = '\0';
488   else
489     *(*text + chunksize-1) = '\0';
490   if (chunksize % 2)
491   {
492     /* Read past pad byte */
493     char c;
494     if (lsx_readbuf(ft, &c, (size_t)1) != 1)
495     {
496       lsx_fail_errno(ft,SOX_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);
497       return(SOX_EOF);
498     }
499   }
500   lsx_debug("%-10s   \"%s\"", chunkDescription, *text);
501   return(SOX_SUCCESS);
502 }
503 
504 /* Comment lengths are words, not double words, and we can have several, so
505    we use a special function, not textChunk().;
506  */
commentChunk(char ** text,char * chunkDescription,sox_format_t * ft)507 static int commentChunk(char **text, char *chunkDescription, sox_format_t * ft)
508 {
509   uint32_t chunksize;
510   unsigned short numComments;
511   uint32_t timeStamp;
512   unsigned short markerId;
513   unsigned short totalCommentLength = 0;
514   unsigned int totalReadLength = 0;
515   unsigned int commentIndex;
516 
517   lsx_readdw(ft, &chunksize);
518   lsx_readw(ft, &numComments);
519   totalReadLength += 2; /* chunksize doesn't count */
520   for(commentIndex = 0; commentIndex < numComments; commentIndex++) {
521     unsigned short commentLength;
522 
523     lsx_readdw(ft, &timeStamp);
524     lsx_readw(ft, &markerId);
525     lsx_readw(ft, &commentLength);
526     if (((size_t)totalCommentLength) + commentLength > USHRT_MAX) {
527         lsx_fail_errno(ft,SOX_EOF,"AIFF: Comment too long in %s header", chunkDescription);
528         return(SOX_EOF);
529     }
530     totalCommentLength += commentLength;
531     /* allocate enough memory to hold the text including a terminating \0 */
532     if(commentIndex == 0) {
533       *text = lsx_malloc((size_t) totalCommentLength + 1);
534     }
535     else {
536       *text = lsx_realloc(*text, (size_t) totalCommentLength + 1);
537     }
538 
539     if (lsx_readbuf(ft, *text + totalCommentLength - commentLength, (size_t) commentLength) != commentLength) {
540         lsx_fail_errno(ft,SOX_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);
541         return(SOX_EOF);
542     }
543     *(*text + totalCommentLength) = '\0';
544     totalReadLength += totalCommentLength + 4 + 2 + 2; /* include header */
545     if (commentLength % 2) {
546         /* Read past pad byte */
547         char c;
548         if (lsx_readbuf(ft, &c, (size_t)1) != 1) {
549             lsx_fail_errno(ft,SOX_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);
550             return(SOX_EOF);
551         }
552         totalReadLength += 1;
553     }
554   }
555   lsx_debug("%-10s   \"%s\"", chunkDescription, *text);
556   /* make sure we read the whole chunk */
557   if (totalReadLength < chunksize) {
558        size_t i;
559        char c;
560        for (i=0; i < chunksize - totalReadLength; i++ )
561            lsx_readbuf(ft, &c, (size_t)1);
562   }
563   return(SOX_SUCCESS);
564 }
565 
lsx_aiffstopread(sox_format_t * ft)566 int lsx_aiffstopread(sox_format_t * ft)
567 {
568         char buf[5];
569         uint32_t chunksize;
570         uint8_t trash;
571 
572         if (!ft->seekable)
573         {
574             while (! lsx_eof(ft))
575             {
576                 if (lsx_readbuf(ft, buf, (size_t)4) != 4)
577                         break;
578 
579                 lsx_readdw(ft, &chunksize);
580                 if (lsx_eof(ft))
581                         break;
582                 buf[4] = '\0';
583                 lsx_warn("Ignoring AIFF tail chunk: `%s', %u bytes long",
584                         buf, chunksize);
585                 if (! strcmp(buf, "MARK") || ! strcmp(buf, "INST"))
586                         lsx_warn("       You're stripping MIDI/loop info!");
587                 while (chunksize-- > 0)
588                 {
589                         if (lsx_readb(ft, &trash) == SOX_EOF)
590                                 break;
591                 }
592             }
593         }
594         return SOX_SUCCESS;
595 }
596 
597 /* When writing, the header is supposed to contain the number of
598    samples and data bytes written.
599    Since we don't know how many samples there are until we're done,
600    we first write the header with an very large number,
601    and at the end we rewind the file and write the header again
602    with the right number.  This only works if the file is seekable;
603    if it is not, the very large size remains in the header.
604    Strictly spoken this is not legal, but the playaiff utility
605    will still be able to play the resulting file. */
606 
lsx_aiffstartwrite(sox_format_t * ft)607 int lsx_aiffstartwrite(sox_format_t * ft)
608 {
609         int rc;
610 
611         /* Needed because lsx_rawwrite() */
612         rc = lsx_rawstartwrite(ft);
613         if (rc)
614             return rc;
615 
616         /* Compute the "very large number" so that a maximum number
617            of samples can be transmitted through a pipe without the
618            risk of causing overflow when calculating the number of bytes.
619            At 48 kHz, 16 bits stereo, this gives ~3 hours of audio.
620            Sorry, the AIFF format does not provide for an indefinite
621            number of samples. */
622         return(aiffwriteheader(ft, (uint64_t) 0x7f000000 / ((ft->encoding.bits_per_sample>>3)*ft->signal.channels)));
623 }
624 
lsx_aiffstopwrite(sox_format_t * ft)625 int lsx_aiffstopwrite(sox_format_t * ft)
626 {
627         /* If we've written an odd number of bytes, write a padding
628            NUL */
629         if (ft->olength % 2 == 1 && ft->encoding.bits_per_sample == 8 && ft->signal.channels == 1)
630         {
631             sox_sample_t buf = 0;
632             lsx_rawwrite(ft, &buf, (size_t) 1);
633         }
634 
635         if (!ft->seekable)
636         {
637             lsx_fail_errno(ft,SOX_EOF,"Non-seekable file.");
638             return(SOX_EOF);
639         }
640         if (lsx_seeki(ft, (off_t)0, SEEK_SET) != 0)
641         {
642                 lsx_fail_errno(ft,errno,"can't rewind output file to rewrite AIFF header");
643                 return(SOX_EOF);
644         }
645         return(aiffwriteheader(ft, ft->olength / ft->signal.channels));
646 }
647 
aiffwriteheader(sox_format_t * ft,uint64_t nframes)648 static int aiffwriteheader(sox_format_t * ft, uint64_t nframes)
649 {
650         int hsize =
651                 8 /*COMM hdr*/ + 18 /*COMM chunk*/ +
652                 8 /*SSND hdr*/ + 12 /*SSND chunk*/;
653         unsigned bits = 0;
654         unsigned i;
655         uint64_t size;
656         size_t padded_comment_size = 0, comment_size = 0;
657         size_t comment_chunk_size = 0;
658         char * comment = lsx_cat_comments(ft->oob.comments);
659 
660         /* MARK and INST chunks */
661         if (ft->oob.instr.nloops) {
662           hsize += 8 /* MARK hdr */ + 2 + 16*ft->oob.instr.nloops;
663           hsize += 8 /* INST hdr */ + 20; /* INST chunk */
664         }
665 
666         if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
667             ft->encoding.bits_per_sample == 8)
668                 bits = 8;
669         else if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
670                  ft->encoding.bits_per_sample == 16)
671                 bits = 16;
672         else if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
673                  ft->encoding.bits_per_sample == 24)
674                 bits = 24;
675         else if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
676                  ft->encoding.bits_per_sample == 32)
677                 bits = 32;
678         else
679         {
680                 lsx_fail_errno(ft,SOX_EFMT,"unsupported output encoding/size for AIFF header");
681                 return(SOX_EOF);
682         }
683 
684         /* COMT comment chunk -- holds comments text with a timestamp and marker id */
685         /* We calculate the comment_chunk_size if we will be writing a comment */
686         if (ft->oob.comments)
687         {
688           comment_size = strlen(comment);
689           /* Must put an even number of characters out.
690            * True 68k processors OS's seem to require this.
691            */
692           padded_comment_size = ((comment_size % 2) == 0) ?
693                                 comment_size : comment_size + 1;
694           /* one comment, timestamp, marker ID and text count */
695           comment_chunk_size = (2 + 4 + 2 + 2 + padded_comment_size);
696           hsize += 8 /* COMT hdr */ + comment_chunk_size;
697         }
698 
699         lsx_writes(ft, "FORM"); /* IFF header */
700         /* file size */
701         size = hsize + nframes * (ft->encoding.bits_per_sample >> 3) * ft->signal.channels;
702         if (size > UINT_MAX)
703         {
704             lsx_warn("file size too big for accurate AIFF header");
705             size = UINT_MAX;
706         }
707         lsx_writedw(ft, (unsigned)size);
708         lsx_writes(ft, "AIFF"); /* File type */
709 
710         /* Now we write the COMT comment chunk using the precomputed sizes */
711         if (ft->oob.comments)
712         {
713           lsx_writes(ft, "COMT");
714           lsx_writedw(ft, (unsigned) comment_chunk_size);
715 
716           /* one comment */
717           lsx_writew(ft, 1);
718 
719           /* time stamp of comment, Unix knows of time from 1/1/1970,
720              Apple knows time from 1/1/1904 */
721           lsx_writedw(ft, (unsigned)((sox_globals.repeatable? 0 : time(NULL)) + 2082844800));
722 
723           /* A marker ID of 0 indicates the comment is not associated
724              with a marker */
725           lsx_writew(ft, 0);
726 
727           /* now write the count and the bytes of text */
728           lsx_writew(ft, (unsigned) padded_comment_size);
729           lsx_writes(ft, comment);
730           if (comment_size != padded_comment_size)
731                 lsx_writes(ft, " ");
732         }
733         free(comment);
734 
735         /* COMM chunk -- describes encoding (and #frames) */
736         lsx_writes(ft, "COMM");
737         lsx_writedw(ft, 18); /* COMM chunk size */
738         lsx_writew(ft, ft->signal.channels); /* nchannels */
739         lsx_writedw(ft, (unsigned) nframes); /* number of frames */
740         lsx_writew(ft, bits); /* sample width, in bits */
741         write_ieee_extended(ft, (double)ft->signal.rate);
742 
743         /* MARK chunk -- set markers */
744         if (ft->oob.instr.nloops) {
745                 lsx_writes(ft, "MARK");
746                 if (ft->oob.instr.nloops > 2)
747                         ft->oob.instr.nloops = 2;
748                 lsx_writedw(ft, 2 + 16u*ft->oob.instr.nloops);
749                 lsx_writew(ft, ft->oob.instr.nloops);
750 
751                 for(i = 0; i < ft->oob.instr.nloops; i++) {
752                         unsigned start = ft->oob.loops[i].start > UINT_MAX
753                             ? UINT_MAX
754                             : ft->oob.loops[i].start;
755                         unsigned end = ft->oob.loops[i].start + ft->oob.loops[i].length > UINT_MAX
756                             ? UINT_MAX
757                             : ft->oob.loops[i].start + ft->oob.loops[i].length;
758                         lsx_writew(ft, i + 1);
759                         lsx_writedw(ft, start);
760                         lsx_writeb(ft, 0);
761                         lsx_writeb(ft, 0);
762                         lsx_writew(ft, i*2 + 1);
763                         lsx_writedw(ft, end);
764                         lsx_writeb(ft, 0);
765                         lsx_writeb(ft, 0);
766                 }
767 
768                 lsx_writes(ft, "INST");
769                 lsx_writedw(ft, 20);
770                 /* random MIDI shit that we default on */
771                 lsx_writeb(ft, (uint8_t)ft->oob.instr.MIDInote);
772                 lsx_writeb(ft, 0);                       /* detune */
773                 lsx_writeb(ft, (uint8_t)ft->oob.instr.MIDIlow);
774                 lsx_writeb(ft, (uint8_t)ft->oob.instr.MIDIhi);
775                 lsx_writeb(ft, 1);                       /* low velocity */
776                 lsx_writeb(ft, 127);                     /* hi  velocity */
777                 lsx_writew(ft, 0);                               /* gain */
778 
779                 /* sustain loop */
780                 lsx_writew(ft, ft->oob.loops[0].type);
781                 lsx_writew(ft, 1);                               /* marker 1 */
782                 lsx_writew(ft, 3);                               /* marker 3 */
783                 /* release loop, if there */
784                 if (ft->oob.instr.nloops == 2) {
785                         lsx_writew(ft, ft->oob.loops[1].type);
786                         lsx_writew(ft, 2);                       /* marker 2 */
787                         lsx_writew(ft, 4);                       /* marker 4 */
788                 } else {
789                         lsx_writew(ft, 0);                       /* no release loop */
790                         lsx_writew(ft, 0);
791                         lsx_writew(ft, 0);
792                 }
793         }
794 
795         /* SSND chunk -- describes data */
796         lsx_writes(ft, "SSND");
797         /* chunk size */
798         lsx_writedw(ft, (unsigned) (8 + nframes * ft->signal.channels * (ft->encoding.bits_per_sample >> 3)));
799         lsx_writedw(ft, 0); /* offset */
800         lsx_writedw(ft, 0); /* block size */
801         return(SOX_SUCCESS);
802 }
803 
lsx_aifcstartwrite(sox_format_t * ft)804 int lsx_aifcstartwrite(sox_format_t * ft)
805 {
806         int rc;
807 
808         /* Needed because lsx_rawwrite() */
809         rc = lsx_rawstartwrite(ft);
810         if (rc)
811             return rc;
812 
813         /* Compute the "very large number" so that a maximum number
814            of samples can be transmitted through a pipe without the
815            risk of causing overflow when calculating the number of bytes.
816            At 48 kHz, 16 bits stereo, this gives ~3 hours of music.
817            Sorry, the AIFC format does not provide for an "infinite"
818            number of samples. */
819         return(aifcwriteheader(ft, (uint64_t) 0x7f000000 / ((ft->encoding.bits_per_sample >> 3)*ft->signal.channels)));
820 }
821 
lsx_aifcstopwrite(sox_format_t * ft)822 int lsx_aifcstopwrite(sox_format_t * ft)
823 {
824         /* If we've written an odd number of bytes, write a padding
825            NUL */
826         if (ft->olength % 2 == 1 && ft->encoding.bits_per_sample == 8 && ft->signal.channels == 1)
827         {
828             sox_sample_t buf = 0;
829             lsx_rawwrite(ft, &buf, (size_t) 1);
830         }
831 
832         if (!ft->seekable)
833         {
834             lsx_fail_errno(ft,SOX_EOF,"Non-seekable file.");
835             return(SOX_EOF);
836         }
837         if (lsx_seeki(ft, (off_t)0, SEEK_SET) != 0)
838         {
839                 lsx_fail_errno(ft,errno,"can't rewind output file to rewrite AIFC header");
840                 return(SOX_EOF);
841         }
842         return(aifcwriteheader(ft, ft->olength / ft->signal.channels));
843 }
844 
aifcwriteheader(sox_format_t * ft,uint64_t nframes)845 static int aifcwriteheader(sox_format_t * ft, uint64_t nframes)
846 {
847         unsigned hsize;
848         unsigned bits = 0;
849         uint64_t size;
850         char *ctype = NULL, *cname = NULL;
851         unsigned cname_len = 0, comm_len = 0, comm_padding = 0;
852 
853         if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
854             ft->encoding.bits_per_sample == 8)
855                 bits = 8;
856         else if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
857                  ft->encoding.bits_per_sample == 16)
858                 bits = 16;
859         else if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
860                  ft->encoding.bits_per_sample == 24)
861                 bits = 24;
862         else if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
863                  ft->encoding.bits_per_sample == 32)
864                 bits = 32;
865         else if (ft->encoding.encoding == SOX_ENCODING_FLOAT &&
866                  ft->encoding.bits_per_sample == 32)
867                 bits = 32;
868         else if (ft->encoding.encoding == SOX_ENCODING_FLOAT &&
869                  ft->encoding.bits_per_sample == 64)
870                 bits = 64;
871         else
872         {
873                 lsx_fail_errno(ft,SOX_EFMT,"unsupported output encoding/size for AIFC header");
874                 return(SOX_EOF);
875         }
876 
877         /* calculate length of COMM chunk (without header) */
878         switch (ft->encoding.encoding) {
879           case SOX_ENCODING_SIGN2:
880             ctype = "NONE";
881             cname = "not compressed";
882             break;
883           case SOX_ENCODING_FLOAT:
884             if (bits == 32) {
885               ctype = "fl32";
886               cname = "32-bit floating point";
887             } else {
888               ctype = "fl64";
889               cname = "64-bit floating point";
890             }
891             break;
892           default: /* can't happen */
893             break;
894         }
895         cname_len = strlen(cname);
896         comm_len = 18+4+1+cname_len;
897         comm_padding = comm_len%2;
898 
899         hsize = 12 /*FVER*/ + 8 /*COMM hdr*/ + comm_len+comm_padding /*COMM chunk*/ +
900                 8 /*SSND hdr*/ + 12 /*SSND chunk*/;
901 
902         lsx_writes(ft, "FORM"); /* IFF header */
903         /* file size */
904         size = hsize + nframes * (ft->encoding.bits_per_sample >> 3) * ft->signal.channels;
905         if (size > UINT_MAX)
906         {
907             lsx_warn("file size too big for accurate AIFC header");
908             size = UINT_MAX;
909         }
910         lsx_writedw(ft, (unsigned)size);
911         lsx_writes(ft, "AIFC"); /* File type */
912 
913         /* FVER chunk */
914         lsx_writes(ft, "FVER");
915         lsx_writedw(ft, 4); /* FVER chunk size */
916         lsx_writedw(ft, 0xa2805140); /* version_date(May23,1990,2:40pm) */
917 
918         /* COMM chunk -- describes encoding (and #frames) */
919         lsx_writes(ft, "COMM");
920         lsx_writedw(ft, comm_len+comm_padding); /* COMM chunk size */
921         lsx_writew(ft, ft->signal.channels); /* nchannels */
922         lsx_writedw(ft, (unsigned) nframes); /* number of frames */
923         lsx_writew(ft, bits); /* sample width, in bits */
924         write_ieee_extended(ft, (double)ft->signal.rate);
925 
926         lsx_writes(ft, ctype); /*compression_type*/
927         lsx_writeb(ft, cname_len);
928         lsx_writes(ft, cname);
929         if (comm_padding)
930           lsx_writeb(ft, 0);
931 
932         /* SSND chunk -- describes data */
933         lsx_writes(ft, "SSND");
934         /* chunk size */
935         lsx_writedw(ft, (unsigned) (8 + nframes * ft->signal.channels * (ft->encoding.bits_per_sample >> 3)));
936         lsx_writedw(ft, 0); /* offset */
937         lsx_writedw(ft, 0); /* block size */
938 
939         /* Any Private chunks shall appear after the required chunks (FORM,FVER,COMM,SSND) */
940         return(SOX_SUCCESS);
941 }
942 
read_ieee_extended(sox_format_t * ft)943 static double read_ieee_extended(sox_format_t * ft)
944 {
945         unsigned char buf[10];
946         if (lsx_readbuf(ft, buf, (size_t)10) != 10)
947         {
948                 lsx_fail_errno(ft,SOX_EOF,"EOF while reading IEEE extended number");
949                 return(SOX_EOF);
950         }
951         return ConvertFromIeeeExtended(buf);
952 }
953 
write_ieee_extended(sox_format_t * ft,double x)954 static void write_ieee_extended(sox_format_t * ft, double x)
955 {
956         char buf[10];
957         ConvertToIeeeExtended(x, buf);
958         lsx_debug_more("converted %g to %o %o %o %o %o %o %o %o %o %o",
959                 x,
960                 buf[0], buf[1], buf[2], buf[3], buf[4],
961                 buf[5], buf[6], buf[7], buf[8], buf[9]);
962         (void)lsx_writebuf(ft, buf, (size_t) 10);
963 }
964 
965 
966 /*
967  * C O N V E R T   T O   I E E E   E X T E N D E D
968  */
969 
970 /* Copyright (C) 1988-1991 Apple Computer, Inc.
971  *
972  * All rights reserved.
973  *
974  * Warranty Information
975  *  Even though Apple has reviewed this software, Apple makes no warranty
976  *  or representation, either express or implied, with respect to this
977  *  software, its quality, accuracy, merchantability, or fitness for a
978  *  particular purpose.  As a result, this software is provided "as is,"
979  *  and you, its user, are assuming the entire risk as to its quality
980  *  and accuracy.
981  *
982  * Machine-independent I/O routines for IEEE floating-point numbers.
983  *
984  * NaN's and infinities are converted to HUGE_VAL, which
985  * happens to be infinity on IEEE machines.  Unfortunately, it is
986  * impossible to preserve NaN's in a machine-independent way.
987  * Infinities are, however, preserved on IEEE machines.
988  *
989  * These routines have been tested on the following machines:
990  *    Apple Macintosh, MPW 3.1 C compiler
991  *    Apple Macintosh, THINK C compiler
992  *    Silicon Graphics IRIS, MIPS compiler
993  *    Cray X/MP and Y/MP
994  *    Digital Equipment VAX
995  *
996  *
997  * Implemented by Malcolm Slaney and Ken Turkowski.
998  *
999  * Malcolm Slaney contributions during 1988-1990 include big- and little-
1000  * endian file I/O, conversion to and from Motorola's extended 80-bit
1001  * floating-point format, and conversions to and from IEEE single-
1002  * precision floating-point format.
1003  *
1004  * In 1991, Ken Turkowski implemented the conversions to and from
1005  * IEEE double-precision format, added more precision to the extended
1006  * conversions, and accommodated conversions involving +/- infinity,
1007  * NaN's, and denormalized numbers.
1008  */
1009 
1010 #define FloatToUnsigned(f) ((uint32_t)(((int32_t)(f - 2147483648.0)) + 2147483647) + 1)
1011 
ConvertToIeeeExtended(double num,char * bytes)1012 static void ConvertToIeeeExtended(double num, char *bytes)
1013 {
1014     int    sign;
1015     int expon;
1016     double fMant, fsMant;
1017     uint32_t hiMant, loMant;
1018 
1019     if (num < 0) {
1020         sign = 0x8000;
1021         num *= -1;
1022     } else {
1023         sign = 0;
1024     }
1025 
1026     if (num == 0) {
1027         expon = 0; hiMant = 0; loMant = 0;
1028     }
1029     else {
1030         fMant = frexp(num, &expon);
1031         if ((expon > 16384) || !(fMant < 1)) {    /* Infinity or NaN */
1032             expon = sign|0x7FFF; hiMant = 0; loMant = 0; /* infinity */
1033         }
1034         else {    /* Finite */
1035             expon += 16382;
1036             if (expon < 0) {    /* denormalized */
1037                 fMant = ldexp(fMant, expon);
1038                 expon = 0;
1039             }
1040             expon |= sign;
1041             fMant = ldexp(fMant, 32);
1042             fsMant = floor(fMant);
1043             hiMant = FloatToUnsigned(fsMant);
1044             fMant = ldexp(fMant - fsMant, 32);
1045             fsMant = floor(fMant);
1046             loMant = FloatToUnsigned(fsMant);
1047         }
1048     }
1049 
1050     bytes[0] = expon >> 8;
1051     bytes[1] = expon;
1052     bytes[2] = hiMant >> 24;
1053     bytes[3] = hiMant >> 16;
1054     bytes[4] = hiMant >> 8;
1055     bytes[5] = hiMant;
1056     bytes[6] = loMant >> 24;
1057     bytes[7] = loMant >> 16;
1058     bytes[8] = loMant >> 8;
1059     bytes[9] = loMant;
1060 }
1061 
1062 
1063 /*
1064  * C O N V E R T   F R O M   I E E E   E X T E N D E D
1065  */
1066 
1067 /*
1068  * Copyright (C) 1988-1991 Apple Computer, Inc.
1069  *
1070  * All rights reserved.
1071  *
1072  * Warranty Information
1073  *  Even though Apple has reviewed this software, Apple makes no warranty
1074  *  or representation, either express or implied, with respect to this
1075  *  software, its quality, accuracy, merchantability, or fitness for a
1076  *  particular purpose.  As a result, this software is provided "as is,"
1077  *  and you, its user, are assuming the entire risk as to its quality
1078  *  and accuracy.
1079  *
1080  * This code may be used and freely distributed as long as it includes
1081  * this copyright notice and the above warranty information.
1082  *
1083  * Machine-independent I/O routines for IEEE floating-point numbers.
1084  *
1085  * NaN's and infinities are converted to HUGE_VAL, which
1086  * happens to be infinity on IEEE machines.  Unfortunately, it is
1087  * impossible to preserve NaN's in a machine-independent way.
1088  * Infinities are, however, preserved on IEEE machines.
1089  *
1090  * These routines have been tested on the following machines:
1091  *    Apple Macintosh, MPW 3.1 C compiler
1092  *    Apple Macintosh, THINK C compiler
1093  *    Silicon Graphics IRIS, MIPS compiler
1094  *    Cray X/MP and Y/MP
1095  *    Digital Equipment VAX
1096  *
1097  *
1098  * Implemented by Malcolm Slaney and Ken Turkowski.
1099  *
1100  * Malcolm Slaney contributions during 1988-1990 include big- and little-
1101  * endian file I/O, conversion to and from Motorola's extended 80-bit
1102  * floating-point format, and conversions to and from IEEE single-
1103  * precision floating-point format.
1104  *
1105  * In 1991, Ken Turkowski implemented the conversions to and from
1106  * IEEE double-precision format, added more precision to the extended
1107  * conversions, and accommodated conversions involving +/- infinity,
1108  * NaN's, and denormalized numbers.
1109  */
1110 
1111 #define UnsignedToFloat(u)         (((double)((int32_t)(u - 2147483647 - 1))) + 2147483648.0)
1112 
1113 /****************************************************************
1114  * Extended precision IEEE floating-point conversion routine.
1115  ****************************************************************/
1116 
ConvertFromIeeeExtended(unsigned char * bytes)1117 static double ConvertFromIeeeExtended(unsigned char *bytes)
1118 {
1119     double    f;
1120     int    expon;
1121     uint32_t hiMant, loMant;
1122 
1123     expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF);
1124     hiMant    =    ((uint32_t)(bytes[2] & 0xFF) << 24)
1125             |    ((uint32_t)(bytes[3] & 0xFF) << 16)
1126             |    ((uint32_t)(bytes[4] & 0xFF) << 8)
1127             |    ((uint32_t)(bytes[5] & 0xFF));
1128     loMant    =    ((uint32_t)(bytes[6] & 0xFF) << 24)
1129             |    ((uint32_t)(bytes[7] & 0xFF) << 16)
1130             |    ((uint32_t)(bytes[8] & 0xFF) << 8)
1131             |    ((uint32_t)(bytes[9] & 0xFF));
1132 
1133     if (expon == 0 && hiMant == 0 && loMant == 0) {
1134         f = 0;
1135     }
1136     else {
1137         if (expon == 0x7FFF) {    /* Infinity or NaN */
1138             f = HUGE_VAL;
1139         }
1140         else {
1141             expon -= 16383;
1142             f  = ldexp(UnsignedToFloat(hiMant), expon-=31);
1143             f += ldexp(UnsignedToFloat(loMant), expon-=32);
1144         }
1145     }
1146 
1147     if (bytes[0] & 0x80)
1148         return -f;
1149     else
1150         return f;
1151 }
1152