sox-devel@lists.sourceforge.net unofficial mirror
 help / color / mirror / code / Atom feed
From: Dave Lambley <dave.lambley@gmail.com>
To: sox-devel@lists.sourceforge.net
Subject: Re: scheduling sox-14.4.2 release
Date: Fri, 24 Oct 2014 00:25:50 +0100	[thread overview]
Message-ID: <CAKze8wuzgURy-bJax=kDL3wXqOqdoys1OwmbdxFSPaXeQjNjgw@mail.gmail.com> (raw)
In-Reply-To: <CAGzDe_YhAvN14q0JvVkjqZhiWRupPSWgaFc_+1=bxxtQ24_Ueg@mail.gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 1856 bytes --]

Hi,

I have a couple of patches which add RF64 support to SoX.  They've been in
the patch queue [*] for a while, can they make the forthcoming release?

RF64 is an EBU developed extension to the WAV file format to add support
for files larger than 4Gb.  The full spec is here,
http://tech.ebu.ch/docs/tech/tech3306-2009.pdf

rf64.patch -- Add read support for RF64 files.
sndfile_workaround.patch -- Extends this support to successfully read files
generated by a buggy version of libsndfile which was distributed with
Ubuntu 10.04 and probably elsewhere.

Best regards,
Dave Lambley

[*] https://sourceforge.net/p/sox/patches/99/

On 16 October 2014 02:56, Chris Bagwell <chris@cnpbagwell.com> wrote:

>
>
> On Sun, Oct 12, 2014 at 7:31 PM, Eric Wong <normalperson@yhbt.net> wrote:
>
>> Chris Bagwell <chris@cnpbagwell.com> wrote:
>> > I'm flexible if anyone has a feature they wanted to get in but here is
>> > rough schedule:
>>
>> Hi Chris, great to know a new release is on the way!
>>
>> I would like my LADSPA latency compensation patch looked at and
>> hopefully merged: https://sourceforge.net/p/sox/patches/101/
>>
>> I think that's it; haven't had much time for audio this year :x
>>
>>
> Hi Eric.  Let me push out the RC build until I have time to review your
> patch and try to incorporate it.  Hopefully done by this weekend.
>
> Thanks!
>
> Chris
>
>
>
> ------------------------------------------------------------------------------
> Comprehensive Server Monitoring with Site24x7.
> Monitor 10 servers for $9/Month.
> Get alerted through email, SMS, voice calls or mobile push notifications.
> Take corrective actions from your mobile device.
> http://p.sf.net/sfu/Zoho
> _______________________________________________
> SoX-devel mailing list
> SoX-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/sox-devel
>
>

[-- Attachment #1.2: Type: text/html, Size: 3208 bytes --]

[-- Attachment #2: rf64.patch --]
[-- Type: text/x-patch, Size: 10486 bytes --]

diff --git a/src/formats.c b/src/formats.c
index 1a8c503..724a4cd 100644
--- a/src/formats.c
+++ b/src/formats.c
@@ -62,6 +62,7 @@ static char const * auto_detect_format(sox_format_t * ft, char const * ext)
   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")
diff --git a/src/wav.c b/src/wav.c
index d714ccf..cf74aae 100644
--- a/src/wav.c
+++ b/src/wav.c
@@ -94,6 +94,8 @@ typedef struct {
     gsm_signal     *gsmsample;
     int            gsmindex;
     size_t      gsmbytecount;    /* counts bytes written to data block */
+    sox_bool       isRF64;          /* True if file being read is a RF64 */
+    uint64_t       ds64_dataSize;   /* Size of data chunk from ds64 header */
 } priv_t;
 
 static char *wav_format_str(unsigned wFormatTag);
@@ -370,9 +372,13 @@ static void wavgsmstopwrite(sox_format_t * ft)
 /****************************************************************************/
 /* General Sox WAV file code                                                */
 /****************************************************************************/
-static int findChunk(sox_format_t * ft, const char *Label, uint32_t *len)
+static int findChunk(sox_format_t * ft, const char *Label, uint64_t *len)
 {
     char magic[5];
+    priv_t *wav = (priv_t *) ft->priv;
+    uint32_t len_tmp;
+
+    lsx_debug("Searching for %2x %2x %2x %2x", Label[0], Label[1], Label[2], Label[3]);
     for (;;)
     {
         if (lsx_reads(ft, magic, (size_t)4) == SOX_EOF)
@@ -382,24 +388,41 @@ static int findChunk(sox_format_t * ft, const char *Label, uint32_t *len)
             return SOX_EOF;
         }
         lsx_debug("WAV Chunk %s", magic);
-        if (lsx_readdw(ft, len) == SOX_EOF)
+        if (lsx_readdw(ft, &len_tmp) == SOX_EOF)
         {
             lsx_fail_errno(ft, SOX_EHDR, "WAVE file %s chunk is too short",
                           magic);
             return SOX_EOF;
         }
 
-        if (strncmp(Label, magic, (size_t)4) == 0)
+        if (len_tmp == 0xffffffff && wav->isRF64==sox_true)
+        {
+            /* Chunk length should come from ds64 header */
+            if (memcmp(magic, "data", (size_t)4)==0)
+            {
+                *len = wav->ds64_dataSize;
+            }
+            else
+            {
+                lsx_fail_errno(ft, SOX_EHDR, "Cannot yet read block sizes of arbitary RF64 chunks, cannot find chunk '%s'", Label);
+                return SOX_EOF;
+            }
+        }
+        else {
+            *len = len_tmp;
+        }
+
+        if (memcmp(Label, magic, (size_t)4) == 0)
             break; /* Found the given chunk */
 
-	/* Chunks are required to be word aligned. */
-	if ((*len) % 2) (*len)++;
+        /* Chunks are required to be word aligned. */
+        if ((*len) % 2) (*len)++;
 
         /* skip to next chunk */
         if (*len > 0 && lsx_seeki(ft, (off_t)(*len), SEEK_CUR) != SOX_SUCCESS)
         {
             lsx_fail_errno(ft,SOX_EHDR,
-                          "WAV chunk appears to have invalid size %d.", *len);
+                          "WAV chunk appears to have invalid size %ld.", *len);
             return SOX_EOF;
         }
     }
@@ -424,10 +447,11 @@ static int startread(sox_format_t * ft)
 {
     priv_t *       wav = (priv_t *) ft->priv;
     char        magic[5];
-    uint32_t    len;
+    uint64_t    len;
 
     /* wave file characteristics */
-    uint32_t      dwRiffLength;
+    uint64_t      qwRiffLength;
+    uint32_t      dwRiffLength_tmp;
     unsigned short wChannels;       /* number of channels */
     uint32_t      dwSamplesPerSecond; /* samples per second per channel */
     uint32_t      dwAvgBytesPerSec;/* estimate of bytes per second needed */
@@ -435,7 +459,7 @@ static int startread(sox_format_t * ft)
     uint32_t wFmtSize;
     uint16_t wExtSize = 0;    /* extended field for non-PCM */
 
-    uint32_t      dwDataLength;    /* length of sound data in bytes */
+    uint64_t      qwDataLength;    /* length of sound data in bytes */
     size_t    bytesPerBlock = 0;
     int    bytespersample;          /* bytes per sample (per channel */
     char text[256];
@@ -445,7 +469,7 @@ static int startread(sox_format_t * ft)
     wav->ignoreSize = ft->signal.length == SOX_IGNORE_LENGTH;
 
     if (lsx_reads(ft, magic, (size_t)4) == SOX_EOF || (strncmp("RIFF", magic, (size_t)4) != 0 &&
-                                             strncmp("RIFX", magic, (size_t)4) != 0))
+                                             strncmp("RIFX", magic, (size_t)4) != 0 && strncmp("RF64", magic, (size_t)4)!=0 ))
     {
         lsx_fail_errno(ft,SOX_EHDR,"WAVE: RIFF header not found");
         return SOX_EOF;
@@ -459,7 +483,17 @@ static int startread(sox_format_t * ft)
     }
     else ft->encoding.reverse_bytes = MACHINE_IS_BIGENDIAN;
 
-    lsx_readdw(ft, &dwRiffLength);
+    if (strncmp("RF64", magic, (size_t)4) == 0)
+    {
+        wav->isRF64 = sox_true;
+    }
+    else
+    {
+        wav->isRF64 = sox_false;
+    }
+
+    lsx_readdw(ft, &dwRiffLength_tmp);
+    qwRiffLength = dwRiffLength_tmp;
 
     if (lsx_reads(ft, magic, (size_t)4) == SOX_EOF || strncmp("WAVE", magic, (size_t)4))
     {
@@ -467,6 +501,21 @@ static int startread(sox_format_t * ft)
         return SOX_EOF;
     }
 
+    if (wav->isRF64 && findChunk(ft, "ds64", &len) != SOX_EOF) {
+        lsx_debug("Found ds64 header");
+
+        if (dwRiffLength_tmp==0xffffffff)
+        {
+            lsx_readqw(ft, &qwRiffLength);
+        }
+        else
+        {
+            lsx_skipbytes(ft, (size_t)8);
+        }
+        lsx_readqw(ft, &wav->ds64_dataSize);
+        lsx_skipbytes(ft, (size_t)len-16);
+    }
+
     /* Now look for the format chunk */
     if (findChunk(ft, "fmt ", &len) == SOX_EOF)
     {
@@ -804,8 +853,11 @@ static int startread(sox_format_t * ft)
         lsx_fail_errno(ft, SOX_EOF, "Could not find data chunk.");
         return SOX_EOF;
     }
-    dwDataLength = len;
-    if (dwDataLength == MS_UNSPEC) {
+
+    /* ds64 size will have been applied in findChunk */
+    qwDataLength = len;
+    /* XXX - does MS_UNSPEC apply to RF64 files? */
+    if (qwDataLength == MS_UNSPEC) {
       wav->ignoreSize = 1;
       lsx_debug("WAV Chunk data's length is value often used in pipes or 4G files.  Ignoring length.");
     }
@@ -819,9 +871,9 @@ static int startread(sox_format_t * ft)
 
     case WAVE_FORMAT_ADPCM:
         wav->numSamples =
-            lsx_ms_adpcm_samples_in((size_t)dwDataLength, (size_t)ft->signal.channels,
+            lsx_ms_adpcm_samples_in((size_t)qwDataLength, (size_t)ft->signal.channels,
                            (size_t)wav->blockAlign, (size_t)wav->samplesPerBlock);
-        lsx_debug_more("datalen %d, numSamples %lu",dwDataLength, (unsigned long)wav->numSamples);
+        lsx_debug_more("datalen %ld, numSamples %lu",qwDataLength, (unsigned long)wav->numSamples);
         wav->blockSamplesRemaining = 0;        /* Samples left in buffer */
         ft->signal.length = wav->numSamples*ft->signal.channels;
         break;
@@ -830,22 +882,22 @@ static int startread(sox_format_t * ft)
         /* Compute easiest part of number of samples.  For every block, there
            are samplesPerBlock samples to read. */
         wav->numSamples =
-            lsx_ima_samples_in((size_t)dwDataLength, (size_t)ft->signal.channels,
+            lsx_ima_samples_in((size_t)qwDataLength, (size_t)ft->signal.channels,
                          (size_t)wav->blockAlign, (size_t)wav->samplesPerBlock);
-        lsx_debug_more("datalen %d, numSamples %lu",dwDataLength, (unsigned long)wav->numSamples);
+        lsx_debug_more("datalen %ld, numSamples %lu",qwDataLength, (unsigned long)wav->numSamples);
         wav->blockSamplesRemaining = 0;        /* Samples left in buffer */
         lsx_ima_init_table();
         ft->signal.length = wav->numSamples*ft->signal.channels;
         break;
 
     case WAVE_FORMAT_GSM610:
-        wav->numSamples = ((dwDataLength / wav->blockAlign) * wav->samplesPerBlock);
+        wav->numSamples = ((qwDataLength / wav->blockAlign) * wav->samplesPerBlock);
         wavgsminit(ft);
         ft->signal.length = wav->numSamples*ft->signal.channels;
         break;
 
     default:
-        wav->numSamples = div_bits(dwDataLength, ft->encoding.bits_per_sample) / ft->signal.channels;
+        wav->numSamples = div_bits(qwDataLength, ft->encoding.bits_per_sample) / ft->signal.channels;
         ft->signal.length = wav->numSamples * ft->signal.channels;
     }
      
@@ -858,8 +910,8 @@ static int startread(sox_format_t * ft)
     lsx_debug("Reading Wave file: %s format, %d channel%s, %d samp/sec",
            wav_format_str(wav->formatTag), ft->signal.channels,
            wChannels == 1 ? "" : "s", dwSamplesPerSecond);
-    lsx_debug("        %d byte/sec, %d block align, %d bits/samp, %u data bytes",
-           dwAvgBytesPerSec, wav->blockAlign, wBitsPerSample, dwDataLength);
+    lsx_debug("        %d byte/sec, %d block align, %d bits/samp, %lu data bytes",
+           dwAvgBytesPerSec, wav->blockAlign, wBitsPerSample, qwDataLength);
 
     /* Can also report extended fmt information */
     switch (wav->formatTag)
@@ -924,8 +976,10 @@ static int startread(sox_format_t * ft)
                 }
                 else
                 {
-                    if (lsx_readdw(ft,&len) == SOX_EOF)
+                    uint32_t len_tmp;
+                    if (lsx_readdw(ft,&len_tmp) == SOX_EOF)
                         break;
+                    len = len_tmp;
                     if (strncmp(magic,"ICRD",(size_t)4) == 0)
                     {
                         lsx_debug("Chunk ICRD");
@@ -981,7 +1035,7 @@ static int startread(sox_format_t * ft)
                     }
                     else
                     {
-                        lsx_debug("Attempting to seek beyond unsupported chunk `%c%c%c%c' of length %d bytes", magic[0], magic[1], magic[2], magic[3], len);
+                        lsx_debug("Attempting to seek beyond unsupported chunk `%c%c%c%c' of length %ld bytes", magic[0], magic[1], magic[2], magic[3], len);
                         len = (len + 1) & ~1u;
                         lsx_seeki(ft, (off_t)len, SEEK_CUR);
                     }

[-- Attachment #3: sndfile_workaround.patch --]
[-- Type: text/x-patch, Size: 2483 bytes --]

diff --git a/src/wav.c b/src/wav.c
index 303a2f9..a0b2cc6 100644
--- a/src/wav.c
+++ b/src/wav.c
@@ -372,6 +372,44 @@ static void wavgsmstopwrite(sox_format_t * ft)
 /****************************************************************************/
 /* General Sox WAV file code                                                */
 /****************************************************************************/
+
+static int sndfile_workaround(uint64_t *len, sox_format_t *ft) {
+    char magic[5];
+    off_t here;
+
+    here = lsx_tell(ft);
+
+    lsx_debug("Attempting work around for bad ds64 length bug");
+
+    /* Seek to last four bytes of chunk, assuming size is correct. */
+    if (lsx_seeki(ft, (off_t)(*len)-4, SEEK_CUR) != SOX_SUCCESS)
+    {
+        lsx_fail_errno(ft, SOX_EHDR, "WAV chunk appears to have invalid size %ld.", *len);
+        return SOX_EOF;
+    }
+
+    /* Get the last four bytes to see if it is an "fmt " chunk */
+    if (lsx_reads(ft, magic, (size_t)4) == SOX_EOF)
+    {
+        lsx_fail_errno(ft,SOX_EHDR, "WAV chunk appears to have invalid size %ld.", *len);
+        return SOX_EOF;
+    }
+
+    /* Seek back to where we were, which won't work if you're piping */
+    if (lsx_seeki(ft, here, SEEK_SET)!=SOX_SUCCESS)
+    {
+        lsx_fail_errno(ft,SOX_EHDR, "Cannot seek backwards to work around possible broken header.");
+        return SOX_EOF;
+    }
+    if (memcmp(magic, "fmt ", (size_t)4)==0)
+    {
+        /* If the last four bytes were "fmt ", len is almost certainly four bytes too big. */
+        lsx_debug("File had libsndfile bug, working around tell=%ld", lsx_tell(ft));
+        *len -= 4;
+    }
+    return SOX_SUCCESS;
+}
+
 static int findChunk(sox_format_t * ft, const char *Label, uint64_t *len)
 {
     char magic[5];
@@ -412,6 +450,18 @@ static int findChunk(sox_format_t * ft, const char *Label, uint64_t *len)
             *len = len_tmp;
         }
 
+        /* Work around for a bug in libsndfile
+         * https://github.com/erikd/libsndfile/commit/7fa1c57c37844a9d44642ea35e6638238b8af19e#src/rf64.c
+           The ds64 chunk should be 0x1c bytes, not 0x20.
+         */
+        if ((*len) == 0x20 && memcmp(Label, "ds64", (size_t)4)==0)
+        {
+            int fail;
+            if ((fail = sndfile_workaround(len, ft)) != SOX_SUCCESS) {
+                return fail;
+            }
+        }
+
         if (memcmp(Label, magic, (size_t)4) == 0)
             break; /* Found the given chunk */
 

[-- Attachment #4: Type: text/plain, Size: 79 bytes --]

------------------------------------------------------------------------------

[-- Attachment #5: Type: text/plain, Size: 158 bytes --]

_______________________________________________
SoX-devel mailing list
SoX-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sox-devel

      reply	other threads:[~2014-10-23 23:26 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-06  3:17 scheduling sox-14.4.2 release Chris Bagwell
2014-10-13  0:31 ` Eric Wong
2014-10-16  1:56   ` Chris Bagwell
2014-10-23 23:25     ` Dave Lambley [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://lists.sourceforge.net/lists/listinfo/sox-devel

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAKze8wuzgURy-bJax=kDL3wXqOqdoys1OwmbdxFSPaXeQjNjgw@mail.gmail.com' \
    --to=sox-devel@lists.sourceforge.net \
    --cc=dave@lambley.me.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/sox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).