shithub: sox

Download patch

ref: e29e9ceb7c25a2d83c09bc8a601de117fc65563c
parent: fdfceb50375dd40150d5a4e91a55a8b027313500
author: Doug Cook <idigdoug@users.sourceforge.net>
date: Mon Mar 21 20:59:35 EDT 2011

Improved large file support

Thanks to Thor Andreassen for getting this started and helping with validation.

sox.h:
- Change SOX_IGNORE_LENGTH to uint64_t
- Change sox_signalinfo_t length to uint64_t
- Change sox_loopinfo_t start and length to uint64_t
- Change sox_format_t olength, tell_off, data_start to uint64_t
- Change sox_trim_get_start and sox_crop_get_start to return uint64_t

sox_i.h:
- Optimize lsx_swapw and lsx_swapdw to use MSVC built-in versions
- Change lsx_filelength to return uint64_t
- Change lsx_check_read_params to take uint64_t for num_samples parameter
- Change div_bits to return uint64_t instead of off_t
- Change lsx_rawstart parameter name for clarity

Formats minimally updated to try to be 64-bit aware; on overflow:
- aiff prints warning then stores UINT_MAX for file length
- aifc prints warning then stores UINT_MAX for file length
- au writes SUN_UNSPEC
- htk prints warning then stores UINT_MAX for file length
- mp3 prints warning then stores 0 for length if length is greater than
  ULONG_MAX. (Can this be improved for systems where long=32bits?)
- smp stores UINT_MAX for loop start and end and file header.
- wve stores 0 for file length

Crop, fade, and trim effects got some attention. Other effects were untouched.
Probably some additional work needed for validating effects on large files.

Additional work that could be done:
- improve warnings and validation when 64-bit values truncated to 32-bit
- fix lsx_parsesamples to use uint64_t
- replace off_t with int64_t

--- a/src/aiff.c
+++ b/src/aiff.c
@@ -26,8 +26,8 @@
 
 /* forward declarations */
 static double read_ieee_extended(sox_format_t *);
-static int aiffwriteheader(sox_format_t *, size_t);
-static int aifcwriteheader(sox_format_t *, size_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 *);
@@ -408,7 +408,7 @@
   reportInstrument(ft);
 
   return lsx_check_read_params(
-      ft, channels, rate, SOX_ENCODING_SIGN2, bits, (off_t)ssndsize, sox_false);
+      ft, channels, rate, SOX_ENCODING_SIGN2, bits, (uint64_t)ssndsize, sox_false);
 }
 
 /* print out the MIDI key allocations, loop points, directions etc */
@@ -582,7 +582,7 @@
            At 48 kHz, 16 bits stereo, this gives ~3 hours of audio.
            Sorry, the AIFF format does not provide for an indefinite
            number of samples. */
-        return(aiffwriteheader(ft, (size_t) 0x7f000000 / ((ft->encoding.bits_per_sample>>3)*ft->signal.channels)));
+        return(aiffwriteheader(ft, (uint64_t) 0x7f000000 / ((ft->encoding.bits_per_sample>>3)*ft->signal.channels)));
 }
 
 int lsx_aiffstopwrite(sox_format_t * ft)
@@ -608,7 +608,7 @@
         return(aiffwriteheader(ft, ft->olength / ft->signal.channels));
 }
 
-static int aiffwriteheader(sox_format_t * ft, size_t nframes)
+static int aiffwriteheader(sox_format_t * ft, uint64_t nframes)
 {
         int hsize =
                 8 /*COMM hdr*/ + 18 /*COMM chunk*/ +
@@ -615,6 +615,7 @@
                 8 /*SSND hdr*/ + 12 /*SSND chunk*/;
         unsigned bits = 0;
         unsigned i;
+        uint64_t size;
         size_t padded_comment_size = 0, comment_size = 0;
         size_t comment_chunk_size = 0;
         char * comment = lsx_cat_comments(ft->oob.comments);
@@ -660,7 +661,13 @@
 
         lsx_writes(ft, "FORM"); /* IFF header */
         /* file size */
-        lsx_writedw(ft, (unsigned) (hsize + nframes * (ft->encoding.bits_per_sample >> 3) * ft->signal.channels));
+        size = hsize + nframes * (ft->encoding.bits_per_sample >> 3) * ft->signal.channels;
+        if (size > UINT_MAX)
+        {
+            lsx_warn("file size too big for accurate AIFF header");
+            size = UINT_MAX;
+        }
+        lsx_writedw(ft, (unsigned)size);
         lsx_writes(ft, "AIFF"); /* File type */
 
         /* Now we write the COMT comment chunk using the precomputed sizes */
@@ -705,12 +712,18 @@
                 lsx_writew(ft, ft->oob.instr.nloops);
 
                 for(i = 0; i < ft->oob.instr.nloops; i++) {
+                        unsigned start = ft->oob.loops[i].start > UINT_MAX
+                            ? UINT_MAX
+                            : ft->oob.loops[i].start;
+                        unsigned end = ft->oob.loops[i].start + ft->oob.loops[i].length > UINT_MAX
+                            ? UINT_MAX
+                            : ft->oob.loops[i].start + ft->oob.loops[i].length;
                         lsx_writew(ft, i + 1);
-                        lsx_writedw(ft, (unsigned) ft->oob.loops[i].start);
+                        lsx_writedw(ft, start);
                         lsx_writeb(ft, 0);
                         lsx_writeb(ft, 0);
                         lsx_writew(ft, i*2 + 1);
-                        lsx_writedw(ft, (unsigned) (ft->oob.loops[i].start + ft->oob.loops[i].length));
+                        lsx_writedw(ft, end);
                         lsx_writeb(ft, 0);
                         lsx_writeb(ft, 0);
                 }
@@ -766,7 +779,7 @@
            At 48 kHz, 16 bits stereo, this gives ~3 hours of music.
            Sorry, the AIFC format does not provide for an "infinite"
            number of samples. */
-        return(aifcwriteheader(ft, (size_t) 0x7f000000 / ((ft->encoding.bits_per_sample >> 3)*ft->signal.channels)));
+        return(aifcwriteheader(ft, (uint64_t) 0x7f000000 / ((ft->encoding.bits_per_sample >> 3)*ft->signal.channels)));
 }
 
 int lsx_aifcstopwrite(sox_format_t * ft)
@@ -792,12 +805,13 @@
         return(aifcwriteheader(ft, ft->olength / ft->signal.channels));
 }
 
-static int aifcwriteheader(sox_format_t * ft, size_t nframes)
+static int aifcwriteheader(sox_format_t * ft, uint64_t nframes)
 {
         unsigned hsize =
                 12 /*FVER*/ + 8 /*COMM hdr*/ + 18+4+1+15 /*COMM chunk*/ +
                 8 /*SSND hdr*/ + 12 /*SSND chunk*/;
         unsigned bits = 0;
+        uint64_t size;
 
         if (ft->encoding.encoding == SOX_ENCODING_SIGN2 &&
             ft->encoding.bits_per_sample == 8)
@@ -819,7 +833,13 @@
 
         lsx_writes(ft, "FORM"); /* IFF header */
         /* file size */
-        lsx_writedw(ft, (unsigned) (hsize + nframes * (ft->encoding.bits_per_sample >> 3) * ft->signal.channels));
+        size = hsize + nframes * (ft->encoding.bits_per_sample >> 3) * ft->signal.channels;
+        if (size > UINT_MAX)
+        {
+            lsx_warn("file size too big for accurate AIFC header");
+            size = UINT_MAX;
+        }
+        lsx_writedw(ft, (unsigned)size);
         lsx_writes(ft, "AIFC"); /* File type */
 
         /* FVER chunk */
--- a/src/au.c
+++ b/src/au.c
@@ -197,12 +197,17 @@
   char * comment  = lsx_cat_comments(ft->oob.comments);
   size_t len      = strlen(comment) + 1;     /* Write out null-terminated */
   size_t info_len = max(4, (len + 3) & ~3u); /* Minimum & multiple of 4 bytes */
-  size_t size     = ft->olength? ft->olength : ft->signal.length;
   int i = ft->encoding.reverse_bytes == MACHINE_IS_BIGENDIAN? 2 : 0;
-  sox_bool error  = sox_false
+  uint64_t size64 = ft->olength ? ft->olength : ft->signal.length;
+  unsigned size = size64 == SOX_UNSPEC
+      ? SUN_UNSPEC
+      : size64*(ft->encoding.bits_per_sample >> 3) > UINT_MAX
+      ? SUN_UNSPEC
+      : (unsigned)(size64*(ft->encoding.bits_per_sample >> 3));
+  sox_bool error = sox_false
   ||lsx_writechars(ft, id[i].str, sizeof(id[i].str))
   ||lsx_writedw(ft, FIXED_HDR + (unsigned)info_len)
-  ||lsx_writedw(ft, (unsigned) (size != SOX_UNSPEC? size*(ft->encoding.bits_per_sample >> 3) : SUN_UNSPEC))
+  ||lsx_writedw(ft, size)
   ||lsx_writedw(ft, ft_enc(ft->encoding.bits_per_sample, ft->encoding.encoding))
   ||lsx_writedw(ft, (unsigned)(ft->signal.rate + .5))
   ||lsx_writedw(ft, ft->signal.channels)
--- a/src/cdr.c
+++ b/src/cdr.c
@@ -25,8 +25,8 @@
 
 static int stopwrite(sox_format_t * ft)
 {
-  size_t const sector_num_samples = 588 * ft->signal.channels;
-  size_t i = ft->olength % sector_num_samples;
+  unsigned const sector_num_samples = 588 * ft->signal.channels;
+  unsigned i = ft->olength % sector_num_samples;
 
   if (i) while (i++ < sector_num_samples)    /* Pad with silence to multiple */
     lsx_writew(ft, 0);                       /* of 1/75th of a second. */
--- a/src/crop.c
+++ b/src/crop.c
@@ -25,7 +25,7 @@
 
 typedef struct {
   int argc;
-  struct {int flag; char * str; size_t at;} pos[2];
+  struct {int flag; char * str; uint64_t at;} pos[2];
 } priv_t;
 
 static int parse(sox_effect_t * effp, char * * argv, sox_rate_t rate)
@@ -32,6 +32,7 @@
 {
   priv_t * p = (priv_t *)effp->priv;
   char const * s, * q;
+  size_t samples;
   int i;
 
   for (i = p->argc - 1; i == 0 || i == 1; --i) {
@@ -40,7 +41,10 @@
     s = p->pos[i].str;
     if (strchr("+-" + 1 - i, *s))
       p->pos[i].flag = *s++;
-    if (!(q = lsx_parsesamples(rate, s, &p->pos[i].at, 't')) || *q)
+
+    q = lsx_parsesamples(rate, s, &samples, 't');
+    p->pos[i].at = samples;
+    if (!q || *q)
       break;
   }
   return i >= 0 ? lsx_usage(effp) : SOX_SUCCESS;
@@ -59,7 +63,7 @@
   priv_t * p = (priv_t *)effp->priv;
   int i;
 
-  p->pos[1].at = SIZE_MAX / 2 / effp->in_signal.channels;
+  p->pos[1].at = ((uint64_t)(-1)) / 2 / effp->in_signal.channels;
   parse(effp, 0, effp->in_signal.rate); /* Re-parse now rate is known */
   for (i = 0; i < 2; ++i) {
     p->pos[i].at *= effp->in_signal.channels;
@@ -140,7 +144,7 @@
   return &handler;
 }
 
-size_t sox_crop_get_start(sox_effect_t * effp)
+uint64_t sox_crop_get_start(sox_effect_t * effp)
 {
   return ((priv_t *)effp->priv)->pos[0].at;
 }
--- a/src/fade.c
+++ b/src/fade.c
@@ -24,7 +24,7 @@
 
 /* Private data for fade file */
 typedef struct { /* These are measured as samples */
-    size_t in_start, in_stop, out_start, out_stop, samplesdone;
+    uint64_t in_start, in_stop, out_start, out_stop, samplesdone;
     char *in_stop_str, *out_start_str, *out_stop_str;
     char in_fadetype, out_fadetype;
     char do_out;
@@ -32,7 +32,7 @@
 } priv_t;
 
 /* prototypes */
-static double fade_gain(size_t index, size_t range, int fadetype);
+static double fade_gain(uint64_t index, uint64_t range, int fadetype);
 
 /*
  * Process options
@@ -47,6 +47,7 @@
     priv_t * fade = (priv_t *) effp->priv;
     char t_char[2];
     int t_argno;
+    size_t samples;
   --argc, ++argv;
 
     if (argc < 1 || argc > 4)
@@ -74,9 +75,10 @@
     fade->in_stop_str = lsx_malloc(strlen(argv[0])+1);
     strcpy(fade->in_stop_str,argv[0]);
     /* Do a dummy parse to see if it will fail */
-    if (lsx_parsesamples(0., fade->in_stop_str, &fade->in_stop, 't') == NULL)
+    if (lsx_parsesamples(0., fade->in_stop_str, &samples, 't') == NULL)
       return lsx_usage(effp);
 
+    fade->in_stop = samples;
     fade->out_start_str = fade->out_stop_str = 0;
 
     for (t_argno = 1; t_argno < argc && t_argno < 3; t_argno++)
@@ -89,8 +91,9 @@
 
             /* Do a dummy parse to see if it will fail */
             if (lsx_parsesamples(0., fade->out_stop_str,
-                                &fade->out_stop, 't') == NULL)
+                                &samples, 't') == NULL)
               return lsx_usage(effp);
+            fade->out_stop = samples;
         }
         else
         {
@@ -99,8 +102,9 @@
 
             /* Do a dummy parse to see if it will fail */
             if (lsx_parsesamples(0., fade->out_start_str,
-                                &fade->out_start, 't') == NULL)
+                                &samples, 't') == NULL)
               return lsx_usage(effp);
+            fade->out_start = samples;
         }
     } /* End for(t_argno) */
 
@@ -115,13 +119,15 @@
 {
     priv_t * fade = (priv_t *) effp->priv;
     sox_bool truncate = sox_false;
+    size_t samples;
 
     /* converting time values to samples */
     fade->in_start = 0;
     if (lsx_parsesamples(effp->in_signal.rate, fade->in_stop_str,
-                        &fade->in_stop, 't') == NULL)
+                        &samples, 't') == NULL)
       return lsx_usage(effp);
 
+    fade->in_stop = samples;
     fade->do_out = 0;
     /* See if user specified a stop time */
     if (fade->out_stop_str)
@@ -128,8 +134,9 @@
     {
         fade->do_out = 1;
         if (lsx_parsesamples(effp->in_signal.rate, fade->out_stop_str,
-                            &fade->out_stop, 't') == NULL)
+                            &samples, 't') == NULL)
           return lsx_usage(effp);
+        fade->out_stop = samples;
 
         if (!(truncate = !!fade->out_stop)) {
           fade->out_stop = effp->in_signal.length / effp->in_signal.channels;
@@ -143,11 +150,10 @@
         if (fade->out_start_str)
         {
             if (lsx_parsesamples(effp->in_signal.rate, fade->out_start_str,
-                        &fade->out_start, 't') == NULL)
+                        &samples, 't') == NULL)
               return lsx_usage(effp);
             /* Fade time is relative to stop time. */
-            fade->out_start = fade->out_stop - fade->out_start;
-
+            fade->out_start = fade->out_stop - samples;
         }
         else
             /* If user doesn't specify fade out length then
@@ -320,7 +326,7 @@
 /* Function returns gain value 0.0 - 1.0 according index / range ratio
 * and -1.0 if  type is invalid
 * todo: to optimize performance calculate gain every now and then and interpolate */
-static double fade_gain(size_t index, size_t range, int type)
+static double fade_gain(uint64_t index, uint64_t range, int type)
 {
     double retval = 0.0, findex = 0.0;
 
--- a/src/flac.c
+++ b/src/flac.c
@@ -45,7 +45,7 @@
   unsigned bits_per_sample;
   unsigned channels;
   unsigned sample_rate;
-  unsigned total_samples;
+  uint64_t total_samples;
 
   /* Decode buffer: */
   FLAC__int32 const * const * decoded_wide_samples;
--- a/src/formats_i.c
+++ b/src/formats_i.c
@@ -53,7 +53,7 @@
 
 int lsx_check_read_params(sox_format_t * ft, unsigned channels,
     sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample,
-    off_t num_samples, sox_bool check_length)
+    uint64_t num_samples, sox_bool check_length)
 {
   ft->signal.length = ft->signal.length == SOX_IGNORE_LENGTH? SOX_UNSPEC : num_samples;
 
@@ -77,7 +77,7 @@
   ft->encoding.bits_per_sample = bits_per_sample;
 
   if (check_length && ft->encoding.bits_per_sample && lsx_filelength(ft)) {
-    off_t calculated_length = div_bits(lsx_filelength(ft) - ft->data_start, ft->encoding.bits_per_sample);
+    uint64_t calculated_length = div_bits(lsx_filelength(ft) - ft->data_start, ft->encoding.bits_per_sample);
     if (!ft->signal.length)
       ft->signal.length = calculated_length;
     else if (num_samples != calculated_length)
@@ -138,12 +138,12 @@
   return ret;
 }
 
-size_t lsx_filelength(sox_format_t * ft)
+uint64_t lsx_filelength(sox_format_t * ft)
 {
   struct stat st;
   int ret = fstat(fileno(ft->fp), &st);
 
-  return (!ret && (st.st_mode & S_IFREG))? (size_t)st.st_size : 0;
+  return (!ret && (st.st_mode & S_IFREG))? (uint64_t)st.st_size : 0;
 }
 
 int lsx_flush(sox_format_t * ft)
@@ -153,7 +153,7 @@
 
 off_t lsx_tell(sox_format_t * ft)
 {
-  return ft->seekable? (ptrdiff_t)ftello(ft->fp) : ft->tell_off;
+  return ft->seekable? (off_t)ftello(ft->fp) : (off_t)ft->tell_off;
 }
 
 int lsx_eof(sox_format_t * ft)
--- a/src/gsrt.c
+++ b/src/gsrt.c
@@ -114,7 +114,7 @@
   lsx_skipbytes(ft, PADDING_SIZE);
 
   return lsx_check_read_params(ft, 1, 8000., encoding,
-      bits_per_sample, num_samples, sox_true);
+      bits_per_sample, (uint64_t)num_samples, sox_true);
 }
 
 static int start_write(sox_format_t * ft)
--- a/src/htk.c
+++ b/src/htk.c
@@ -43,16 +43,22 @@
     return SOX_EOF;
   }
   return lsx_check_read_params(ft, 1, 1e7 / period_100ns, SOX_ENCODING_SIGN2,
-      (unsigned)bytes_per_sample << 3, (off_t)num_samples, sox_true);
+      (unsigned)bytes_per_sample << 3, (uint64_t)num_samples, sox_true);
 }
 
 static int write_header(sox_format_t * ft)
 {
   double period_100ns = 1e7 / ft->signal.rate;
+  uint64_t len = ft->olength? ft->olength:ft->signal.length;
 
+  if (len > UINT_MAX)
+  {
+    lsx_warn("length greater than 32 bits - cannot fit actual length in header");
+    len = UINT_MAX;
+  }
   if (!ft->olength && floor(period_100ns) != period_100ns)
     lsx_warn("rounding sample period %f (x 100ns) to nearest integer", period_100ns);
-  return lsx_writedw(ft, (unsigned)(ft->olength? ft->olength:ft->signal.length))
+  return lsx_writedw(ft, (unsigned)len)
       || lsx_writedw(ft, (unsigned)(period_100ns + .5))
       || lsx_writew(ft, ft->encoding.bits_per_sample >> 3)
       || lsx_writew(ft, Waveform) ? SOX_EOF : SOX_SUCCESS;
--- a/src/mp3-util.h
+++ b/src/mp3-util.h
@@ -114,8 +114,9 @@
           free(utf8);
         }
       if ((utf8 = utf8_id3tag_findframe(tag, "TLEN", 0))) {
-        if (atoi((char *)utf8) > 0) {
-          ft->signal.length = atoi((char *)utf8); /* In ms; convert to samples later */
+        unsigned long tlen = strtoul((char *)utf8, NULL, 10);
+        if (tlen > 0 && tlen < ULONG_MAX) {
+          ft->signal.length= tlen; /* In ms; convert to samples later */
           lsx_debug("got exact duration from ID3 TLEN");
         }
         free(utf8);
--- a/src/mp3.c
+++ b/src/mp3.c
@@ -218,7 +218,7 @@
   lame_global_flags *gfp;
   float *pcm_buffer;
   size_t pcm_buffer_size;
-  unsigned long num_samples;
+  uint64_t num_samples;
   int vbr_tag;
   LSX_DLENTRIES_TO_PTRS(LAME_FUNC_ENTRIES, lame_dl);
 #endif /*HAVE_LAME*/
@@ -441,7 +441,7 @@
   if (ignore_length)
     ft->signal.length = SOX_UNSPEC;
   else {
-    ft->signal.length = (size_t)(ft->signal.length * .001 * ft->signal.rate + .5);
+    ft->signal.length = (uint64_t)(ft->signal.length * .001 * ft->signal.rate + .5);
     ft->signal.length *= ft->signal.channels;  /* Keep separate from line above! */
   }
 
@@ -740,7 +740,7 @@
   return id3v2_size;
 }
 
-static void rewrite_id3v2_tag(sox_format_t * ft, size_t id3v2_size, size_t num_samples)
+static void rewrite_id3v2_tag(sox_format_t * ft, size_t id3v2_size, uint64_t num_samples)
 {
   priv_t *p = (priv_t *)ft->priv;
   FILE *fp = ft->fp;
@@ -763,8 +763,13 @@
     return;
   }
 
-  p->lame_set_num_samples(p->gfp, num_samples);
-  lsx_debug("updated MP3 TLEN to %d samples", num_samples);
+  if (num_samples > ULONG_MAX)
+  {
+    lsx_warn("cannot accurately update track length info - file is too long");
+    num_samples = 0;
+  }
+  p->lame_set_num_samples(p->gfp, (unsigned long)num_samples);
+  lsx_debug("updated MP3 TLEN to %ld samples", (unsigned long)num_samples);
 
   new_size = p->lame_get_id3v2_tag(p->gfp, buffer, id3v2_size);
 
@@ -794,7 +799,7 @@
   free(buffer);
 }
 
-static void rewrite_tags(sox_format_t * ft, unsigned long num_samples)
+static void rewrite_tags(sox_format_t * ft, uint64_t num_samples)
 {
   priv_t *p = (priv_t *)ft->priv;
   FILE *fp = ft->fp;
@@ -889,7 +894,7 @@
   p->lame_set_msgf  (p->gfp,msgf);
 
   p->num_samples = ft->signal.length == SOX_IGNORE_LENGTH ? 0 : ft->signal.length / max(ft->signal.channels, 1);
-  p->lame_set_num_samples(p->gfp, p->num_samples);
+  p->lame_set_num_samples(p->gfp, p->num_samples > ULONG_MAX ? 0 : (unsigned long)p->num_samples);
 
   ft->signal.precision = MP3_LAME_PRECISION;
 
@@ -1093,7 +1098,7 @@
 static int stopwrite(sox_format_t * ft)
 {
   priv_t *p = (priv_t *) ft->priv;
-  unsigned long num_samples = ft->olength == SOX_IGNORE_LENGTH ? 0 : ft->olength / max(ft->signal.channels, 1);
+  uint64_t num_samples = ft->olength == SOX_IGNORE_LENGTH ? 0 : ft->olength / max(ft->signal.channels, 1);
   int written = p->lame_encode_flush(p->gfp, p->mp3_buffer, (int)p->mp3_buffer_size);
 
   if (written < 0)
--- a/src/smp.c
+++ b/src/smp.c
@@ -60,8 +60,8 @@
 
 /* Private data for SMP file */
 typedef struct {
-  uint32_t NoOfSamps;           /* Sample data count in words */
-  size_t dataStart;
+  uint64_t NoOfSamps;           /* Sample data count in words */
+  uint64_t dataStart;
   /* comment memory resides in private data because it's small */
   char comment[COMMENTLEN + NAMELEN + 3];
 } priv_t;
@@ -114,9 +114,13 @@
 
         for(i = 0; i < 8; i++) {        /* copy the 8 loops */
             if (ft->oob.loops[i].type != 0) {
-                trailer->loops[i].start = ft->oob.loops[i].start;
+                trailer->loops[i].start = ft->oob.loops[i].start > UINT_MAX
+                    ? UINT_MAX
+                    : ft->oob.loops[i].start;
                 /* to mark it as not set */
-                trailer->loops[i].end = ft->oob.loops[i].start + ft->oob.loops[i].length;
+                trailer->loops[i].end = ft->oob.loops[i].start + ft->oob.loops[i].length > UINT_MAX
+                    ? UINT_MAX
+                    : ft->oob.loops[i].start + ft->oob.loops[i].length;
                 trailer->loops[i].type = ft->oob.loops[i].type;
                 trailer->loops[i].count = ft->oob.loops[i].count;
             } else {
@@ -170,7 +174,8 @@
 
 static int sox_smpseek(sox_format_t * ft, uint64_t offset)
 {
-    size_t new_offset, channel_block, alignment;
+    uint64_t new_offset;
+    size_t channel_block, alignment;
     priv_t * smp = (priv_t *) ft->priv;
 
     new_offset = offset * (ft->encoding.bits_per_sample >> 3);
@@ -203,7 +208,9 @@
 {
         priv_t * smp = (priv_t *) ft->priv;
         int namelen, commentlen;
-        size_t samplestart, i;
+        off_t samplestart;
+        size_t i;
+        unsigned dw;
         struct smpheader header;
         struct smptrailer trailer;
 
@@ -245,7 +252,8 @@
         sox_append_comments(&ft->oob.comments, smp->comment);
 
         /* Extract out the sample size (always intel format) */
-        lsx_readdw(ft, &(smp->NoOfSamps));
+        lsx_readdw(ft, &dw);
+        smp->NoOfSamps = dw;
         /* mark the start of the sample data */
         samplestart = lsx_tell(ft);
 
@@ -391,7 +399,7 @@
                 lsx_fail_errno(ft,errno,"SMP unable to seek back to save size");
                 return(SOX_EOF);
         }
-        lsx_writedw(ft, smp->NoOfSamps);
+        lsx_writedw(ft, smp->NoOfSamps > UINT_MAX ? UINT_MAX : (unsigned)smp->NoOfSamps);
 
         return(SOX_SUCCESS);
 }
--- a/src/sndfile.c
+++ b/src/sndfile.c
@@ -236,7 +236,7 @@
   /* lsf excepts unbuffered I/O behavior for get_filelen() so force that */
   fflush(ft->fp);
 
-  return lsx_filelength((sox_format_t *)user_data);
+  return (sf_count_t)lsx_filelength((sox_format_t *)user_data);
 }
 
 static sf_count_t vio_seek(sf_count_t offset, int whence, void *user_data)
@@ -329,9 +329,9 @@
 }
 
 static int check_read_params(sox_format_t * ft, unsigned channels,
-    sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample, off_t length)
+    sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample, uint64_t length)
 {
-  ft->signal.length = (size_t)length;
+  ft->signal.length = length;
 
   if (channels && ft->signal.channels && ft->signal.channels != channels)
     lsx_warn("`%s': overriding number of channels", ft->filename);
@@ -407,7 +407,7 @@
 #endif
 
   return check_read_params(ft, (unsigned)sf->sf_info->channels, rate,
-      encoding, bits_per_sample, (off_t)(sf->sf_info->frames * sf->sf_info->channels));
+      encoding, bits_per_sample, (uint64_t)(sf->sf_info->frames * sf->sf_info->channels));
 }
 
 /*
--- a/src/soundtool.c
+++ b/src/soundtool.c
@@ -39,7 +39,7 @@
   }
   comments[text_field_len] = '\0'; /* Be defensive against incorrect files */
   sox_append_comments(&ft->oob.comments, comments);
-  return lsx_check_read_params(ft, 1, (sox_rate_t)rate, SOX_ENCODING_UNSIGNED, 8, (off_t)nsamples, sox_true);
+  return lsx_check_read_params(ft, 1, (sox_rate_t)rate, SOX_ENCODING_UNSIGNED, 8, (uint64_t)nsamples, sox_true);
 }
 
 static int write_header(sox_format_t * ft)
@@ -46,7 +46,7 @@
 {
   char * comment = lsx_cat_comments(ft->oob.comments);
   char text_buf[text_field_len];
-  size_t length = ft->olength? ft->olength:ft->signal.length;
+  uint64_t length = ft->olength? ft->olength:ft->signal.length;
 
   memset(text_buf, 0, sizeof(text_buf));
   strncpy(text_buf, comment, text_field_len - 1);
--- a/src/sox-fmt.c
+++ b/src/sox-fmt.c
@@ -68,7 +68,7 @@
   lsx_seeki(ft, (off_t)(headers_bytes - FIXED_HDR - comments_bytes), SEEK_CUR);
 
   return lsx_check_read_params(
-      ft, num_channels, rate, SOX_ENCODING_SIGN2, 32, (off_t)num_samples, sox_true);
+      ft, num_channels, rate, SOX_ENCODING_SIGN2, 32, num_samples, sox_true);
 }
 
 static int write_header(sox_format_t * ft)
--- a/src/sox.c
+++ b/src/sox.c
@@ -190,9 +190,9 @@
 static sox_encodinginfo_t combiner_encoding, ofile_encoding_options;
 static size_t mixing_clips = 0;
 static size_t current_input = 0;
-static unsigned long input_wide_samples = 0;
-static unsigned long read_wide_samples = 0;
-static unsigned long output_samples = 0;
+static uint64_t input_wide_samples = 0;
+static uint64_t read_wide_samples = 0;
+static uint64_t output_samples = 0;
 static sox_bool input_eof = sox_false;
 static sox_bool output_eof = sox_false;
 static sox_bool user_abort = sox_false;
@@ -277,7 +277,7 @@
   FILE * const output = sox_mode == sox_soxi? stdout : stderr;
   char const * text, * text2 = NULL;
   char buffer[30];
-  size_t ws = ft->signal.length / ft->signal.channels;
+  uint64_t ws = ft->signal.length / ft->signal.channels;
   (void)full;
 
   fprintf(output, "\n");
@@ -372,7 +372,7 @@
     ft->signal.precision);
 
   if (ft->signal.length && ft->signal.channels && ft->signal.rate) {
-    size_t ws = ft->signal.length / ft->signal.channels;
+    uint64_t ws = ft->signal.length / ft->signal.channels;
     char const * text, * text2 = NULL;
     fprintf(output,
         "Duration       : %s = %lu samples %c %g CDDA sectors\n",
@@ -1552,7 +1552,8 @@
 static void calculate_output_signal_parameters(void)
 {
   sox_bool known_length = combine_method != sox_sequence;
-  size_t i, olen = 0;
+  size_t i;
+  uint64_t olen = 0;
 
   /* Report all input files and gather info on differing rates & numbers of
    * channels, and on the resulting output audio length: */
@@ -1591,7 +1592,7 @@
 
   if (!known_length)
     olen = 0;
-  ofile->signal.length = (size_t)(olen * ofile->signal.channels * ofile->signal.rate / combiner_signal.rate + .5);
+  ofile->signal.length = (uint64_t)(olen * ofile->signal.channels * ofile->signal.rate / combiner_signal.rate + .5);
 }
 
 static void set_combiner_and_output_encoding_parameters(void)
@@ -2533,7 +2534,7 @@
 {
   sox_format_t * ft = sox_open_read(filename, NULL, NULL, NULL);
   double secs;
-  size_t ws;
+  uint64_t ws;
   char const * text = NULL;
 
   if (!ft)
--- a/src/sox.h
+++ b/src/sox.h
@@ -234,7 +234,7 @@
 typedef double sox_rate_t;
 
 #define SOX_UNSPEC 0 /* unknown value for signal parameter = 0 */
-#define SOX_IGNORE_LENGTH (size_t)(-1) /* unspecified length for signal.length = -1 */
+#define SOX_IGNORE_LENGTH (uint64_t)(-1) /* unspecified length for signal.length = -1 */
 
 /* Signal parameters; SOX_UNSPEC (= 0) if unknown */
 typedef struct sox_signalinfo_t {
@@ -241,7 +241,7 @@
   sox_rate_t       rate;         /* samples per second, 0 if unknown */
   unsigned         channels;     /* number of sound channels, 0 if unknown */
   unsigned         precision;    /* bits per sample, 0 if unknown */
-  size_t           length;       /* samples * chans in file, 0 if unknown, -1 if unspecified */
+  uint64_t         length;       /* samples * chans in file, 0 if unknown, -1 if unspecified */
   double           * mult;       /* Effects headroom multiplier; may be null */
 } sox_signalinfo_t;
 
@@ -356,8 +356,8 @@
 
 /* Looping parameters (out-of-band data) */
 typedef struct sox_loopinfo_t {
-  size_t    start;      /* first sample */
-  size_t    length;     /* length */
+  uint64_t  start;      /* first sample */
+  uint64_t  length;     /* length */
   unsigned  count;      /* number of repeats, 0=forever */
   uint8_t   type;       /* 0=no, 1=forward, 2=forward/back (see sox_loop_... for valid values) */
 } sox_loopinfo_t;
@@ -483,14 +483,14 @@
   sox_oob_t        oob;             /* comments, instrument info, loop info (out-of-band data) */
   sox_bool         seekable;        /* Can seek on this file */
   char             mode;            /* Read or write mode ('r' or 'w') */
-  size_t           olength;         /* Samples * chans written to file */
+  uint64_t         olength;         /* Samples * chans written to file */
   size_t           clips;           /* Incremented if clipping occurs */
   int              sox_errno;       /* Failure error code */
   char             sox_errstr[256]; /* Failure error text */
   FILE             * fp;            /* File stream pointer */
   lsx_io_type      io_type;         /* Stores whether this is a file, pipe or URL */
-  long             tell_off;        /* Current offset within file */
-  long             data_start;      /* Offset at which headers end and sound data begins (set by lsx_check_read_params) */
+  uint64_t         tell_off;        /* Current offset within file */
+  uint64_t         data_start;      /* Offset at which headers end and sound data begins (set by lsx_check_read_params) */
   sox_format_handler_t handler;     /* Format handler for this file */
   void             * priv;          /* Format handler's private data area */
 };
@@ -742,9 +742,9 @@
  * wants to trim and use a sox_seek() operation instead.  After
  * sox_seek()'ing, you should set the trim option to 0.
  */
-size_t sox_trim_get_start(sox_effect_t * effp);
+uint64_t sox_trim_get_start(sox_effect_t * effp);
 void sox_trim_clear_start(sox_effect_t * effp);
-size_t sox_crop_get_start(sox_effect_t * effp);
+uint64_t sox_crop_get_start(sox_effect_t * effp);
 void sox_crop_clear_start(sox_effect_t * effp);
 
 typedef int (* sox_playlist_callback_t)(void *, char *);
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -128,6 +128,9 @@
 #include <byteswap.h>
 #define lsx_swapw(x) bswap_16(x)
 #define lsx_swapdw(x) bswap_32(x)
+#elif defined(_MSC_VER)
+#define lsx_swapw(x) _byteswap_ushort(x)
+#define lsx_swapdw(x) _byteswap_ulong(x)
 #else
 #define lsx_swapw(uw) (((uw >> 8) | (uw << 8)) & 0xffff)
 #define lsx_swapdw(udw) ((udw >> 24) | ((udw >> 8) & 0xff00) | ((udw << 8) & 0xff0000) | (udw << 24))
@@ -198,7 +201,7 @@
 int lsx_flush(sox_format_t * ft);
 int lsx_seeki(sox_format_t * ft, off_t offset, int whence);
 int lsx_unreadb(sox_format_t * ft, unsigned ub);
-size_t lsx_filelength(sox_format_t * ft);
+uint64_t lsx_filelength(sox_format_t * ft);
 off_t lsx_tell(sox_format_t * ft);
 void lsx_clearerr(sox_format_t * ft);
 void lsx_rewind(sox_format_t * ft);
@@ -222,11 +225,11 @@
 
 int lsx_check_read_params(sox_format_t * ft, unsigned channels,
     sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample,
-    off_t num_samples, sox_bool check_length);
+    uint64_t num_samples, sox_bool check_length);
 #define LSX_FORMAT_HANDLER(name) \
 sox_format_handler_t const * lsx_##name##_format_fn(void); \
 sox_format_handler_t const * lsx_##name##_format_fn(void)
-#define div_bits(size, bits) (off_t)((double)(size) * 8 / bits)
+#define div_bits(size, bits) ((uint64_t)(size) * 8 / bits)
 
 /* Raw I/O */
 int lsx_rawstartread(sox_format_t * ft);
@@ -235,7 +238,7 @@
 int lsx_rawstartwrite(sox_format_t * ft);
 size_t lsx_rawwrite(sox_format_t * ft, const sox_sample_t *buf, size_t nsamp);
 int lsx_rawseek(sox_format_t * ft, uint64_t offset);
-int lsx_rawstart(sox_format_t * ft, sox_bool default_rate, sox_bool default_channels, sox_bool default_length, sox_encoding_t encoding, unsigned size);
+int lsx_rawstart(sox_format_t * ft, sox_bool default_rate, sox_bool default_channels, sox_bool default_length, sox_encoding_t encoding, unsigned bits_per_sample);
 #define lsx_rawstartread(ft) lsx_rawstart(ft, sox_false, sox_false, sox_false, SOX_ENCODING_UNKNOWN, 0)
 #define lsx_rawstartwrite lsx_rawstartread
 #define lsx_rawstopread NULL
--- a/src/sphere.c
+++ b/src/sphere.c
@@ -133,19 +133,19 @@
 
   num_samples = num_samples_ul;
   return lsx_check_read_params(ft, channels, (sox_rate_t)rate, encoding,
-      bytes_per_sample << 3, (off_t)(num_samples * channels), sox_true);
+      bytes_per_sample << 3, (uint64_t)num_samples * channels, sox_true);
 }
 
 static int write_header(sox_format_t * ft)
 {
   char buf[128];
-  long samples = (ft->olength ? ft->olength : ft->signal.length) / ft->signal.channels;
+  uint64_t samples = (ft->olength ? ft->olength : ft->signal.length) / ft->signal.channels;
 
   lsx_writes(ft, "NIST_1A\n");
   lsx_writes(ft, "   1024\n");
 
   if (samples) {
-    sprintf(buf, "sample_count -i %ld\n", samples);
+    sprintf(buf, "sample_count -i %lu\n", (unsigned long)samples);
     lsx_writes(ft, buf);
   }
 
--- a/src/trim.c
+++ b/src/trim.c
@@ -16,12 +16,12 @@
     sox_bool end_is_absolute;
 
     /* options converted to values */
-    size_t start;
-    size_t length;
+    uint64_t start;
+    uint64_t length;
 
     /* internal stuff */
-    size_t index;
-    size_t trimmed;
+    uint64_t index;
+    uint64_t trimmed;
 } priv_t;
 
 /*
@@ -31,6 +31,7 @@
 {
     char *end;
     priv_t * trim = (priv_t *) effp->priv;
+    size_t samples;
   --argc, ++argv;
 
     /* Do not know sample rate yet so hold off on completely parsing
@@ -46,14 +47,16 @@
             trim->end_str = lsx_malloc(strlen(end)+1);
             strcpy(trim->end_str, end);
             /* Do a dummy parse to see if it will fail */
-            if (lsx_parsesamples(0., trim->end_str, &trim->length, 't') == NULL)
+            if (lsx_parsesamples(0., trim->end_str, &samples, 't') == NULL)
               return lsx_usage(effp);
+            trim->length = samples;
         case 1:
             trim->start_str = lsx_malloc(strlen(argv[0])+1);
             strcpy(trim->start_str,argv[0]);
             /* Do a dummy parse to see if it will fail */
-            if (lsx_parsesamples(0., trim->start_str, &trim->start, 't') == NULL)
+            if (lsx_parsesamples(0., trim->start_str, &samples, 't') == NULL)
               return lsx_usage(effp);
+            trim->start = samples;
             break;
         default:
             return lsx_usage(effp);
@@ -68,16 +71,19 @@
 static int sox_trim_start(sox_effect_t * effp)
 {
     priv_t * trim = (priv_t *) effp->priv;
+    size_t samples;
 
     if (lsx_parsesamples(effp->in_signal.rate, trim->start_str,
-                        &trim->start, 't') == NULL)
+                        &samples, 't') == NULL)
       return lsx_usage(effp);
+    trim->start = samples;
 
     if (trim->end_str)
     {
         if (lsx_parsesamples(effp->in_signal.rate, trim->end_str,
-                    &trim->length, 't') == NULL)
+                    &samples, 't') == NULL)
           return lsx_usage(effp);
+        trim->length = samples;
         if (trim->end_is_absolute) {
             if (trim->length < trim->start) {
                 lsx_warn("end earlier than start");
@@ -175,7 +181,7 @@
     return (SOX_SUCCESS);
 }
 
-size_t sox_trim_get_start(sox_effect_t * effp)
+uint64_t sox_trim_get_start(sox_effect_t * effp)
 {
     priv_t * trim = (priv_t *)effp->priv;
     return trim->start;
--- a/src/wav.c
+++ b/src/wav.c
@@ -885,7 +885,7 @@
     }
 
     /* Horrible way to find Cool Edit marker points. Taken from Quake source*/
-    ft->oob.loops[0].start = ~0u;
+    ft->oob.loops[0].start = SOX_IGNORE_LENGTH;
     if(ft->seekable){
         /*Got this from the quake source.  I think it 32bit aligns the chunks
          * doubt any machine writing Cool Edit Chunks writes them at an odd
@@ -1615,7 +1615,7 @@
   if (ft->encoding.bits_per_sample & 7)
     lsx_fail_errno(ft, SOX_ENOTSUP, "seeking not supported with this encoding");
   else if (wav->formatTag == WAVE_FORMAT_GSM610) {
-    int new_offset, alignment;
+    int alignment;
     size_t gsmoff;
 
     /* rounding bytes to blockAlign so that we
@@ -1627,7 +1627,7 @@
     ft->sox_errno = lsx_seeki(ft, (off_t)(gsmoff + wav->dataStart), SEEK_SET);
     if (ft->sox_errno == SOX_SUCCESS) {
       /* offset is in samples */
-      new_offset = offset;
+      uint64_t new_offset = offset;
       alignment = offset % wav->samplesPerBlock;
       if (alignment != 0)
           new_offset += (wav->samplesPerBlock - alignment);
--- a/src/wavpack.c
+++ b/src/wavpack.c
@@ -45,7 +45,7 @@
 static int ft_unreadb(void * ft, int b) {
   return lsx_unreadb((sox_format_t *)ft, (unsigned)b);}
 static uint32_t ft_filelength(void * ft) {
-  return lsx_filelength((sox_format_t *)ft);}
+  return (uint32_t)lsx_filelength((sox_format_t *)ft);}
 static int ft_is_seekable(void *ft) {
   return ((sox_format_t *)ft)->seekable;}
 static int32_t ft_write_b_buf(void * ft, void * buf, int32_t len) {
@@ -71,7 +71,7 @@
     lsx_warn("`%s': overriding sample rate", ft->filename);
   else ft->signal.rate = WavpackGetSampleRate(p->codec);
 
-  ft->signal.length = WavpackGetNumSamples(p->codec) * ft->signal.channels;
+  ft->signal.length = (uint64_t)WavpackGetNumSamples(p->codec) * ft->signal.channels;
   ft->encoding.encoding = (WavpackGetMode(p->codec) & MODE_FLOAT)?
     SOX_ENCODING_WAVPACKF : SOX_ENCODING_WAVPACK;
   return SOX_SUCCESS;
@@ -105,6 +105,7 @@
 {
   priv_t * p = (priv_t *)ft->priv;
   WavpackConfig config;
+  uint64_t size64;
 
   p->codec = WavpackOpenFileOutput(ft_write_b_buf, ft, NULL);
   memset(&config, 0, sizeof(config));
@@ -115,7 +116,8 @@
   config.num_channels      = ft->signal.channels;
   config.sample_rate       = (int32_t)(ft->signal.rate + .5);
   config.flags = CONFIG_VERY_HIGH_FLAG;
-  if (!WavpackSetConfiguration(p->codec, &config, ft->signal.length? (uint32_t) ft->signal.length / ft->signal.channels : (uint32_t)-1)) {
+  size64 = ft->signal.length / ft->signal.channels;
+  if (!WavpackSetConfiguration(p->codec, &config, size64 && size64 <= UINT_MAX ? (uint32_t)size64 : (uint32_t)-1)) {
     lsx_fail_errno(ft, SOX_EHDR, "%s", WavpackGetErrorMessage(p->codec));
     return SOX_EOF;
   }
--- a/src/wve.c
+++ b/src/wve.c
@@ -35,13 +35,15 @@
     lsx_fail_errno(ft, SOX_EHDR, "wve: can't find Psion identifier");
     return SOX_EOF;
   }
-  return lsx_check_read_params(ft, 1, 8000., SOX_ENCODING_ALAW, 8, (off_t)num_samples, sox_true);
+  return lsx_check_read_params(ft, 1, 8000., SOX_ENCODING_ALAW, 8, (uint64_t)num_samples, sox_true);
 }
 
 static int write_header(sox_format_t * ft)
 {
+  uint64_t size64 = ft->olength? ft->olength:ft->signal.length;
+  unsigned size = size64 > UINT_MAX ? 0 : (unsigned)size64;
   return lsx_writechars(ft, ID1, sizeof(ID1))
-      || lsx_writedw(ft, (unsigned)(ft->olength? ft->olength:ft->signal.length))
+      || lsx_writedw(ft, size)
       || lsx_writechars(ft, ID2, sizeof(ID2))? SOX_EOF:SOX_SUCCESS;
 }