Sigrid Solveig Haflínudóttirfix warnings6bc6a9b3 years agoHistory
1157 lines · 38.9 KB · C
RawDownload
/* libSoX SGI/Amiga AIFF format. * Copyright 1991-2007 Guido van Rossum And Sundry Contributors * * This source code is freely redistributable and may be used for * any purpose.  This copyright notice must be maintained. * Guido van Rossum And Sundry Contributors are not responsible for * the consequences of using this software. * * Used by SGI on 4D/35 and Indigo. * This is a subformat of the EA-IFF-85 format. * This is related to the IFF format used by the Amiga. * But, apparently, not the same. * Also AIFF-C format output that is defined in DAVIC 1.4 Part 9 Annex B * (usable for japanese-data-broadcasting, specified by ARIB STD-B24.) */ #include "sox_i.h"#include "aiff.h"#include "id3.h" #include <time.h>      /* for time stamping comments */#include <stdlib.h>#include <string.h>#include <stdio.h>#include <errno.h>#include <limits.h> /* forward declarations */static double read_ieee_extended(sox_format_t *);static int aiffwriteheader(sox_format_t *, uint64_t);static int aifcwriteheader(sox_format_t *, uint64_t);static void write_ieee_extended(sox_format_t *, double);static double ConvertFromIeeeExtended(unsigned char*);static void ConvertToIeeeExtended(double, char *);static int textChunk(char **text, char *chunkDescription, sox_format_t * ft);static int commentChunk(char **text, char *chunkDescription, sox_format_t * ft);static void reportInstrument(sox_format_t * ft); int lsx_aiffstartread(sox_format_t * ft){  char buf[5];  uint32_t totalsize;  uint32_t chunksize;  unsigned short channels = 0;  sox_encoding_t enc = SOX_ENCODING_SIGN2;  uint32_t frames;  unsigned short bits = 0;  double rate = 0.0;  uint32_t offset = 0;  uint32_t blocksize = 0;  int foundcomm = 0, foundmark = 0, foundinstr = 0, is_sowt = 0;  struct mark {    unsigned short id;    uint32_t position;    char name[40];  } marks[32];  unsigned short looptype;  int i, j;  unsigned short nmarks = 0;  unsigned short sustainLoopBegin = 0, sustainLoopEnd = 0,                 releaseLoopBegin = 0, releaseLoopEnd = 0;  off_t seekto = 0;  size_t ssndsize = 0;  char *annotation;  char *author;  char *copyright;  char *nametext;   uint8_t trash8;  uint16_t trash16;  uint32_t trash32;   int rc;   /* FORM chunk */  if (lsx_reads(ft, buf, (size_t)4) == SOX_EOF || strncmp(buf, "FORM", (size_t)4) != 0) {    lsx_fail_errno(ft,SOX_EHDR,"AIFF header does not begin with magic word `FORM'");    return(SOX_EOF);  }  lsx_readdw(ft, &totalsize);  if (lsx_reads(ft, buf, (size_t)4) == SOX_EOF || (strncmp(buf, "AIFF", (size_t)4) != 0 &&        strncmp(buf, "AIFC", (size_t)4) != 0)) {    lsx_fail_errno(ft,SOX_EHDR,"AIFF `FORM' chunk does not specify `AIFF' or `AIFC' as type");    return(SOX_EOF);  }    /* Skip everything but the COMM chunk and the SSND chunk */  /* The SSND chunk must be the last in the file */  while (1) {    if (lsx_reads(ft, buf, (size_t)4) == SOX_EOF) {      if (seekto > 0)        break;      else {        lsx_fail_errno(ft,SOX_EHDR,"Missing SSND chunk in AIFF file");        return(SOX_EOF);      }    }    if (strncmp(buf, "COMM", (size_t)4) == 0) {      /* COMM chunk */      lsx_readdw(ft, &chunksize);      lsx_readw(ft, &channels);      lsx_readdw(ft, &frames);      lsx_readw(ft, &bits);      rate = read_ieee_extended(ft);      chunksize -= 18;      if (chunksize > 0) {        lsx_reads(ft, buf, (size_t)4);        chunksize -= 4;        if (strncmp(buf, "sowt", (size_t)4) == 0) {          /* CD audio as read on Mac OS machines */          /* Need to endian swap all the data */          is_sowt = 1;        }        else if (strncmp(buf, "fl32", (size_t)4) == 0 ||            strncmp(buf, "FL32", (size_t)4) == 0) {          enc = SOX_ENCODING_FLOAT;          if (bits != 32) {            lsx_fail_errno(ft, SOX_EHDR,              "Sample size of %u is not consistent with `fl32' compression type", bits);            return SOX_EOF;          }        }        else if (strncmp(buf, "fl64", (size_t)4) == 0 ||            strncmp(buf, "FL64", (size_t)4) == 0) {          enc = SOX_ENCODING_FLOAT;          if (bits != 64) {            lsx_fail_errno(ft, SOX_EHDR,              "Sample size of %u is not consistent with `fl64' compression type", bits);            return SOX_EOF;          }        }        else if (strncmp(buf, "NONE", (size_t)4) != 0 &&            strncmp(buf, "twos", (size_t)4) != 0) {          buf[4] = 0;          lsx_fail_errno(ft, SOX_EHDR, "Unsupported AIFC compression type `%s'", buf);          return(SOX_EOF);        }      }      while(chunksize-- > 0)        lsx_readb(ft, &trash8);      foundcomm = 1;    }    else if (strncmp(buf, "SSND", (size_t)4) == 0) {      /* SSND chunk */      lsx_readdw(ft, &chunksize);      lsx_readdw(ft, &offset);      lsx_readdw(ft, &blocksize);      chunksize -= 8;      ssndsize = chunksize;      /* word-align chunksize in case it wasn't       * done by writing application already.       */      chunksize += (chunksize % 2);      /* if can't seek, just do sound now */      if (!ft->seekable)        break;      /* else, seek to end of sound and hunt for more */      seekto = lsx_tell(ft);      lsx_seeki(ft, (off_t)chunksize, SEEK_CUR);    }    else if (strncmp(buf, "MARK", (size_t)4) == 0) {      /* MARK chunk */      lsx_readdw(ft, &chunksize);      if (chunksize >= sizeof(nmarks)) {        lsx_readw(ft, &nmarks);        chunksize -= sizeof(nmarks);      }      else nmarks = 0;       /* Some programs like to always have a MARK chunk       * but will set number of marks to 0 and force       * software to detect and ignore it.       */      if (nmarks == 0)        foundmark = 0;      else        foundmark = 1;       /* Make sure its not larger then we support */      if (nmarks > 32)        nmarks = 32;       for(i = 0; i < nmarks && chunksize; i++) {        unsigned char len, read_len, tmp_c;         if (chunksize < 6)          break;        lsx_readw(ft, &(marks[i].id));        lsx_readdw(ft, &(marks[i].position));        chunksize -= 6;        /* If error reading length then         * don't try to read more bytes         * based on that value.         */        if (lsx_readb(ft, &len) != SOX_SUCCESS)          break;        --chunksize;        if (len > chunksize)          len = chunksize;        read_len = len;        if (read_len > 39)          read_len = 39;        for(j = 0; j < len && chunksize; j++) {          lsx_readb(ft, &tmp_c);          if (j < read_len)            marks[i].name[j] = tmp_c;          chunksize--;        }        marks[i].name[read_len] = 0;        if ((len & 1) == 0 && chunksize) {          chunksize--;          lsx_readb(ft, &trash8);        }      }      /* HA HA!  Sound Designer (and others) makes */      /* bogus files. It spits out bogus chunksize */      /* for MARK field */      while(chunksize-- > 0)        lsx_readb(ft, &trash8);    }    else if (strncmp(buf, "INST", (size_t)4) == 0) {      /* INST chunk */      lsx_readdw(ft, &chunksize);      lsx_readsb(ft, &(ft->oob.instr.MIDInote));      lsx_readb(ft, &trash8);      lsx_readsb(ft, &(ft->oob.instr.MIDIlow));      lsx_readsb(ft, &(ft->oob.instr.MIDIhi));      /* Low  velocity */      lsx_readb(ft, &trash8);      /* Hi  velocity */      lsx_readb(ft, &trash8);      lsx_readw(ft, &trash16);/* gain */      lsx_readw(ft, &looptype); /* sustain loop */      ft->oob.loops[0].type = looptype;      lsx_readw(ft, &sustainLoopBegin); /* begin marker */      lsx_readw(ft, &sustainLoopEnd);    /* end marker */      lsx_readw(ft, &looptype); /* release loop */      ft->oob.loops[1].type = looptype;      lsx_readw(ft, &releaseLoopBegin);  /* begin marker */      lsx_readw(ft, &releaseLoopEnd);    /* end marker */       foundinstr = 1;    }    else if (strncmp(buf, "APPL", (size_t)4) == 0) {      lsx_readdw(ft, &chunksize);      /* word-align chunksize in case it wasn't       * done by writing application already.       */      chunksize += (chunksize % 2);      while(chunksize-- > 0)        lsx_readb(ft, &trash8);    }    else if (strncmp(buf, "ALCH", (size_t)4) == 0) {      /* I think this is bogus and gets grabbed by APPL */      /* INST chunk */      lsx_readdw(ft, &trash32);                /* ENVS - jeez! */      lsx_readdw(ft, &chunksize);      while(chunksize-- > 0)        lsx_readb(ft, &trash8);    }    else if (strncmp(buf, "ANNO", (size_t)4) == 0) {      rc = textChunk(&annotation, "Annotation:", ft);      if (rc) {        /* Fail already called in function */        return(SOX_EOF);      }      if (annotation)        sox_append_comments(&ft->oob.comments, annotation);      free(annotation);    }    else if (strncmp(buf, "COMT", (size_t)4) == 0) {      char *comment = NULL;      rc = commentChunk(&comment, "Comment:", ft);      if (rc) {        /* Fail already called in function */        return(SOX_EOF);      }      if (comment)        sox_append_comments(&ft->oob.comments, comment);      free(comment);    }    else if (strncmp(buf, "AUTH", (size_t)4) == 0) {      /* Author chunk */      rc = textChunk(&author, "Author:", ft);      if (rc) {        /* Fail already called in function */        return(SOX_EOF);      }      free(author);    }    else if (strncmp(buf, "NAME", (size_t)4) == 0) {      /* Name chunk */      rc = textChunk(&nametext, "Name:", ft);      if (rc) {        /* Fail already called in function */        return(SOX_EOF);      }      free(nametext);    }    else if (strncmp(buf, "(c) ", (size_t)4) == 0) {      /* Copyright chunk */      rc = textChunk(&copyright, "Copyright:", ft);      if (rc) {        /* Fail already called in function */        return(SOX_EOF);      }      free(copyright);    }    else if (strncmp(buf, "ID3 ", 4) == 0) {      off_t offs;      lsx_readdw(ft, &chunksize);      offs = lsx_tell(ft);      lsx_id3_read_tag(ft, 0);      lsx_seeki(ft, offs + chunksize, SEEK_SET);    }    else {      if (lsx_eof(ft))        break;      buf[4] = 0;      lsx_debug("AIFFstartread: ignoring `%s' chunk", buf);      lsx_readdw(ft, &chunksize);      if (lsx_eof(ft))        break;      /* account for padding after odd-sized chunks */      chunksize += chunksize & 1;      /* Skip the chunk using lsx_readb() so we may read         from a pipe */      while (chunksize-- > 0) {        if (lsx_readb(ft, &trash8) == SOX_EOF)          break;      }    }    if (lsx_eof(ft))      break;  }   /*   * if a pipe, we lose all chunks after sound.   * Like, say, instrument loops.   */  if (ft->seekable) {    if (seekto > 0)      lsx_seeki(ft, seekto, SEEK_SET);    else {      lsx_fail_errno(ft,SOX_EOF,"AIFF: no sound data on input file");      return(SOX_EOF);    }  }  /* SSND chunk just read */  if (blocksize != 0)    lsx_warn("AIFF header has invalid blocksize.  Ignoring but expect a premature EOF");   ssndsize -= offset;  while (offset-- > 0) {    if (lsx_readb(ft, &trash8) == SOX_EOF) {      lsx_fail_errno(ft,errno,"unexpected EOF while skipping AIFF offset");      return(SOX_EOF);    }  }   if (foundcomm) {    if      (bits <=  8) bits = 8;    else if (bits <= 16) bits = 16;    else if (bits <= 24) bits = 24;    else if (bits <= 32) bits = 32;    else if (bits == 64 && enc == SOX_ENCODING_FLOAT) { /* no-op */ }    else {      lsx_fail_errno(ft,SOX_EFMT,"unsupported sample size in AIFF header: %d", bits);      return(SOX_EOF);    }  } else  {    if ((ft->signal.channels == SOX_UNSPEC)        || (ft->signal.rate == SOX_UNSPEC)        || (ft->encoding.encoding == SOX_ENCODING_UNKNOWN)        || (ft->encoding.bits_per_sample == 0)) {      lsx_report("You must specify # channels, sample rate, signed/unsigned,");      lsx_report("and 8/16 on the command line.");      lsx_fail_errno(ft,SOX_EFMT,"Bogus AIFF file: no COMM section.");      return(SOX_EOF);    }   }  ssndsize /= bits >> 3;   /* Cope with 'sowt' CD tracks as read on Macs */  if (is_sowt)    ft->encoding.reverse_bytes = !ft->encoding.reverse_bytes;   if (foundmark && !foundinstr) {    lsx_debug("Ignoring MARK chunk since no INSTR found.");    foundmark = 0;  }  if (!foundmark && foundinstr) {    lsx_debug("Ignoring INSTR chunk since no MARK found.");    foundinstr = 0;  }  if (foundmark && foundinstr) {    int i2;    int slbIndex = 0, sleIndex = 0;    int rlbIndex = 0, rleIndex = 0;     /* find our loop markers and save their marker indexes */    for(i2 = 0; i2 < nmarks; i2++) {      if(marks[i2].id == sustainLoopBegin)        slbIndex = i2;      if(marks[i2].id == sustainLoopEnd)        sleIndex = i2;      if(marks[i2].id == releaseLoopBegin)        rlbIndex = i2;      if(marks[i2].id == releaseLoopEnd)        rleIndex = i2;    }     ft->oob.instr.nloops = 0;    if (ft->oob.loops[0].type != 0) {      ft->oob.loops[0].start = marks[slbIndex].position;      ft->oob.loops[0].length =        marks[sleIndex].position - marks[slbIndex].position;      /* really the loop count should be infinite */      ft->oob.loops[0].count = 1;      ft->oob.instr.loopmode = SOX_LOOP_SUSTAIN_DECAY | ft->oob.loops[0].type;      ft->oob.instr.nloops++;    }    if (ft->oob.loops[1].type != 0) {      ft->oob.loops[1].start = marks[rlbIndex].position;      ft->oob.loops[1].length =        marks[rleIndex].position - marks[rlbIndex].position;      /* really the loop count should be infinite */      ft->oob.loops[1].count = 1;      ft->oob.instr.loopmode = SOX_LOOP_SUSTAIN_DECAY | ft->oob.loops[1].type;      ft->oob.instr.nloops++;    }  }  reportInstrument(ft);   return lsx_check_read_params(      ft, channels, rate, enc, bits, (uint64_t)ssndsize, sox_false);} /* print out the MIDI key allocations, loop points, directions etc */static void reportInstrument(sox_format_t * ft){  unsigned loopNum;   if(ft->oob.instr.nloops > 0)    lsx_report("AIFF Loop markers:");  for(loopNum  = 0; loopNum < ft->oob.instr.nloops; loopNum++) {    if (ft->oob.loops[loopNum].count) {      lsx_report("Loop %d: start: %6lu", loopNum, (unsigned long)ft->oob.loops[loopNum].start);      lsx_report(" end:   %6lu",              (unsigned long)(ft->oob.loops[loopNum].start + ft->oob.loops[loopNum].length));      lsx_report(" count: %6d", ft->oob.loops[loopNum].count);      lsx_report(" type:  ");      switch(ft->oob.loops[loopNum].type & ~SOX_LOOP_SUSTAIN_DECAY) {      case 0: lsx_report("off"); break;      case 1: lsx_report("forward"); break;      case 2: lsx_report("forward/backward"); break;      }    }  }  lsx_report("Unity MIDI Note: %d", ft->oob.instr.MIDInote);  lsx_report("Low   MIDI Note: %d", ft->oob.instr.MIDIlow);  lsx_report("High  MIDI Note: %d", ft->oob.instr.MIDIhi);} /* Process a text chunk, allocate memory, display it if verbose and return */static int textChunk(char **text, char *chunkDescription, sox_format_t * ft){  uint32_t chunksize0;  size_t chunksize;  lsx_readdw(ft, &chunksize0);  chunksize = chunksize0;   /* allocate enough memory to hold the text including a terminating \0 */  if (chunksize != SOX_SIZE_MAX)    *text = lsx_malloc((size_t)chunksize+1);  else    *text = lsx_malloc((size_t)chunksize);   if (lsx_readbuf(ft, *text, (size_t) chunksize) != chunksize)  {    lsx_fail_errno(ft,SOX_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);    return(SOX_EOF);  }  if (chunksize != SOX_SIZE_MAX)    *(*text + chunksize) = '\0';  else    *(*text + chunksize-1) = '\0';  if (chunksize % 2)  {    /* Read past pad byte */    char c;    if (lsx_readbuf(ft, &c, (size_t)1) != 1)    {      lsx_fail_errno(ft,SOX_EOF,"AIFF: Unexpected EOF in %s header", chunkDescription);      return(SOX_EOF);    }  }  lsx_debug("%-10s   \"%s\"", chunkDescription, *text);

Lines 1–500 of 1157.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t