summaryrefslogtreecommitdiff
path: root/icedax/aiff.c
diff options
context:
space:
mode:
Diffstat (limited to 'icedax/aiff.c')
-rw-r--r--icedax/aiff.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/icedax/aiff.c b/icedax/aiff.c
new file mode 100644
index 0000000..cd1d98d
--- /dev/null
+++ b/icedax/aiff.c
@@ -0,0 +1,188 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)aiff.c 1.5 01/10/27 Copyright 1998,1999 Heiko Eissfeldt */
+/***
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Heiko Eissfeldt
+ *
+ *
+ * ---------------------------------------------------------------------
+ * definitions for aiff pcm output
+ * ---------------------------------------------------------------------
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <standard.h>
+#include <schily.h>
+#include "mytype.h"
+#include "byteorder.h"
+#include "sndfile.h"
+
+typedef UINT4 FOURCC; /* a four character code */
+typedef struct CHUNKHDR {
+ FOURCC ckid; /* chunk ID */
+ UINT4 dwSize; /* chunk size */
+} CHUNKHDR;
+
+#define mmioFOURCC(ch0, ch1, ch2, ch3) \
+ ((UINT4)(unsigned char)(ch3) | ((UINT4)(unsigned char)(ch2) << 8) | \
+ ((UINT4)(unsigned char)(ch1) << 16) | ((UINT4)(unsigned char)(ch0) << 24))
+
+#define FOURCC_FORM mmioFOURCC ('F', 'O', 'R', 'M')
+#define FOURCC_AIFF mmioFOURCC ('A', 'I', 'F', 'F')
+#define FOURCC_COMM mmioFOURCC ('C', 'O', 'M', 'M')
+#define FOURCC_SSND mmioFOURCC ('S', 'S', 'N', 'D')
+
+typedef struct AIFFHDR {
+ CHUNKHDR formChk;
+ FOURCC formType;
+
+ CHUNKHDR commChk; /* Common chunk */
+ /* from now on, alignment prevents us from using the original types :-(( */
+ unsigned char numChannels[2]; /* Audio Channels */
+ unsigned char numSampleFrames[4]; /* # of samples */
+ unsigned char samplesize[2]; /* bits per sample */
+ unsigned char sample_rate[10]; /* sample rate in extended float */
+
+ unsigned char ssndChkid[4]; /* Sound data chunk */
+ unsigned char dwSize[4]; /* size of chunk */
+ unsigned char offset[4]; /* start of 1st sample */
+ unsigned char blocksize[4]; /* aligned sound data block size */
+} AIFFHDR;
+
+static AIFFHDR AiffHdr;
+
+/* Prototypes */
+static int Format_samplerate(unsigned long rate, unsigned char the_rate[10]);
+static int InitSound(int audio, long channels, unsigned long rate,
+ long nBitsPerSample, unsigned long expected_bytes);
+static int ExitSound(int audio, unsigned long nBytesDone);
+static unsigned long GetHdrSize(void);
+static unsigned long InSizeToOutSize(unsigned long BytesToDo);
+
+
+/* format the sample rate into an
+ bigendian 10-byte IEEE-754 floating point number
+ */
+static int Format_samplerate(unsigned long rate, unsigned char the_rate[10])
+{
+ int i;
+
+ /* normalize rate */
+ for (i = 0; (rate & 0xffff) != 0; rate <<= 1, i++) {
+ if ((rate & 0x8000) != 0) {
+ break;
+ }
+ }
+
+ /* set exponent and sign */
+ the_rate[1] = 14-i;
+ the_rate[0] = 0x40; /* LSB = sign */
+
+ /* 16-bit part of mantisse for sample rate */
+ the_rate[3] = rate & 0xff;
+ the_rate[2] = (rate >> 8) & 0xff;
+
+ /* initialize lower digits of mantisse */
+ the_rate[4] = the_rate[5] = the_rate[6] =
+ the_rate[7] = the_rate[8] = the_rate[9] = 0;
+
+ return 0;
+}
+
+static int InitSound(int audio, long channels, unsigned long rate,
+ long nBitsPerSample, unsigned long expected_bytes)
+{
+ UINT4 tmp;
+
+ fillbytes(&AiffHdr, sizeof(AiffHdr), '\0');
+ AiffHdr.formChk.ckid = cpu_to_be32(FOURCC_FORM);
+ AiffHdr.formChk.dwSize= cpu_to_be32(expected_bytes +
+ offset_of(AIFFHDR,blocksize)+sizeof(AiffHdr.blocksize)
+ - offsetof(AIFFHDR,formType));
+ AiffHdr.formType = cpu_to_be32(FOURCC_AIFF);
+
+ AiffHdr.commChk.ckid = cpu_to_be32(FOURCC_COMM);
+ AiffHdr.commChk.dwSize= cpu_to_be32(offset_of(AIFFHDR,ssndChkid)
+ - offset_of(AIFFHDR,numChannels));
+
+ AiffHdr.numChannels[1]= channels;
+ tmp = cpu_to_be32(expected_bytes/(channels * (nBitsPerSample/8)));
+ AiffHdr.numSampleFrames[0] = tmp >> 24;
+ AiffHdr.numSampleFrames[1] = tmp >> 16;
+ AiffHdr.numSampleFrames[2] = tmp >> 8;
+ AiffHdr.numSampleFrames[3] = tmp >> 0;
+ AiffHdr.samplesize[1] = nBitsPerSample;
+ Format_samplerate(rate, AiffHdr.sample_rate);
+
+ memcpy(AiffHdr.ssndChkid, "SSND", 4);
+ tmp = cpu_to_be32(expected_bytes + offset_of(AIFFHDR,blocksize)+sizeof(AiffHdr.blocksize) - offset_of(AIFFHDR, offset));
+ AiffHdr.dwSize[0] = tmp >> 24;
+ AiffHdr.dwSize[1] = tmp >> 16;
+ AiffHdr.dwSize[2] = tmp >> 8;
+ AiffHdr.dwSize[3] = tmp >> 0;
+
+ return write (audio, &AiffHdr, sizeof (AiffHdr));
+}
+
+static int ExitSound(int audio, unsigned long nBytesDone )
+{
+ UINT4 tmp;
+
+ AiffHdr.formChk.dwSize= cpu_to_be32(nBytesDone + sizeof(AIFFHDR)
+ - offsetof(AIFFHDR,commChk));
+ tmp = cpu_to_be32(nBytesDone/(
+ AiffHdr.numChannels[1] * AiffHdr.samplesize[1]/ULONG_C(8)));
+ AiffHdr.numSampleFrames[0] = tmp >> 24;
+ AiffHdr.numSampleFrames[1] = tmp >> 16;
+ AiffHdr.numSampleFrames[2] = tmp >> 8;
+ AiffHdr.numSampleFrames[3] = tmp >> 0;
+
+ /* If an odd number of bytes has been written,
+ extend the chunk with one dummy byte. This is a requirement for AIFF. */
+ if ((nBytesDone & 1) && (lseek(audio, 1L, SEEK_CUR) == -1)) {
+ return 0;
+ }
+
+ /* goto beginning */
+ if (lseek(audio, 0L, SEEK_SET) == -1) {
+ return 0;
+ }
+ return write (audio, &AiffHdr, sizeof (AiffHdr));
+}
+
+static unsigned long GetHdrSize()
+{
+ return sizeof( AiffHdr );
+}
+
+static unsigned long InSizeToOutSize(unsigned long BytesToDo)
+{
+ return BytesToDo;
+}
+
+struct soundfile aiffsound =
+{
+ InitSound, /* init header method */
+ ExitSound, /* exit header method */
+ GetHdrSize, /* report header size method */
+ /* get sound samples out */
+ (int (*)(int audio, unsigned char *buf, unsigned long BytesToDo))write,
+ InSizeToOutSize, /* compressed? output file size */
+ 1 /* needs big endian samples */
+};
+
+