ref: 2640ff882bb75deead9b7d66bd661b18d9fdb831
parent: 2e70428b90fcaa851427c3ebc557d9f4a8e19853
author: rrt <rrt>
date: Sat Nov 25 12:29:51 EST 2006
AIFF-C output support from shashimoto
--- a/src/aiff.c
+++ b/src/aiff.c
@@ -38,6 +38,10 @@
* Jul 12, 2000 - Leigh Smith <leigh@tomandandy.com>
* Replaced ANNO with COMT chunk writing headers and added COMT
* chunk reading
+ *
+ * Nov 24, 2006 - Shinji Hashimoto <sh@tw.tokai-tv.co.jp>
+ * added AIFF-C format output that is defined in DAVIC 1.4 Part 9 Annex B
+ * (usable for japanese-data-broadcasting, specified by ARIB STD-B24.)
*/
#include "st_i.h"
@@ -64,6 +68,7 @@
/* forward declarations */
static double read_ieee_extended(ft_t);
static int aiffwriteheader(ft_t, st_size_t);
+static int aifcwriteheader(ft_t, st_size_t);
static void write_ieee_extended(ft_t, double);
static double ConvertFromIeeeExtended(unsigned char*);
static void ConvertToIeeeExtended(double, char *);
@@ -188,7 +193,7 @@
else if (strncmp(buf, "NONE", 4) != 0)
{
buf[4] = 0;
- st_fail_errno(ft,ST_EHDR,"Can not support AIFC files that contain compressed data: %s",buf);
+ st_fail_errno(ft,ST_EHDR,"AIFC files that contain compressed data are not supported: %s",buf);
return(ST_EOF);
}
}
@@ -702,7 +707,7 @@
if (rc)
return rc;
- /* AIFF is in Big Endian format. Swap whats read in on Little */
+ /* AIFF is in Big Endian format. Swap what's read in on Little */
/* Endian machines. */
if (ST_IS_LITTLEENDIAN)
{
@@ -902,6 +907,125 @@
return(ST_SUCCESS);
}
+int st_aifcstartwrite(ft_t ft)
+{
+ aiff_t aiff = (aiff_t ) ft->priv;
+ int rc;
+
+ /* Needed because st_rawwrite() */
+ rc = st_rawstartwrite(ft);
+ if (rc)
+ return rc;
+
+ /* AIFC is in Big Endian format. Swap what's read in on Little */
+ /* Endian machines. */
+ if (ST_IS_LITTLEENDIAN)
+ {
+ ft->swap = ft->swap ? 0 : 1;
+ }
+
+ aiff->nsamples = 0;
+ if ((ft->info.encoding == ST_ENCODING_ULAW ||
+ ft->info.encoding == ST_ENCODING_ALAW) &&
+ ft->info.size == ST_SIZE_BYTE) {
+ st_report("expanding 8-bit u-law to signed 16 bits");
+ ft->info.encoding = ST_ENCODING_SIGN2;
+ ft->info.size = ST_SIZE_WORD;
+ }
+ if (ft->info.encoding != -1 && ft->info.encoding != ST_ENCODING_SIGN2)
+ st_report("AIFC only supports signed data. Forcing to signed.");
+ ft->info.encoding = ST_ENCODING_SIGN2; /* We have a fixed encoding */
+
+ /* Compute the "very large number" so that a maximum number
+ of samples can be transmitted through a pipe without the
+ risk of causing overflow when calculating the number of bytes.
+ 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, 0x7f000000L / (ft->info.size*ft->info.channels)));
+}
+
+int st_aifcstopwrite(ft_t ft)
+{
+ aiff_t aiff = (aiff_t ) ft->priv;
+ int rc;
+
+ /* Needed because of st_rawwrite(). Call now to flush
+ * buffer now before seeking around below.
+ */
+ rc = st_rawstopwrite(ft);
+ if (rc)
+ return rc;
+
+ if (!ft->seekable)
+ {
+ st_fail_errno(ft,ST_EOF,"Non-seekable file.");
+ return(ST_EOF);
+ }
+ if (st_seeki(ft, 0L, SEEK_SET) != 0)
+ {
+ st_fail_errno(ft,errno,"can't rewind output file to rewrite AIFC header");
+ return(ST_EOF);
+ }
+ return(aifcwriteheader(ft, aiff->nsamples / ft->info.channels));
+}
+
+static int aifcwriteheader(ft_t ft, st_size_t nframes)
+{
+ int hsize =
+ 12 /*FVER*/ + 8 /*COMM hdr*/ + 18+4+1+15 /*COMM chunk*/ +
+ 8 /*SSND hdr*/ + 12 /*SSND chunk*/;
+ int bits = 0;
+
+ if (ft->info.encoding == ST_ENCODING_SIGN2 &&
+ ft->info.size == ST_SIZE_BYTE)
+ bits = 8;
+ else if (ft->info.encoding == ST_ENCODING_SIGN2 &&
+ ft->info.size == ST_SIZE_WORD)
+ bits = 16;
+ else if (ft->info.encoding == ST_ENCODING_SIGN2 &&
+ ft->info.size == ST_SIZE_DWORD)
+ bits = 32;
+ else
+ {
+ st_fail_errno(ft,ST_EFMT,"unsupported output encoding/size for AIFC header");
+ return(ST_EOF);
+ }
+
+ st_writes(ft, "FORM"); /* IFF header */
+ /* file size */
+ st_writedw(ft, hsize + nframes * ft->info.size * ft->info.channels);
+ st_writes(ft, "AIFC"); /* File type */
+
+ /* FVER chunk */
+ st_writes(ft, "FVER");
+ st_writedw(ft, 4); /* FVER chunk size */
+ st_writedw(ft, 0xa2805140L); /* version_date(May23,1990,2:40pm) */
+
+ /* COMM chunk -- describes encoding (and #frames) */
+ st_writes(ft, "COMM");
+ st_writedw(ft, 18+4+1+15); /* COMM chunk size */
+ st_writew(ft, ft->info.channels); /* nchannels */
+ st_writedw(ft, nframes); /* number of frames */
+ st_writew(ft, bits); /* sample width, in bits */
+ write_ieee_extended(ft, (double)ft->info.rate);
+
+ st_writes(ft, "NONE"); /*compression_type*/
+ st_writeb(ft, 14);
+ st_writes(ft, "not compressed");
+ st_writeb(ft, 0);
+
+ /* SSND chunk -- describes data */
+ st_writes(ft, "SSND");
+ /* chunk size */
+ st_writedw(ft, 8 + nframes * ft->info.channels * ft->info.size);
+ st_writedw(ft, 0); /* offset */
+ st_writedw(ft, 0); /* block size */
+
+ /* Any Private chunks shall appear after the required chunks (FORM,FVER,COMM,SSND) */
+ return(ST_SUCCESS);
+}
+
static double read_ieee_extended(ft_t ft)
{
char buf[10];
@@ -1124,4 +1248,28 @@
const st_format_t *st_aiff_format_fn(void)
{
return &st_aiff_format;
+}
+
+static char *aifcnames[] = {
+ "aifc",
+ "aiffc",
+ NULL
+};
+
+static st_format_t st_aifc_format = {
+ aifcnames,
+ NULL,
+ ST_FILE_STEREO | ST_FILE_LOOPS | ST_FILE_SEEK,
+ st_aiffstartread,
+ st_aiffread,
+ st_aiffstopread,
+ st_aifcstartwrite,
+ st_aiffwrite,
+ st_aifcstopwrite,
+ st_aiffseek
+};
+
+const st_format_t *st_aifc_format_fn(void)
+{
+ return &st_aifc_format;
}
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -17,6 +17,7 @@
/* File format handlers. */
st_format_fn_t st_format_fns[] = {
st_aiff_format_fn,
+ st_aifc_format_fn,
st_al_format_fn,
#if defined(HAVE_ALSA)
st_alsa_format_fn,
--- a/src/st_i.h
+++ b/src/st_i.h
@@ -151,6 +151,7 @@
extern st_format_fn_t st_format_fns[];
extern const st_format_t *st_aiff_format_fn(void);
+extern const st_format_t *st_aifc_format_fn(void);
#ifdef HAVE_ALSA
extern const st_format_t *st_alsa_format_fn(void);
#endif
--- a/src/testall.bat
+++ b/src/testall.bat
@@ -26,6 +26,7 @@
call t.bat 8svx
call t.bat aiff
+call t.bat aifc
call t.bat au
call t.bat avr -u
call t.bat cdr
--- a/src/testall.sh
+++ b/src/testall.sh
@@ -10,6 +10,7 @@
}
t 8svx
t aiff
+t aifc
t au
t avr -u
t cdr
--- a/src/tests.sh
+++ b/src/tests.sh
@@ -44,10 +44,10 @@
format1=ub
rate=8012
-convertToAndFrom sb ub sw uw s3 u3 sl u4 raw dat au wav aiff flac al
+convertToAndFrom sb ub sw uw s3 u3 sl u4 raw dat au wav aiff aifc flac al
format1=sw
-convertToAndFrom sw uw s3 u3 sl u4 raw au wav aiff flac ul
+convertToAndFrom sw uw s3 u3 sl u4 raw au wav aiff aifc flac ul
format1=u3
convertToAndFrom s3 u3 sl u4 wav flac
@@ -62,7 +62,7 @@
convertToAndFrom ul sw uw sl raw dat
format1=Wav
-convertToAndFrom Wav 8svx aiff au avr dat maud sf smp
+convertToAndFrom Wav 8svx aiff aifc au avr dat maud sf smp
rate=5512
convertToAndFrom hcom
rate=8000