#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 | 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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 49 of file format_wav.c.
#define WAV_BUF_SIZE 320 |
static void __reg_module | ( | void | ) | [static] |
Definition at line 539 of file format_wav.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 539 of file format_wav.c.
static int check_header | ( | FILE * | f, | |
int | hz | |||
) | [static] |
Definition at line 74 of file format_wav.c.
References ast_log(), format, LOG_WARNING, and type.
00075 { 00076 int type, size, formtype; 00077 int fmt, hsize; 00078 short format, chans, bysam, bisam; 00079 int bysec; 00080 int freq; 00081 int data; 00082 if (fread(&type, 1, 4, f) != 4) { 00083 ast_log(LOG_WARNING, "Read failed (type)\n"); 00084 return -1; 00085 } 00086 if (fread(&size, 1, 4, f) != 4) { 00087 ast_log(LOG_WARNING, "Read failed (size)\n"); 00088 return -1; 00089 } 00090 size = ltohl(size); 00091 if (fread(&formtype, 1, 4, f) != 4) { 00092 ast_log(LOG_WARNING, "Read failed (formtype)\n"); 00093 return -1; 00094 } 00095 if (memcmp(&type, "RIFF", 4)) { 00096 ast_log(LOG_WARNING, "Does not begin with RIFF\n"); 00097 return -1; 00098 } 00099 if (memcmp(&formtype, "WAVE", 4)) { 00100 ast_log(LOG_WARNING, "Does not contain WAVE\n"); 00101 return -1; 00102 } 00103 if (fread(&fmt, 1, 4, f) != 4) { 00104 ast_log(LOG_WARNING, "Read failed (fmt)\n"); 00105 return -1; 00106 } 00107 if (memcmp(&fmt, "fmt ", 4)) { 00108 ast_log(LOG_WARNING, "Does not say fmt\n"); 00109 return -1; 00110 } 00111 if (fread(&hsize, 1, 4, f) != 4) { 00112 ast_log(LOG_WARNING, "Read failed (formtype)\n"); 00113 return -1; 00114 } 00115 if (ltohl(hsize) < 16) { 00116 ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize)); 00117 return -1; 00118 } 00119 if (fread(&format, 1, 2, f) != 2) { 00120 ast_log(LOG_WARNING, "Read failed (format)\n"); 00121 return -1; 00122 } 00123 if (ltohs(format) != 1) { 00124 ast_log(LOG_WARNING, "Not a wav file %d\n", ltohs(format)); 00125 return -1; 00126 } 00127 if (fread(&chans, 1, 2, f) != 2) { 00128 ast_log(LOG_WARNING, "Read failed (format)\n"); 00129 return -1; 00130 } 00131 if (ltohs(chans) != 1) { 00132 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans)); 00133 return -1; 00134 } 00135 if (fread(&freq, 1, 4, f) != 4) { 00136 ast_log(LOG_WARNING, "Read failed (freq)\n"); 00137 return -1; 00138 } 00139 if (((ltohl(freq) != 8000) && (ltohl(freq) != 16000)) || 00140 ((ltohl(freq) == 8000) && (hz != 8000)) || 00141 ((ltohl(freq) == 16000) && (hz != 16000))) { 00142 ast_log(LOG_WARNING, "Unexpected frequency mismatch %d (expecting %d)\n", ltohl(freq),hz); 00143 return -1; 00144 } 00145 /* Ignore the byte frequency */ 00146 if (fread(&bysec, 1, 4, f) != 4) { 00147 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n"); 00148 return -1; 00149 } 00150 /* Check bytes per sample */ 00151 if (fread(&bysam, 1, 2, f) != 2) { 00152 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n"); 00153 return -1; 00154 } 00155 if (ltohs(bysam) != 2) { 00156 ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam)); 00157 return -1; 00158 } 00159 if (fread(&bisam, 1, 2, f) != 2) { 00160 ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam)); 00161 return -1; 00162 } 00163 /* Skip any additional header */ 00164 if (fseek(f,ltohl(hsize)-16,SEEK_CUR) == -1 ) { 00165 ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", ltohl(hsize)-16 ); 00166 return -1; 00167 } 00168 /* Skip any facts and get the first data block */ 00169 for(;;) 00170 { 00171 char buf[4]; 00172 00173 /* Begin data chunk */ 00174 if (fread(&buf, 1, 4, f) != 4) { 00175 ast_log(LOG_WARNING, "Read failed (data)\n"); 00176 return -1; 00177 } 00178 /* Data has the actual length of data in it */ 00179 if (fread(&data, 1, 4, f) != 4) { 00180 ast_log(LOG_WARNING, "Read failed (data)\n"); 00181 return -1; 00182 } 00183 data = ltohl(data); 00184 if(memcmp(buf, "data", 4) == 0 ) 00185 break; 00186 if(memcmp(buf, "fact", 4) != 0 ) { 00187 ast_log(LOG_WARNING, "Unknown block - not fact or data\n"); 00188 return -1; 00189 } 00190 if (fseek(f,data,SEEK_CUR) == -1 ) { 00191 ast_log(LOG_WARNING, "Failed to skip fact block: %d\n", 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 }
static int load_module | ( | void | ) | [static] |
Definition at line 521 of file format_wav.c.
References ast_format_register, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, wav16_f, and wav_f.
00522 { 00523 if (ast_format_register(&wav_f) 00524 || ast_format_register(&wav16_f)) 00525 return AST_MODULE_LOAD_FAILURE; 00526 return AST_MODULE_LOAD_SUCCESS; 00527 }
static int unload_module | ( | void | ) | [static] |
Definition at line 529 of file format_wav.c.
References ast_format_unregister(), ast_format::name, wav16_f, and wav_f.
00530 { 00531 return ast_format_unregister(wav_f.name) 00532 || ast_format_unregister(wav16_f.name); 00533 }
static int update_header | ( | FILE * | f | ) | [static] |
Definition at line 204 of file format_wav.c.
References ast_log(), fwrite, and LOG_WARNING.
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 /* data starts 44 bytes in */ 00213 bytes = end - 44; 00214 datalen = htoll(bytes); 00215 /* chunk size is bytes of data plus 36 bytes of header */ 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 }
static void wav_close | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 340 of file format_wav.c.
References ast_filestream::_private, ast_log(), wav_desc::bytes, errno, ast_filestream::f, ast_filestream::filename, fwrite, LOG_WARNING, and update_header().
00341 { 00342 char zero = 0; 00343 struct wav_desc *fs = (struct wav_desc *)s->_private; 00344 00345 if (s->filename) { 00346 update_header(s->f); 00347 } 00348 00349 /* Pad to even length */ 00350 if (fs->bytes & 0x1) { 00351 if (!fwrite(&zero, 1, 1, s->f)) { 00352 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00353 } 00354 } 00355 }
static int wav_open | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 316 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.
00317 { 00318 /* We don't have any header to read or anything really, but 00319 if we did, it would go here. We also might want to check 00320 and be sure it's a valid file. */ 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 }
static struct ast_frame* wav_read | ( | struct ast_filestream * | s, | |
int * | whennext | |||
) | [static] |
Definition at line 357 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.
00358 { 00359 int res; 00360 int samples; /* actual samples read */ 00361 #if __BYTE_ORDER == __BIG_ENDIAN 00362 int x; 00363 #endif 00364 short *tmp; 00365 int bytes; 00366 off_t here; 00367 /* Send a frame from the file to the appropriate channel */ 00368 struct wav_desc *fs = (struct wav_desc *)s->_private; 00369 00370 bytes = (fs->hz == 16000 ? (WAV_BUF_SIZE * 2) : WAV_BUF_SIZE); 00371 00372 here = ftello(s->f); 00373 if (fs->maxlen - here < bytes) /* truncate if necessary */ 00374 bytes = fs->maxlen - here; 00375 if (bytes < 0) 00376 bytes = 0; 00377 /* ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */ 00378 s->fr.frametype = AST_FRAME_VOICE; 00379 s->fr.subclass.codec = (fs->hz == 16000 ? AST_FORMAT_SLINEAR16 : AST_FORMAT_SLINEAR); 00380 s->fr.mallocd = 0; 00381 AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes); 00382 00383 if ( (res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) <= 0 ) { 00384 if (res) 00385 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); 00386 return NULL; 00387 } 00388 s->fr.datalen = res; 00389 s->fr.samples = samples = res / 2; 00390 00391 tmp = (short *)(s->fr.data.ptr); 00392 #if __BYTE_ORDER == __BIG_ENDIAN 00393 /* file format is little endian so we need to swap */ 00394 for( x = 0; x < samples; x++) 00395 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8); 00396 #endif 00397 00398 *whennext = samples; 00399 return &s->fr; 00400 }
static int wav_rewrite | ( | struct ast_filestream * | s, | |
const char * | comment | |||
) | [static] |
Definition at line 327 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().
00328 { 00329 /* We don't have any header to read or anything really, but 00330 if we did, it would go here. We also might want to check 00331 and be sure it's a valid file. */ 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 }
static int wav_seek | ( | struct ast_filestream * | fs, | |
off_t | sample_offset, | |||
int | whence | |||
) | [static] |
Definition at line 451 of file format_wav.c.
References ast_filestream::f, and SEEK_FORCECUR.
00452 { 00453 off_t min, max, cur, offset = 0, samples; 00454 00455 samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */ 00456 min = 44; /* wav header is 44 bytes */ 00457 cur = ftello(fs->f); 00458 fseeko(fs->f, 0, SEEK_END); 00459 max = ftello(fs->f); 00460 if (whence == SEEK_SET) 00461 offset = samples + min; 00462 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) 00463 offset = samples + cur; 00464 else if (whence == SEEK_END) 00465 offset = max - samples; 00466 if (whence != SEEK_FORCECUR) { 00467 offset = (offset > max)?max:offset; 00468 } 00469 /* always protect the header space. */ 00470 offset = (offset < min)?min:offset; 00471 return fseeko(fs->f, offset, SEEK_SET); 00472 }
static off_t wav_tell | ( | struct ast_filestream * | fs | ) | [static] |
Definition at line 481 of file format_wav.c.
References ast_filestream::f.
00482 { 00483 off_t offset; 00484 offset = ftello(fs->f); 00485 /* subtract header size to get samples, then divide by 2 for 16 bit samples */ 00486 return (offset - 44)/2; 00487 }
static int wav_trunc | ( | struct ast_filestream * | fs | ) | [static] |
Definition at line 474 of file format_wav.c.
References ast_filestream::f, and update_header().
00475 { 00476 if (ftruncate(fileno(fs->f), ftello(fs->f))) 00477 return -1; 00478 return update_header(fs->f); 00479 }
static int wav_write | ( | struct ast_filestream * | fs, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 402 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, fwrite, wav_desc::hz, and LOG_WARNING.
00403 { 00404 #if __BYTE_ORDER == __BIG_ENDIAN 00405 int x; 00406 short tmp[16000], *tmpi; 00407 #endif 00408 struct wav_desc *s = (struct wav_desc *)fs->_private; 00409 int res; 00410 00411 if (f->frametype != AST_FRAME_VOICE) { 00412 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); 00413 return -1; 00414 } 00415 if ((f->subclass.codec != AST_FORMAT_SLINEAR) && (f->subclass.codec != AST_FORMAT_SLINEAR16)) { 00416 ast_log(LOG_WARNING, "Asked to write non-SLINEAR%s frame (%s)!\n", s->hz == 16000 ? "16" : "", ast_getformatname(f->subclass.codec)); 00417 return -1; 00418 } 00419 if (f->subclass.codec != fs->fmt->format) { 00420 ast_log(LOG_WARNING, "Can't change SLINEAR frequency during write\n"); 00421 return -1; 00422 } 00423 if (!f->datalen) 00424 return -1; 00425 00426 #if __BYTE_ORDER == __BIG_ENDIAN 00427 /* swap and write */ 00428 if (f->datalen > sizeof(tmp)) { 00429 ast_log(LOG_WARNING, "Data length is too long\n"); 00430 return -1; 00431 } 00432 tmpi = f->data.ptr; 00433 for (x=0; x < f->datalen/2; x++) 00434 tmp[x] = (tmpi[x] << 8) | ((tmpi[x] & 0xff00) >> 8); 00435 00436 if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) { 00437 #else 00438 /* just write */ 00439 if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen ) { 00440 #endif 00441 ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno)); 00442 return -1; 00443 } 00444 00445 s->bytes += f->datalen; 00446 00447 return 0; 00448 00449 }
static int write_header | ( | FILE * | f, | |
int | writehz | |||
) | [static] |
Definition at line 245 of file format_wav.c.
References ast_log(), fwrite, and LOG_WARNING.
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 /* Write a wav header, ignoring sizes which will be filled in later */ 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 }
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND } [static] |
Definition at line 539 of file format_wav.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 539 of file format_wav.c.
struct ast_format wav16_f [static] |
struct ast_format wav_f [static] |