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