2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* @(#)aiff.c 1.5 01/10/27 Copyright 1998,1999 Heiko Eissfeldt */
15 * CopyPolicy: GNU Public License 2 applies
16 * Copyright (C) by Heiko Eissfeldt
19 * ---------------------------------------------------------------------
20 * definitions for aiff pcm output
21 * ---------------------------------------------------------------------
31 #include "byteorder.h"
34 typedef UINT4 FOURCC; /* a four character code */
35 typedef struct CHUNKHDR {
36 FOURCC ckid; /* chunk ID */
37 UINT4 dwSize; /* chunk size */
40 #define mmioFOURCC(ch0, ch1, ch2, ch3) \
41 ((UINT4)(unsigned char)(ch3) | ((UINT4)(unsigned char)(ch2) << 8) | \
42 ((UINT4)(unsigned char)(ch1) << 16) | ((UINT4)(unsigned char)(ch0) << 24))
44 #define FOURCC_FORM mmioFOURCC ('F', 'O', 'R', 'M')
45 #define FOURCC_AIFF mmioFOURCC ('A', 'I', 'F', 'F')
46 #define FOURCC_COMM mmioFOURCC ('C', 'O', 'M', 'M')
47 #define FOURCC_SSND mmioFOURCC ('S', 'S', 'N', 'D')
49 typedef struct AIFFHDR {
53 CHUNKHDR commChk; /* Common chunk */
54 /* from now on, alignment prevents us from using the original types :-(( */
55 unsigned char numChannels[2]; /* Audio Channels */
56 unsigned char numSampleFrames[4]; /* # of samples */
57 unsigned char samplesize[2]; /* bits per sample */
58 unsigned char sample_rate[10]; /* sample rate in extended float */
60 unsigned char ssndChkid[4]; /* Sound data chunk */
61 unsigned char dwSize[4]; /* size of chunk */
62 unsigned char offset[4]; /* start of 1st sample */
63 unsigned char blocksize[4]; /* aligned sound data block size */
66 static AIFFHDR AiffHdr;
69 static int Format_samplerate(unsigned long rate, unsigned char the_rate[10]);
70 static int InitSound(int audio, long channels, unsigned long rate,
71 long nBitsPerSample, unsigned long expected_bytes);
72 static int ExitSound(int audio, unsigned long nBytesDone);
73 static unsigned long GetHdrSize(void);
74 static unsigned long InSizeToOutSize(unsigned long BytesToDo);
77 /* format the sample rate into an
78 bigendian 10-byte IEEE-754 floating point number
80 static int Format_samplerate(unsigned long rate, unsigned char the_rate[10])
85 for (i = 0; (rate & 0xffff) != 0; rate <<= 1, i++) {
86 if ((rate & 0x8000) != 0) {
91 /* set exponent and sign */
93 the_rate[0] = 0x40; /* LSB = sign */
95 /* 16-bit part of mantisse for sample rate */
96 the_rate[3] = rate & 0xff;
97 the_rate[2] = (rate >> 8) & 0xff;
99 /* initialize lower digits of mantisse */
100 the_rate[4] = the_rate[5] = the_rate[6] =
101 the_rate[7] = the_rate[8] = the_rate[9] = 0;
106 static int InitSound(int audio, long channels, unsigned long rate,
107 long nBitsPerSample, unsigned long expected_bytes)
111 fillbytes(&AiffHdr, sizeof(AiffHdr), '\0');
112 AiffHdr.formChk.ckid = cpu_to_be32(FOURCC_FORM);
113 AiffHdr.formChk.dwSize= cpu_to_be32(expected_bytes +
114 offset_of(AIFFHDR,blocksize)+sizeof(AiffHdr.blocksize)
115 - offsetof(AIFFHDR,formType));
116 AiffHdr.formType = cpu_to_be32(FOURCC_AIFF);
118 AiffHdr.commChk.ckid = cpu_to_be32(FOURCC_COMM);
119 AiffHdr.commChk.dwSize= cpu_to_be32(offset_of(AIFFHDR,ssndChkid)
120 - offset_of(AIFFHDR,numChannels));
122 AiffHdr.numChannels[1]= channels;
123 tmp = cpu_to_be32(expected_bytes/(channels * (nBitsPerSample/8)));
124 AiffHdr.numSampleFrames[0] = tmp >> 24;
125 AiffHdr.numSampleFrames[1] = tmp >> 16;
126 AiffHdr.numSampleFrames[2] = tmp >> 8;
127 AiffHdr.numSampleFrames[3] = tmp >> 0;
128 AiffHdr.samplesize[1] = nBitsPerSample;
129 Format_samplerate(rate, AiffHdr.sample_rate);
131 memcpy(AiffHdr.ssndChkid, "SSND", 4);
132 tmp = cpu_to_be32(expected_bytes + offset_of(AIFFHDR,blocksize)+sizeof(AiffHdr.blocksize) - offset_of(AIFFHDR, offset));
133 AiffHdr.dwSize[0] = tmp >> 24;
134 AiffHdr.dwSize[1] = tmp >> 16;
135 AiffHdr.dwSize[2] = tmp >> 8;
136 AiffHdr.dwSize[3] = tmp >> 0;
138 return write (audio, &AiffHdr, sizeof (AiffHdr));
141 static int ExitSound(int audio, unsigned long nBytesDone )
145 AiffHdr.formChk.dwSize= cpu_to_be32(nBytesDone + sizeof(AIFFHDR)
146 - offsetof(AIFFHDR,commChk));
147 tmp = cpu_to_be32(nBytesDone/(
148 AiffHdr.numChannels[1] * AiffHdr.samplesize[1]/ULONG_C(8)));
149 AiffHdr.numSampleFrames[0] = tmp >> 24;
150 AiffHdr.numSampleFrames[1] = tmp >> 16;
151 AiffHdr.numSampleFrames[2] = tmp >> 8;
152 AiffHdr.numSampleFrames[3] = tmp >> 0;
154 /* If an odd number of bytes has been written,
155 extend the chunk with one dummy byte. This is a requirement for AIFF. */
156 if ((nBytesDone & 1) && (lseek(audio, 1L, SEEK_CUR) == -1)) {
161 if (lseek(audio, 0L, SEEK_SET) == -1) {
164 return write (audio, &AiffHdr, sizeof (AiffHdr));
167 static unsigned long GetHdrSize()
169 return sizeof( AiffHdr );
172 static unsigned long InSizeToOutSize(unsigned long BytesToDo)
177 struct soundfile aiffsound =
179 InitSound, /* init header method */
180 ExitSound, /* exit header method */
181 GetHdrSize, /* report header size method */
182 /* get sound samples out */
183 (int (*)(int audio, unsigned char *buf, unsigned long BytesToDo))write,
184 InSizeToOutSize, /* compressed? output file size */
185 1 /* needs big endian samples */