2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
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)
29 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
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"
48 /* Some Ideas for this code came from makewave.c by Jeffrey Chilton */
50 /* Portions of the conversion code are by guido@sienanet.it */
52 #define WAV_BUF_SIZE 320
54 struct wav_desc
{ /* format-specific parameters */
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). */
67 #if __BYTE_ORDER == __LITTLE_ENDIAN
73 #if __BYTE_ORDER == __BIG_ENDIAN
75 (((((b) ) & 0xFF) << 24) | \
76 ((((b) >> 8) & 0xFF) << 16) | \
77 ((((b) >> 16) & 0xFF) << 8) | \
78 ((((b) >> 24) & 0xFF) ))
80 (((((b) ) & 0xFF) << 8) | \
81 ((((b) >> 8) & 0xFF) ))
82 #define ltohl(b) htoll(b)
83 #define ltohs(b) htols(b)
85 #error "Endianess not defined"
90 static int check_header(FILE *f
)
92 int type
, size
, formtype
;
94 short format
, chans
, bysam
, bisam
;
98 if (fread(&type
, 1, 4, f
) != 4) {
99 ast_log(LOG_WARNING
, "Read failed (type)\n");
102 if (fread(&size
, 1, 4, f
) != 4) {
103 ast_log(LOG_WARNING
, "Read failed (size)\n");
107 if (fread(&formtype
, 1, 4, f
) != 4) {
108 ast_log(LOG_WARNING
, "Read failed (formtype)\n");
111 if (memcmp(&type
, "RIFF", 4)) {
112 ast_log(LOG_WARNING
, "Does not begin with RIFF\n");
115 if (memcmp(&formtype
, "WAVE", 4)) {
116 ast_log(LOG_WARNING
, "Does not contain WAVE\n");
119 if (fread(&fmt
, 1, 4, f
) != 4) {
120 ast_log(LOG_WARNING
, "Read failed (fmt)\n");
123 if (memcmp(&fmt
, "fmt ", 4)) {
124 ast_log(LOG_WARNING
, "Does not say fmt\n");
127 if (fread(&hsize
, 1, 4, f
) != 4) {
128 ast_log(LOG_WARNING
, "Read failed (formtype)\n");
131 if (ltohl(hsize
) < 16) {
132 ast_log(LOG_WARNING
, "Unexpected header size %d\n", ltohl(hsize
));
135 if (fread(&format
, 1, 2, f
) != 2) {
136 ast_log(LOG_WARNING
, "Read failed (format)\n");
139 if (ltohs(format
) != 1) {
140 ast_log(LOG_WARNING
, "Not a wav file %d\n", ltohs(format
));
143 if (fread(&chans
, 1, 2, f
) != 2) {
144 ast_log(LOG_WARNING
, "Read failed (format)\n");
147 if (ltohs(chans
) != 1) {
148 ast_log(LOG_WARNING
, "Not in mono %d\n", ltohs(chans
));
151 if (fread(&freq
, 1, 4, f
) != 4) {
152 ast_log(LOG_WARNING
, "Read failed (freq)\n");
155 if (ltohl(freq
) != DEFAULT_SAMPLE_RATE
) {
156 ast_log(LOG_WARNING
, "Unexpected freqency %d\n", ltohl(freq
));
159 /* Ignore the byte frequency */
160 if (fread(&bysec
, 1, 4, f
) != 4) {
161 ast_log(LOG_WARNING
, "Read failed (BYTES_PER_SECOND)\n");
164 /* Check bytes per sample */
165 if (fread(&bysam
, 1, 2, f
) != 2) {
166 ast_log(LOG_WARNING
, "Read failed (BYTES_PER_SAMPLE)\n");
169 if (ltohs(bysam
) != 2) {
170 ast_log(LOG_WARNING
, "Can only handle 16bits per sample: %d\n", ltohs(bysam
));
173 if (fread(&bisam
, 1, 2, f
) != 2) {
174 ast_log(LOG_WARNING
, "Read failed (Bits Per Sample): %d\n", ltohs(bisam
));
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 );
182 /* Skip any facts and get the first data block */
187 /* Begin data chunk */
188 if (fread(&buf
, 1, 4, f
) != 4) {
189 ast_log(LOG_WARNING
, "Read failed (data)\n");
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");
198 if(memcmp(buf
, "data", 4) == 0 )
200 if(memcmp(buf
, "fact", 4) != 0 ) {
201 ast_log(LOG_WARNING
, "Unknown block - not fact or data\n");
204 if (fseek(f
,data
,SEEK_CUR
) == -1 ) {
205 ast_log(LOG_WARNING
, "Failed to skip fact block: %d\n", data
);
210 curpos
= lseek(fd
, 0, SEEK_CUR
);
211 truelength
= lseek(fd
, 0, SEEK_END
);
212 lseek(fd
, curpos
, SEEK_SET
);
213 truelength
-= curpos
;
218 static int update_header(FILE *f
)
221 int datalen
,filelen
,bytes
;
224 fseek(f
, 0, SEEK_END
);
226 /* data starts 44 bytes in */
228 datalen
= htoll(bytes
);
229 /* chunk size is bytes of data plus 36 bytes of header */
230 filelen
= htoll(36 + bytes
);
233 ast_log(LOG_WARNING
, "Unable to find our position\n");
236 if (fseek(f
, 4, SEEK_SET
)) {
237 ast_log(LOG_WARNING
, "Unable to set our position\n");
240 if (fwrite(&filelen
, 1, 4, f
) != 4) {
241 ast_log(LOG_WARNING
, "Unable to set write file size\n");
244 if (fseek(f
, 40, SEEK_SET
)) {
245 ast_log(LOG_WARNING
, "Unable to set our position\n");
248 if (fwrite(&datalen
, 1, 4, f
) != 4) {
249 ast_log(LOG_WARNING
, "Unable to set write datalen\n");
252 if (fseeko(f
, cur
, SEEK_SET
)) {
253 ast_log(LOG_WARNING
, "Unable to return to position\n");
259 static int write_header(FILE *f
)
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 */
271 if (fwrite("RIFF", 1, 4, f
) != 4) {
272 ast_log(LOG_WARNING
, "Unable to write header\n");
275 if (fwrite(&size
, 1, 4, f
) != 4) {
276 ast_log(LOG_WARNING
, "Unable to write header\n");
279 if (fwrite("WAVEfmt ", 1, 8, f
) != 8) {
280 ast_log(LOG_WARNING
, "Unable to write header\n");
283 if (fwrite(&hs
, 1, 4, f
) != 4) {
284 ast_log(LOG_WARNING
, "Unable to write header\n");
287 if (fwrite(&fmt
, 1, 2, f
) != 2) {
288 ast_log(LOG_WARNING
, "Unable to write header\n");
291 if (fwrite(&chans
, 1, 2, f
) != 2) {
292 ast_log(LOG_WARNING
, "Unable to write header\n");
295 if (fwrite(&hz
, 1, 4, f
) != 4) {
296 ast_log(LOG_WARNING
, "Unable to write header\n");
299 if (fwrite(&bhz
, 1, 4, f
) != 4) {
300 ast_log(LOG_WARNING
, "Unable to write header\n");
303 if (fwrite(&bysam
, 1, 2, f
) != 2) {
304 ast_log(LOG_WARNING
, "Unable to write header\n");
307 if (fwrite(&bisam
, 1, 2, f
) != 2) {
308 ast_log(LOG_WARNING
, "Unable to write header\n");
311 if (fwrite("data", 1, 4, f
) != 4) {
312 ast_log(LOG_WARNING
, "Unable to write header\n");
315 if (fwrite(&size
, 1, 4, f
) != 4) {
316 ast_log(LOG_WARNING
, "Unable to write header\n");
322 static int wav_open(struct ast_filestream
*s
)
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)
333 static int wav_rewrite(struct ast_filestream
*s
, const char *comment
)
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. */
339 if (write_header(s
->f
))
344 static void wav_close(struct ast_filestream
*s
)
347 struct wav_desc
*fs
= (struct wav_desc
*)s
->_private
;
348 /* Pad to even length */
350 fwrite(&zero
, 1, 1, s
->f
);
353 static struct ast_frame
*wav_read(struct ast_filestream
*s
, int *whennext
)
356 int samples
; /* actual samples read */
359 int bytes
= WAV_BUF_SIZE
; /* in bytes */
361 /* Send a frame from the file to the appropriate channel */
362 struct wav_desc
*fs
= (struct wav_desc
*)s
->_private
;
365 if (fs
->maxlen
- here
< bytes
) /* truncate if necessary */
366 bytes
= fs
->maxlen
- here
;
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
;
373 AST_FRAME_SET_BUFFER(&s
->fr
, s
->buf
, AST_FRIENDLY_OFFSET
, bytes
);
375 if ( (res
= fread(s
->fr
.data
, 1, s
->fr
.datalen
, s
->f
)) <= 0 ) {
377 ast_log(LOG_WARNING
, "Short read (%d) (%s)!\n", res
, strerror(errno
));
381 s
->fr
.samples
= samples
= res
/ 2;
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);
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 */
400 for (x
=0; x
< samples
; x
++)
401 tmp
[x
] = tmp
[x
] >> GAIN
;
409 static int wav_write(struct ast_filestream
*fs
, struct ast_frame
*f
)
412 short tmp
[8000], *tmpi
;
414 struct wav_desc
*s
= (struct wav_desc
*)fs
->_private
;
417 if (f
->frametype
!= AST_FRAME_VOICE
) {
418 ast_log(LOG_WARNING
, "Asked to write non-voice frame!\n");
421 if (f
->subclass
!= AST_FORMAT_SLINEAR
) {
422 ast_log(LOG_WARNING
, "Asked to write non-SLINEAR frame (%d)!\n", f
->subclass
);
425 if (f
->datalen
> sizeof(tmp
)) {
426 ast_log(LOG_WARNING
, "Data length is too long\n");
433 printf("Data Length: %d\n", f
->datalen
);
437 /* Volume adjust here to accomodate */
438 for (x
=0;x
<f
->datalen
/2;x
++) {
439 tmpf
= ((float)tmpi
[x
]) * ((float)(1 << GAIN
));
445 tmp
[x
] &= ~((1 << GAIN
) - 1);
447 #if __BYTE_ORDER == __BIG_ENDIAN
448 tmp
[x
] = (tmp
[x
] << 8) | ((tmp
[x
] & 0xff00) >> 8);
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
));
457 s
->bytes
+= f
->datalen
;
458 update_header(fs
->f
);
464 static int wav_seek(struct ast_filestream
*fs
, off_t sample_offset
, int whence
)
466 off_t min
, max
, cur
, offset
= 0, samples
;
468 samples
= sample_offset
* 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */
469 min
= 44; /* wav header is 44 bytes */
471 fseeko(fs
->f
, 0, SEEK_END
);
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
;
482 /* always protect the header space. */
483 offset
= (offset
< min
)?min
:offset
;
484 return fseeko(fs
->f
, offset
, SEEK_SET
);
487 static int wav_trunc(struct ast_filestream
*fs
)
489 if (ftruncate(fileno(fs
->f
), ftello(fs
->f
)))
491 return update_header(fs
->f
);
494 static off_t
wav_tell(struct ast_filestream
*fs
)
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;
502 static const struct ast_format wav_f
= {
505 .format
= AST_FORMAT_SLINEAR
,
507 .rewrite
= wav_rewrite
,
514 .buf_size
= WAV_BUF_SIZE
+ AST_FRIENDLY_OFFSET
,
515 .desc_size
= sizeof(struct wav_desc
),
518 static int load_module(void)
520 return ast_format_register(&wav_f
);
523 static int unload_module(void)
525 return ast_format_unregister(wav_f
.name
);
528 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Microsoft WAV format (8000Hz Signed Linear)");