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