/* @(#)aiff.c 1.5 01/10/27 Copyright 1998,1999 Heiko Eissfeldt */
#ifndef lint
static char sccsid[] =
"@(#)aiff.c 1.5 01/10/27 Copyright 1998,1999 Heiko Eissfeldt";
#endif
/***
* 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;
/* format the sample rate into an
bigendian 10-byte IEEE-754 floating point number
*/
static int Format_samplerate __PR((unsigned long rate, unsigned char the_rate[10]));
static int Format_samplerate(rate, the_rate)
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 __PR(( int audio, long channels, unsigned long rate, long nBitsPerSample, unsigned long expected_bytes ));
static int InitSound ( audio, channels, rate, nBitsPerSample, expected_bytes)
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 __PR(( int audio, unsigned long nBytesDone ));
static int ExitSound ( audio, nBytesDone )
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 __PR(( void ));
static unsigned long GetHdrSize( )
{
return sizeof( AiffHdr );
}
static unsigned long InSizeToOutSize __PR(( unsigned long BytesToDo ));
static unsigned long InSizeToOutSize ( BytesToDo )
unsigned long BytesToDo;
{
return BytesToDo;
}
struct soundfile aiffsound =
{
InitSound, /* init header method */
ExitSound, /* exit header method */
GetHdrSize, /* report header size method */
(int (*) __PR(( int audio, unsigned char *buf, unsigned long BytesToDo ))) write, /* get sound samples out */
InSizeToOutSize, /* compressed? output file size */
1 /* needs big endian samples */
};
syntax highlighted by Code2HTML, v. 0.9.1