1 /*
2  *   toform.c
3  *
4  *   Support for various output formats for tosha.
5  *
6  *   Oliver Fromme  <olli@fromme.com>
7  *
8  *   Copyright (C) 1997,1998,1999
9  *        Oliver Fromme.  All rights reserved.
10  *
11  *   Redistribution and use in source and binary forms, with or without
12  *   modification, are permitted provided that the following conditions
13  *   are met:
14  *   1. Redistributions of source code must retain the above copyright
15  *      notice, this list of conditions and the following disclaimer.
16  *   2. Redistributions in binary form must reproduce the above copyright
17  *      notice, this list of conditions and the following disclaimer in the
18  *      documentation and/or other materials provided with the distribution.
19  *   3. Neither the name of the author nor the names of any co-contributors
20  *      may be used to endorse or promote products derived from this software
21  *      without specific prior written permission.
22  *
23  *   THIS SOFTWARE IS PROVIDED BY OLIVER FROMME AND CONTRIBUTORS ``AS IS'' AND
24  *   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  *   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  *   ARE DISCLAIMED.  IN NO EVENT SHALL OLIVER FROMME OR CONTRIBUTORS BE LIABLE
27  *   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  *   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  *   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  *   SUCH DAMAGE.
34  *
35  *   @(#)$Id: toform.c,v 1.3 1999/01/01 23:31:58 olli Exp $
36  */
37 
38 static const char cvsid[]
39     = "@(#)$Id: toform.c,v 1.3 1999/01/01 23:31:58 olli Exp $";
40 
41 #include <string.h>
42 #include <sys/types.h>
43 #include <sys/uio.h>
44 #include <unistd.h>
45 
46 #include "utils.h"
47 #include "global.h"
48 
49 #include "toform.h"
50 
51 #define CD_DA_SAMPLERATE  44100
52 
53 /*   Note: the 1st line in the following list is the default.   */
54 
55 const formspec format[] = {
56 	{"pcm",  "pcm",  "raw",  raw_writeheader,  RAW_SWAPBYTES},
57 	{"mcp",  "mcp",  "war",  war_writeheader,  WAR_SWAPBYTES},
58 	{"aiff", "iff",  "aiff", aiff_writeheader, AIFF_SWAPBYTES},
59 	{"wav",  "riff", "wav",  wav_writeheader,  WAV_SWAPBYTES},
60 	{"au",   "sun",  "au",   au_writeheader,   AU_SWAPBYTES},
61 	{NULL, NULL, NULL, NULL, 0}
62 };
63 
64 void
65 copy_le2 (unsigned char *buf, unsigned int x)
66 {
67 	buf[0] = x & 0xff;
68 	buf[1] = x >> 8;
69 }
70 
71 void
72 copy_le4 (unsigned char *buf, unsigned int x)
73 {
74 	copy_le2 (buf + 0, x & 0xffff);
75 	copy_le2 (buf + 2, x >> 16);
76 }
77 
78 void
79 copy_be2 (unsigned char *buf, unsigned int x)
80 {
81 	buf[0] = x >> 8;
82 	buf[1] = x & 0xff;
83 }
84 
85 void
86 copy_be4 (unsigned char *buf, unsigned int x)
87 {
88 	copy_be2 (buf + 0, x >> 16);
89 	copy_be2 (buf + 2, x & 0xffff);
90 }
91 
92 /*
93  *   ===================
94  *         RAW/PCM
95  *   ===================
96  */
97 
98 int
99 raw_writeheader (ulong tracksize, int fd)
100 {
101 	return 0;
102 }
103 
104 /*
105  *   ===================
106  *         WAR/MCP
107  *   ===================
108  */
109 
110 int
111 war_writeheader (ulong tracksize, int fd)
112 {
113 	return 0;
114 }
115 
116 /*
117  *   ================
118  *         AIFF
119  *   ================
120  */
121 
122 unsigned char aiffhead[54] =
123 	"FORM....AIFFCOMM....ccssssbbrrrrrrrrrrSSND....ooookkkk";
124 
125 #define AIFF_O_FORMSIZE  4	/* [4] track size (ts) in bytes + 46 */
126 #define AIFF_O_COMMSIZE  16	/* [4] 18 */
127 #define AIFF_O_NUMCHAN   20	/* [2] number of channels (2) */
128 #define AIFF_O_NUMSAMP   22	/* [4] number of stereo samples (ts / 4) */
129 #define AIFF_O_BPS       26	/* [2] bits per channel sample (16) */
130 #define AIFF_O_RATE      28	/* [10] IEEE sample rate spec */
131 #define AIFF_O_SSNDSIZE  42	/* [4] track size (ts) in bytes + 8 */
132 #define AIFF_O_OFFSET    46	/* [4] sound offset (0) */
133 #define AIFF_O_BSIZE     50	/* [4] sound block size (0) */
134 
135 const unsigned char ieee44100[10] = {
136 	0x40, 0x0e,
137 	CD_DA_SAMPLERATE >> 8, CD_DA_SAMPLERATE & 0xff,
138 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
139 };
140 
141 int
142 aiff_writeheader (ulong tracksize, int fd)
143 {
144 	int headsize = sizeof(aiffhead);
145 
146 	copy_be4 (aiffhead + AIFF_O_FORMSIZE, tracksize + headsize - 8);
147 	copy_be4 (aiffhead + AIFF_O_COMMSIZE, 18);
148 	copy_be2 (aiffhead + AIFF_O_NUMCHAN,  2);
149 	copy_be4 (aiffhead + AIFF_O_NUMSAMP,  tracksize >> 2);
150 	copy_be2 (aiffhead + AIFF_O_BPS,      16);
151 	memcpy   (aiffhead + AIFF_O_RATE,     ieee44100, sizeof(ieee44100));
152 	copy_be4 (aiffhead + AIFF_O_SSNDSIZE, tracksize + 8);
153 	copy_be4 (aiffhead + AIFF_O_OFFSET,   0);
154 	copy_be4 (aiffhead + AIFF_O_BSIZE,    0);
155 	return write (fd, aiffhead, headsize);
156 }
157 
158 /*
159  *   ====================
160  *         WAV/RIFF
161  *   ====================
162  */
163 
164 unsigned char wavhead[44] =
165 	"RIFF....WAVEfmt ....ffccrrrryyyyaabbdata....";
166 
167 #define WAV_O_RIFFSIZE  4	/* [4] track size in bytes + 36 */
168 #define WAV_O_FMTSIZE   16	/* [4] 16 */
169 #define WAV_O_FORMAT    20	/* [2] 1 (PCM) */
170 #define WAV_O_NUMCHAN   22	/* [2] number of channels (2) */
171 #define WAV_O_RATE      24	/* [4] sample rate (44100) */
172 #define WAV_O_BYTERATE  28	/* [4] bytes per second (44100 * 4) */
173 #define WAV_O_ALIGN     32	/* [2] sample alignment (4 bytes) */
174 #define WAV_O_BPS       34	/* [2] bits per channel sample (16) */
175 #define WAV_O_DATASIZE  40	/* [4] track size in bytes */
176 
177 int
178 wav_writeheader (ulong tracksize, int fd)
179 {
180 	int headsize = sizeof(wavhead);
181 
182 	copy_le4 (wavhead + WAV_O_RIFFSIZE, tracksize + headsize - 8);
183 	copy_le4 (wavhead + WAV_O_FMTSIZE,  16);
184 	copy_le2 (wavhead + WAV_O_FORMAT,   1);
185 	copy_le2 (wavhead + WAV_O_NUMCHAN,  2);
186 	copy_le4 (wavhead + WAV_O_RATE,     CD_DA_SAMPLERATE);
187 	copy_le4 (wavhead + WAV_O_BYTERATE, CD_DA_SAMPLERATE << 2);
188 	copy_le2 (wavhead + WAV_O_ALIGN,    4);
189 	copy_le2 (wavhead + WAV_O_BPS,      16);
190 	copy_le4 (wavhead + WAV_O_DATASIZE, tracksize);
191 	return write (fd, wavhead, headsize);
192 }
193 
194 /*
195  *   ==================
196  *         SUN/AU
197  *   ==================
198  */
199 
200 unsigned char auhead[28] =
201 	".sndoooo....ffffrrrrcccctosh";
202 
203 #define AU_O_OFFSET    4	/* [4] file offset of sound data (28) */
204 #define AU_O_DATASIZE  8	/* [4] track size in bytes */
205 #define AU_O_FORMAT    12	/* [4] 3 (linear-16) */
206 #define AU_O_RATE      16	/* [4] sample rate (44100) */
207 #define AU_O_NUMCHAN   20	/* [4] number of channels (2) */
208 
209 int
210 au_writeheader (ulong tracksize, int fd)
211 {
212 	int headsize = sizeof(auhead);
213 
214 	copy_be4 (auhead + AU_O_OFFSET,   headsize);
215 	copy_be4 (auhead + AU_O_DATASIZE, tracksize);
216 	copy_be4 (auhead + AU_O_FORMAT,   3);
217 	copy_be4 (auhead + AU_O_RATE,     CD_DA_SAMPLERATE);
218 	copy_be4 (auhead + AU_O_NUMCHAN,  2);
219 	return write (fd, auhead, headsize);
220 }
221 
222 /* EOF */
223