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