00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 364578 $")
00034
00035 #include "asterisk/mod_format.h"
00036 #include "asterisk/module.h"
00037 #include "asterisk/endian.h"
00038
00039
00040
00041
00042
00043 #define WAV_BUF_SIZE 320
00044
00045 #define WAV_HEADER_SIZE 44
00046
00047 struct wav_desc {
00048 int hz;
00049 int bytes;
00050 int lasttimeout;
00051 int maxlen;
00052 struct timeval last;
00053 };
00054
00055 #define BLOCKSIZE 160
00056
00057 #if __BYTE_ORDER == __LITTLE_ENDIAN
00058 #define htoll(b) (b)
00059 #define htols(b) (b)
00060 #define ltohl(b) (b)
00061 #define ltohs(b) (b)
00062 #else
00063 #if __BYTE_ORDER == __BIG_ENDIAN
00064 #define htoll(b) \
00065 (((((b) ) & 0xFF) << 24) | \
00066 ((((b) >> 8) & 0xFF) << 16) | \
00067 ((((b) >> 16) & 0xFF) << 8) | \
00068 ((((b) >> 24) & 0xFF) ))
00069 #define htols(b) \
00070 (((((b) ) & 0xFF) << 8) | \
00071 ((((b) >> 8) & 0xFF) ))
00072 #define ltohl(b) htoll(b)
00073 #define ltohs(b) htols(b)
00074 #else
00075 #error "Endianess not defined"
00076 #endif
00077 #endif
00078
00079
00080 static int check_header_fmt(FILE *f, int hsize, int hz)
00081 {
00082 short format, chans, bysam, bisam;
00083 int bysec;
00084 int freq;
00085 if (hsize < 16) {
00086 ast_log(LOG_WARNING, "Unexpected header size %d\n", hsize);
00087 return -1;
00088 }
00089 if (fread(&format, 1, 2, f) != 2) {
00090 ast_log(LOG_WARNING, "Read failed (format)\n");
00091 return -1;
00092 }
00093 if (ltohs(format) != 1) {
00094 ast_log(LOG_WARNING, "Not a wav file %d\n", ltohs(format));
00095 return -1;
00096 }
00097 if (fread(&chans, 1, 2, f) != 2) {
00098 ast_log(LOG_WARNING, "Read failed (format)\n");
00099 return -1;
00100 }
00101 if (ltohs(chans) != 1) {
00102 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
00103 return -1;
00104 }
00105 if (fread(&freq, 1, 4, f) != 4) {
00106 ast_log(LOG_WARNING, "Read failed (freq)\n");
00107 return -1;
00108 }
00109 if (((ltohl(freq) != 8000) && (ltohl(freq) != 16000)) ||
00110 ((ltohl(freq) == 8000) && (hz != 8000)) ||
00111 ((ltohl(freq) == 16000) && (hz != 16000))) {
00112 ast_log(LOG_WARNING, "Unexpected frequency mismatch %d (expecting %d)\n", ltohl(freq),hz);
00113 return -1;
00114 }
00115
00116 if (fread(&bysec, 1, 4, f) != 4) {
00117 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n");
00118 return -1;
00119 }
00120
00121 if (fread(&bysam, 1, 2, f) != 2) {
00122 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n");
00123 return -1;
00124 }
00125 if (ltohs(bysam) != 2) {
00126 ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam));
00127 return -1;
00128 }
00129 if (fread(&bisam, 1, 2, f) != 2) {
00130 ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam));
00131 return -1;
00132 }
00133
00134 if (fseek(f,hsize-16,SEEK_CUR) == -1 ) {
00135 ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", hsize-16 );
00136 return -1;
00137 }
00138 return 0;
00139 }
00140
00141 static int check_header(FILE *f, int hz)
00142 {
00143 int type, size, formtype;
00144 int data;
00145 if (fread(&type, 1, 4, f) != 4) {
00146 ast_log(LOG_WARNING, "Read failed (type)\n");
00147 return -1;
00148 }
00149 if (fread(&size, 1, 4, f) != 4) {
00150 ast_log(LOG_WARNING, "Read failed (size)\n");
00151 return -1;
00152 }
00153 size = ltohl(size);
00154 if (fread(&formtype, 1, 4, f) != 4) {
00155 ast_log(LOG_WARNING, "Read failed (formtype)\n");
00156 return -1;
00157 }
00158 if (memcmp(&type, "RIFF", 4)) {
00159 ast_log(LOG_WARNING, "Does not begin with RIFF\n");
00160 return -1;
00161 }
00162 if (memcmp(&formtype, "WAVE", 4)) {
00163 ast_log(LOG_WARNING, "Does not contain WAVE\n");
00164 return -1;
00165 }
00166
00167 for(;;)
00168 {
00169 char buf[4];
00170
00171
00172 if (fread(&buf, 1, 4, f) != 4) {
00173 ast_log(LOG_WARNING, "Read failed (block header format)\n");
00174 return -1;
00175 }
00176
00177 if (fread(&data, 1, 4, f) != 4) {
00178 ast_log(LOG_WARNING, "Read failed (block '%.4s' header length)\n", buf);
00179 return -1;
00180 }
00181 data = ltohl(data);
00182 if (memcmp(&buf, "fmt ", 4) == 0) {
00183 if (check_header_fmt(f, data, hz))
00184 return -1;
00185 continue;
00186 }
00187 if(memcmp(buf, "data", 4) == 0 )
00188 break;
00189 ast_log(LOG_DEBUG, "Skipping unknown block '%.4s'\n", buf);
00190 if (fseek(f,data,SEEK_CUR) == -1 ) {
00191 ast_log(LOG_WARNING, "Failed to skip '%.4s' block: %d\n", buf, data);
00192 return -1;
00193 }
00194 }
00195 #if 0
00196 curpos = lseek(fd, 0, SEEK_CUR);
00197 truelength = lseek(fd, 0, SEEK_END);
00198 lseek(fd, curpos, SEEK_SET);
00199 truelength -= curpos;
00200 #endif
00201 return data;
00202 }
00203
00204 static int update_header(FILE *f)
00205 {
00206 off_t cur,end;
00207 int datalen,filelen,bytes;
00208
00209 cur = ftello(f);
00210 fseek(f, 0, SEEK_END);
00211 end = ftello(f);
00212
00213 bytes = end - 44;
00214 datalen = htoll(bytes);
00215
00216 filelen = htoll(36 + bytes);
00217
00218 if (cur < 0) {
00219 ast_log(LOG_WARNING, "Unable to find our position\n");
00220 return -1;
00221 }
00222 if (fseek(f, 4, SEEK_SET)) {
00223 ast_log(LOG_WARNING, "Unable to set our position\n");
00224 return -1;
00225 }
00226 if (fwrite(&filelen, 1, 4, f) != 4) {
00227 ast_log(LOG_WARNING, "Unable to set write file size\n");
00228 return -1;
00229 }
00230 if (fseek(f, 40, SEEK_SET)) {
00231 ast_log(LOG_WARNING, "Unable to set our position\n");
00232 return -1;
00233 }
00234 if (fwrite(&datalen, 1, 4, f) != 4) {
00235 ast_log(LOG_WARNING, "Unable to set write datalen\n");
00236 return -1;
00237 }
00238 if (fseeko(f, cur, SEEK_SET)) {
00239 ast_log(LOG_WARNING, "Unable to return to position\n");
00240 return -1;
00241 }
00242 return 0;
00243 }
00244
00245 static int write_header(FILE *f, int writehz)
00246 {
00247 unsigned int hz;
00248 unsigned int bhz;
00249 unsigned int hs = htoll(16);
00250 unsigned short fmt = htols(1);
00251 unsigned short chans = htols(1);
00252 unsigned short bysam = htols(2);
00253 unsigned short bisam = htols(16);
00254 unsigned int size = htoll(0);
00255
00256 if (writehz == 16000) {
00257 hz = htoll(16000);
00258 bhz = htoll(32000);
00259 } else {
00260 hz = htoll(8000);
00261 bhz = htoll(16000);
00262 }
00263
00264 fseek(f,0,SEEK_SET);
00265 if (fwrite("RIFF", 1, 4, f) != 4) {
00266 ast_log(LOG_WARNING, "Unable to write header\n");
00267 return -1;
00268 }
00269 if (fwrite(&size, 1, 4, f) != 4) {
00270 ast_log(LOG_WARNING, "Unable to write header\n");
00271 return -1;
00272 }
00273 if (fwrite("WAVEfmt ", 1, 8, f) != 8) {
00274 ast_log(LOG_WARNING, "Unable to write header\n");
00275 return -1;
00276 }
00277 if (fwrite(&hs, 1, 4, f) != 4) {
00278 ast_log(LOG_WARNING, "Unable to write header\n");
00279 return -1;
00280 }
00281 if (fwrite(&fmt, 1, 2, f) != 2) {
00282 ast_log(LOG_WARNING, "Unable to write header\n");
00283 return -1;
00284 }
00285 if (fwrite(&chans, 1, 2, f) != 2) {
00286 ast_log(LOG_WARNING, "Unable to write header\n");
00287 return -1;
00288 }
00289 if (fwrite(&hz, 1, 4, f) != 4) {
00290 ast_log(LOG_WARNING, "Unable to write header\n");
00291 return -1;
00292 }
00293 if (fwrite(&bhz, 1, 4, f) != 4) {
00294 ast_log(LOG_WARNING, "Unable to write header\n");
00295 return -1;
00296 }
00297 if (fwrite(&bysam, 1, 2, f) != 2) {
00298 ast_log(LOG_WARNING, "Unable to write header\n");
00299 return -1;
00300 }
00301 if (fwrite(&bisam, 1, 2, f) != 2) {
00302 ast_log(LOG_WARNING, "Unable to write header\n");
00303 return -1;
00304 }
00305 if (fwrite("data", 1, 4, f) != 4) {
00306 ast_log(LOG_WARNING, "Unable to write header\n");
00307 return -1;
00308 }
00309 if (fwrite(&size, 1, 4, f) != 4) {
00310 ast_log(LOG_WARNING, "Unable to write header\n");
00311 return -1;
00312 }
00313 return 0;
00314 }
00315
00316 static int wav_open(struct ast_filestream *s)
00317 {
00318
00319
00320
00321 struct wav_desc *tmp = (struct wav_desc *)s->_private;
00322 if ((tmp->maxlen = check_header(s->f, (s->fmt->format == AST_FORMAT_SLINEAR16 ? 16000 : 8000))) < 0)
00323 return -1;
00324 return 0;
00325 }
00326
00327 static int wav_rewrite(struct ast_filestream *s, const char *comment)
00328 {
00329
00330
00331
00332
00333 struct wav_desc *tmp = (struct wav_desc *)s->_private;
00334 tmp->hz = (s->fmt->format == AST_FORMAT_SLINEAR16 ? 16000 : 8000);
00335 if (write_header(s->f,tmp->hz))
00336 return -1;
00337 return 0;
00338 }
00339
00340 static void wav_close(struct ast_filestream *s)
00341 {
00342 char zero = 0;
00343 struct wav_desc *fs = (struct wav_desc *)s->_private;
00344
00345 if (s->mode == O_RDONLY) {
00346 return;
00347 }
00348
00349 if (s->filename) {
00350 update_header(s->f);
00351 }
00352
00353
00354 if (fs->bytes & 0x1) {
00355 if (!fwrite(&zero, 1, 1, s->f)) {
00356 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
00357 }
00358 }
00359 }
00360
00361 static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
00362 {
00363 int res;
00364 int samples;
00365 #if __BYTE_ORDER == __BIG_ENDIAN
00366 int x;
00367 short *tmp;
00368 #endif
00369 int bytes;
00370 off_t here;
00371
00372 struct wav_desc *fs = (struct wav_desc *)s->_private;
00373
00374 bytes = (fs->hz == 16000 ? (WAV_BUF_SIZE * 2) : WAV_BUF_SIZE);
00375
00376 here = ftello(s->f);
00377 if (fs->maxlen - here < bytes)
00378 bytes = fs->maxlen - here;
00379 if (bytes < 0)
00380 bytes = 0;
00381
00382 s->fr.frametype = AST_FRAME_VOICE;
00383 s->fr.subclass.codec = (fs->hz == 16000 ? AST_FORMAT_SLINEAR16 : AST_FORMAT_SLINEAR);
00384 s->fr.mallocd = 0;
00385 AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes);
00386
00387 if ( (res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) <= 0 ) {
00388 if (res)
00389 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00390 return NULL;
00391 }
00392 s->fr.datalen = res;
00393 s->fr.samples = samples = res / 2;
00394
00395 #if __BYTE_ORDER == __BIG_ENDIAN
00396 tmp = (short *)(s->fr.data.ptr);
00397
00398 for( x = 0; x < samples; x++)
00399 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
00400 #endif
00401
00402 *whennext = samples;
00403 return &s->fr;
00404 }
00405
00406 static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
00407 {
00408 #if __BYTE_ORDER == __BIG_ENDIAN
00409 int x;
00410 short tmp[16000], *tmpi;
00411 #endif
00412 struct wav_desc *s = (struct wav_desc *)fs->_private;
00413 int res;
00414
00415 if (f->frametype != AST_FRAME_VOICE) {
00416 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00417 return -1;
00418 }
00419 if ((f->subclass.codec != AST_FORMAT_SLINEAR) && (f->subclass.codec != AST_FORMAT_SLINEAR16)) {
00420 ast_log(LOG_WARNING, "Asked to write non-SLINEAR%s frame (%s)!\n", s->hz == 16000 ? "16" : "", ast_getformatname(f->subclass.codec));
00421 return -1;
00422 }
00423 if (f->subclass.codec != fs->fmt->format) {
00424 ast_log(LOG_WARNING, "Can't change SLINEAR frequency during write\n");
00425 return -1;
00426 }
00427 if (!f->datalen)
00428 return -1;
00429
00430 #if __BYTE_ORDER == __BIG_ENDIAN
00431
00432 if (f->datalen > sizeof(tmp)) {
00433 ast_log(LOG_WARNING, "Data length is too long\n");
00434 return -1;
00435 }
00436 tmpi = f->data.ptr;
00437 for (x=0; x < f->datalen/2; x++)
00438 tmp[x] = (tmpi[x] << 8) | ((tmpi[x] & 0xff00) >> 8);
00439
00440 if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) {
00441 #else
00442
00443 if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen ) {
00444 #endif
00445 ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno));
00446 return -1;
00447 }
00448
00449 s->bytes += f->datalen;
00450
00451 return 0;
00452
00453 }
00454
00455 static int wav_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
00456 {
00457 off_t min = WAV_HEADER_SIZE, max, cur, offset = 0, samples;
00458
00459 samples = sample_offset * 2;
00460
00461 if ((cur = ftello(fs->f)) < 0) {
00462 ast_log(AST_LOG_WARNING, "Unable to determine current position in wav filestream %p: %s\n", fs, strerror(errno));
00463 return -1;
00464 }
00465
00466 if (fseeko(fs->f, 0, SEEK_END) < 0) {
00467 ast_log(AST_LOG_WARNING, "Unable to seek to end of wav filestream %p: %s\n", fs, strerror(errno));
00468 return -1;
00469 }
00470
00471 if ((max = ftello(fs->f)) < 0) {
00472 ast_log(AST_LOG_WARNING, "Unable to determine max position in wav filestream %p: %s\n", fs, strerror(errno));
00473 return -1;
00474 }
00475
00476 if (whence == SEEK_SET)
00477 offset = samples + min;
00478 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
00479 offset = samples + cur;
00480 else if (whence == SEEK_END)
00481 offset = max - samples;
00482 if (whence != SEEK_FORCECUR) {
00483 offset = (offset > max)?max:offset;
00484 }
00485
00486 offset = (offset < min)?min:offset;
00487 return fseeko(fs->f, offset, SEEK_SET);
00488 }
00489
00490 static int wav_trunc(struct ast_filestream *fs)
00491 {
00492 int fd;
00493 off_t cur;
00494
00495 if ((fd = fileno(fs->f)) < 0) {
00496 ast_log(AST_LOG_WARNING, "Unable to determine file descriptor for wav filestream %p: %s\n", fs, strerror(errno));
00497 return -1;
00498 }
00499 if ((cur = ftello(fs->f)) < 0) {
00500 ast_log(AST_LOG_WARNING, "Unable to determine current position in wav filestream %p: %s\n", fs, strerror(errno));
00501 return -1;
00502 }
00503
00504 if (ftruncate(fd, cur)) {
00505 return -1;
00506 }
00507 return update_header(fs->f);
00508 }
00509
00510 static off_t wav_tell(struct ast_filestream *fs)
00511 {
00512 off_t offset;
00513 offset = ftello(fs->f);
00514
00515 return (offset - 44)/2;
00516 }
00517
00518 static const struct ast_format wav16_f = {
00519 .name = "wav16",
00520 .exts = "wav16",
00521 .format = AST_FORMAT_SLINEAR16,
00522 .open = wav_open,
00523 .rewrite = wav_rewrite,
00524 .write = wav_write,
00525 .seek = wav_seek,
00526 .trunc = wav_trunc,
00527 .tell = wav_tell,
00528 .read = wav_read,
00529 .close = wav_close,
00530 .buf_size = (WAV_BUF_SIZE * 2) + AST_FRIENDLY_OFFSET,
00531 .desc_size = sizeof(struct wav_desc),
00532 };
00533
00534 static const struct ast_format wav_f = {
00535 .name = "wav",
00536 .exts = "wav",
00537 .format = AST_FORMAT_SLINEAR,
00538 .open = wav_open,
00539 .rewrite = wav_rewrite,
00540 .write = wav_write,
00541 .seek = wav_seek,
00542 .trunc = wav_trunc,
00543 .tell = wav_tell,
00544 .read = wav_read,
00545 .close = wav_close,
00546 .buf_size = WAV_BUF_SIZE + AST_FRIENDLY_OFFSET,
00547 .desc_size = sizeof(struct wav_desc),
00548 };
00549
00550 static int load_module(void)
00551 {
00552 if (ast_format_register(&wav_f)
00553 || ast_format_register(&wav16_f))
00554 return AST_MODULE_LOAD_FAILURE;
00555 return AST_MODULE_LOAD_SUCCESS;
00556 }
00557
00558 static int unload_module(void)
00559 {
00560 return ast_format_unregister(wav_f.name)
00561 || ast_format_unregister(wav16_f.name);
00562 }
00563
00564 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Microsoft WAV/WAV16 format (8kHz/16kHz Signed Linear)",
00565 .load = load_module,
00566 .unload = unload_module,
00567 .load_pri = AST_MODPRI_APP_DEPEND
00568 );