remove extraneous svn:executable properties
[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 <unistd.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30 #include <stdlib.h>
31 #include <sys/time.h>
32 #include <stdio.h>
33 #include <errno.h>
34 #include <string.h>
35
36 #include "asterisk.h"
37
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39
40 #include "asterisk/lock.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/file.h"
43 #include "asterisk/logger.h"
44 #include "asterisk/sched.h"
45 #include "asterisk/module.h"
46 #include "asterisk/endian.h"
47
48 /* Some Ideas for this code came from makewave.c by Jeffrey Chilton */
49
50 /* Portions of the conversion code are by guido@sienanet.it */
51
52 struct ast_filestream {
53         void *reserved[AST_RESERVED_POINTERS];
54         /* This is what a filestream means to us */
55         FILE *f; /* Descriptor */
56         int bytes;
57         int needsgain;
58         struct ast_frame fr;                            /* Frame information */
59         char waste[AST_FRIENDLY_OFFSET];        /* Buffer for sending frames, etc */
60         char empty;                                                     /* Empty character */
61         short buf[160]; 
62         int foffset;
63         int lasttimeout;
64         int maxlen;
65         struct timeval last;
66 };
67
68
69 AST_MUTEX_DEFINE_STATIC(wav_lock);
70 static int glistcnt = 0;
71
72 static char *name = "wav";
73 static char *desc = "Microsoft WAV format (8000hz Signed Linear)";
74 static char *exts = "wav";
75
76 #define BLOCKSIZE 160
77
78 #define GAIN 2          /* 2^GAIN is the multiple to increase the volume by */
79
80 #if __BYTE_ORDER == __LITTLE_ENDIAN
81 #define htoll(b) (b)
82 #define htols(b) (b)
83 #define ltohl(b) (b)
84 #define ltohs(b) (b)
85 #else
86 #if __BYTE_ORDER == __BIG_ENDIAN
87 #define htoll(b)  \
88           (((((b)      ) & 0xFF) << 24) | \
89                ((((b) >>  8) & 0xFF) << 16) | \
90                    ((((b) >> 16) & 0xFF) <<  8) | \
91                    ((((b) >> 24) & 0xFF)      ))
92 #define htols(b) \
93           (((((b)      ) & 0xFF) << 8) | \
94                    ((((b) >> 8) & 0xFF)      ))
95 #define ltohl(b) htoll(b)
96 #define ltohs(b) htols(b)
97 #else
98 #error "Endianess not defined"
99 #endif
100 #endif
101
102
103 static int check_header(FILE *f)
104 {
105         int type, size, formtype;
106         int fmt, hsize;
107         short format, chans, bysam, bisam;
108         int bysec;
109         int freq;
110         int data;
111         if (fread(&type, 1, 4, f) != 4) {
112                 ast_log(LOG_WARNING, "Read failed (type)\n");
113                 return -1;
114         }
115         if (fread(&size, 1, 4, f) != 4) {
116                 ast_log(LOG_WARNING, "Read failed (size)\n");
117                 return -1;
118         }
119         size = ltohl(size);
120         if (fread(&formtype, 1, 4, f) != 4) {
121                 ast_log(LOG_WARNING, "Read failed (formtype)\n");
122                 return -1;
123         }
124         if (memcmp(&type, "RIFF", 4)) {
125                 ast_log(LOG_WARNING, "Does not begin with RIFF\n");
126                 return -1;
127         }
128         if (memcmp(&formtype, "WAVE", 4)) {
129                 ast_log(LOG_WARNING, "Does not contain WAVE\n");
130                 return -1;
131         }
132         if (fread(&fmt, 1, 4, f) != 4) {
133                 ast_log(LOG_WARNING, "Read failed (fmt)\n");
134                 return -1;
135         }
136         if (memcmp(&fmt, "fmt ", 4)) {
137                 ast_log(LOG_WARNING, "Does not say fmt\n");
138                 return -1;
139         }
140         if (fread(&hsize, 1, 4, f) != 4) {
141                 ast_log(LOG_WARNING, "Read failed (formtype)\n");
142                 return -1;
143         }
144         if (ltohl(hsize) < 16) {
145                 ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize));
146                 return -1;
147         }
148         if (fread(&format, 1, 2, f) != 2) {
149                 ast_log(LOG_WARNING, "Read failed (format)\n");
150                 return -1;
151         }
152         if (ltohs(format) != 1) {
153                 ast_log(LOG_WARNING, "Not a wav file %d\n", ltohs(format));
154                 return -1;
155         }
156         if (fread(&chans, 1, 2, f) != 2) {
157                 ast_log(LOG_WARNING, "Read failed (format)\n");
158                 return -1;
159         }
160         if (ltohs(chans) != 1) {
161                 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
162                 return -1;
163         }
164         if (fread(&freq, 1, 4, f) != 4) {
165                 ast_log(LOG_WARNING, "Read failed (freq)\n");
166                 return -1;
167         }
168         if (ltohl(freq) != 8000) {
169                 ast_log(LOG_WARNING, "Unexpected freqency %d\n", ltohl(freq));
170                 return -1;
171         }
172         /* Ignore the byte frequency */
173         if (fread(&bysec, 1, 4, f) != 4) {
174                 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n");
175                 return -1;
176         }
177         /* Check bytes per sample */
178         if (fread(&bysam, 1, 2, f) != 2) {
179                 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n");
180                 return -1;
181         }
182         if (ltohs(bysam) != 2) {
183                 ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam));
184                 return -1;
185         }
186         if (fread(&bisam, 1, 2, f) != 2) {
187                 ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam));
188                 return -1;
189         }
190         /* Skip any additional header */
191         if (fseek(f,ltohl(hsize)-16,SEEK_CUR) == -1 ) {
192                 ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", ltohl(hsize)-16 );
193                 return -1;
194         }
195         /* Skip any facts and get the first data block */
196         for(;;)
197         { 
198                 char buf[4];
199             
200             /* Begin data chunk */
201             if (fread(&buf, 1, 4, f) != 4) {
202                         ast_log(LOG_WARNING, "Read failed (data)\n");
203                         return -1;
204             }
205             /* Data has the actual length of data in it */
206             if (fread(&data, 1, 4, f) != 4) {
207                         ast_log(LOG_WARNING, "Read failed (data)\n");
208                         return -1;
209             }
210             data = ltohl(data);
211             if(memcmp(buf, "data", 4) == 0 ) 
212                         break;
213             if(memcmp(buf, "fact", 4) != 0 ) {
214                         ast_log(LOG_WARNING, "Unknown block - not fact or data\n");
215                         return -1;
216             }
217             if (fseek(f,data,SEEK_CUR) == -1 ) {
218                         ast_log(LOG_WARNING, "Failed to skip fact block: %d\n", data );
219                         return -1;
220             }
221         }
222 #if 0
223         curpos = lseek(fd, 0, SEEK_CUR);
224         truelength = lseek(fd, 0, SEEK_END);
225         lseek(fd, curpos, SEEK_SET);
226         truelength -= curpos;
227 #endif  
228         return data;
229 }
230
231 static int update_header(FILE *f)
232 {
233         off_t cur,end;
234         int datalen,filelen,bytes;
235         
236         
237         cur = ftell(f);
238         fseek(f, 0, SEEK_END);
239         end = ftell(f);
240         /* data starts 44 bytes in */
241         bytes = end - 44;
242         datalen = htoll(bytes);
243         /* chunk size is bytes of data plus 36 bytes of header */
244         filelen = htoll(36 + bytes);
245         
246         if (cur < 0) {
247                 ast_log(LOG_WARNING, "Unable to find our position\n");
248                 return -1;
249         }
250         if (fseek(f, 4, SEEK_SET)) {
251                 ast_log(LOG_WARNING, "Unable to set our position\n");
252                 return -1;
253         }
254         if (fwrite(&filelen, 1, 4, f) != 4) {
255                 ast_log(LOG_WARNING, "Unable to set write file size\n");
256                 return -1;
257         }
258         if (fseek(f, 40, SEEK_SET)) {
259                 ast_log(LOG_WARNING, "Unable to set our position\n");
260                 return -1;
261         }
262         if (fwrite(&datalen, 1, 4, f) != 4) {
263                 ast_log(LOG_WARNING, "Unable to set write datalen\n");
264                 return -1;
265         }
266         if (fseek(f, cur, SEEK_SET)) {
267                 ast_log(LOG_WARNING, "Unable to return to position\n");
268                 return -1;
269         }
270         return 0;
271 }
272
273 static int write_header(FILE *f)
274 {
275         unsigned int hz=htoll(8000);
276         unsigned int bhz = htoll(16000);
277         unsigned int hs = htoll(16);
278         unsigned short fmt = htols(1);
279         unsigned short chans = htols(1);
280         unsigned short bysam = htols(2);
281         unsigned short bisam = htols(16);
282         unsigned int size = htoll(0);
283         /* Write a wav header, ignoring sizes which will be filled in later */
284         fseek(f,0,SEEK_SET);
285         if (fwrite("RIFF", 1, 4, f) != 4) {
286                 ast_log(LOG_WARNING, "Unable to write header\n");
287                 return -1;
288         }
289         if (fwrite(&size, 1, 4, f) != 4) {
290                 ast_log(LOG_WARNING, "Unable to write header\n");
291                 return -1;
292         }
293         if (fwrite("WAVEfmt ", 1, 8, f) != 8) {
294                 ast_log(LOG_WARNING, "Unable to write header\n");
295                 return -1;
296         }
297         if (fwrite(&hs, 1, 4, f) != 4) {
298                 ast_log(LOG_WARNING, "Unable to write header\n");
299                 return -1;
300         }
301         if (fwrite(&fmt, 1, 2, f) != 2) {
302                 ast_log(LOG_WARNING, "Unable to write header\n");
303                 return -1;
304         }
305         if (fwrite(&chans, 1, 2, f) != 2) {
306                 ast_log(LOG_WARNING, "Unable to write header\n");
307                 return -1;
308         }
309         if (fwrite(&hz, 1, 4, f) != 4) {
310                 ast_log(LOG_WARNING, "Unable to write header\n");
311                 return -1;
312         }
313         if (fwrite(&bhz, 1, 4, f) != 4) {
314                 ast_log(LOG_WARNING, "Unable to write header\n");
315                 return -1;
316         }
317         if (fwrite(&bysam, 1, 2, f) != 2) {
318                 ast_log(LOG_WARNING, "Unable to write header\n");
319                 return -1;
320         }
321         if (fwrite(&bisam, 1, 2, f) != 2) {
322                 ast_log(LOG_WARNING, "Unable to write header\n");
323                 return -1;
324         }
325         if (fwrite("data", 1, 4, f) != 4) {
326                 ast_log(LOG_WARNING, "Unable to write header\n");
327                 return -1;
328         }
329         if (fwrite(&size, 1, 4, f) != 4) {
330                 ast_log(LOG_WARNING, "Unable to write header\n");
331                 return -1;
332         }
333         return 0;
334 }
335
336 static struct ast_filestream *wav_open(FILE *f)
337 {
338         /* We don't have any header to read or anything really, but
339            if we did, it would go here.  We also might want to check
340            and be sure it's a valid file.  */
341         struct ast_filestream *tmp;
342         if ((tmp = malloc(sizeof(struct ast_filestream)))) {
343                 memset(tmp, 0, sizeof(struct ast_filestream));
344                 if ((tmp->maxlen = check_header(f)) < 0) {
345                         free(tmp);
346                         return NULL;
347                 }
348                 if (ast_mutex_lock(&wav_lock)) {
349                         ast_log(LOG_WARNING, "Unable to lock wav list\n");
350                         free(tmp);
351                         return NULL;
352                 }
353                 tmp->f = f;
354                 tmp->needsgain = 1;
355                 tmp->fr.data = tmp->buf;
356                 tmp->fr.frametype = AST_FRAME_VOICE;
357                 tmp->fr.subclass = AST_FORMAT_SLINEAR;
358                 /* datalen will vary for each frame */
359                 tmp->fr.src = name;
360                 tmp->fr.mallocd = 0;
361                 tmp->bytes = 0;
362                 glistcnt++;
363                 ast_mutex_unlock(&wav_lock);
364                 ast_update_use_count();
365         }
366         return tmp;
367 }
368
369 static struct ast_filestream *wav_rewrite(FILE *f, const char *comment)
370 {
371         /* We don't have any header to read or anything really, but
372            if we did, it would go here.  We also might want to check
373            and be sure it's a valid file.  */
374         struct ast_filestream *tmp;
375         if ((tmp = malloc(sizeof(struct ast_filestream)))) {
376                 memset(tmp, 0, sizeof(struct ast_filestream));
377                 if (write_header(f)) {
378                         free(tmp);
379                         return NULL;
380                 }
381                 if (ast_mutex_lock(&wav_lock)) {
382                         ast_log(LOG_WARNING, "Unable to lock wav list\n");
383                         free(tmp);
384                         return NULL;
385                 }
386                 tmp->f = f;
387                 glistcnt++;
388                 ast_mutex_unlock(&wav_lock);
389                 ast_update_use_count();
390         } else
391                 ast_log(LOG_WARNING, "Out of memory\n");
392         return tmp;
393 }
394
395 static void wav_close(struct ast_filestream *s)
396 {
397         char zero = 0;
398         if (ast_mutex_lock(&wav_lock)) {
399                 ast_log(LOG_WARNING, "Unable to lock wav list\n");
400                 return;
401         }
402         glistcnt--;
403         ast_mutex_unlock(&wav_lock);
404         ast_update_use_count();
405         /* Pad to even length */
406         if (s->bytes & 0x1)
407                 fwrite(&zero, 1, 1, s->f);
408         fclose(s->f);
409         free(s);
410         s = NULL;
411 }
412
413 static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
414 {
415         int res;
416         int delay;
417         int x;
418         short tmp[sizeof(s->buf) / 2];
419         int bytes = sizeof(tmp);
420         off_t here;
421         /* Send a frame from the file to the appropriate channel */
422         here = ftell(s->f);
423         if ((s->maxlen - here) < bytes)
424                 bytes = s->maxlen - here;
425         if (bytes < 0)
426                 bytes = 0;
427 /*      ast_log(LOG_DEBUG, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */
428         
429         if ( (res = fread(tmp, 1, bytes, s->f)) <= 0 ) {
430                 if (res) {
431                         ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
432                 }
433                 return NULL;
434         }
435
436 #if __BYTE_ORDER == __BIG_ENDIAN
437         for( x = 0; x < sizeof(tmp)/2; x++) tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
438 #endif
439
440         if (s->needsgain) {
441                 for (x=0;x<sizeof(tmp)/2;x++)
442                         if (tmp[x] & ((1 << GAIN) - 1)) {
443                                 /* If it has data down low, then it's not something we've artificially increased gain
444                                    on, so we don't need to gain adjust it */
445                                 s->needsgain = 0;
446                         }
447         }
448         if (s->needsgain) {
449                 for (x=0;x<sizeof(tmp)/2;x++) {
450                         s->buf[x] = tmp[x] >> GAIN;
451                 }
452         } else {
453                 memcpy(s->buf, tmp, sizeof(s->buf));
454         }
455                         
456         delay = res / 2;
457         s->fr.frametype = AST_FRAME_VOICE;
458         s->fr.subclass = AST_FORMAT_SLINEAR;
459         s->fr.offset = AST_FRIENDLY_OFFSET;
460         s->fr.datalen = res;
461         s->fr.data = s->buf;
462         s->fr.mallocd = 0;
463         s->fr.samples = delay;
464         *whennext = delay;
465         return &s->fr;
466 }
467
468 static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
469 {
470         int res = 0;
471         int x;
472         short tmp[8000], *tmpi;
473         float tmpf;
474         if (f->frametype != AST_FRAME_VOICE) {
475                 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
476                 return -1;
477         }
478         if (f->subclass != AST_FORMAT_SLINEAR) {
479                 ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass);
480                 return -1;
481         }
482         if (f->datalen > sizeof(tmp)) {
483                 ast_log(LOG_WARNING, "Data length is too long\n");
484                 return -1;
485         }
486         if (!f->datalen)
487                 return -1;
488
489 #if 0
490         printf("Data Length: %d\n", f->datalen);
491 #endif  
492
493         if (fs->buf) {
494                 tmpi = f->data;
495                 /* Volume adjust here to accomodate */
496                 for (x=0;x<f->datalen/2;x++) {
497                         tmpf = ((float)tmpi[x]) * ((float)(1 << GAIN));
498                         if (tmpf > 32767.0)
499                                 tmpf = 32767.0;
500                         if (tmpf < -32768.0)
501                                 tmpf = -32768.0;
502                         tmp[x] = tmpf;
503                         tmp[x] &= ~((1 << GAIN) - 1);
504
505 #if __BYTE_ORDER == __BIG_ENDIAN
506                         tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
507 #endif
508
509                 }
510                 if ((fwrite(tmp, 1, f->datalen, fs->f) != f->datalen) ) {
511                         ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno));
512                         return -1;
513                 }
514         } else {
515                 ast_log(LOG_WARNING, "Cannot write data to file.\n");
516                 return -1;
517         }
518         
519         fs->bytes += f->datalen;
520         update_header(fs->f);
521                 
522         return 0;
523
524 }
525
526 static int wav_seek(struct ast_filestream *fs, long sample_offset, int whence)
527 {
528         off_t min,max,cur;
529         long offset=0,samples;
530         
531         samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */
532         min = 44; /* wav header is 44 bytes */
533         cur = ftell(fs->f);
534         fseek(fs->f, 0, SEEK_END);
535         max = ftell(fs->f);
536         if (whence == SEEK_SET)
537                 offset = samples + min;
538         else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
539                 offset = samples + cur;
540         else if (whence == SEEK_END)
541                 offset = max - samples;
542         if (whence != SEEK_FORCECUR) {
543                 offset = (offset > max)?max:offset;
544         }
545         /* always protect the header space. */
546         offset = (offset < min)?min:offset;
547         return fseek(fs->f,offset,SEEK_SET);
548 }
549
550 static int wav_trunc(struct ast_filestream *fs)
551 {
552         if (ftruncate(fileno(fs->f), ftell(fs->f)))
553                 return -1;
554         return update_header(fs->f);
555 }
556
557 static long wav_tell(struct ast_filestream *fs)
558 {
559         off_t offset;
560         offset = ftell(fs->f);
561         /* subtract header size to get samples, then divide by 2 for 16 bit samples */
562         return (offset - 44)/2;
563 }
564
565 static char *wav_getcomment(struct ast_filestream *s)
566 {
567         return NULL;
568 }
569
570 int load_module()
571 {
572         return ast_format_register(name, exts, AST_FORMAT_SLINEAR,
573                                                                 wav_open,
574                                                                 wav_rewrite,
575                                                                 wav_write,
576                                                                 wav_seek,
577                                                                 wav_trunc,
578                                                                 wav_tell,
579                                                                 wav_read,
580                                                                 wav_close,
581                                                                 wav_getcomment);
582                                                                 
583                                                                 
584 }
585
586 int unload_module()
587 {
588         return ast_format_unregister(name);
589 }       
590
591 int usecount()
592 {
593         return glistcnt;
594 }
595
596 char *description()
597 {
598         return desc;
599 }
600
601
602 char *key()
603 {
604         return ASTERISK_GPL_KEY;
605 }