#include "asterisk.h"
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
Go to the source code of this file.
Data Structures | |
struct | wav_desc |
Defines | |
#define | BLOCKSIZE 160 |
#define | WAV_BUF_SIZE 320 |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | check_header (FILE *f, int hz) |
static int | check_header_fmt (FILE *f, int hsize, int hz) |
static int | load_module (void) |
static int | unload_module (void) |
static int | update_header (FILE *f) |
static void | wav_close (struct ast_filestream *s) |
static int | wav_open (struct ast_filestream *s) |
static struct ast_frame * | wav_read (struct ast_filestream *s, int *whennext) |
static int | wav_rewrite (struct ast_filestream *s, const char *comment) |
static int | wav_seek (struct ast_filestream *fs, off_t sample_offset, int whence) |
static off_t | wav_tell (struct ast_filestream *fs) |
static int | wav_trunc (struct ast_filestream *fs) |
static int | wav_write (struct ast_filestream *fs, struct ast_frame *f) |
static int | write_header (FILE *f, int writehz) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Microsoft WAV/WAV16 format (8kHz/16kHz Signed Linear)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_format | wav16_f |
static struct ast_format | wav_f |
Definition in file format_wav.c.
#define BLOCKSIZE 160 |
Definition at line 53 of file format_wav.c.
#define WAV_BUF_SIZE 320 |
static void __reg_module | ( | void | ) | [static] |
Definition at line 541 of file format_wav.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 541 of file format_wav.c.
static int check_header | ( | FILE * | f, | |
int | hz | |||
) | [static] |
Definition at line 139 of file format_wav.c.
References ast_log(), check_header_fmt(), LOG_DEBUG, LOG_WARNING, and type.
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 /* Skip any facts and get the first data block */ 00165 for(;;) 00166 { 00167 char buf[4]; 00168 00169 /* Begin data chunk */ 00170 if (fread(&buf, 1, 4, f) != 4) { 00171 ast_log(LOG_WARNING, "Read failed (block header format)\n"); 00172 return -1; 00173 } 00174 /* Data has the actual length of data in it */ 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 }
static int check_header_fmt | ( | FILE * | f, | |
int | hsize, | |||
int | hz | |||
) | [static] |
Definition at line 78 of file format_wav.c.
References ast_log(), format, and LOG_WARNING.
Referenced by check_header().
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 /* Ignore the byte frequency */ 00114 if (fread(&bysec, 1, 4, f) != 4) { 00115 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n"); 00116 return -1; 00117 } 00118 /* Check bytes per sample */ 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 /* Skip any additional header */ 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 }
static int load_module | ( | void | ) | [static] |
Definition at line 523 of file format_wav.c.
References ast_format_register, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, wav16_f, and wav_f.
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 }
static int unload_module | ( | void | ) | [static] |
Definition at line 531 of file format_wav.c.
References ast_format_unregister(), ast_format::name, wav16_f, and wav_f.
00532 { 00533 return ast_format_unregister(wav_f.name) 00534 || ast_format_unregister(wav16_f.name); 00535 }
static int update_header | ( | FILE * | f | ) | [static] |
Definition at line 202 of file format_wav.c.
References ast_log(), and LOG_WARNING.
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 /* data starts 44 bytes in */ 00211 bytes = end - 44; 00212 datalen = htoll(bytes); 00213 /* chunk size is bytes of data plus 36 bytes of header */ 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 }
static void wav_close | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 338 of file format_wav.c.
References ast_filestream::_private, ast_log(), wav_desc::bytes, errno, ast_filestream::f, ast_filestream::filename, LOG_WARNING, ast_filestream::mode, and update_header().
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 /* Pad to even length */ 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 }
static int wav_open | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 314 of file format_wav.c.
References ast_filestream::_private, AST_FORMAT_SLINEAR16, check_header(), ast_filestream::f, ast_filestream::fmt, ast_format::format, and wav_desc::maxlen.
00315 { 00316 /* We don't have any header to read or anything really, but 00317 if we did, it would go here. We also might want to check 00318 and be sure it's a valid file. */ 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 }
static struct ast_frame* wav_read | ( | struct ast_filestream * | s, | |
int * | whennext | |||
) | [static] |
Definition at line 359 of file format_wav.c.
References ast_filestream::_private, AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_FRAME_SET_BUFFER, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_filestream::buf, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, errno, ast_filestream::f, ast_filestream::fr, ast_frame::frametype, wav_desc::hz, LOG_WARNING, ast_frame::mallocd, wav_desc::maxlen, ast_frame::ptr, ast_frame::samples, ast_frame::subclass, and WAV_BUF_SIZE.
00360 { 00361 int res; 00362 int samples; /* actual samples read */ 00363 #if __BYTE_ORDER == __BIG_ENDIAN 00364 int x; 00365 short *tmp; 00366 #endif 00367 int bytes; 00368 off_t here; 00369 /* Send a frame from the file to the appropriate channel */ 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) /* truncate if necessary */ 00376 bytes = fs->maxlen - here; 00377 if (bytes < 0) 00378 bytes = 0; 00379 /* ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */ 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 /* file format is little endian so we need to swap */ 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 }
static int wav_rewrite | ( | struct ast_filestream * | s, | |
const char * | comment | |||
) | [static] |
Definition at line 325 of file format_wav.c.
References ast_filestream::_private, AST_FORMAT_SLINEAR16, ast_filestream::f, ast_filestream::fmt, ast_format::format, wav_desc::hz, and write_header().
00326 { 00327 /* We don't have any header to read or anything really, but 00328 if we did, it would go here. We also might want to check 00329 and be sure it's a valid file. */ 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 }
static int wav_seek | ( | struct ast_filestream * | fs, | |
off_t | sample_offset, | |||
int | whence | |||
) | [static] |
Definition at line 453 of file format_wav.c.
References ast_filestream::f, and SEEK_FORCECUR.
00454 { 00455 off_t min, max, cur, offset = 0, samples; 00456 00457 samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */ 00458 min = 44; /* wav header is 44 bytes */ 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 /* always protect the header space. */ 00472 offset = (offset < min)?min:offset; 00473 return fseeko(fs->f, offset, SEEK_SET); 00474 }
static off_t wav_tell | ( | struct ast_filestream * | fs | ) | [static] |
Definition at line 483 of file format_wav.c.
References ast_filestream::f.
00484 { 00485 off_t offset; 00486 offset = ftello(fs->f); 00487 /* subtract header size to get samples, then divide by 2 for 16 bit samples */ 00488 return (offset - 44)/2; 00489 }
static int wav_trunc | ( | struct ast_filestream * | fs | ) | [static] |
Definition at line 476 of file format_wav.c.
References ast_filestream::f, and update_header().
00477 { 00478 if (ftruncate(fileno(fs->f), ftello(fs->f))) 00479 return -1; 00480 return update_header(fs->f); 00481 }
static int wav_write | ( | struct ast_filestream * | fs, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 404 of file format_wav.c.
References ast_filestream::_private, AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_FRAME_VOICE, ast_getformatname(), ast_log(), errno, ast_filestream::f, f, ast_filestream::fmt, ast_format::format, wav_desc::hz, and LOG_WARNING.
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 /* swap and write */ 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 /* just write */ 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 }
static int write_header | ( | FILE * | f, | |
int | writehz | |||
) | [static] |
Definition at line 243 of file format_wav.c.
References ast_log(), and LOG_WARNING.
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 /* Write a wav header, ignoring sizes which will be filled in later */ 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 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Microsoft WAV/WAV16 format (8kHz/16kHz Signed Linear)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND } [static] |
Definition at line 541 of file format_wav.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 541 of file format_wav.c.
struct ast_format wav16_f [static] |
struct ast_format wav_f [static] |