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 /* @(#)wav.c 1.4 01/10/27 Copyright 1998,1999 Heiko Eissfeldt */
15 * CopyPolicy: GNU Public License 2 applies
16 * Copyright (C) by Heiko Eissfeldt
23 #include "byteorder.h"
27 * ---------------------------------------------------------------------
28 * definitions for RIFF-output (from windows MMSYSTEM)
29 * ---------------------------------------------------------------------
32 typedef unsigned int FOURCC; /* a four character code */
34 typedef struct CHUNKHDR {
35 FOURCC ckid; /* chunk ID */
36 unsigned int dwSize; /* chunk size */
39 /* flags for 'wFormatTag' field of WAVEFORMAT */
40 #define WAVE_FORMAT_PCM 1
42 /* specific waveform format structure for PCM data */
43 typedef struct pcmwaveformat_tag {
44 unsigned short wFormatTag; /* format type */
45 unsigned short nChannels; /* number of channels (i.e. mono, stereo, etc.) */
46 unsigned int nSamplesPerSec; /* sample rate */
47 unsigned int nAvgBytesPerSec;/* for buffer size estimate */
48 unsigned short nBlockAlign; /* block size of data */
49 unsigned short wBitsPerSample;
51 typedef PCMWAVEFORMAT *PPCMWAVEFORMAT;
55 #define mmioFOURCC(ch0, ch1, ch2, ch3) \
56 ((unsigned int)(unsigned char)(ch0) | ((unsigned int)(unsigned char)(ch1) << 8) | \
57 ((unsigned int)(unsigned char)(ch2) << 16) | ((unsigned int)(unsigned char)(ch3) << 24))
59 #define FOURCC_RIFF mmioFOURCC ('R', 'I', 'F', 'F')
60 #define FOURCC_LIST mmioFOURCC ('L', 'I', 'S', 'T')
61 #define FOURCC_WAVE mmioFOURCC ('W', 'A', 'V', 'E')
62 #define FOURCC_FMT mmioFOURCC ('f', 'm', 't', ' ')
63 #define FOURCC_DATA mmioFOURCC ('d', 'a', 't', 'a')
66 /* simplified Header for standard WAV files */
67 typedef struct WAVEHDR {
71 unsigned short wFormatTag; /* format type */
72 unsigned short nChannels; /* number of channels (i.e. mono, stereo, etc.) */
73 unsigned int nSamplesPerSec; /* sample rate */
74 unsigned int nAvgBytesPerSec;/* for buffer estimation */
75 unsigned short nBlockAlign; /* block size of data */
76 unsigned short wBitsPerSample;
80 #define IS_STD_WAV_HEADER(waveHdr) ( \
81 waveHdr.chkRiff.ckid == FOURCC_RIFF && \
82 waveHdr.fccWave == FOURCC_WAVE && \
83 waveHdr.chkFmt.ckid == FOURCC_FMT && \
84 waveHdr.chkData.ckid == FOURCC_DATA && \
85 waveHdr.wFormatTag == WAVE_FORMAT_PCM)
87 static WAVEHDR waveHdr;
89 static int _InitSound(int audio, long channels, unsigned long rate,
90 long nBitsPerSample, unsigned long expected_bytes);
92 static int _InitSound(int audio, long channels, unsigned long rate,
93 long nBitsPerSample, unsigned long expected_bytes)
95 unsigned long nBlockAlign = channels * ((nBitsPerSample + 7) / 8);
96 unsigned long nAvgBytesPerSec = nBlockAlign * rate;
97 unsigned long temp = expected_bytes + sizeof(WAVEHDR) - sizeof(CHUNKHDR);
99 waveHdr.chkRiff.ckid = cpu_to_le32(FOURCC_RIFF);
100 waveHdr.fccWave = cpu_to_le32(FOURCC_WAVE);
101 waveHdr.chkFmt.ckid = cpu_to_le32(FOURCC_FMT);
102 waveHdr.chkFmt.dwSize = cpu_to_le32(sizeof (PCMWAVEFORMAT));
103 waveHdr.wFormatTag = cpu_to_le16(WAVE_FORMAT_PCM);
104 waveHdr.nChannels = cpu_to_le16(channels);
105 waveHdr.nSamplesPerSec = cpu_to_le32(rate);
106 waveHdr.nBlockAlign = cpu_to_le16(nBlockAlign);
107 waveHdr.nAvgBytesPerSec = cpu_to_le32(nAvgBytesPerSec);
108 waveHdr.wBitsPerSample = cpu_to_le16(nBitsPerSample);
109 waveHdr.chkData.ckid = cpu_to_le32(FOURCC_DATA);
110 waveHdr.chkRiff.dwSize = cpu_to_le32(temp);
111 waveHdr.chkData.dwSize = cpu_to_le32(expected_bytes);
113 return write (audio, &waveHdr, sizeof (waveHdr));
116 static int _ExitSound(int audio, unsigned long nBytesDone);
118 static int _ExitSound(int audio, unsigned long nBytesDone)
120 unsigned long temp = nBytesDone + sizeof(WAVEHDR) - sizeof(CHUNKHDR);
122 waveHdr.chkRiff.dwSize = cpu_to_le32(temp);
123 waveHdr.chkData.dwSize = cpu_to_le32(nBytesDone);
126 if (lseek(audio, 0L, SEEK_SET) == -1) {
129 return write (audio, &waveHdr, sizeof (waveHdr));
132 static unsigned long _GetHdrSize(void);
134 static unsigned long _GetHdrSize(void)
136 return sizeof( waveHdr );
139 static unsigned long InSizeToOutSize(unsigned long BytesToDo);
141 static unsigned long InSizeToOutSize(unsigned long BytesToDo)
146 struct soundfile wavsound =
148 _InitSound, /* init header method */
149 _ExitSound, /* exit header method */
150 _GetHdrSize, /* report header size method */
151 /* get sound samples out */
152 (int (*)(int audio, unsigned char *buf, unsigned long BytesToDo)) write,
153 InSizeToOutSize, /* compressed? output file size */
154 0 /* needs big endian samples */