1 /* @(#)wav.c 1.14 10/01/31 Copyright 1998,1999 Heiko Eissfeldt, Copyright 2006-2010 J. Schilling */
2 #include "config.h"
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)wav.c 1.14 10/01/31 Copyright 1998,1999 Heiko Eissfeldt, Copyright 2006-2010 J. Schilling";
6
7 #endif
8 /*
9 * Copyright (C) by Heiko Eissfeldt
10 * Copyright (c) 2006-2010 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #include "config.h"
27 #include <schily/stdio.h>
28 #include <schily/standard.h>
29 #include <schily/unistd.h>
30 #include "mytype.h"
31 #include "byteorder.h"
32 #include "sndfile.h"
33 #include "global.h"
34
35 /*
36 * ---------------------------------------------------------------------
37 * definitions for RIFF-output (from windows MMSYSTEM)
38 * ---------------------------------------------------------------------
39 */
40
41 typedef unsigned int FOURCC; /* a four character code */
42
43 typedef struct CHUNKHDR {
44 FOURCC ckid; /* chunk ID */
45 unsigned int dwSize; /* chunk size */
46 } CHUNKHDR;
47
48 /*
49 * flags for 'wFormatTag' field of WAVEFORMAT
50 */
51 #define WAVE_FORMAT_PCM 1
52
53 /*
54 * specific waveform format structure for PCM data
55 */
56 typedef struct pcmwaveformat_tag {
57 unsigned short wFormatTag; /* format type */
58 unsigned short nChannels; /* number of channels (i.e. mono, stereo, etc.) */
59 unsigned int nSamplesPerSec; /* sample rate */
60 unsigned int nAvgBytesPerSec; /* for buffer size estimate */
61 unsigned short nBlockAlign; /* block size of data */
62 unsigned short wBitsPerSample;
63 } PCMWAVEFORMAT;
64 typedef PCMWAVEFORMAT *PPCMWAVEFORMAT;
65
66
67 /*
68 * MMIO macros
69 */
70 #define mmioFOURCC(ch0, ch1, ch2, ch3) \
71 ((unsigned int)(unsigned char)(ch0) | \
72 ((unsigned int)(unsigned char)(ch1) << 8) | \
73 ((unsigned int)(unsigned char)(ch2) << 16) | \
74 ((unsigned int)(unsigned char)(ch3) << 24))
75
76 #define FOURCC_RIFF mmioFOURCC('R', 'I', 'F', 'F')
77 #define FOURCC_LIST mmioFOURCC('L', 'I', 'S', 'T')
78 #define FOURCC_WAVE mmioFOURCC('W', 'A', 'V', 'E')
79 #define FOURCC_FMT mmioFOURCC('f', 'm', 't', ' ')
80 #define FOURCC_DATA mmioFOURCC('d', 'a', 't', 'a')
81
82
83 /*
84 * simplified Header for standard WAV files
85 */
86 typedef struct WAVEHDR {
87 CHUNKHDR chkRiff;
88 FOURCC fccWave;
89 CHUNKHDR chkFmt;
90 unsigned short wFormatTag; /* format type */
91 unsigned short nChannels; /* number of channels (i.e. mono, stereo, etc.) */
92 unsigned int nSamplesPerSec; /* sample rate */
93 unsigned int nAvgBytesPerSec; /* for buffer estimation */
94 unsigned short nBlockAlign; /* block size of data */
95 unsigned short wBitsPerSample;
96 CHUNKHDR chkData;
97 } WAVEHDR;
98
99 #define IS_STD_WAV_HEADER(waveHdr) \
100 (waveHdr.chkRiff.ckid == FOURCC_RIFF && \
101 waveHdr.fccWave == FOURCC_WAVE && \
102 waveHdr.chkFmt.ckid == FOURCC_FMT && \
103 waveHdr.chkData.ckid == FOURCC_DATA && \
104 waveHdr.wFormatTag == WAVE_FORMAT_PCM)
105
106 LOCAL WAVEHDR waveHdr;
107
108 LOCAL int _InitSound __PR((int audio, long channels, Ulong rate,
109 long nBitsPerSample,
110 Ulong expected_bytes));
111 LOCAL int _ExitSound __PR((int audio, Ulong nBytesDone));
112 LOCAL Ulong _GetHdrSize __PR((void));
113 LOCAL Ulong InSizeToOutSize __PR((Ulong BytesToDo));
114
115
116 LOCAL int
_InitSound(audio,channels,rate,nBitsPerSample,expected_bytes)117 _InitSound(audio, channels, rate, nBitsPerSample, expected_bytes)
118 int audio;
119 long channels;
120 Ulong rate;
121 long nBitsPerSample;
122 Ulong expected_bytes;
123 {
124 Ulong nBlockAlign = channels * ((nBitsPerSample + 7) / 8);
125 Ulong nAvgBytesPerSec = nBlockAlign * rate;
126 Ulong temp = expected_bytes +
127 sizeof (WAVEHDR) - sizeof (CHUNKHDR);
128
129 waveHdr.chkRiff.ckid = cpu_to_le32(FOURCC_RIFF);
130 waveHdr.fccWave = cpu_to_le32(FOURCC_WAVE);
131 waveHdr.chkFmt.ckid = cpu_to_le32(FOURCC_FMT);
132 waveHdr.chkFmt.dwSize = cpu_to_le32(sizeof (PCMWAVEFORMAT));
133 waveHdr.wFormatTag = cpu_to_le16(WAVE_FORMAT_PCM);
134 waveHdr.nChannels = cpu_to_le16(channels);
135 waveHdr.nSamplesPerSec = cpu_to_le32(rate);
136 waveHdr.nBlockAlign = cpu_to_le16(nBlockAlign);
137 waveHdr.nAvgBytesPerSec = cpu_to_le32(nAvgBytesPerSec);
138 waveHdr.wBitsPerSample = cpu_to_le16(nBitsPerSample);
139 waveHdr.chkData.ckid = cpu_to_le32(FOURCC_DATA);
140 waveHdr.chkRiff.dwSize = cpu_to_le32(temp);
141 waveHdr.chkData.dwSize = cpu_to_le32(expected_bytes);
142
143 global.md5offset = sizeof (waveHdr);
144
145 return (write(audio, &waveHdr, sizeof (waveHdr)));
146 }
147
148 LOCAL int
_ExitSound(audio,nBytesDone)149 _ExitSound(audio, nBytesDone)
150 int audio;
151 Ulong nBytesDone;
152 {
153 Ulong temp = nBytesDone +
154 sizeof (WAVEHDR) - sizeof (CHUNKHDR);
155
156 waveHdr.chkRiff.dwSize = cpu_to_le32(temp);
157 waveHdr.chkData.dwSize = cpu_to_le32(nBytesDone);
158
159 /*
160 * goto beginning
161 */
162 if (lseek(audio, 0L, SEEK_SET) == -1) {
163 return (0);
164 }
165 return (write(audio, &waveHdr, sizeof (waveHdr)));
166 }
167
168 LOCAL Ulong
_GetHdrSize()169 _GetHdrSize()
170 {
171 return (sizeof (waveHdr));
172 }
173
174 LOCAL Ulong
InSizeToOutSize(BytesToDo)175 InSizeToOutSize(BytesToDo)
176 Ulong BytesToDo;
177 {
178 return (BytesToDo);
179 }
180
181 struct soundfile wavsound =
182 {
183 _InitSound, /* init header method */
184 _ExitSound, /* exit header method */
185 _GetHdrSize, /* report header size method */
186 (int (*) __PR((int audio,
187 Uchar *buf,
188 size_t BytesToDo))) write, /* get sound samples out */
189 InSizeToOutSize, /* compressed? output file size */
190 0, /* needs big endian samples */
191 "WAVE"
192 };
193