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