Reverting format addition for now
[asterisk/asterisk.git] / formats / format_wav.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Work with WAV in the proprietary Microsoft format.
22  * Microsoft WAV format (8000hz Signed Linear)
23  * \arg File name extension: wav (lower case)
24  * \ingroup formats
25  */
26  
27 #include "asterisk.h"
28
29 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
30
31 #include "asterisk/mod_format.h"
32 #include "asterisk/module.h"
33 #include "asterisk/endian.h"
34
35 /* Some Ideas for this code came from makewave.c by Jeffrey Chilton */
36
37 /* Portions of the conversion code are by guido@sienanet.it */
38
39 #define WAV_BUF_SIZE    320
40
41 struct wav_desc {       /* format-specific parameters */
42         int bytes;
43         int lasttimeout;
44         int maxlen;
45         struct timeval last;
46 };
47
48 #define BLOCKSIZE 160
49
50 #if __BYTE_ORDER == __LITTLE_ENDIAN
51 #define htoll(b) (b)
52 #define htols(b) (b)
53 #define ltohl(b) (b)
54 #define ltohs(b) (b)
55 #else
56 #if __BYTE_ORDER == __BIG_ENDIAN
57 #define htoll(b)  \
58           (((((b)      ) & 0xFF) << 24) | \
59                ((((b) >>  8) & 0xFF) << 16) | \
60                    ((((b) >> 16) & 0xFF) <<  8) | \
61                    ((((b) >> 24) & 0xFF)      ))
62 #define htols(b) \
63           (((((b)      ) & 0xFF) << 8) | \
64                    ((((b) >> 8) & 0xFF)      ))
65 #define ltohl(b) htoll(b)
66 #define ltohs(b) htols(b)
67 #else
68 #error "Endianess not defined"
69 #endif
70 #endif
71
72
73 static int check_header(FILE *f)
74 {
75         int type, size, formtype;
76         int fmt, hsize;
77         short format, chans, bysam, bisam;
78         int bysec;
79         int freq;
80         int data;
81         if (fread(&type, 1, 4, f) != 4) {
82                 ast_log(LOG_WARNING, "Read failed (type)\n");
83                 return -1;
84         }
85         if (fread(&size, 1, 4, f) != 4) {
86                 ast_log(LOG_WARNING, "Read failed (size)\n");
87                 return -1;
88         }
89         size = ltohl(size);
90         if (fread(&formtype, 1, 4, f) != 4) {
91                 ast_log(LOG_WARNING, "Read failed (formtype)\n");
92                 return -1;
93         }
94         if (memcmp(&type, "RIFF", 4)) {
95                 ast_log(LOG_WARNING, "Does not begin with RIFF\n");
96                 return -1;
97         }
98         if (memcmp(&formtype, "WAVE", 4)) {
99                 ast_log(LOG_WARNING, "Does not contain WAVE\n");
100                 return -1;
101         }
102         if (fread(&fmt, 1, 4, f) != 4) {
103                 ast_log(LOG_WARNING, "Read failed (fmt)\n");
104                 return -1;
105         }
106         if (memcmp(&fmt, "fmt ", 4)) {
107                 ast_log(LOG_WARNING, "Does not say fmt\n");
108                 return -1;
109         }
110         if (fread(&hsize, 1, 4, f) != 4) {
111                 ast_log(LOG_WARNING, "Read failed (formtype)\n");
112                 return -1;
113         }
114         if (ltohl(hsize) < 16) {
115                 ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize));
116                 return -1;
117         }
118         if (fread(&format, 1, 2, f) != 2) {
119                 ast_log(LOG_WARNING, "Read failed (format)\n");
120                 return -1;
121         }
122         if (ltohs(format) != 1) {
123                 ast_log(LOG_WARNING, "Not a wav file %d\n", ltohs(format));
124                 return -1;
125         }
126         if (fread(&chans, 1, 2, f) != 2) {
127                 ast_log(LOG_WARNING, "Read failed (format)\n");
128                 return -1;
129         }
130         if (ltohs(chans) != 1) {
131                 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
132                 return -1;
133         }
134         if (fread(&freq, 1, 4, f) != 4) {
135                 ast_log(LOG_WARNING, "Read failed (freq)\n");
136                 return -1;
137         }
138         if (ltohl(freq) != DEFAULT_SAMPLE_RATE) {
139                 ast_log(LOG_WARNING, "Unexpected freqency %d\n", ltohl(freq));
140                 return -1;
141         }
142         /* Ignore the byte frequency */
143         if (fread(&bysec, 1, 4, f) != 4) {
144                 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n");
145                 return -1;
146         }
147         /* Check bytes per sample */
148         if (fread(&bysam, 1, 2, f) != 2) {
149                 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n");
150                 return -1;
151         }
152         if (ltohs(bysam) != 2) {
153                 ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam));
154                 return -1;
155         }
156         if (fread(&bisam, 1, 2, f) != 2) {
157                 ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam));
158                 return -1;
159         }
160         /* Skip any additional header */
161         if (fseek(f,ltohl(hsize)-16,SEEK_CUR) == -1 ) {
162                 ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", ltohl(hsize)-16 );
163                 return -1;
164         }
165         /* Skip any facts and get the first data block */
166         for(;;)
167         { 
168                 char buf[4];
169             
170             /* Begin data chunk */
171             if (fread(&buf, 1, 4, f) != 4) {
172                         ast_log(LOG_WARNING, "Read failed (data)\n");
173                         return -1;
174             }
175             /* Data has the actual length of data in it */
176             if (fread(&data, 1, 4, f) != 4) {
177                         ast_log(LOG_WARNING, "Read failed (data)\n");
178                         return -1;
179             }
180             data = ltohl(data);
181             if(memcmp(buf, "data", 4) == 0 ) 
182                         break;
183             if(memcmp(buf, "fact", 4) != 0 ) {
184                         ast_log(LOG_WARNING, "Unknown block - not fact or data\n");
185                         return -1;
186             }
187             if (fseek(f,data,SEEK_CUR) == -1 ) {
188                         ast_log(LOG_WARNING, "Failed to skip fact block: %d\n", data );
189                         return -1;
190             }
191         }
192 #if 0
193         curpos = lseek(fd, 0, SEEK_CUR);
194         truelength = lseek(fd, 0, SEEK_END);
195         lseek(fd, curpos, SEEK_SET);
196         truelength -= curpos;
197 #endif  
198         return data;
199 }
200
201 static int update_header(FILE *f)
202 {
203         off_t cur,end;
204         int datalen,filelen,bytes;
205         
206         cur = ftello(f);
207         fseek(f, 0, SEEK_END);
208         end = ftello(f);
209         /* data starts 44 bytes in */
210         bytes = end - 44;
211         datalen = htoll(bytes);
212         /* chunk size is bytes of data plus 36 bytes of header */
213         filelen = htoll(36 + bytes);
214         
215         if (cur < 0) {
216                 ast_log(LOG_WARNING, "Unable to find our position\n");
217                 return -1;
218         }
219         if (fseek(f, 4, SEEK_SET)) {
220                 ast_log(LOG_WARNING, "Unable to set our position\n");
221                 return -1;
222         }
223         if (fwrite(&filelen, 1, 4, f) != 4) {
224                 ast_log(LOG_WARNING, "Unable to set write file size\n");
225                 return -1;
226         }
227         if (fseek(f, 40, SEEK_SET)) {
228                 ast_log(LOG_WARNING, "Unable to set our position\n");
229                 return -1;
230         }
231         if (fwrite(&datalen, 1, 4, f) != 4) {
232                 ast_log(LOG_WARNING, "Unable to set write datalen\n");
233                 return -1;
234         }
235         if (fseeko(f, cur, SEEK_SET)) {
236                 ast_log(LOG_WARNING, "Unable to return to position\n");
237                 return -1;
238         }
239         return 0;
240 }
241
242 static int write_header(FILE *f)
243 {
244         unsigned int hz=htoll(8000);
245         unsigned int bhz = htoll(16000);
246         unsigned int hs = htoll(16);
247         unsigned short fmt = htols(1);
248         unsigned short chans = htols(1);
249         unsigned short bysam = htols(2);
250         unsigned short bisam = htols(16);
251         unsigned int size = htoll(0);
252         /* Write a wav header, ignoring sizes which will be filled in later */
253         fseek(f,0,SEEK_SET);
254         if (fwrite("RIFF", 1, 4, f) != 4) {
255                 ast_log(LOG_WARNING, "Unable to write header\n");
256                 return -1;
257         }
258         if (fwrite(&size, 1, 4, f) != 4) {
259                 ast_log(LOG_WARNING, "Unable to write header\n");
260                 return -1;
261         }
262         if (fwrite("WAVEfmt ", 1, 8, f) != 8) {
263                 ast_log(LOG_WARNING, "Unable to write header\n");
264                 return -1;
265         }
266         if (fwrite(&hs, 1, 4, f) != 4) {
267                 ast_log(LOG_WARNING, "Unable to write header\n");
268                 return -1;
269         }
270         if (fwrite(&fmt, 1, 2, f) != 2) {
271                 ast_log(LOG_WARNING, "Unable to write header\n");
272                 return -1;
273         }
274         if (fwrite(&chans, 1, 2, f) != 2) {
275                 ast_log(LOG_WARNING, "Unable to write header\n");
276                 return -1;
277         }
278         if (fwrite(&hz, 1, 4, f) != 4) {
279                 ast_log(LOG_WARNING, "Unable to write header\n");
280                 return -1;
281         }
282         if (fwrite(&bhz, 1, 4, f) != 4) {
283                 ast_log(LOG_WARNING, "Unable to write header\n");
284                 return -1;
285         }
286         if (fwrite(&bysam, 1, 2, f) != 2) {
287                 ast_log(LOG_WARNING, "Unable to write header\n");
288                 return -1;
289         }
290         if (fwrite(&bisam, 1, 2, f) != 2) {
291                 ast_log(LOG_WARNING, "Unable to write header\n");
292                 return -1;
293         }
294         if (fwrite("data", 1, 4, f) != 4) {
295                 ast_log(LOG_WARNING, "Unable to write header\n");
296                 return -1;
297         }
298         if (fwrite(&size, 1, 4, f) != 4) {
299                 ast_log(LOG_WARNING, "Unable to write header\n");
300                 return -1;
301         }
302         return 0;
303 }
304
305 static int wav_open(struct ast_filestream *s)
306 {
307         /* We don't have any header to read or anything really, but
308            if we did, it would go here.  We also might want to check
309            and be sure it's a valid file.  */
310         struct wav_desc *tmp = (struct wav_desc *)s->_private;
311         if ((tmp->maxlen = check_header(s->f)) < 0)
312                 return -1;
313         return 0;
314 }
315
316 static int wav_rewrite(struct ast_filestream *s, const char *comment)
317 {
318         /* We don't have any header to read or anything really, but
319            if we did, it would go here.  We also might want to check
320            and be sure it's a valid file.  */
321
322         if (write_header(s->f))
323                 return -1;
324         return 0;
325 }
326
327 static void wav_close(struct ast_filestream *s)
328 {
329         char zero = 0;
330         struct wav_desc *fs = (struct wav_desc *)s->_private;
331
332         if (s->filename) {
333                 update_header(s->f);
334         }
335
336         /* Pad to even length */
337         if (fs->bytes & 0x1)
338                 fwrite(&zero, 1, 1, s->f);
339 }
340
341 static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
342 {
343         int res;
344         int samples;    /* actual samples read */
345 #if __BYTE_ORDER == __BIG_ENDIAN
346         int x;
347 #endif
348         short *tmp;
349         int bytes = WAV_BUF_SIZE;       /* in bytes */
350         off_t here;
351         /* Send a frame from the file to the appropriate channel */
352         struct wav_desc *fs = (struct wav_desc *)s->_private;
353
354         here = ftello(s->f);
355         if (fs->maxlen - here < bytes)          /* truncate if necessary */
356                 bytes = fs->maxlen - here;
357         if (bytes < 0)
358                 bytes = 0;
359 /*      ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */
360         s->fr.frametype = AST_FRAME_VOICE;
361         s->fr.subclass = AST_FORMAT_SLINEAR;
362         s->fr.mallocd = 0;
363         AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes);
364         
365         if ( (res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) <= 0 ) {
366                 if (res)
367                         ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
368                 return NULL;
369         }
370         s->fr.datalen = res;
371         s->fr.samples = samples = res / 2;
372
373         tmp = (short *)(s->fr.data.ptr);
374 #if __BYTE_ORDER == __BIG_ENDIAN
375         /* file format is little endian so we need to swap */
376         for( x = 0; x < samples; x++)
377                 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
378 #endif
379
380         *whennext = samples;
381         return &s->fr;
382 }
383
384 static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
385 {
386 #if __BYTE_ORDER == __BIG_ENDIAN
387         int x;
388         short tmp[8000], *tmpi;
389 #endif
390         struct wav_desc *s = (struct wav_desc *)fs->_private;
391         int res;
392
393         if (f->frametype != AST_FRAME_VOICE) {
394                 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
395                 return -1;
396         }
397         if (f->subclass != AST_FORMAT_SLINEAR) {
398                 ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass);
399                 return -1;
400         }
401         if (!f->datalen)
402                 return -1;
403
404 #if __BYTE_ORDER == __BIG_ENDIAN
405         /* swap and write */
406         if (f->datalen > sizeof(tmp)) {
407                 ast_log(LOG_WARNING, "Data length is too long\n");
408                 return -1;
409         }
410         tmpi = f->data.ptr;
411         for (x=0; x < f->datalen/2; x++) 
412                 tmp[x] = (tmpi[x] << 8) | ((tmpi[x] & 0xff00) >> 8);
413
414         if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) {
415 #else
416         /* just write */
417         if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen ) {
418 #endif
419                 ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno));
420                 return -1;
421         }
422
423         s->bytes += f->datalen;
424                 
425         return 0;
426
427 }
428
429 static int wav_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
430 {
431         off_t min, max, cur, offset = 0, samples;
432
433         samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */
434         min = 44; /* wav header is 44 bytes */
435         cur = ftello(fs->f);
436         fseeko(fs->f, 0, SEEK_END);
437         max = ftello(fs->f);
438         if (whence == SEEK_SET)
439                 offset = samples + min;
440         else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
441                 offset = samples + cur;
442         else if (whence == SEEK_END)
443                 offset = max - samples;
444         if (whence != SEEK_FORCECUR) {
445                 offset = (offset > max)?max:offset;
446         }
447         /* always protect the header space. */
448         offset = (offset < min)?min:offset;
449         return fseeko(fs->f, offset, SEEK_SET);
450 }
451
452 static int wav_trunc(struct ast_filestream *fs)
453 {
454         if (ftruncate(fileno(fs->f), ftello(fs->f)))
455                 return -1;
456         return update_header(fs->f);
457 }
458
459 static off_t wav_tell(struct ast_filestream *fs)
460 {
461         off_t offset;
462         offset = ftello(fs->f);
463         /* subtract header size to get samples, then divide by 2 for 16 bit samples */
464         return (offset - 44)/2;
465 }
466
467 static const struct ast_format wav_f = {
468         .name = "wav",
469         .exts = "wav",
470         .format = AST_FORMAT_SLINEAR,
471         .open = wav_open,
472         .rewrite = wav_rewrite,
473         .write = wav_write,
474         .seek = wav_seek,
475         .trunc = wav_trunc,
476         .tell = wav_tell,
477         .read = wav_read,
478         .close = wav_close,
479         .buf_size = WAV_BUF_SIZE + AST_FRIENDLY_OFFSET,
480         .desc_size = sizeof(struct wav_desc),
481 };
482
483 static int load_module(void)
484 {
485         if (ast_format_register(&wav_f))
486                 return AST_MODULE_LOAD_FAILURE;
487         return AST_MODULE_LOAD_SUCCESS;
488 }
489
490 static int unload_module(void)
491 {
492         return ast_format_unregister(wav_f.name);
493 }       
494
495 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Microsoft WAV format (8000Hz Signed Linear)");