shithub: sox

Download patch

ref: 214a4aaa1bade3fda71e807bd1051d8813a9636b
parent: b5b04948bce38297bef0811a1d0e3fd6b6eb7616
author: cbagwell <cbagwell>
date: Sun Jun 16 23:00:54 EDT 2002

Adding in new PRC format

--- a/Changelog
+++ b/Changelog
@@ -28,6 +28,8 @@
     private sizes being to small.
   o Jimen Ching adds -d option to specify 64bit data size and changed
     Ulaw/Alaw encoding to default to 8bit data size if not specified.
+  o Bert van Leeuwen added a file handler for Psion record.app used
+    for System/Alarms in some Psion devices.
 
 sox-12.17.3
 -----------
--- a/Makefile.dos
+++ b/Makefile.dos
@@ -15,8 +15,8 @@
 FOBJ	= 8svx.obj adpcm.obj aiff.obj alsa.obj au.obj auto.obj \
           avr.obj cdr.obj cvsd.obj dat.obj g711.obj g721.obj g723_16.obj \
 	  g723_24.obj g723_40.obj g72x.obj gsm.obj \
-	  hcom.obj ima_rw.obj maud.obj mp3.obj nulfile.obj oss.obj raw.obj \
-	  sf.obj smp.obj sndrtool.obj sphere.obj sunaudio.obj \
+	  hcom.obj ima_rw.obj maud.obj mp3.obj nulfile.obj oss.obj prc.obj \
+	  raw.obj sf.obj smp.obj sndrtool.obj sphere.obj sunaudio.obj \
 	  tx16w.obj voc.obj vorbis.obj wav.obj wve.obj
 
 EOBJ	= avg.obj band.obj bandpass.obj breject.obj btrworth.obj chorus.obj \
--- a/Makefile.gcc
+++ b/Makefile.gcc
@@ -21,8 +21,9 @@
 
 FOBJ	= 8svx.o adpcm.o aiff.o alsa.o au.o auto.o avr.o cdr.o cvsd.o dat.o \
 	  g711.o g721.o g723_16.o g723_24.o g723_40.o g72x.o gsm.o hcom.o \
-	  ima_rw.o maud.o mp3.o nulfile.o oss.o raw.o sf.o smp.o sndrtool.o \
-	  sphere.o sunaudio.o tx16w.o voc.o vorbis.o wav.o wve.o
+	  ima_rw.o maud.o mp3.o nulfile.o oss.o prc.o raw.o sf.o smp.o \
+	  sndrtool.o sphere.o sunaudio.o tx16w.o voc.o vorbis.o \
+          wav.o wve.o
 
 EOBJ    = avg.o band.o bandpass.o breject.o btrworth.o chorus.o compand.o \
           copy.o dcshift.o deemphas.o earwax.o echo.o echos.o fade.o \
--- a/TODO
+++ b/TODO
@@ -1,9 +1,11 @@
 People are encouraged to pick some of these and implement it.  Send
 all patches to cbagwell@users.sourceforge.net.
 
+  o Add new PRC format in to auto.c
+
   o Still passing some options using CFLAGS instead of stconfig.h.
 
-  o Lots of effects are sing "double" to prevent overflow of
+  o Lots of effects are using "double" to prevent overflow of
     st_sample_t math.  With ststdint.h we now have a portable way
     of detecting uin64_t...  Use that when possible to speed up
     math (won't have to convert back and forth from int to float).
--- a/sox.1
+++ b/sox.1
@@ -478,6 +478,12 @@
 the highest quality samples your sound card can handle.  Example:
 .I -t ossdsp -w -s /dev/dsp
 .TP 10
+.B .prc
+Psion record.app
+.br
+Used in some Psion devices for System alarms.  This format is newer then
+the .wve format that is used in some Psion devices.
+.TP 10
 .B .sf
 IRCAM Sound Files.
 .br
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -46,8 +46,8 @@
 
 FOBJ	= 8svx.o adpcm.o aiff.o au.o auto.o avr.o cdr.o \
 	  cvsd.o dat.o g711.o g721.o g723_16.o g723_24.o g723_40.o \
-	  g72x.o gsm.o hcom.o ima_rw.o maud.o mp3.o nulfile.o raw.o sf.o \
-	  smp.o sndrtool.o sphere.o tx16w.o voc.o vorbis.o \
+	  g72x.o gsm.o hcom.o ima_rw.o maud.o mp3.o nulfile.o prc.o \
+	  raw.o sf.o smp.o sndrtool.o sphere.o tx16w.o voc.o vorbis.o \
 	  wav.o wve.o
 
 EOBJ	= avg.o band.o bandpass.o breject.o btrworth.o chorus.o compand.o \
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -132,6 +132,12 @@
 };
 #endif
 
+/* Psion .prc */
+static char *prcnames[] = {
+      "prc",
+      (char *) 0
+};
+
 static char *rawnames[] = {
         "raw",
         (char *) 0
@@ -242,7 +248,6 @@
       (char *) 0
 };
 
-
 st_format_t st_formats[] = {
     {aiffnames,
         ST_FILE_STEREO | ST_FILE_LOOPS | ST_FILE_SEEK,
@@ -314,6 +319,9 @@
         st_ossdspstartread, st_rawread, st_rawstopread,
         st_ossdspstartwrite, st_rawwrite, st_rawstopwrite, st_format_nothing_seek},
 #endif
+    {prcnames, ST_FILE_SEEK,
+	st_prcstartread, st_prcread, st_rawstopread,
+	st_prcstartwrite, st_prcwrite, st_prcstopwrite, st_prcseek},
     {rawnames, ST_FILE_STEREO | ST_FILE_SEEK,
         st_rawstartread, st_rawread, st_rawstopread,
         st_rawstartwrite, st_rawwrite, st_rawstopwrite, st_rawseek},
--- /dev/null
+++ b/src/prc.c
@@ -1,0 +1,198 @@
+/*
+ * Psion record.app format (format of files needed for Revo,Revo+,Mako in 
+ * System/Alarms to provide new alarm sounds. Note that the file normally
+ * has no extension, so I've made it .prc for now (Psion ReCord), until
+ * somebody can come up with a better one. Also, I have absolutely no idea
+ * what the header format is, I just looked at a few files, saw they all
+ * had identical headers except for two places where the length words go,
+ * so its very likely that most of this is wrong. It has worked for me,
+ * however.
+ * Based (heavily) on the wve.c format file. 
+ * Hacked by Bert van Leeuwen (bert@e.co.za)
+ */
+
+#include "st_i.h"
+#include "g72x.h"
+#include <string.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+/* Magic numbers used in Psion audio files */
+#define PSION_PRC_HDRSIZE   72
+
+typedef struct prcpriv
+    {
+    uint32_t length;
+    short padding;
+    short repeats;
+      /*For seeking */
+        st_size_t dataStart;
+    } *prc_t;
+
+char header[]={
+  0x37,0x00,0x00,0x10,0x6d,0x00,0x00,0x10,
+  0x7e,0x00,0x00,0x10,0xcf,0xac,0x08,0x55,
+  0x14,0x00,0x00,0x00,0x04,0x52,0x00,0x00,
+  0x10,0x34,0x00,0x00,0x00,0x89,0x00,0x00,
+  0x10,0x25,0x00,0x00,0x00,0x7e,0x00,0x00,
+  0x10,0x2a,0x52,0x65,0x63,0x6f,0x72,0x64,
+  0x2e,0x61,0x70,0x70
+};
+
+static void prcwriteheader(ft_t ft);
+
+int st_prcseek(ft_t ft, st_size_t offset)
+{
+        prc_t prc = (prc_t ) ft->priv;
+
+        return st_seek(ft,offset*ft->info.size + prc->dataStart,SEEK_SET);
+}
+
+int st_prcstartread(ft_t ft)
+{
+        prc_t p = (prc_t ) ft->priv;
+        char head[sizeof(header)];
+        int rc;
+
+        uint16_t len;
+
+        /* Needed for rawread() */
+        rc = st_rawstartread(ft);
+        if (rc)
+            return rc;
+
+        /* PRC is in little endian format.  Swap whats read in
+         * on big endian machines.
+         */
+        if (ST_IS_LITTLEENDIAN)
+        {
+                ft->swap = ft->swap ? 1 : 0;
+        }
+
+        /* Check the header */
+        st_read(ft, head,1, sizeof(header));
+        if (memcmp(head, header, sizeof(header))==0) {
+                st_report("Found Psion record.app header");
+        }
+        else
+        {
+                st_fail_errno(ft,ST_EHDR,"Psion header doesn't start with the correct bytes\nTry the '.al' (A-law raw) file type with '-t al -r 8000 filename'");
+                return (ST_EOF);
+        }
+
+        st_readw(ft, &(len));
+	p->length=len;
+	st_report("Found length=%d",len);
+
+	/* dummy read rest */
+        st_read(ft, head,1,14+2+2);
+
+        ft->info.encoding = ST_ENCODING_ALAW;
+        ft->info.size = ST_SIZE_BYTE;
+
+        if (ft->info.rate != 0)
+            st_report("PRC must use 8000 sample rate.  Overriding");
+        ft->info.rate = 8000;
+
+        if (ft->info.channels != -1 && ft->info.channels != 1)
+            st_report("PRC must only supports 1 channel.  Overriding");
+        ft->info.channels = 1;
+
+        p->dataStart = ftell(ft->fp);
+        ft->length = p->length/ft->info.size;
+
+        return (ST_SUCCESS);
+}
+
+/* When writing, the header is supposed to contain the number of
+   data bytes written, unless it is written to a pipe.
+   Since we don't know how many bytes will follow until we're done,
+   we first write the header with an unspecified number of bytes,
+   and at the end we rewind the file and write the header again
+   with the right size.  This only works if the file is seekable;
+   if it is not, the unspecified size remains in the header
+   (this is illegal). */
+
+int st_prcstartwrite(ft_t ft)
+{
+        prc_t p = (prc_t ) ft->priv;
+        int rc;
+
+        /* Needed for rawwrite() */
+        rc = st_rawstartwrite(ft);
+        if (rc)
+            return ST_EOF;
+
+        /* prc is in little endian format.  Swap whats read in
+         * on big endian machines.
+         */
+        if (ST_IS_LITTLEENDIAN)
+        {
+                ft->swap = ft->swap ? 1 : 0;
+        }
+
+        p->length = 0;
+        if (p->repeats == 0)
+            p->repeats = 1;
+
+        if (ft->info.rate != 0)
+            st_report("PRC must use 8000 sample rate.  Overriding");
+
+        if (ft->info.channels != -1 && ft->info.channels != 1)
+            st_report("PRC must only supports 1 channel.  Overriding");
+
+        ft->info.encoding = ST_ENCODING_ALAW;
+        ft->info.size = ST_SIZE_BYTE;
+        ft->info.rate = 8000;
+
+        prcwriteheader(ft);
+        return ST_SUCCESS;
+}
+
+st_ssize_t st_prcread(ft_t ft, st_sample_t *buf, st_ssize_t samp)
+{
+        return st_rawread(ft, buf, samp);
+}
+
+st_ssize_t st_prcwrite(ft_t ft, st_sample_t *buf, st_ssize_t samp)
+{
+        prc_t p = (prc_t ) ft->priv;
+        p->length += samp * ft->info.size;
+	st_report("length now = %d", p->length);
+        return st_rawwrite(ft, buf, samp);
+}
+
+int st_prcstopwrite(ft_t ft)
+{
+
+        /* Call before seeking to flush buffer */
+        st_rawstopwrite(ft);
+
+        if (!ft->seekable)
+        {
+            st_warn("Header will be have invalid file length since file is not seekable");
+            return ST_SUCCESS;
+        }
+
+        if (fseek(ft->fp, 0L, 0) != 0)
+        {
+                st_fail_errno(ft,errno,"Can't rewind output file to rewrite Psion header.");
+                return(ST_EOF);
+        }
+        prcwriteheader(ft);
+}
+
+static void prcwriteheader(ft_t ft)
+{
+  char nullbuf[15];
+  prc_t p = (prc_t ) ft->priv;
+
+  st_report("Final length=%d",p->length);
+  memset(nullbuf,0,14);
+  st_write(ft, header, 1, sizeof(header));
+  st_writew(ft, p->length);
+  st_write(ft, nullbuf,1,14);
+  st_writew(ft, p->length);
+  st_write(ft, nullbuf,1,2);
+}
--- a/src/st_i.h
+++ b/src/st_i.h
@@ -248,6 +248,13 @@
 int st_ossdspstartwrite(ft_t ft);
 #endif
 
+int st_prcstartread(ft_t ft);
+st_ssize_t st_prcread(ft_t ft, st_sample_t *buf, st_ssize_t len);
+int st_prcstartwrite(ft_t ft);
+st_ssize_t st_prcwrite(ft_t ft, st_sample_t *buf, st_ssize_t len);
+int st_prcstopwrite(ft_t ft);
+int st_prcseek(ft_t ft, st_size_t offset);
+
 int st_rawstartread(ft_t ft);
 st_ssize_t st_rawread(ft_t ft, st_sample_t *buf, st_ssize_t nsamp);
 int st_rawstopread(ft_t ft);
--- a/src/testall.sh
+++ b/src/testall.sh
@@ -17,6 +17,7 @@
 t dat
 t hcom -r 22050
 t maud
+t prc
 t sf 
 t smp
 t sndt