90ef986ef0be2237c49e1f3c8ccf645b8e6048c0
[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 /*** MODULEINFO
28         <support_level>core</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34
35 #include "asterisk/mod_format.h"
36 #include "asterisk/module.h"
37 #include "asterisk/endian.h"
38 #include "asterisk/format_cache.h"
39 #include "asterisk/format.h"
40 #include "asterisk/codec.h"
41
42 /* Some Ideas for this code came from makewave.c by Jeffrey Chilton */
43
44 /* Portions of the conversion code are by guido@sienanet.it */
45
46 #define WAV_BUF_SIZE    320
47
48 #define WAV_HEADER_SIZE 44
49
50 struct wav_desc {       /* format-specific parameters */
51         int hz;
52         int bytes;
53         int lasttimeout;
54         int maxlen;
55         struct timeval last;
56 };
57
58 #define BLOCKSIZE 160
59
60 #if __BYTE_ORDER == __LITTLE_ENDIAN
61 #define htoll(b) (b)
62 #define htols(b) (b)
63 #define ltohl(b) (b)
64 #define ltohs(b) (b)
65 #else
66 #if __BYTE_ORDER == __BIG_ENDIAN
67 #define htoll(b) \
68         (((((b)      ) & 0xFF) << 24) | \
69         ((( (b) >>  8) & 0xFF) << 16) | \
70         ((( (b) >> 16) & 0xFF) <<  8) | \
71         ((( (b) >> 24) & 0xFF)      ))
72 #define htols(b) \
73         (((((b)      ) & 0xFF) <<  8) | \
74         ((( (b) >>  8) & 0xFF)      ))
75 #define ltohl(b) htoll(b)
76 #define ltohs(b) htols(b)
77 #else
78 #error "Endianess not defined"
79 #endif
80 #endif
81
82
83 static int check_header_fmt(FILE *f, int hsize, int hz)
84 {
85         short format, chans, bysam, bisam;
86         int bysec;
87         int freq;
88         if (hsize < 16) {
89                 ast_log(LOG_WARNING, "Unexpected header size %d\n", hsize);
90                 return -1;
91         }
92         if (fread(&format, 1, 2, f) != 2) {
93                 ast_log(LOG_WARNING, "Read failed (format)\n");
94                 return -1;
95         }
96         if (ltohs(format) != 1) {
97                 ast_log(LOG_WARNING, "Not a supported wav file format (%d). Only PCM encoded, 16 bit, mono, 8kHz files are supported with a lowercase '.wav' extension.\n", ltohs(format));
98                 return -1;
99         }
100         if (fread(&chans, 1, 2, f) != 2) {
101                 ast_log(LOG_WARNING, "Read failed (format)\n");
102                 return -1;
103         }
104         if (ltohs(chans) != 1) {
105                 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
106                 return -1;
107         }
108         if (fread(&freq, 1, 4, f) != 4) {
109                 ast_log(LOG_WARNING, "Read failed (freq)\n");
110                 return -1;
111         }
112         if (((ltohl(freq) != 8000) && (ltohl(freq) != 16000)) ||
113                 ((ltohl(freq) == 8000) && (hz != 8000)) ||
114                 ((ltohl(freq) == 16000) && (hz != 16000))) {
115                 ast_log(LOG_WARNING, "Unexpected frequency mismatch %d (expecting %d)\n", ltohl(freq),hz);
116                 return -1;
117         }
118         /* Ignore the byte frequency */
119         if (fread(&bysec, 1, 4, f) != 4) {
120                 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n");
121                 return -1;
122         }
123         /* Check bytes per sample */
124         if (fread(&bysam, 1, 2, f) != 2) {
125                 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n");
126                 return -1;
127         }
128         if (ltohs(bysam) != 2) {
129                 ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam));
130                 return -1;
131         }
132         if (fread(&bisam, 1, 2, f) != 2) {
133                 ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam));
134                 return -1;
135         }
136         /* Skip any additional header */
137         if (fseek(f,hsize-16,SEEK_CUR) == -1 ) {
138                 ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", hsize-16 );
139                 return -1;
140         }
141         return 0;
142 }
143
144 static int check_header(FILE *f, int hz)
145 {
146         int type, size, formtype;
147         int data;
148         if (fread(&type, 1, 4, f) != 4) {
149                 ast_log(LOG_WARNING, "Read failed (type)\n");
150                 return -1;
151         }
152         if (fread(&size, 1, 4, f) != 4) {
153                 ast_log(LOG_WARNING, "Read failed (size)\n");
154                 return -1;
155         }
156 #if __BYTE_ORDER == __BIG_ENDIAN
157         size = ltohl(size);
158 #endif
159         if (fread(&formtype, 1, 4, f) != 4) {
160                 ast_log(LOG_WARNING, "Read failed (formtype)\n");
161                 return -1;
162         }
163         if (memcmp(&type, "RIFF", 4)) {
164                 ast_log(LOG_WARNING, "Does not begin with RIFF\n");
165                 return -1;
166         }
167         if (memcmp(&formtype, "WAVE", 4)) {
168                 ast_log(LOG_WARNING, "Does not contain WAVE\n");
169                 return -1;
170         }
171         /* Skip any facts and get the first data block */
172         for(;;)
173         { 
174                 char buf[4];
175                 
176                 /* Begin data chunk */
177                 if (fread(&buf, 1, 4, f) != 4) {
178                         ast_log(LOG_WARNING, "Read failed (block header format)\n");
179                         return -1;
180                 }
181                 /* Data has the actual length of data in it */
182                 if (fread(&data, 1, 4, f) != 4) {
183                         ast_log(LOG_WARNING, "Read failed (block '%.4s' header length)\n", buf);
184                         return -1;
185                 }
186 #if __BYTE_ORDER == __BIG_ENDIAN
187                 data = ltohl(data);
188 #endif
189                 if (memcmp(&buf, "fmt ", 4) == 0) {
190                         if (check_header_fmt(f, data, hz))
191                                 return -1;
192                         continue;
193                 }
194                 if(memcmp(buf, "data", 4) == 0 ) 
195                         break;
196                 ast_log(LOG_DEBUG, "Skipping unknown block '%.4s'\n", buf);
197                 if (fseek(f,data,SEEK_CUR) == -1 ) {
198                         ast_log(LOG_WARNING, "Failed to skip '%.4s' block: %d\n", buf, data);
199                         return -1;
200                 }
201         }
202 #if 0
203         curpos = lseek(fd, 0, SEEK_CUR);
204         truelength = lseek(fd, 0, SEEK_END);
205         lseek(fd, curpos, SEEK_SET);
206         truelength -= curpos;
207 #endif  
208         return data;
209 }
210
211 static int update_header(FILE *f)
212 {
213         off_t cur,end;
214         int datalen,filelen,bytes;
215         
216         cur = ftello(f);
217         fseek(f, 0, SEEK_END);
218         end = ftello(f);
219         /* data starts 44 bytes in */
220         bytes = end - 44;
221         datalen = htoll(bytes);
222         /* chunk size is bytes of data plus 36 bytes of header */
223         filelen = htoll(36 + bytes);
224         
225         if (cur < 0) {
226                 ast_log(LOG_WARNING, "Unable to find our position\n");
227                 return -1;
228         }
229         if (fseek(f, 4, SEEK_SET)) {
230                 ast_log(LOG_WARNING, "Unable to set our position\n");
231                 return -1;
232         }
233         if (fwrite(&filelen, 1, 4, f) != 4) {
234                 ast_log(LOG_WARNING, "Unable to set write file size\n");
235                 return -1;
236         }
237         if (fseek(f, 40, SEEK_SET)) {
238                 ast_log(LOG_WARNING, "Unable to set our position\n");
239                 return -1;
240         }
241         if (fwrite(&datalen, 1, 4, f) != 4) {
242                 ast_log(LOG_WARNING, "Unable to set write datalen\n");
243                 return -1;
244         }
245         if (fseeko(f, cur, SEEK_SET)) {
246                 ast_log(LOG_WARNING, "Unable to return to position\n");
247                 return -1;
248         }
249         return 0;
250 }
251
252 static int write_header(FILE *f, int writehz)
253 {
254         unsigned int hz;
255         unsigned int bhz;
256         unsigned int hs = htoll(16);
257         unsigned short fmt = htols(1);
258         unsigned short chans = htols(1);
259         unsigned short bysam = htols(2);
260         unsigned short bisam = htols(16);
261         unsigned int size = htoll(0);
262
263         if (writehz == 16000) {
264                 hz = htoll(16000);
265                 bhz = htoll(32000);
266         } else {
267                 hz = htoll(8000);
268                 bhz = htoll(16000);
269         }
270         /* Write a wav header, ignoring sizes which will be filled in later */
271         fseek(f,0,SEEK_SET);
272         if (fwrite("RIFF", 1, 4, f) != 4) {
273                 ast_log(LOG_WARNING, "Unable to write header\n");
274                 return -1;
275         }
276         if (fwrite(&size, 1, 4, f) != 4) {
277                 ast_log(LOG_WARNING, "Unable to write header\n");
278                 return -1;
279         }
280         if (fwrite("WAVEfmt ", 1, 8, f) != 8) {
281                 ast_log(LOG_WARNING, "Unable to write header\n");
282                 return -1;
283         }
284         if (fwrite(&hs, 1, 4, f) != 4) {
285                 ast_log(LOG_WARNING, "Unable to write header\n");
286                 return -1;
287         }
288         if (fwrite(&fmt, 1, 2, f) != 2) {
289                 ast_log(LOG_WARNING, "Unable to write header\n");
290                 return -1;
291         }
292         if (fwrite(&chans, 1, 2, f) != 2) {
293                 ast_log(LOG_WARNING, "Unable to write header\n");
294                 return -1;
295         }
296         if (fwrite(&hz, 1, 4, f) != 4) {
297                 ast_log(LOG_WARNING, "Unable to write header\n");
298                 return -1;
299         }
300         if (fwrite(&bhz, 1, 4, f) != 4) {
301                 ast_log(LOG_WARNING, "Unable to write header\n");
302                 return -1;
303         }
304         if (fwrite(&bysam, 1, 2, f) != 2) {
305                 ast_log(LOG_WARNING, "Unable to write header\n");
306                 return -1;
307         }
308         if (fwrite(&bisam, 1, 2, f) != 2) {
309                 ast_log(LOG_WARNING, "Unable to write header\n");
310                 return -1;
311         }
312         if (fwrite("data", 1, 4, f) != 4) {
313                 ast_log(LOG_WARNING, "Unable to write header\n");
314                 return -1;
315         }
316         if (fwrite(&size, 1, 4, f) != 4) {
317                 ast_log(LOG_WARNING, "Unable to write header\n");
318                 return -1;
319         }
320         return 0;
321 }
322
323 static int wav_open(struct ast_filestream *s)
324 {
325         /* We don't have any header to read or anything really, but
326            if we did, it would go here.  We also might want to check
327            and be sure it's a valid file.  */
328         struct wav_desc *tmp = (struct wav_desc *)s->_private;
329         if ((tmp->maxlen = check_header(s->f, ast_format_get_sample_rate(s->fmt->format))) < 0)
330                 return -1;
331         return 0;
332 }
333
334 static int wav_rewrite(struct ast_filestream *s, const char *comment)
335 {
336         /* We don't have any header to read or anything really, but
337            if we did, it would go here.  We also might want to check
338            and be sure it's a valid file.  */
339
340         struct wav_desc *tmp = (struct wav_desc *)s->_private;
341         tmp->hz = ast_format_get_sample_rate(s->fmt->format);
342         if (write_header(s->f,tmp->hz))
343                 return -1;
344         return 0;
345 }
346
347 static void wav_close(struct ast_filestream *s)
348 {
349         char zero = 0;
350         struct wav_desc *fs = (struct wav_desc *)s->_private;
351
352         if (s->mode == O_RDONLY) {
353                 return;
354         }
355
356         if (s->filename) {
357                 update_header(s->f);
358         }
359
360         /* Pad to even length */
361         if (fs->bytes & 0x1) {
362                 if (!fwrite(&zero, 1, 1, s->f)) {
363                         ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
364                 }
365         }
366 }
367
368 static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
369 {
370         int res;
371         int samples;    /* actual samples read */
372 #if __BYTE_ORDER == __BIG_ENDIAN
373         int x;
374         short *tmp;
375 #endif
376         int bytes;
377         off_t here;
378         /* Send a frame from the file to the appropriate channel */
379         struct wav_desc *fs = (struct wav_desc *)s->_private;
380
381         bytes = (fs->hz == 16000 ? (WAV_BUF_SIZE * 2) : WAV_BUF_SIZE);
382
383         here = ftello(s->f);
384         if (fs->maxlen - here < bytes)          /* truncate if necessary */
385                 bytes = fs->maxlen - here;
386         if (bytes < 0)
387                 bytes = 0;
388 /*      ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */
389         AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes);
390         
391         if ( (res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) <= 0 ) {
392                 if (res)
393                         ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
394                 return NULL;
395         }
396         s->fr.datalen = res;
397         s->fr.samples = samples = res / 2;
398
399 #if __BYTE_ORDER == __BIG_ENDIAN
400         tmp = (short *)(s->fr.data.ptr);
401         /* file format is little endian so we need to swap */
402         for( x = 0; x < samples; x++)
403                 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
404 #endif
405
406         *whennext = samples;
407         return &s->fr;
408 }
409
410 static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
411 {
412 #if __BYTE_ORDER == __BIG_ENDIAN
413         int x;
414         short tmp[16000], *tmpi;
415 #endif
416         struct wav_desc *s = (struct wav_desc *)fs->_private;
417         int res;
418
419         if (!f->datalen)
420                 return -1;
421
422 #if __BYTE_ORDER == __BIG_ENDIAN
423         /* swap and write */
424         if (f->datalen > sizeof(tmp)) {
425                 ast_log(LOG_WARNING, "Data length is too long\n");
426                 return -1;
427         }
428         tmpi = f->data.ptr;
429         for (x=0; x < f->datalen/2; x++) 
430                 tmp[x] = (tmpi[x] << 8) | ((tmpi[x] & 0xff00) >> 8);
431
432         if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) {
433 #else
434         /* just write */
435         if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen ) {
436 #endif
437                 ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno));
438                 return -1;
439         }
440
441         s->bytes += f->datalen;
442                 
443         return 0;
444
445 }
446
447 static int wav_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
448 {
449         off_t min = WAV_HEADER_SIZE, max, cur, offset = 0, samples;
450
451         samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */
452
453         if ((cur = ftello(fs->f)) < 0) {
454                 ast_log(AST_LOG_WARNING, "Unable to determine current position in wav filestream %p: %s\n", fs, strerror(errno));
455                 return -1;
456         }
457
458         if (fseeko(fs->f, 0, SEEK_END) < 0) {
459                 ast_log(AST_LOG_WARNING, "Unable to seek to end of wav filestream %p: %s\n", fs, strerror(errno));
460                 return -1;
461         }
462
463         if ((max = ftello(fs->f)) < 0) {
464                 ast_log(AST_LOG_WARNING, "Unable to determine max position in wav filestream %p: %s\n", fs, strerror(errno));
465                 return -1;
466         }
467
468         if (whence == SEEK_SET) {
469                 offset = samples + min;
470         } else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) {
471                 offset = samples + cur;
472         } else if (whence == SEEK_END) {
473                 offset = max - samples;
474         }
475         if (whence != SEEK_FORCECUR) {
476                 offset = (offset > max)?max:offset;
477         }
478         /* always protect the header space. */
479         offset = (offset < min)?min:offset;
480         return fseeko(fs->f, offset, SEEK_SET);
481 }
482
483 static int wav_trunc(struct ast_filestream *fs)
484 {
485         int fd;
486         off_t cur;
487
488         if ((fd = fileno(fs->f)) < 0) {
489                 ast_log(AST_LOG_WARNING, "Unable to determine file descriptor for wav filestream %p: %s\n", fs, strerror(errno));
490                 return -1;
491         }
492         if ((cur = ftello(fs->f)) < 0) {
493                 ast_log(AST_LOG_WARNING, "Unable to determine current position in wav filestream %p: %s\n", fs, strerror(errno));
494                 return -1;
495         }
496         /* Truncate file to current length */
497         if (ftruncate(fd, cur)) {
498                 return -1;
499         }
500         return update_header(fs->f);
501 }
502
503 static off_t wav_tell(struct ast_filestream *fs)
504 {
505         off_t offset;
506         offset = ftello(fs->f);
507         /* subtract header size to get samples, then divide by 2 for 16 bit samples */
508         return (offset - 44)/2;
509 }
510
511 static struct ast_format_def wav16_f = {
512         .name = "wav16",
513         .exts = "wav16",
514         .open = wav_open,
515         .rewrite = wav_rewrite,
516         .write = wav_write,
517         .seek = wav_seek,
518         .trunc = wav_trunc,
519         .tell = wav_tell,
520         .read = wav_read,
521         .close = wav_close,
522         .buf_size = (WAV_BUF_SIZE * 2) + AST_FRIENDLY_OFFSET,
523         .desc_size = sizeof(struct wav_desc),
524 };
525
526 static struct ast_format_def wav_f = {
527         .name = "wav",
528         .exts = "wav",
529         .open = wav_open,
530         .rewrite = wav_rewrite,
531         .write = wav_write,
532         .seek = wav_seek,
533         .trunc = wav_trunc,
534         .tell = wav_tell,
535         .read = wav_read,
536         .close = wav_close,
537         .buf_size = WAV_BUF_SIZE + AST_FRIENDLY_OFFSET,
538         .desc_size = sizeof(struct wav_desc),
539 };
540
541 static int load_module(void)
542 {
543         wav_f.format = ast_format_slin;
544         wav16_f.format = ast_format_slin16;
545         if (ast_format_def_register(&wav_f)
546                 || ast_format_def_register(&wav16_f))
547                 return AST_MODULE_LOAD_FAILURE;
548         return AST_MODULE_LOAD_SUCCESS;
549 }
550
551 static int unload_module(void)
552 {
553         return ast_format_def_unregister(wav_f.name)
554                 || ast_format_def_unregister(wav16_f.name);
555 }
556
557 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Microsoft WAV/WAV16 format (8kHz/16kHz Signed Linear)",
558         .support_level = AST_MODULE_SUPPORT_CORE,
559         .load = load_module,
560         .unload = unload_module,
561         .load_pri = AST_MODPRI_APP_DEPEND
562 );