1 /* AVR file format handler for SoX 2 * Copyright (C) 1999 Jan Paul Schmidt <jps@fundament.org> 3 * 4 * This library is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU Lesser General Public License as published by 6 * the Free Software Foundation; either version 2.1 of the License, or (at 7 * your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public License 15 * along with this library; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 #include "sox_i.h" 20 21 #include <stdio.h> 22 #include <string.h> 23 24 #define AVR_MAGIC "2BIT" 25 26 /* Taken from the Audio File Formats FAQ */ 27 28 typedef struct { 29 char magic [5]; /* 2BIT */ 30 char name [8]; /* null-padded sample name */ 31 unsigned short mono; /* 0 = mono, 0xffff = stereo */ 32 unsigned short rez; /* 8 = 8 bit, 16 = 16 bit */ 33 unsigned short sign; /* 0 = unsigned, 0xffff = signed */ 34 unsigned short loop; /* 0 = no loop, 0xffff = looping sample */ 35 unsigned short midi; /* 0xffff = no MIDI note assigned, 36 0xffXX = single key note assignment 37 0xLLHH = key split, low/hi note */ 38 uint32_t rate; /* sample frequency in hertz */ 39 uint32_t size; /* sample length in bytes or words (see rez) */ 40 uint32_t lbeg; /* offset to start of loop in bytes or words. 41 set to zero if unused. */ 42 uint32_t lend; /* offset to end of loop in bytes or words. 43 set to sample length if unused. */ 44 unsigned short res1; /* Reserved, MIDI keyboard split */ 45 unsigned short res2; /* Reserved, sample compression */ 46 unsigned short res3; /* Reserved */ 47 char ext[20]; /* Additional filename space, used 48 if (name[7] != 0) */ 49 char user[64]; /* User defined. Typically ASCII message. */ 50 } priv_t; 51 52 53 54 /* 55 * Do anything required before you start reading samples. 56 * Read file header. 57 * Find out sampling rate, 58 * size and encoding of samples, 59 * mono/stereo/quad. 60 */ 61 62 63 static int startread(sox_format_t * ft) 64 { 65 priv_t * avr = (priv_t *)ft->priv; 66 int rc; 67 68 lsx_reads(ft, avr->magic, (size_t)4); 69 70 if (strncmp (avr->magic, AVR_MAGIC, (size_t)4)) { 71 lsx_fail_errno(ft,SOX_EHDR,"AVR: unknown header"); 72 return(SOX_EOF); 73 } 74 75 lsx_readbuf(ft, avr->name, sizeof(avr->name)); 76 77 lsx_readw (ft, &(avr->mono)); 78 if (avr->mono) { 79 ft->signal.channels = 2; 80 } 81 else { 82 ft->signal.channels = 1; 83 } 84 85 lsx_readw (ft, &(avr->rez)); 86 if (avr->rez == 8) { 87 ft->encoding.bits_per_sample = 8; 88 } 89 else if (avr->rez == 16) { 90 ft->encoding.bits_per_sample = 16; 91 } 92 else { 93 lsx_fail_errno(ft,SOX_EFMT,"AVR: unsupported sample resolution"); 94 return(SOX_EOF); 95 } 96 97 lsx_readw (ft, &(avr->sign)); 98 if (avr->sign) { 99 ft->encoding.encoding = SOX_ENCODING_SIGN2; 100 } 101 else { 102 ft->encoding.encoding = SOX_ENCODING_UNSIGNED; 103 } 104 105 lsx_readw (ft, &(avr->loop)); 106 107 lsx_readw (ft, &(avr->midi)); 108 109 lsx_readdw (ft, &(avr->rate)); 110 /* 111 * No support for AVRs created by ST-Replay, 112 * Replay Proffesional and PRO-Series 12. 113 * 114 * Just masking the upper byte out. 115 */ 116 ft->signal.rate = (avr->rate & 0x00ffffff); 117 118 lsx_readdw (ft, &(avr->size)); 119 120 lsx_readdw (ft, &(avr->lbeg)); 121 122 lsx_readdw (ft, &(avr->lend)); 123 124 lsx_readw (ft, &(avr->res1)); 125 126 lsx_readw (ft, &(avr->res2)); 127 128 lsx_readw (ft, &(avr->res3)); 129 130 lsx_readbuf(ft, avr->ext, sizeof(avr->ext)); 131 132 lsx_readbuf(ft, avr->user, sizeof(avr->user)); 133 134 rc = lsx_rawstartread (ft); 135 if (rc) 136 return rc; 137 138 return(SOX_SUCCESS); 139 } 140 141 static int startwrite(sox_format_t * ft) 142 { 143 priv_t * avr = (priv_t *)ft->priv; 144 int rc; 145 146 if (!ft->seekable) { 147 lsx_fail_errno(ft,SOX_EOF,"AVR: file is not seekable"); 148 return(SOX_EOF); 149 } 150 151 rc = lsx_rawstartwrite (ft); 152 if (rc) 153 return rc; 154 155 /* magic */ 156 lsx_writes(ft, AVR_MAGIC); 157 158 /* name */ 159 lsx_writeb(ft, 0); 160 lsx_writeb(ft, 0); 161 lsx_writeb(ft, 0); 162 lsx_writeb(ft, 0); 163 lsx_writeb(ft, 0); 164 lsx_writeb(ft, 0); 165 lsx_writeb(ft, 0); 166 lsx_writeb(ft, 0); 167 168 /* mono */ 169 if (ft->signal.channels == 1) { 170 lsx_writew (ft, 0); 171 } 172 else if (ft->signal.channels == 2) { 173 lsx_writew (ft, 0xffff); 174 } 175 else { 176 lsx_fail_errno(ft,SOX_EFMT,"AVR: number of channels not supported"); 177 return(0); 178 } 179 180 /* rez */ 181 if (ft->encoding.bits_per_sample == 8) { 182 lsx_writew (ft, 8); 183 } 184 else if (ft->encoding.bits_per_sample == 16) { 185 lsx_writew (ft, 16); 186 } 187 else { 188 lsx_fail_errno(ft,SOX_EFMT,"AVR: unsupported sample resolution"); 189 return(SOX_EOF); 190 } 191 192 /* sign */ 193 if (ft->encoding.encoding == SOX_ENCODING_SIGN2) { 194 lsx_writew (ft, 0xffff); 195 } 196 else if (ft->encoding.encoding == SOX_ENCODING_UNSIGNED) { 197 lsx_writew (ft, 0); 198 } 199 else { 200 lsx_fail_errno(ft,SOX_EFMT,"AVR: unsupported encoding"); 201 return(SOX_EOF); 202 } 203 204 /* loop */ 205 lsx_writew (ft, 0xffff); 206 207 /* midi */ 208 lsx_writew (ft, 0xffff); 209 210 /* rate */ 211 lsx_writedw(ft, (unsigned)(ft->signal.rate + .5)); 212 213 /* size */ 214 /* Don't know the size yet. */ 215 lsx_writedw (ft, 0); 216 217 /* lbeg */ 218 lsx_writedw (ft, 0); 219 220 /* lend */ 221 /* Don't know the size yet, so we can't set lend, either. */ 222 lsx_writedw (ft, 0); 223 224 /* res1 */ 225 lsx_writew (ft, 0); 226 227 /* res2 */ 228 lsx_writew (ft, 0); 229 230 /* res3 */ 231 lsx_writew (ft, 0); 232 233 /* ext */ 234 lsx_writebuf(ft, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(avr->ext)); 235 236 /* user */ 237 lsx_writebuf(ft, 238 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 239 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 240 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 241 "\0\0\0\0", sizeof (avr->user)); 242 243 return(SOX_SUCCESS); 244 } 245 246 static size_t write_samples(sox_format_t * ft, const sox_sample_t *buf, size_t nsamp) 247 { 248 priv_t * avr = (priv_t *)ft->priv; 249 250 avr->size += nsamp; 251 252 return (lsx_rawwrite (ft, buf, nsamp)); 253 } 254 255 static int stopwrite(sox_format_t * ft) 256 { 257 priv_t * avr = (priv_t *)ft->priv; 258 259 unsigned size = avr->size / ft->signal.channels; 260 261 /* Fix size */ 262 lsx_seeki(ft, (off_t)26, SEEK_SET); 263 lsx_writedw (ft, size); 264 265 /* Fix lend */ 266 lsx_seeki(ft, (off_t)34, SEEK_SET); 267 lsx_writedw (ft, size); 268 269 return(SOX_SUCCESS); 270 } 271 272 LSX_FORMAT_HANDLER(avr) 273 { 274 static char const * const names[] = { "avr", NULL }; 275 static unsigned const write_encodings[] = { 276 SOX_ENCODING_SIGN2, 16, 8, 0, 277 SOX_ENCODING_UNSIGNED, 16, 8, 0, 278 0}; 279 static sox_format_handler_t handler = {SOX_LIB_VERSION_CODE, 280 "Audio Visual Research format; used on the Mac", 281 names, SOX_FILE_BIG_END | SOX_FILE_MONO | SOX_FILE_STEREO, 282 startread, lsx_rawread, NULL, 283 startwrite, write_samples, stopwrite, 284 NULL, write_encodings, NULL, sizeof(priv_t) 285 }; 286 return &handler; 287 } 288