Merged revisions 60325 via svnmerge from
[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 <unistd.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <stdlib.h>
35 #include <sys/time.h>
36 #include <stdio.h>
37 #include <errno.h>
38 #include <string.h>
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 #define WAV_BUF_SIZE    320
53
54 struct wav_desc {       /* format-specific parameters */
55         int bytes;
56         int needsgain;
57         int lasttimeout;
58         int maxlen;
59         struct timeval last;
60 };
61
62 #define BLOCKSIZE 160
63
64 #define GAIN 0          /* 2^GAIN is the multiple to increase the volume by.  The original value of GAIN was 2, or 4x (12 dB),
65                          * but there were many reports of the clipping of loud signal peaks (issue 5823 for example). */
66
67 #if __BYTE_ORDER == __LITTLE_ENDIAN
68 #define htoll(b) (b)
69 #define htols(b) (b)
70 #define ltohl(b) (b)
71 #define ltohs(b) (b)
72 #else
73 #if __BYTE_ORDER == __BIG_ENDIAN
74 #define htoll(b)  \
75           (((((b)      ) & 0xFF) << 24) | \
76                ((((b) >>  8) & 0xFF) << 16) | \
77                    ((((b) >> 16) & 0xFF) <<  8) | \
78                    ((((b) >> 24) & 0xFF)      ))
79 #define htols(b) \
80           (((((b)      ) & 0xFF) << 8) | \
81                    ((((b) >> 8) & 0xFF)      ))
82 #define ltohl(b) htoll(b)
83 #define ltohs(b) htols(b)
84 #else
85 #error "Endianess not defined"
86 #endif
87 #endif
88
89
90 static int check_header(FILE *f)
91 {
92         int type, size, formtype;
93         int fmt, hsize;
94         short format, chans, bysam, bisam;
95         int bysec;
96         int freq;
97         int data;
98         if (fread(&type, 1, 4, f) != 4) {
99                 ast_log(LOG_WARNING, "Read failed (type)\n");
100                 return -1;
101         }
102         if (fread(&size, 1, 4, f) != 4) {
103                 ast_log(LOG_WARNING, "Read failed (size)\n");
104                 return -1;
105         }
106         size = ltohl(size);
107         if (fread(&formtype, 1, 4, f) != 4) {
108                 ast_log(LOG_WARNING, "Read failed (formtype)\n");
109                 return -1;
110         }
111         if (memcmp(&type, "RIFF", 4)) {
112                 ast_log(LOG_WARNING, "Does not begin with RIFF\n");
113                 return -1;
114         }
115         if (memcmp(&formtype, "WAVE", 4)) {
116                 ast_log(LOG_WARNING, "Does not contain WAVE\n");
117                 return -1;
118         }
119         if (fread(&fmt, 1, 4, f) != 4) {
120                 ast_log(LOG_WARNING, "Read failed (fmt)\n");
121                 return -1;
122         }
123         if (memcmp(&fmt, "fmt ", 4)) {
124                 ast_log(LOG_WARNING, "Does not say fmt\n");
125                 return -1;
126         }
127         if (fread(&hsize, 1, 4, f) != 4) {
128                 ast_log(LOG_WARNING, "Read failed (formtype)\n");
129                 return -1;
130         }
131         if (ltohl(hsize) < 16) {
132                 ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize));
133                 return -1;
134         }
135         if (fread(&format, 1, 2, f) != 2) {
136                 ast_log(LOG_WARNING, "Read failed (format)\n");
137                 return -1;
138         }
139         if (ltohs(format) != 1) {
140                 ast_log(LOG_WARNING, "Not a wav file %d\n", ltohs(format));
141                 return -1;
142         }
143         if (fread(&chans, 1, 2, f) != 2) {
144                 ast_log(LOG_WARNING, "Read failed (format)\n");
145                 return -1;
146         }
147         if (ltohs(chans) != 1) {
148                 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
149                 return -1;
150         }
151         if (fread(&freq, 1, 4, f) != 4) {
152                 ast_log(LOG_WARNING, "Read failed (freq)\n");
153                 return -1;
154         }
155         if (ltohl(freq) != DEFAULT_SAMPLE_RATE) {
156                 ast_log(LOG_WARNING, "Unexpected freqency %d\n", ltohl(freq));
157                 return -1;
158         }
159         /* Ignore the byte frequency */
160         if (fread(&bysec, 1, 4, f) != 4) {
161                 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n");
162                 return -1;
163         }
164         /* Check bytes per sample */
165         if (fread(&bysam, 1, 2, f) != 2) {
166                 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n");
167                 return -1;
168         }
169         if (ltohs(bysam) != 2) {
170                 ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam));
171                 return -1;
172         }
173         if (fread(&bisam, 1, 2, f) != 2) {
174                 ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam));
175                 return -1;
176         }
177         /* Skip any additional header */
178         if (fseek(f,ltohl(hsize)-16,SEEK_CUR) == -1 ) {
179                 ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", ltohl(hsize)-16 );
180                 return -1;
181         }
182         /* Skip any facts and get the first data block */
183         for(;;)
184         { 
185                 char buf[4];
186             
187             /* Begin data chunk */
188             if (fread(&buf, 1, 4, f) != 4) {
189                         ast_log(LOG_WARNING, "Read failed (data)\n");
190                         return -1;
191             }
192             /* Data has the actual length of data in it */
193             if (fread(&data, 1, 4, f) != 4) {
194                         ast_log(LOG_WARNING, "Read failed (data)\n");
195                         return -1;
196             }
197             data = ltohl(data);
198             if(memcmp(buf, "data", 4) == 0 ) 
199                         break;
200             if(memcmp(buf, "fact", 4) != 0 ) {
201                         ast_log(LOG_WARNING, "Unknown block - not fact or data\n");
202                         return -1;
203             }
204             if (fseek(f,data,SEEK_CUR) == -1 ) {
205                         ast_log(LOG_WARNING, "Failed to skip fact block: %d\n", data );
206                         return -1;
207             }
208         }
209 #if 0
210         curpos = lseek(fd, 0, SEEK_CUR);
211         truelength = lseek(fd, 0, SEEK_END);
212         lseek(fd, curpos, SEEK_SET);
213         truelength -= curpos;
214 #endif  
215         return data;
216 }
217
218 static int update_header(FILE *f)
219 {
220         off_t cur,end;
221         int datalen,filelen,bytes;
222         
223         cur = ftello(f);
224         fseek(f, 0, SEEK_END);
225         end = ftello(f);
226         /* data starts 44 bytes in */
227         bytes = end - 44;
228         datalen = htoll(bytes);
229         /* chunk size is bytes of data plus 36 bytes of header */
230         filelen = htoll(36 + bytes);
231         
232         if (cur < 0) {
233                 ast_log(LOG_WARNING, "Unable to find our position\n");
234                 return -1;
235         }
236         if (fseek(f, 4, SEEK_SET)) {
237                 ast_log(LOG_WARNING, "Unable to set our position\n");
238                 return -1;
239         }
240         if (fwrite(&filelen, 1, 4, f) != 4) {
241                 ast_log(LOG_WARNING, "Unable to set write file size\n");
242                 return -1;
243         }
244         if (fseek(f, 40, SEEK_SET)) {
245                 ast_log(LOG_WARNING, "Unable to set our position\n");
246                 return -1;
247         }
248         if (fwrite(&datalen, 1, 4, f) != 4) {
249                 ast_log(LOG_WARNING, "Unable to set write datalen\n");
250                 return -1;
251         }
252         if (fseeko(f, cur, SEEK_SET)) {
253                 ast_log(LOG_WARNING, "Unable to return to position\n");
254                 return -1;
255         }
256         return 0;
257 }
258
259 static int write_header(FILE *f)
260 {
261         unsigned int hz=htoll(8000);
262         unsigned int bhz = htoll(16000);
263         unsigned int hs = htoll(16);
264         unsigned short fmt = htols(1);
265         unsigned short chans = htols(1);
266         unsigned short bysam = htols(2);
267         unsigned short bisam = htols(16);
268         unsigned int size = htoll(0);
269         /* Write a wav header, ignoring sizes which will be filled in later */
270         fseek(f,0,SEEK_SET);
271         if (fwrite("RIFF", 1, 4, f) != 4) {
272                 ast_log(LOG_WARNING, "Unable to write header\n");
273                 return -1;
274         }
275         if (fwrite(&size, 1, 4, f) != 4) {
276                 ast_log(LOG_WARNING, "Unable to write header\n");
277                 return -1;
278         }
279         if (fwrite("WAVEfmt ", 1, 8, f) != 8) {
280                 ast_log(LOG_WARNING, "Unable to write header\n");
281                 return -1;
282         }
283         if (fwrite(&hs, 1, 4, f) != 4) {
284                 ast_log(LOG_WARNING, "Unable to write header\n");
285                 return -1;
286         }
287         if (fwrite(&fmt, 1, 2, f) != 2) {
288                 ast_log(LOG_WARNING, "Unable to write header\n");
289                 return -1;
290         }
291         if (fwrite(&chans, 1, 2, f) != 2) {
292                 ast_log(LOG_WARNING, "Unable to write header\n");
293                 return -1;
294         }
295         if (fwrite(&hz, 1, 4, f) != 4) {
296                 ast_log(LOG_WARNING, "Unable to write header\n");
297                 return -1;
298         }
299         if (fwrite(&bhz, 1, 4, f) != 4) {
300                 ast_log(LOG_WARNING, "Unable to write header\n");
301                 return -1;
302         }
303         if (fwrite(&bysam, 1, 2, f) != 2) {
304                 ast_log(LOG_WARNING, "Unable to write header\n");
305                 return -1;
306         }
307         if (fwrite(&bisam, 1, 2, f) != 2) {
308                 ast_log(LOG_WARNING, "Unable to write header\n");
309                 return -1;
310         }
311         if (fwrite("data", 1, 4, f) != 4) {
312                 ast_log(LOG_WARNING, "Unable to write header\n");
313                 return -1;
314         }
315         if (fwrite(&size, 1, 4, f) != 4) {
316                 ast_log(LOG_WARNING, "Unable to write header\n");
317                 return -1;
318         }
319         return 0;
320 }
321
322 static int wav_open(struct ast_filestream *s)
323 {
324         /* We don't have any header to read or anything really, but
325            if we did, it would go here.  We also might want to check
326            and be sure it's a valid file.  */
327         struct wav_desc *tmp = (struct wav_desc *)s->private;
328         if ((tmp->maxlen = check_header(s->f)) < 0)
329                 return -1;
330         return 0;
331 }
332
333 static int wav_rewrite(struct ast_filestream *s, const char *comment)
334 {
335         /* We don't have any header to read or anything really, but
336            if we did, it would go here.  We also might want to check
337            and be sure it's a valid file.  */
338
339         if (write_header(s->f))
340                 return -1;
341         return 0;
342 }
343
344 static void wav_close(struct ast_filestream *s)
345 {
346         char zero = 0;
347         struct wav_desc *fs = (struct wav_desc *)s->private;
348         /* Pad to even length */
349         if (fs->bytes & 0x1)
350                 fwrite(&zero, 1, 1, s->f);
351 }
352
353 static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
354 {
355         int res;
356         int samples;    /* actual samples read */
357         int x;
358         short *tmp;
359         int bytes = WAV_BUF_SIZE;       /* in bytes */
360         off_t here;
361         /* Send a frame from the file to the appropriate channel */
362         struct wav_desc *fs = (struct wav_desc *)s->private;
363
364         here = ftello(s->f);
365         if (fs->maxlen - here < bytes)          /* truncate if necessary */
366                 bytes = fs->maxlen - here;
367         if (bytes < 0)
368                 bytes = 0;
369 /*      ast_log(LOG_DEBUG, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */
370         s->fr.frametype = AST_FRAME_VOICE;
371         s->fr.subclass = AST_FORMAT_SLINEAR;
372         s->fr.mallocd = 0;
373         AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes);
374         
375         if ( (res = fread(s->fr.data, 1, s->fr.datalen, s->f)) <= 0 ) {
376                 if (res)
377                         ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
378                 return NULL;
379         }
380         s->fr.datalen = res;
381         s->fr.samples = samples = res / 2;
382
383         tmp = (short *)(s->fr.data);
384 #if __BYTE_ORDER == __BIG_ENDIAN
385         /* file format is little endian so we need to swap */
386         for( x = 0; x < samples; x++)
387                 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
388 #endif
389
390         if (fs->needsgain) {
391                 for (x=0; x < samples; x++) {
392                         if (tmp[x] & ((1 << GAIN) - 1)) {
393                                 /* If it has data down low, then it's not something we've artificially increased gain
394                                    on, so we don't need to gain adjust it */
395                                 fs->needsgain = 0;
396                                 break;
397                         }
398                 }
399                 if (fs->needsgain) {
400                         for (x=0; x < samples; x++)
401                                 tmp[x] = tmp[x] >> GAIN;
402                 }
403         }
404                         
405         *whennext = samples;
406         return &s->fr;
407 }
408
409 static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
410 {
411         int x;
412         short tmp[8000], *tmpi;
413         float tmpf;
414         struct wav_desc *s = (struct wav_desc *)fs->private;
415         int res;
416
417         if (f->frametype != AST_FRAME_VOICE) {
418                 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
419                 return -1;
420         }
421         if (f->subclass != AST_FORMAT_SLINEAR) {
422                 ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass);
423                 return -1;
424         }
425         if (f->datalen > sizeof(tmp)) {
426                 ast_log(LOG_WARNING, "Data length is too long\n");
427                 return -1;
428         }
429         if (!f->datalen)
430                 return -1;
431
432 #if 0
433         printf("Data Length: %d\n", f->datalen);
434 #endif  
435
436         tmpi = f->data;
437         /* Volume adjust here to accomodate */
438         for (x=0;x<f->datalen/2;x++) {
439                 tmpf = ((float)tmpi[x]) * ((float)(1 << GAIN));
440                 if (tmpf > 32767.0)
441                         tmpf = 32767.0;
442                 if (tmpf < -32768.0)
443                         tmpf = -32768.0;
444                 tmp[x] = tmpf;
445                 tmp[x] &= ~((1 << GAIN) - 1);
446
447 #if __BYTE_ORDER == __BIG_ENDIAN
448                 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
449 #endif
450
451         }
452         if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) {
453                 ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno));
454                 return -1;
455         }
456
457         s->bytes += f->datalen;
458         update_header(fs->f);
459                 
460         return 0;
461
462 }
463
464 static int wav_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
465 {
466         off_t min, max, cur, offset = 0, samples;
467
468         samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */
469         min = 44; /* wav header is 44 bytes */
470         cur = ftello(fs->f);
471         fseeko(fs->f, 0, SEEK_END);
472         max = ftello(fs->f);
473         if (whence == SEEK_SET)
474                 offset = samples + min;
475         else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
476                 offset = samples + cur;
477         else if (whence == SEEK_END)
478                 offset = max - samples;
479         if (whence != SEEK_FORCECUR) {
480                 offset = (offset > max)?max:offset;
481         }
482         /* always protect the header space. */
483         offset = (offset < min)?min:offset;
484         return fseeko(fs->f, offset, SEEK_SET);
485 }
486
487 static int wav_trunc(struct ast_filestream *fs)
488 {
489         if (ftruncate(fileno(fs->f), ftello(fs->f)))
490                 return -1;
491         return update_header(fs->f);
492 }
493
494 static off_t wav_tell(struct ast_filestream *fs)
495 {
496         off_t offset;
497         offset = ftello(fs->f);
498         /* subtract header size to get samples, then divide by 2 for 16 bit samples */
499         return (offset - 44)/2;
500 }
501
502 static const struct ast_format wav_f = {
503         .name = "wav",
504         .exts = "wav",
505         .format = AST_FORMAT_SLINEAR,
506         .open = wav_open,
507         .rewrite = wav_rewrite,
508         .write = wav_write,
509         .seek = wav_seek,
510         .trunc = wav_trunc,
511         .tell = wav_tell,
512         .read = wav_read,
513         .close = wav_close,
514         .buf_size = WAV_BUF_SIZE + AST_FRIENDLY_OFFSET,
515         .desc_size = sizeof(struct wav_desc),
516 };
517
518 static int load_module(void)
519 {
520         return ast_format_register(&wav_f);
521 }
522
523 static int unload_module(void)
524 {
525         return ast_format_unregister(wav_f.name);
526 }       
527
528 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Microsoft WAV format (8000Hz Signed Linear)");