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 
20 #include <time.h>      /* for time stamping comments */
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <errno.h>
25 #include <limits.h>
26 
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);
37 
lsx_aiffstartread(sox_format_t * ft)38 int lsx_aiffstartread(sox_format_t * ft)
39 {
40   char buf[5];
41   uint32_t totalsize;
42   uint32_t chunksize;
43   unsigned short channels = 0;
44   sox_encoding_t enc = SOX_ENCODING_SIGN2;
45   uint32_t frames;
46   unsigned short bits = 0;
47   double rate = 0.0;
48   uint32_t offset = 0;
49   uint32_t blocksize = 0;
50   int foundcomm = 0, foundmark = 0, foundinstr = 0, is_sowt = 0;
51   struct mark {
52     unsigned short id;
53     uint32_t position;
54     char name[40];
55   } marks[32];
56   unsigned short looptype;
57   int i, j;
58   unsigned short nmarks = 0;
59   unsigned short sustainLoopBegin = 0, sustainLoopEnd = 0,
60                  releaseLoopBegin = 0, releaseLoopEnd = 0;
61   off_t seekto = 0;
62   size_t ssndsize = 0;
63   char *annotation;
64   char *author;
65   char *comment = NULL;
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 (ssndsize > 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       rc = commentChunk(&comment, "Comment:", ft);
274       if (rc) {
275         /* Fail already called in function */
276         return(SOX_EOF);
277       }
278       if (comment)
279         sox_append_comments(&ft->oob.comments, comment);
280       free(comment);
281     }
282     else if (strncmp(buf, "AUTH", (size_t)4) == 0) {
283       /* Author chunk */
284       rc = textChunk(&author, "Author:", ft);
285       if (rc) {
286         /* Fail already called in function */
287         return(SOX_EOF);
288       }
289       free(author);
290     }
291     else if (strncmp(buf, "NAME", (size_t)4) == 0) {
292       /* Name chunk */
293       rc = textChunk(&nametext, "Name:", ft);
294       if (rc) {
295         /* Fail already called in function */
296         return(SOX_EOF);
297       }
298       free(nametext);
299     }
300     else if (strncmp(buf, "(c) ", (size_t)4) == 0) {
301       /* Copyright chunk */
302       rc = textChunk(&copyright, "Copyright:", ft);
303       if (rc) {
304         /* Fail already called in function */
305         return(SOX_EOF);
306       }
307       free(copyright);
308     }
309     else {
310       if (lsx_eof(ft))
311         break;
312       buf[4] = 0;
313       lsx_debug("AIFFstartread: ignoring `%s' chunk", buf);
314       lsx_readdw(ft, &chunksize);
315       if (lsx_eof(ft))
316         break;
317       /* Skip the chunk using lsx_readb() so we may read
318          from a pipe */
319       while (chunksize-- > 0) {
320         if (lsx_readb(ft, &trash8) == SOX_EOF)
321           break;
322       }
323     }
324     if (lsx_eof(ft))
325       break;
326   }
327 
328   /*
329    * if a pipe, we lose all chunks after sound.
330    * Like, say, instrument loops.
331    */
332   if (ft->seekable) {
333     if (seekto > 0)
334       lsx_seeki(ft, seekto, SEEK_SET);
335     else {
336       lsx_fail_errno(ft,SOX_EOF,"AIFF: no sound data on input file");
337       return(SOX_EOF);
338     }
339   }
340   /* SSND chunk just read */
341   if (blocksize != 0)
342     lsx_warn("AIFF header has invalid blocksize.  Ignoring but expect a premature EOF");
343 
344   ssndsize -= offset;
345   while (offset-- > 0) {
346     if (lsx_readb(ft, &trash8) == SOX_EOF) {
347       lsx_fail_errno(ft,errno,"unexpected EOF while skipping AIFF offset");
348       return(SOX_EOF);
349     }
350   }
351 
352   if (foundcomm) {
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 */;
358     else {
359       lsx_fail_errno(ft,SOX_EFMT,"unsupported sample size in AIFF header: %d", bits);
360       return(SOX_EOF);
361     }
362   } else  {
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.");
370       return(SOX_EOF);
371     }
372 
373   }
374   ssndsize /= bits >> 3;
375 
376   /* Cope with 'sowt' CD tracks as read on Macs */
377   if (is_sowt)
378     ft->encoding.reverse_bytes = !ft->encoding.reverse_bytes;
379 
380   if (foundmark && !foundinstr) {
381     lsx_debug("Ignoring MARK chunk since no INSTR found.");
382     foundmark = 0;
383   }
384   if (!foundmark && foundinstr) {
385     lsx_debug("Ignoring INSTR chunk since no MARK found.");
386     foundinstr = 0;
387   }
388   if (foundmark && foundinstr) {
389     int i2;
390     int slbIndex = 0, sleIndex = 0;
391     int rlbIndex = 0, rleIndex = 0;
392 
393     /* find our loop markers and save their marker indexes */
394     for(i2 = 0; i2 < nmarks; i2++) {
395       if(marks[i2].id == sustainLoopBegin)
396         slbIndex = i2;
397       if(marks[i2].id == sustainLoopEnd)
398         sleIndex = i2;
399       if(marks[i2].id == releaseLoopBegin)
400         rlbIndex = i2;
401       if(marks[i2].id == releaseLoopEnd)
402         rleIndex = i2;
403     }
404 
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++;
414     }
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++;
423     }
424   }
425   reportInstrument(ft);
426 
427   return lsx_check_read_params(
428       ft, channels, rate, enc, bits, (uint64_t)ssndsize, sox_false);
429 }
430 
431 /* print out the MIDI key allocations, loop points, directions etc */
reportInstrument(sox_format_t * ft)432 static void reportInstrument(sox_format_t * ft)
433 {
434   unsigned loopNum;
435 
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;
449       }
450     }
451   }
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);
455 }
456 
457 /* Process a text chunk, allocate memory, display it if verbose and return */
textChunk(char ** text,char * chunkDescription,sox_format_t * ft)458 static int textChunk(char **text, char *chunkDescription, sox_format_t * ft)
459 {
460   uint32_t chunksize0;
461   size_t chunksize;
462   lsx_readdw(ft, &chunksize0);
463   chunksize = chunksize0;
464 
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);
468   else
469     *text = lsx_malloc((size_t)chunksize);
470 
471   if (lsx_readbuf(ft, *text, (size_t) chunksize) != chunksize)
472   {
473     lsx_fail_errno(ft,SOX_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);
474     return(SOX_EOF);
475   }
476   if (chunksize != SOX_SIZE_MAX)
477     *(*text + chunksize) = '\0';
478   else
479     *(*text + chunksize-1) = '\0';
480   if (chunksize % 2)
481   {
482     /* Read past pad byte */
483     char c;
484     if (lsx_readbuf(ft, &c, (size_t)1) != 1)
485     {
486       lsx_fail_errno(ft,SOX_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);
487       return(SOX_EOF);
488     }
489   }
490   lsx_debug("%-10s   \"%s\"", chunkDescription, *text);
491   return(SOX_SUCCESS);
492 }
493 
494 /* Comment lengths are words, not double words, and we can have several, so
495    we use a special function, not textChunk().;
496  */
commentChunk(char ** text,char * chunkDescription,sox_format_t * ft)497 static int commentChunk(char **text, char *chunkDescription, sox_format_t * ft)
498 {
499   uint32_t chunksize;
500   unsigned short numComments;
501   uint32_t timeStamp;
502   unsigned short markerId;
503   unsigned short totalCommentLength = 0;
504   unsigned int totalReadLength = 0;
505   unsigned int commentIndex;
506 
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;
512 
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);
518         return(SOX_EOF);
519     }
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);
524     }
525     else {
526       *text = lsx_realloc(*text, (size_t) totalCommentLength + 1);
527     }
528 
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);
531         return(SOX_EOF);
532     }
533     *(*text + totalCommentLength) = '\0';
534     totalReadLength += totalCommentLength + 4 + 2 + 2; /* include header */
535     if (commentLength % 2) {
536         /* Read past pad byte */
537         char c;
538         if (lsx_readbuf(ft, &c, (size_t)1) != 1) {
539             lsx_fail_errno(ft,SOX_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);
540             return(SOX_EOF);
541         }
542         totalReadLength += 1;
543     }
544   }
545   lsx_debug("%-10s   \"%s\"", chunkDescription, *text);
546   /* make sure we read the whole chunk */
547   if (totalReadLength < chunksize) {
548        size_t i;
549        char c;
550        for (i=0; i < chunksize - totalReadLength; i++ )
551            lsx_readbuf(ft, &c, (size_t)1);
552   }
553   return(SOX_SUCCESS);
554 }
555 
lsx_aiffstopread(sox_format_t * ft)556 int lsx_aiffstopread(sox_format_t * ft)
557 {
558         char buf[5];
559         uint32_t chunksize;
560         uint8_t trash;
561 
562         if (!ft->seekable)
563         {
564             while (! lsx_eof(ft))
565             {
566                 if (lsx_readbuf(ft, buf, (size_t)4) != 4)
567                         break;
568 
569                 lsx_readdw(ft, &chunksize);
570                 if (lsx_eof(ft))
571                         break;
572                 buf[4] = '\0';
573                 lsx_warn("Ignoring AIFF tail chunk: `%s', %u bytes long",
574                         buf, chunksize);
575                 if (! strcmp(buf, "MARK") || ! strcmp(buf, "INST"))
576                         lsx_warn("       You're stripping MIDI/loop info!");
577                 while (chunksize-- > 0)
578                 {
579                         if (lsx_readb(ft, &trash) == SOX_EOF)
580                                 break;
581                 }
582             }
583         }
584         return SOX_SUCCESS;
585 }
586 
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. */
596 
lsx_aiffstartwrite(sox_format_t * ft)597 int lsx_aiffstartwrite(sox_format_t * ft)
598 {
599         int rc;
600 
601         /* Needed because lsx_rawwrite() */
602         rc = lsx_rawstartwrite(ft);
603         if (rc)
604             return rc;
605 
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)));
613 }
614 
lsx_aiffstopwrite(sox_format_t * ft)615 int lsx_aiffstopwrite(sox_format_t * ft)
616 {
617         /* If we've written an odd number of bytes, write a padding
618            NUL */
619         if (ft->olength % 2 == 1 && ft->encoding.bits_per_sample == 8 && ft->signal.channels == 1)
620         {
621             sox_sample_t buf = 0;
622             lsx_rawwrite(ft, &buf, (size_t) 1);
623         }
624 
625         if (!ft->seekable)
626         {
627             lsx_fail_errno(ft,SOX_EOF,"Non-seekable file.");
628             return(SOX_EOF);
629         }
630         if (lsx_seeki(ft, (off_t)0, SEEK_SET) != 0)
631         {
632                 lsx_fail_errno(ft,errno,"can't rewind output file to rewrite AIFF header");
633                 return(SOX_EOF);
634         }
635         return(aiffwriteheader(ft, ft->olength / ft->signal.channels));
636 }
637 
aiffwriteheader(sox_format_t * ft,uint64_t nframes)638 static int aiffwriteheader(sox_format_t * ft, uint64_t nframes)
639 {
640         int hsize =
641                 8 /*COMM hdr*/ + 18 /*COMM chunk*/ +
642                 8 /*SSND hdr*/ + 12 /*SSND chunk*/;
643         unsigned bits = 0;
644         unsigned i;
645         uint64_t size;
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);
649 
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 */
654         }
655 
656         if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
657             ft->encoding.bits_per_sample == 8)
658                 bits = 8;
659         else if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
660                  ft->encoding.bits_per_sample == 16)
661                 bits = 16;
662         else if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
663                  ft->encoding.bits_per_sample == 24)
664                 bits = 24;
665         else if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
666                  ft->encoding.bits_per_sample == 32)
667                 bits = 32;
668         else
669         {
670                 lsx_fail_errno(ft,SOX_EFMT,"unsupported output encoding/size for AIFF header");
671                 return(SOX_EOF);
672         }
673 
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)
677         {
678           comment_size = strlen(comment);
679           /* Must put an even number of characters out.
680            * True 68k processors OS's seem to require this.
681            */
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;
687         }
688 
689         lsx_writes(ft, "FORM"); /* IFF header */
690         /* file size */
691         size = hsize + nframes * (ft->encoding.bits_per_sample >> 3) * ft->signal.channels;
692         if (size > UINT_MAX)
693         {
694             lsx_warn("file size too big for accurate AIFF header");
695             size = UINT_MAX;
696         }
697         lsx_writedw(ft, (unsigned)size);
698         lsx_writes(ft, "AIFF"); /* File type */
699 
700         /* Now we write the COMT comment chunk using the precomputed sizes */
701         if (ft->oob.comments)
702         {
703           lsx_writes(ft, "COMT");
704           lsx_writedw(ft, (unsigned) comment_chunk_size);
705 
706           /* one comment */
707           lsx_writew(ft, 1);
708 
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));
712 
713           /* A marker ID of 0 indicates the comment is not associated
714              with a marker */
715           lsx_writew(ft, 0);
716 
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)
721                 lsx_writes(ft, " ");
722         }
723         free(comment);
724 
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);
732 
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);
740 
741                 for(i = 0; i < ft->oob.instr.nloops; i++) {
742                         unsigned start = ft->oob.loops[i].start > UINT_MAX
743                             ? UINT_MAX
744                             : ft->oob.loops[i].start;
745                         unsigned end = ft->oob.loops[i].start + ft->oob.loops[i].length > UINT_MAX
746                             ? UINT_MAX
747                             : ft->oob.loops[i].start + ft->oob.loops[i].length;
748                         lsx_writew(ft, i + 1);
749                         lsx_writedw(ft, start);
750                         lsx_writeb(ft, 0);
751                         lsx_writeb(ft, 0);
752                         lsx_writew(ft, i*2 + 1);
753                         lsx_writedw(ft, end);
754                         lsx_writeb(ft, 0);
755                         lsx_writeb(ft, 0);
756                 }
757 
758                 lsx_writes(ft, "INST");
759                 lsx_writedw(ft, 20);
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 */
768 
769                 /* sustain loop */
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 */
778                 } else {
779                         lsx_writew(ft, 0);                       /* no release loop */
780                         lsx_writew(ft, 0);
781                         lsx_writew(ft, 0);
782                 }
783         }
784 
785         /* SSND chunk -- describes data */
786         lsx_writes(ft, "SSND");
787         /* chunk size */
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 */
791         return(SOX_SUCCESS);
792 }
793 
lsx_aifcstartwrite(sox_format_t * ft)794 int lsx_aifcstartwrite(sox_format_t * ft)
795 {
796         int rc;
797 
798         /* Needed because lsx_rawwrite() */
799         rc = lsx_rawstartwrite(ft);
800         if (rc)
801             return rc;
802 
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)));
810 }
811 
lsx_aifcstopwrite(sox_format_t * ft)812 int lsx_aifcstopwrite(sox_format_t * ft)
813 {
814         /* If we've written an odd number of bytes, write a padding
815            NUL */
816         if (ft->olength % 2 == 1 && ft->encoding.bits_per_sample == 8 && ft->signal.channels == 1)
817         {
818             sox_sample_t buf = 0;
819             lsx_rawwrite(ft, &buf, (size_t) 1);
820         }
821 
822         if (!ft->seekable)
823         {
824             lsx_fail_errno(ft,SOX_EOF,"Non-seekable file.");
825             return(SOX_EOF);
826         }
827         if (lsx_seeki(ft, (off_t)0, SEEK_SET) != 0)
828         {
829                 lsx_fail_errno(ft,errno,"can't rewind output file to rewrite AIFC header");
830                 return(SOX_EOF);
831         }
832         return(aifcwriteheader(ft, ft->olength / ft->signal.channels));
833 }
834 
aifcwriteheader(sox_format_t * ft,uint64_t nframes)835 static int aifcwriteheader(sox_format_t * ft, uint64_t nframes)
836 {
837         unsigned hsize;
838         unsigned bits = 0;
839         uint64_t size;
840         char *ctype = NULL, *cname = NULL;
841         unsigned cname_len = 0, comm_len = 0, comm_padding = 0;
842 
843         if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
844             ft->encoding.bits_per_sample == 8)
845                 bits = 8;
846         else if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
847                  ft->encoding.bits_per_sample == 16)
848                 bits = 16;
849         else if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
850                  ft->encoding.bits_per_sample == 24)
851                 bits = 24;
852         else if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
853                  ft->encoding.bits_per_sample == 32)
854                 bits = 32;
855         else if (ft->encoding.encoding == SOX_ENCODING_FLOAT &&
856                  ft->encoding.bits_per_sample == 32)
857                 bits = 32;
858         else if (ft->encoding.encoding == SOX_ENCODING_FLOAT &&
859                  ft->encoding.bits_per_sample == 64)
860                 bits = 64;
861         else
862         {
863                 lsx_fail_errno(ft,SOX_EFMT,"unsupported output encoding/size for AIFC header");
864                 return(SOX_EOF);
865         }
866 
867         /* calculate length of COMM chunk (without header) */
868         switch (ft->encoding.encoding) {
869           case SOX_ENCODING_SIGN2:
870             ctype = "NONE";
871             cname = "not compressed";
872             break;
873           case SOX_ENCODING_FLOAT:
874             if (bits == 32) {
875               ctype = "fl32";
876               cname = "32-bit floating point";
877             } else {
878               ctype = "fl64";
879               cname = "64-bit floating point";
880             }
881             break;
882           default: /* can't happen */
883             break;
884         }
885         cname_len = strlen(cname);
886         comm_len = 18+4+1+cname_len;
887         comm_padding = comm_len%2;
888 
889         hsize = 12 /*FVER*/ + 8 /*COMM hdr*/ + comm_len+comm_padding /*COMM chunk*/ +
890                 8 /*SSND hdr*/ + 12 /*SSND chunk*/;
891 
892         lsx_writes(ft, "FORM"); /* IFF header */
893         /* file size */
894         size = hsize + nframes * (ft->encoding.bits_per_sample >> 3) * ft->signal.channels;
895         if (size > UINT_MAX)
896         {
897             lsx_warn("file size too big for accurate AIFC header");
898             size = UINT_MAX;
899         }
900         lsx_writedw(ft, (unsigned)size);
901         lsx_writes(ft, "AIFC"); /* File type */
902 
903         /* FVER chunk */
904         lsx_writes(ft, "FVER");
905         lsx_writedw(ft, 4); /* FVER chunk size */
906         lsx_writedw(ft, 0xa2805140); /* version_date(May23,1990,2:40pm) */
907 
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);
915 
916         lsx_writes(ft, ctype); /*compression_type*/
917         lsx_writeb(ft, cname_len);
918         lsx_writes(ft, cname);
919         if (comm_padding)
920           lsx_writeb(ft, 0);
921 
922         /* SSND chunk -- describes data */
923         lsx_writes(ft, "SSND");
924         /* chunk size */
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 */
928 
929         /* Any Private chunks shall appear after the required chunks (FORM,FVER,COMM,SSND) */
930         return(SOX_SUCCESS);
931 }
932 
read_ieee_extended(sox_format_t * ft)933 static double read_ieee_extended(sox_format_t * ft)
934 {
935         unsigned char buf[10];
936         if (lsx_readbuf(ft, buf, (size_t)10) != 10)
937         {
938                 lsx_fail_errno(ft,SOX_EOF,"EOF while reading IEEE extended number");
939                 return(SOX_EOF);
940         }
941         return ConvertFromIeeeExtended(buf);
942 }
943 
write_ieee_extended(sox_format_t * ft,double x)944 static void write_ieee_extended(sox_format_t * ft, double x)
945 {
946         char buf[10];
947         ConvertToIeeeExtended(x, buf);
948         lsx_debug_more("converted %g to %o %o %o %o %o %o %o %o %o %o",
949                 x,
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);
953 }
954 
955 
956 /*
957  * C O N V E R T   T O   I E E E   E X T E N D E D
958  */
959 
960 /* Copyright (C) 1988-1991 Apple Computer, Inc.
961  *
962  * All rights reserved.
963  *
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
970  *  and accuracy.
971  *
972  * Machine-independent I/O routines for IEEE floating-point numbers.
973  *
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.
978  *
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
983  *    Cray X/MP and Y/MP
984  *    Digital Equipment VAX
985  *
986  *
987  * Implemented by Malcolm Slaney and Ken Turkowski.
988  *
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.
993  *
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.
998  */
999 
1000 #define FloatToUnsigned(f) ((uint32_t)(((int32_t)(f - 2147483648.0)) + 2147483647) + 1)
1001 
ConvertToIeeeExtended(double num,char * bytes)1002 static void ConvertToIeeeExtended(double num, char *bytes)
1003 {
1004     int    sign;
1005     int expon;
1006     double fMant, fsMant;
1007     uint32_t hiMant, loMant;
1008 
1009     if (num < 0) {
1010         sign = 0x8000;
1011         num *= -1;
1012     } else {
1013         sign = 0;
1014     }
1015 
1016     if (num == 0) {
1017         expon = 0; hiMant = 0; loMant = 0;
1018     }
1019     else {
1020         fMant = frexp(num, &expon);
1021         if ((expon > 16384) || !(fMant < 1)) {    /* Infinity or NaN */
1022             expon = sign|0x7FFF; hiMant = 0; loMant = 0; /* infinity */
1023         }
1024         else {    /* Finite */
1025             expon += 16382;
1026             if (expon < 0) {    /* denormalized */
1027                 fMant = ldexp(fMant, expon);
1028                 expon = 0;
1029             }
1030             expon |= sign;
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);
1037         }
1038     }
1039 
1040     bytes[0] = expon >> 8;
1041     bytes[1] = expon;
1042     bytes[2] = hiMant >> 24;
1043     bytes[3] = hiMant >> 16;
1044     bytes[4] = hiMant >> 8;
1045     bytes[5] = hiMant;
1046     bytes[6] = loMant >> 24;
1047     bytes[7] = loMant >> 16;
1048     bytes[8] = loMant >> 8;
1049     bytes[9] = loMant;
1050 }
1051 
1052 
1053 /*
1054  * C O N V E R T   F R O M   I E E E   E X T E N D E D
1055  */
1056 
1057 /*
1058  * Copyright (C) 1988-1991 Apple Computer, Inc.
1059  *
1060  * All rights reserved.
1061  *
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
1068  *  and accuracy.
1069  *
1070  * This code may be used and freely distributed as long as it includes
1071  * this copyright notice and the above warranty information.
1072  *
1073  * Machine-independent I/O routines for IEEE floating-point numbers.
1074  *
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.
1079  *
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
1086  *
1087  *
1088  * Implemented by Malcolm Slaney and Ken Turkowski.
1089  *
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.
1094  *
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.
1099  */
1100 
1101 #define UnsignedToFloat(u)         (((double)((int32_t)(u - 2147483647 - 1))) + 2147483648.0)
1102 
1103 /****************************************************************
1104  * Extended precision IEEE floating-point conversion routine.
1105  ****************************************************************/
1106 
ConvertFromIeeeExtended(unsigned char * bytes)1107 static double ConvertFromIeeeExtended(unsigned char *bytes)
1108 {
1109     double    f;
1110     int    expon;
1111     uint32_t hiMant, loMant;
1112 
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));
1122 
1123     if (expon == 0 && hiMant == 0 && loMant == 0) {
1124         f = 0;
1125     }
1126     else {
1127         if (expon == 0x7FFF) {    /* Infinity or NaN */
1128             f = HUGE_VAL;
1129         }
1130         else {
1131             expon -= 16383;
1132             f  = ldexp(UnsignedToFloat(hiMant), expon-=31);
1133             f += ldexp(UnsignedToFloat(loMant), expon-=32);
1134         }
1135     }
1136 
1137     if (bytes[0] & 0x80)
1138         return -f;
1139     else
1140         return f;
1141 }
1142