Exemplo n.º 1
0
/*
 * (Re)fill the stream buffer that is to be decoded.  If any data
 * still exists in the buffer then they are first shifted to be
 * front of the stream buffer.
 */
static int sox_mp3_input(sox_format_t * ft)
{
    priv_t *p = (priv_t *) ft->priv;
    size_t bytes_read;
    size_t remaining;

    remaining = p->Stream.bufend - p->Stream.next_frame;

    /* libmad does not consume all the buffer it's given. Some
     * data, part of a truncated frame, is left unused at the
     * end of the buffer. That data must be put back at the
     * beginning of the buffer and taken in account for
     * refilling the buffer. This means that the input buffer
     * must be large enough to hold a complete frame at the
     * highest observable bit-rate (currently 448 kb/s).
     * TODO: Is 2016 bytes the size of the largest frame?
     * (448000*(1152/32000))/8
     */
    memmove(p->mp3_buffer, p->Stream.next_frame, remaining);

    bytes_read = lsx_readbuf(ft, p->mp3_buffer+remaining,
                            p->mp3_buffer_size-remaining);
    if (bytes_read == 0)
    {
        return SOX_EOF;
    }

    p->mad_stream_buffer(&p->Stream, p->mp3_buffer, bytes_read+remaining);
    p->Stream.error = 0;

    return SOX_SUCCESS;
}
Exemplo n.º 2
0
static int dvms_read_header(sox_format_t * ft, struct dvms_header *hdr)
{
        unsigned char hdrbuf[DVMS_HEADER_LEN];
        unsigned char *pch = hdrbuf;
        int i;
        unsigned sum;

        if (lsx_readbuf(ft, hdrbuf, sizeof(hdrbuf)) != sizeof(hdrbuf))
        {
                return (SOX_EOF);
        }
        for(i = sizeof(hdrbuf), sum = 0; i > /*2*/3; i--) /* Deti bug */
                sum += *pch++;
        pch = hdrbuf;
        memcpy(hdr->Filename, pch, sizeof(hdr->Filename));
        pch += sizeof(hdr->Filename);
        hdr->Id = get16_le(&pch);
        hdr->State = get16_le(&pch);
        hdr->Unixtime = get32_le(&pch);
        hdr->Usender = get16_le(&pch);
        hdr->Ureceiver = get16_le(&pch);
        hdr->Length = get32_le(&pch);
        hdr->Srate = get16_le(&pch);
        hdr->Days = get16_le(&pch);
        hdr->Custom1 = get16_le(&pch);
        hdr->Custom2 = get16_le(&pch);
        memcpy(hdr->Info, pch, sizeof(hdr->Info));
        pch += sizeof(hdr->Info);
        memcpy(hdr->extend, pch, sizeof(hdr->extend));
        pch += sizeof(hdr->extend);
        hdr->Crc = get16_le(&pch);
        if (sum != hdr->Crc)
        {
                lsx_report("DVMS header checksum error, read %u, calculated %u",
                     hdr->Crc, sum);
                return (SOX_EOF);
        }
        return (SOX_SUCCESS);
}
Exemplo n.º 3
0
static int callback_read(void* ft_data, unsigned char* ptr, int nbytes)
{
  sox_format_t* ft = (sox_format_t*)ft_data;
  return lsx_readbuf(ft, ptr, (size_t)nbytes);
}
Exemplo n.º 4
0
static int startread(sox_format_t * ft)
{
  priv_t *p = (priv_t *) ft->priv;
  size_t ReadSize;
  sox_bool ignore_length = ft->signal.length == SOX_IGNORE_LENGTH;
  int open_library_result;

  LSX_DLLIBRARY_OPEN(
      p,
      mad_dl,
      MAD_FUNC_ENTRIES,
      "MAD decoder library",
      mad_library_names,
      open_library_result);
  if (open_library_result)
    return SOX_EOF;

  p->mp3_buffer_size = sox_globals.bufsiz;
  p->mp3_buffer = lsx_malloc(p->mp3_buffer_size);

  ft->signal.length = SOX_UNSPEC;
  if (ft->seekable) {
#ifdef USING_ID3TAG
    read_comments(ft);
    rewind((FILE*)ft->fp);
    if (!ft->signal.length)
#endif
      if (!ignore_length)
        ft->signal.length = mp3_duration_ms(ft);
  }

  p->mad_stream_init(&p->Stream);
  p->mad_frame_init(&p->Frame);
  p->mad_synth_init(&p->Synth);
  mad_timer_reset(&p->Timer);

  ft->encoding.encoding = SOX_ENCODING_MP3;

  /* Decode at least one valid frame to find out the input
   * format.  The decoded frame will be saved off so that it
   * can be processed later.
   */
  ReadSize = lsx_readbuf(ft, p->mp3_buffer, p->mp3_buffer_size);
  if (ReadSize != p->mp3_buffer_size && ferror((FILE*)ft->fp))
    return SOX_EOF;

  p->mad_stream_buffer(&p->Stream, p->mp3_buffer, ReadSize);

  /* Find a valid frame before starting up.  This makes sure
   * that we have a valid MP3 and also skips past ID3v2 tags
   * at the beginning of the audio file.
   */
  p->Stream.error = 0;
  while (p->mad_frame_decode(&p->Frame,&p->Stream))
  {
      /* check whether input buffer needs a refill */
      if (p->Stream.error == MAD_ERROR_BUFLEN)
      {
          if (sox_mp3_input(ft) == SOX_EOF)
              return SOX_EOF;

          continue;
      }

      /* Consume any ID3 tags */
      sox_mp3_inputtag(ft);

      /* FIXME: We should probably detect when we've read
       * a bunch of non-ID3 data and still haven't found a
       * frame.  In that case we can abort early without
       * scanning the whole file.
       */
      p->Stream.error = 0;
  }

  if (p->Stream.error)
  {
      lsx_fail_errno(ft,SOX_EOF,"No valid MP3 frame found");
      return SOX_EOF;
  }

  switch(p->Frame.header.mode)
  {
      case MAD_MODE_SINGLE_CHANNEL:
      case MAD_MODE_DUAL_CHANNEL:
      case MAD_MODE_JOINT_STEREO:
      case MAD_MODE_STEREO:
          ft->signal.channels = MAD_NCHANNELS(&p->Frame.header);
          break;
      default:
          lsx_fail_errno(ft, SOX_EFMT, "Cannot determine number of channels");
          return SOX_EOF;
  }

  p->FrameCount=1;

  p->mad_timer_add(&p->Timer,p->Frame.header.duration);
  p->mad_synth_frame(&p->Synth,&p->Frame);
  ft->signal.precision = MP3_MAD_PRECISION;
  ft->signal.rate=p->Synth.pcm.samplerate;
  if (ignore_length)
    ft->signal.length = SOX_UNSPEC;
  else {
    ft->signal.length = (uint64_t)(ft->signal.length * .001 * ft->signal.rate + .5);
    ft->signal.length *= ft->signal.channels;  /* Keep separate from line above! */
  }

  p->cursamp = 0;

  return SOX_SUCCESS;
}
Exemplo n.º 5
0
static char const * auto_detect_format(sox_format_t * ft, char const * ext)
{
  char data[AUTO_DETECT_SIZE];
  size_t len = lsx_readbuf(ft, data, ft->seekable? sizeof(data) : PIPE_AUTO_DETECT_SIZE);
  #define CHECK(type, p2, l2, d2, p1, l1, d1) if (len >= p1 + l1 && \
      !memcmp(data + p1, d1, (size_t)l1) && !memcmp(data + p2, d2, (size_t)l2)) return #type;
  CHECK(voc   , 0, 0, ""     , 0, 20, "Creative Voice File\x1a")
  CHECK(smp   , 0, 0, ""     , 0, 17, "SOUND SAMPLE DATA")
  CHECK(wve   , 0, 0, ""     , 0, 15, "ALawSoundFile**")
  CHECK(gsrt  , 0, 0, ""     , 16, 9, "ring.bin")
  CHECK(amr-wb, 0, 0, ""     , 0,  9, "#!AMR-WB\n")
  CHECK(prc   , 0, 0, ""     , 0,  8, "\x37\x00\x00\x10\x6d\x00\x00\x10")
  CHECK(sph   , 0, 0, ""     , 0,  7, "NIST_1A")
  CHECK(amr-nb, 0, 0, ""     , 0,  6, "#!AMR\n")
  CHECK(txw   , 0, 0, ""     , 0,  6, "LM8953")
  CHECK(sndt  , 0, 0, ""     , 0,  6, "SOUND\x1a")
  CHECK(vorbis, 0, 4, "OggS" , 29, 6, "vorbis")
  CHECK(opus  , 0, 4, "OggS" , 28, 8, "OpusHead")
  CHECK(speex , 0, 4, "OggS" , 28, 6, "Speex")
  CHECK(hcom  ,65, 4, "FSSD" , 128,4, "HCOM")
  CHECK(wav   , 0, 4, "RIFF" , 8,  4, "WAVE")
  CHECK(wav   , 0, 4, "RIFX" , 8,  4, "WAVE")
  CHECK(wav   , 0, 4, "RF64" , 8,  4, "WAVE")
  CHECK(aiff  , 0, 4, "FORM" , 8,  4, "AIFF")
  CHECK(aifc  , 0, 4, "FORM" , 8,  4, "AIFC")
  CHECK(8svx  , 0, 4, "FORM" , 8,  4, "8SVX")
  CHECK(maud  , 0, 4, "FORM" , 8,  4, "MAUD")
  CHECK(xa    , 0, 0, ""     , 0,  4, "XA\0\0")
  CHECK(xa    , 0, 0, ""     , 0,  4, "XAI\0")
  CHECK(xa    , 0, 0, ""     , 0,  4, "XAJ\0")
  CHECK(au    , 0, 0, ""     , 0,  4, ".snd")
  CHECK(au    , 0, 0, ""     , 0,  4, "dns.")
  CHECK(au    , 0, 0, ""     , 0,  4, "\0ds.")
  CHECK(au    , 0, 0, ""     , 0,  4, ".sd\0")
  CHECK(flac  , 0, 0, ""     , 0,  4, "fLaC")
  CHECK(avr   , 0, 0, ""     , 0,  4, "2BIT")
  CHECK(caf   , 0, 0, ""     , 0,  4, "caff")
  CHECK(wv    , 0, 0, ""     , 0,  4, "wvpk")
  CHECK(paf   , 0, 0, ""     , 0,  4, " paf")
  CHECK(sf    , 0, 0, ""     , 0,  4, "\144\243\001\0")
  CHECK(sf    , 0, 0, ""     , 0,  4, "\0\001\243\144")
  CHECK(sf    , 0, 0, ""     , 0,  4, "\144\243\002\0")
  CHECK(sf    , 0, 0, ""     , 0,  4, "\0\002\243\144")
  CHECK(sf    , 0, 0, ""     , 0,  4, "\144\243\003\0")
  CHECK(sf    , 0, 0, ""     , 0,  4, "\0\003\243\144")
  CHECK(sf    , 0, 0, ""     , 0,  4, "\144\243\004\0")
  CHECK(sox   , 0, 0, ""     , 0,  4, ".SoX")
  CHECK(sox   , 0, 0, ""     , 0,  4, "XoS.")

  if (ext && !strcasecmp(ext, "snd"))
  CHECK(sndr  , 7, 1, ""     , 0,  2, "\0")
  #undef CHECK

#if HAVE_MAGIC
  if (sox_globals.use_magic) {
    static magic_t magic;
    char const * filetype = NULL;
    if (!magic) {
      magic = magic_open(MAGIC_MIME | MAGIC_SYMLINK);
      if (magic)
        magic_load(magic, NULL);
    }
    if (magic)
      filetype = magic_buffer(magic, data, len);
    if (filetype && strncmp(filetype, "application/octet-stream", (size_t)24) &&
          !lsx_strends(filetype, "/unknown") &&
          strncmp(filetype, "text/plain", (size_t)10) )
      return filetype;
    else if (filetype)
      lsx_debug("libmagic detected %s", filetype);
  }
#endif
  return NULL;
}
Exemplo n.º 6
0
static int startread(sox_format_t * ft)
{
    priv_t * avr = (priv_t *)ft->priv;
    int rc;

    lsx_reads(ft, avr->magic, (size_t)4);

    if (strncmp (avr->magic, AVR_MAGIC, (size_t)4)) {
        lsx_fail_errno(ft,SOX_EHDR,"AVR: unknown header");
        return(SOX_EOF);
    }

    lsx_readbuf(ft, avr->name, sizeof(avr->name));

    lsx_readw (ft, &(avr->mono));
    if (avr->mono) {
        ft->signal.channels = 2;
    }
    else {
        ft->signal.channels = 1;
    }

    lsx_readw (ft, &(avr->rez));
    if (avr->rez == 8) {
        ft->encoding.bits_per_sample = 8;
    }
    else if (avr->rez == 16) {
        ft->encoding.bits_per_sample = 16;
    }
    else {
        lsx_fail_errno(ft,SOX_EFMT,"AVR: unsupported sample resolution");
        return(SOX_EOF);
    }

    lsx_readw (ft, &(avr->sign));
    if (avr->sign) {
        ft->encoding.encoding = SOX_ENCODING_SIGN2;
    }
    else {
        ft->encoding.encoding = SOX_ENCODING_UNSIGNED;
    }

    lsx_readw (ft, &(avr->loop));

    lsx_readw (ft, &(avr->midi));

    lsx_readdw (ft, &(avr->rate));
    /*
     * No support for AVRs created by ST-Replay,
     * Replay Proffesional and PRO-Series 12.
     *
     * Just masking the upper byte out.
     */
    ft->signal.rate = (avr->rate & 0x00ffffff);

    lsx_readdw (ft, &(avr->size));

    lsx_readdw (ft, &(avr->lbeg));

    lsx_readdw (ft, &(avr->lend));

    lsx_readw (ft, &(avr->res1));

    lsx_readw (ft, &(avr->res2));

    lsx_readw (ft, &(avr->res3));

    lsx_readbuf(ft, avr->ext, sizeof(avr->ext));

    lsx_readbuf(ft, avr->user, sizeof(avr->user));

    rc = lsx_rawstartread (ft);
    if (rc)
        return rc;

    return(SOX_SUCCESS);
}
Exemplo n.º 7
0
/*-----------------------------------------------------------------
 * startread() -- start reading a VOC file
 *-----------------------------------------------------------------*/
static int startread(sox_format_t * ft)
{
  int rtn = SOX_SUCCESS;
  char header[20];
  priv_t * v = (priv_t *) ft->priv;
  unsigned short sbseek;
  int rc;
  int ii;                       /* for getting rid of lseek */
  unsigned char uc;

  if (lsx_readbuf(ft, header, (size_t)20) != 20) {
    lsx_fail_errno(ft, SOX_EHDR, "unexpected EOF in VOC header");
    return (SOX_EOF);
  }
  if (strncmp(header, "Creative Voice File\032", (size_t)19)) {
    lsx_fail_errno(ft, SOX_EHDR, "VOC file header incorrect");
    return (SOX_EOF);
  }

  /* read the offset to data, from start of file */
  /* after this read we have read 20 bytes of header + 2 */
  lsx_readw(ft, &sbseek);

  /* ANN:  read to skip the header, instead of lseek */
  /* this should allow use with pipes.... */
  for (ii = 22; ii < sbseek; ii++)
    lsx_readb(ft, &uc);

  v->rate = -1;
  v->block_remaining = 0;
  v->total_size = 0;    /* ANN added */
  v->extended = 0;

  /* read until we get the format information.... */
  rc = getblock(ft);
  if (rc)
    return rc;

  /* get rate of data */
  if (v->rate == -1) {
    lsx_fail_errno(ft, SOX_EOF, "Input .voc file had no sound!");
    return (SOX_EOF);
  }

  /* setup word length of data */

  /* ANN:  Check VOC format and map to the proper libSoX format value */
  switch (v->format) {
    case VOC_FMT_LIN8U:        /*     0    8 bit unsigned linear PCM */
      ft->encoding.encoding = SOX_ENCODING_UNSIGNED;
      v->size = 8;
      break;
    case VOC_FMT_CRLADPCM4:    /*     1    Creative 8-bit to 4-bit ADPCM */
      ft->encoding.encoding = SOX_ENCODING_CL_ADPCM;
      v->size = 4;
      break;
    case VOC_FMT_CRLADPCM3:    /*     2    Creative 8-bit to 3-bit ADPCM */
      ft->encoding.encoding = SOX_ENCODING_CL_ADPCM;
      v->size = 3;
      break;
    case VOC_FMT_CRLADPCM2:    /*     3    Creative 8-bit to 2-bit ADPCM */
      ft->encoding.encoding = SOX_ENCODING_CL_ADPCM;
      v->size = 2;
      break;
    case VOC_FMT_LIN16:        /*     4    16-bit signed PCM */
      ft->encoding.encoding = SOX_ENCODING_SIGN2;
      v->size = 16;
      break;
    case VOC_FMT_ALAW: /*     6    CCITT a-Law 8-bit PCM */
      ft->encoding.encoding = SOX_ENCODING_ALAW;
      v->size = 8;
      break;
    case VOC_FMT_MU255:        /*     7    CCITT u-Law 8-bit PCM */
      ft->encoding.encoding = SOX_ENCODING_ULAW;
      v->size = 8;
      break;
    case VOC_FMT_CRLADPCM4A:   /*0x200    Creative 16-bit to 4-bit ADPCM */
      ft->encoding.encoding = SOX_ENCODING_CL_ADPCM16;
      v->size = 4;
      break;
    default:
      lsx_fail("Unknown VOC format %d", v->format);
      rtn = SOX_EOF;
      break;
  }
  ft->encoding.bits_per_sample = v->size;

  /* setup number of channels */
  if (ft->signal.channels == 0)
    ft->signal.channels = v->channels;

  return (SOX_SUCCESS);
}
Exemplo n.º 8
0
static int sox_mp3seek(sox_format_t * ft, uint64_t offset)
{
  priv_t   * p = (priv_t *) ft->priv;
  size_t   initial_bitrate = p->Frame.header.bitrate;
  size_t   tagsize = 0, consumed = 0;
  sox_bool vbr = sox_false; /* Variable Bit Rate */
  sox_bool depadded = sox_false;
  uint64_t to_skip_samples = 0;

  /* Reset all */
  lsx_rewind(ft);
  mad_timer_reset(&p->Timer);
  p->FrameCount = 0;

  /* They where opened in startread */
  mad_synth_finish(&p->Synth);
  p->mad_frame_finish(&p->Frame);
  p->mad_stream_finish(&p->Stream);

  p->mad_stream_init(&p->Stream);
  p->mad_frame_init(&p->Frame);
  p->mad_synth_init(&p->Synth);

  offset /= ft->signal.channels;
  to_skip_samples = offset;

  while(sox_true) {  /* Read data from the MP3 file */
    size_t padding = 0;
    size_t read;
    size_t leftover = p->Stream.bufend - p->Stream.next_frame;

    memcpy(p->mp3_buffer, p->Stream.this_frame, leftover);
    read = lsx_readbuf(ft, p->mp3_buffer + leftover, p->mp3_buffer_size - leftover);
    if (read == 0) {
      lsx_debug("seek failure. unexpected EOF (frames=%" PRIuPTR " leftover=%" PRIuPTR ")", p->FrameCount, leftover);
      break;
    }
    for (; !depadded && padding < read && !p->mp3_buffer[padding]; ++padding);
    depadded = sox_true;
    p->mad_stream_buffer(&p->Stream, p->mp3_buffer + padding, leftover + read - padding);

    while (sox_true) {  /* Decode frame headers */
      static unsigned short samples;
      p->Stream.error = MAD_ERROR_NONE;

      /* Not an audio frame */
      if (p->mad_header_decode(&p->Frame.header, &p->Stream) == -1) {
        if (p->Stream.error == MAD_ERROR_BUFLEN)
          break;  /* Normal behaviour; get some more data from the file */
        if (!MAD_RECOVERABLE(p->Stream.error)) {
          lsx_warn("unrecoverable MAD error");
          break;
        }
        if (p->Stream.error == MAD_ERROR_LOSTSYNC) {
          unsigned available = (p->Stream.bufend - p->Stream.this_frame);
          tagsize = tagtype(p->Stream.this_frame, (size_t) available);
          if (tagsize) {   /* It's some ID3 tags, so just skip */
            if (tagsize >= available) {
              lsx_seeki(ft, (off_t)(tagsize - available), SEEK_CUR);
              depadded = sox_false;
            }
            p->mad_stream_skip(&p->Stream, min(tagsize, available));
          }
          else lsx_warn("MAD lost sync");
        }
        else lsx_warn("recoverable MAD error");
        continue;
      }

      consumed += p->Stream.next_frame - p->Stream.this_frame;
      vbr      |= (p->Frame.header.bitrate != initial_bitrate);

      samples = 32 * MAD_NSBSAMPLES(&p->Frame.header);

      p->FrameCount++;
      p->mad_timer_add(&p->Timer, p->Frame.header.duration);

      if(to_skip_samples <= samples)
      {
        p->mad_frame_decode(&p->Frame,&p->Stream);
        p->mad_synth_frame(&p->Synth, &p->Frame);
        p->cursamp = to_skip_samples;
        return SOX_SUCCESS;
      }
      else to_skip_samples -= samples;

      /* If not VBR, we can extrapolate frame size */
      if (p->FrameCount == 64 && !vbr) {
        p->FrameCount = offset / samples;
        to_skip_samples = offset % samples;

        if (SOX_SUCCESS != lsx_seeki(ft, (off_t)(p->FrameCount * consumed / 64 + tagsize), SEEK_SET))
          return SOX_EOF;

        /* Reset Stream for refilling buffer */
        p->mad_stream_finish(&p->Stream);
        p->mad_stream_init(&p->Stream);
        break;
      }
    }
  };

  return SOX_EOF;
}
Exemplo n.º 9
0
static int start_read(sox_format_t * ft)
{
  unsigned long header_size_ul = 0, num_samples_ul = 0;
  sox_encoding_t encoding = SOX_ENCODING_SIGN2;
  size_t     header_size, bytes_read;
  size_t     num_samples = 0;
  unsigned       bytes_per_sample = 0;
  unsigned       channels = 1;
  unsigned       rate = 16000;
  char           fldname[64], fldtype[16], fldsval[128];
  char           * buf;

  /* Magic header */
  if (lsx_reads(ft, fldname, (size_t)8) || strncmp(fldname, "NIST_1A", (size_t)7) != 0) {
    lsx_fail_errno(ft, SOX_EHDR, "Sphere header does not begin with magic word `NIST_1A'");
    return (SOX_EOF);
  }

  if (lsx_reads(ft, fldsval, (size_t)8)) {
    lsx_fail_errno(ft, SOX_EHDR, "Error reading Sphere header");
    return (SOX_EOF);
  }

  /* Determine header size, and allocate a buffer large enough to hold it. */
  sscanf(fldsval, "%lu", &header_size_ul);
  buf = lsx_malloc(header_size = header_size_ul);

  /* Skip what we have read so far */
  header_size -= 16;

  if (lsx_reads(ft, buf, header_size) == SOX_EOF) {
    lsx_fail_errno(ft, SOX_EHDR, "Error reading Sphere header");
    free(buf);
    return (SOX_EOF);
  }

  header_size -= (strlen(buf) + 1);

  while (strncmp(buf, "end_head", (size_t)8) != 0) {
    if (strncmp(buf, "sample_n_bytes", (size_t)14) == 0)
      sscanf(buf, "%63s %15s %u", fldname, fldtype, &bytes_per_sample);
    else if (strncmp(buf, "channel_count", (size_t)13) == 0)
      sscanf(buf, "%63s %15s %u", fldname, fldtype, &channels);
    else if (strncmp(buf, "sample_count ", (size_t)13) == 0)
      sscanf(buf, "%53s %15s %lu", fldname, fldtype, &num_samples_ul);
    else if (strncmp(buf, "sample_rate ", (size_t)12) == 0)
      sscanf(buf, "%53s %15s %u", fldname, fldtype, &rate);
    else if (strncmp(buf, "sample_coding", (size_t)13) == 0) {
      sscanf(buf, "%63s %15s %127s", fldname, fldtype, fldsval);
      if (!strcasecmp(fldsval, "ulaw") || !strcasecmp(fldsval, "mu-law"))
        encoding = SOX_ENCODING_ULAW;
      else if (!strcasecmp(fldsval, "pcm"))
        encoding = SOX_ENCODING_SIGN2;
      else {
        lsx_fail_errno(ft, SOX_EFMT, "sph: unsupported coding `%s'", fldsval);
        free(buf);
        return SOX_EOF;
      }
    }
    else if (strncmp(buf, "sample_byte_format", (size_t)18) == 0) {
      sscanf(buf, "%53s %15s %127s", fldname, fldtype, fldsval);
      if (strcmp(fldsval, "01") == 0)         /* Data is little endian. */
        ft->encoding.reverse_bytes = MACHINE_IS_BIGENDIAN;
      else if (strcmp(fldsval, "10") == 0)    /* Data is big endian. */
        ft->encoding.reverse_bytes = MACHINE_IS_LITTLEENDIAN;
      else if (strcmp(fldsval, "1")) {
        lsx_fail_errno(ft, SOX_EFMT, "sph: unsupported coding `%s'", fldsval);
        free(buf);
        return SOX_EOF;
      }
    }

    if (lsx_reads(ft, buf, header_size) == SOX_EOF) {
      lsx_fail_errno(ft, SOX_EHDR, "Error reading Sphere header");
      free(buf);
      return (SOX_EOF);
    }

    header_size -= (strlen(buf) + 1);
  }

  if (!bytes_per_sample)
    bytes_per_sample = encoding == SOX_ENCODING_ULAW? 1 : 2;

  while (header_size) {
    bytes_read = lsx_readbuf(ft, buf, header_size);
    if (bytes_read == 0) {
      free(buf);
      return (SOX_EOF);
    }
    header_size -= bytes_read;
  }
  free(buf);

  if (ft->seekable) {
    /* Check first four bytes of data to see if it's shorten compressed. */
    char           shorten_check[4];

    if (lsx_readchars(ft, shorten_check, sizeof(shorten_check)))
      return SOX_EOF;
    lsx_seeki(ft, -(off_t)sizeof(shorten_check), SEEK_CUR);

    if (!memcmp(shorten_check, "ajkg", sizeof(shorten_check))) {
      lsx_fail_errno(ft, SOX_EFMT,
                     "File uses shorten compression, cannot handle this.");
      return (SOX_EOF);
    }
  }

  num_samples = num_samples_ul;
  return lsx_check_read_params(ft, channels, (sox_rate_t)rate, encoding,
      bytes_per_sample << 3, (uint64_t)num_samples * channels, sox_true);
}