#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) |
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) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Microsoft WAV format (8000Hz 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .load_pri = 10, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_format | wav_f |
Definition in file format_wav.c.
#define BLOCKSIZE 160 |
Definition at line 48 of file format_wav.c.
#define WAV_BUF_SIZE 320 |
static void __reg_module | ( | void | ) | [static] |
Definition at line 502 of file format_wav.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 502 of file format_wav.c.
static int check_header | ( | FILE * | f | ) | [static] |
Definition at line 73 of file format_wav.c.
References ast_log(), buf, DEFAULT_SAMPLE_RATE, format, LOG_WARNING, and type.
00074 { 00075 int type, size, formtype; 00076 int fmt, hsize; 00077 short format, chans, bysam, bisam; 00078 int bysec; 00079 int freq; 00080 int data; 00081 if (fread(&type, 1, 4, f) != 4) { 00082 ast_log(LOG_WARNING, "Read failed (type)\n"); 00083 return -1; 00084 } 00085 if (fread(&size, 1, 4, f) != 4) { 00086 ast_log(LOG_WARNING, "Read failed (size)\n"); 00087 return -1; 00088 } 00089 size = ltohl(size); 00090 if (fread(&formtype, 1, 4, f) != 4) { 00091 ast_log(LOG_WARNING, "Read failed (formtype)\n"); 00092 return -1; 00093 } 00094 if (memcmp(&type, "RIFF", 4)) { 00095 ast_log(LOG_WARNING, "Does not begin with RIFF\n"); 00096 return -1; 00097 } 00098 if (memcmp(&formtype, "WAVE", 4)) { 00099 ast_log(LOG_WARNING, "Does not contain WAVE\n"); 00100 return -1; 00101 } 00102 if (fread(&fmt, 1, 4, f) != 4) { 00103 ast_log(LOG_WARNING, "Read failed (fmt)\n"); 00104 return -1; 00105 } 00106 if (memcmp(&fmt, "fmt ", 4)) { 00107 ast_log(LOG_WARNING, "Does not say fmt\n"); 00108 return -1; 00109 } 00110 if (fread(&hsize, 1, 4, f) != 4) { 00111 ast_log(LOG_WARNING, "Read failed (formtype)\n"); 00112 return -1; 00113 } 00114 if (ltohl(hsize) < 16) { 00115 ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize)); 00116 return -1; 00117 } 00118 if (fread(&format, 1, 2, f) != 2) { 00119 ast_log(LOG_WARNING, "Read failed (format)\n"); 00120 return -1; 00121 } 00122 if (ltohs(format) != 1) { 00123 ast_log(LOG_WARNING, "Not a wav file %d\n", ltohs(format)); 00124 return -1; 00125 } 00126 if (fread(&chans, 1, 2, f) != 2) { 00127 ast_log(LOG_WARNING, "Read failed (format)\n"); 00128 return -1; 00129 } 00130 if (ltohs(chans) != 1) { 00131 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans)); 00132 return -1; 00133 } 00134 if (fread(&freq, 1, 4, f) != 4) { 00135 ast_log(LOG_WARNING, "Read failed (freq)\n"); 00136 return -1; 00137 } 00138 if (ltohl(freq) != DEFAULT_SAMPLE_RATE) { 00139 ast_log(LOG_WARNING, "Unexpected frequency %d\n", ltohl(freq)); 00140 return -1; 00141 } 00142 /* Ignore the byte frequency */ 00143 if (fread(&bysec, 1, 4, f) != 4) { 00144 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n"); 00145 return -1; 00146 } 00147 /* Check bytes per sample */ 00148 if (fread(&bysam, 1, 2, f) != 2) { 00149 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n"); 00150 return -1; 00151 } 00152 if (ltohs(bysam) != 2) { 00153 ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam)); 00154 return -1; 00155 } 00156 if (fread(&bisam, 1, 2, f) != 2) { 00157 ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam)); 00158 return -1; 00159 } 00160 /* Skip any additional header */ 00161 if (fseek(f,ltohl(hsize)-16,SEEK_CUR) == -1 ) { 00162 ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", ltohl(hsize)-16 ); 00163 return -1; 00164 } 00165 /* Skip any facts and get the first data block */ 00166 for(;;) 00167 { 00168 char buf[4]; 00169 00170 /* Begin data chunk */ 00171 if (fread(&buf, 1, 4, f) != 4) { 00172 ast_log(LOG_WARNING, "Read failed (data)\n"); 00173 return -1; 00174 } 00175 /* Data has the actual length of data in it */ 00176 if (fread(&data, 1, 4, f) != 4) { 00177 ast_log(LOG_WARNING, "Read failed (data)\n"); 00178 return -1; 00179 } 00180 data = ltohl(data); 00181 if(memcmp(buf, "data", 4) == 0 ) 00182 break; 00183 if(memcmp(buf, "fact", 4) != 0 ) { 00184 ast_log(LOG_WARNING, "Unknown block - not fact or data\n"); 00185 return -1; 00186 } 00187 if (fseek(f,data,SEEK_CUR) == -1 ) { 00188 ast_log(LOG_WARNING, "Failed to skip fact block: %d\n", data ); 00189 return -1; 00190 } 00191 } 00192 #if 0 00193 curpos = lseek(fd, 0, SEEK_CUR); 00194 truelength = lseek(fd, 0, SEEK_END); 00195 lseek(fd, curpos, SEEK_SET); 00196 truelength -= curpos; 00197 #endif 00198 return data; 00199 }
static int load_module | ( | void | ) | [static] |
Definition at line 486 of file format_wav.c.
References ast_format_register, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, and wav_f.
00487 { 00488 if (ast_format_register(&wav_f)) 00489 return AST_MODULE_LOAD_FAILURE; 00490 return AST_MODULE_LOAD_SUCCESS; 00491 }
static int unload_module | ( | void | ) | [static] |
Definition at line 493 of file format_wav.c.
References ast_format_unregister(), ast_format::name, and wav_f.
00494 { 00495 return ast_format_unregister(wav_f.name); 00496 }
static int update_header | ( | FILE * | f | ) | [static] |
Definition at line 201 of file format_wav.c.
References ast_log(), fwrite, and LOG_WARNING.
00202 { 00203 off_t cur,end; 00204 int datalen,filelen,bytes; 00205 00206 cur = ftello(f); 00207 fseek(f, 0, SEEK_END); 00208 end = ftello(f); 00209 /* data starts 44 bytes in */ 00210 bytes = end - 44; 00211 datalen = htoll(bytes); 00212 /* chunk size is bytes of data plus 36 bytes of header */ 00213 filelen = htoll(36 + bytes); 00214 00215 if (cur < 0) { 00216 ast_log(LOG_WARNING, "Unable to find our position\n"); 00217 return -1; 00218 } 00219 if (fseek(f, 4, SEEK_SET)) { 00220 ast_log(LOG_WARNING, "Unable to set our position\n"); 00221 return -1; 00222 } 00223 if (fwrite(&filelen, 1, 4, f) != 4) { 00224 ast_log(LOG_WARNING, "Unable to set write file size\n"); 00225 return -1; 00226 } 00227 if (fseek(f, 40, SEEK_SET)) { 00228 ast_log(LOG_WARNING, "Unable to set our position\n"); 00229 return -1; 00230 } 00231 if (fwrite(&datalen, 1, 4, f) != 4) { 00232 ast_log(LOG_WARNING, "Unable to set write datalen\n"); 00233 return -1; 00234 } 00235 if (fseeko(f, cur, SEEK_SET)) { 00236 ast_log(LOG_WARNING, "Unable to return to position\n"); 00237 return -1; 00238 } 00239 return 0; 00240 }
static void wav_close | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 327 of file format_wav.c.
References ast_log(), wav_desc::bytes, errno, fwrite, LOG_WARNING, s, and update_header().
00328 { 00329 char zero = 0; 00330 struct wav_desc *fs = (struct wav_desc *)s->_private; 00331 00332 if (s->filename) { 00333 update_header(s->f); 00334 } 00335 00336 /* Pad to even length */ 00337 if (fs->bytes & 0x1) { 00338 if (!fwrite(&zero, 1, 1, s->f)) { 00339 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00340 } 00341 } 00342 }
static int wav_open | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 305 of file format_wav.c.
References check_header(), wav_desc::maxlen, and s.
00306 { 00307 /* We don't have any header to read or anything really, but 00308 if we did, it would go here. We also might want to check 00309 and be sure it's a valid file. */ 00310 struct wav_desc *tmp = (struct wav_desc *)s->_private; 00311 if ((tmp->maxlen = check_header(s->f)) < 0) 00312 return -1; 00313 return 0; 00314 }
static struct ast_frame* wav_read | ( | struct ast_filestream * | s, | |
int * | whennext | |||
) | [static] |
Definition at line 344 of file format_wav.c.
References AST_FORMAT_SLINEAR, AST_FRAME_SET_BUFFER, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), errno, LOG_WARNING, wav_desc::maxlen, s, ast_frame::samples, and WAV_BUF_SIZE.
00345 { 00346 int res; 00347 int samples; /* actual samples read */ 00348 #if __BYTE_ORDER == __BIG_ENDIAN 00349 int x; 00350 #endif 00351 short *tmp; 00352 int bytes = WAV_BUF_SIZE; /* in bytes */ 00353 off_t here; 00354 /* Send a frame from the file to the appropriate channel */ 00355 struct wav_desc *fs = (struct wav_desc *)s->_private; 00356 00357 here = ftello(s->f); 00358 if (fs->maxlen - here < bytes) /* truncate if necessary */ 00359 bytes = fs->maxlen - here; 00360 if (bytes < 0) 00361 bytes = 0; 00362 /* ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */ 00363 s->fr.frametype = AST_FRAME_VOICE; 00364 s->fr.subclass = AST_FORMAT_SLINEAR; 00365 s->fr.mallocd = 0; 00366 AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes); 00367 00368 if ( (res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) <= 0 ) { 00369 if (res) 00370 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); 00371 return NULL; 00372 } 00373 s->fr.datalen = res; 00374 s->fr.samples = samples = res / 2; 00375 00376 tmp = (short *)(s->fr.data.ptr); 00377 #if __BYTE_ORDER == __BIG_ENDIAN 00378 /* file format is little endian so we need to swap */ 00379 for( x = 0; x < samples; x++) 00380 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8); 00381 #endif 00382 00383 *whennext = samples; 00384 return &s->fr; 00385 }
static int wav_rewrite | ( | struct ast_filestream * | s, | |
const char * | comment | |||
) | [static] |
Definition at line 316 of file format_wav.c.
References s, and write_header().
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 00322 if (write_header(s->f)) 00323 return -1; 00324 return 0; 00325 }
static int wav_seek | ( | struct ast_filestream * | fs, | |
off_t | sample_offset, | |||
int | whence | |||
) | [static] |
Definition at line 432 of file format_wav.c.
References ast_filestream::f, and SEEK_FORCECUR.
00433 { 00434 off_t min, max, cur, offset = 0, samples; 00435 00436 samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */ 00437 min = 44; /* wav header is 44 bytes */ 00438 cur = ftello(fs->f); 00439 fseeko(fs->f, 0, SEEK_END); 00440 max = ftello(fs->f); 00441 if (whence == SEEK_SET) 00442 offset = samples + min; 00443 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) 00444 offset = samples + cur; 00445 else if (whence == SEEK_END) 00446 offset = max - samples; 00447 if (whence != SEEK_FORCECUR) { 00448 offset = (offset > max)?max:offset; 00449 } 00450 /* always protect the header space. */ 00451 offset = (offset < min)?min:offset; 00452 return fseeko(fs->f, offset, SEEK_SET); 00453 }
static off_t wav_tell | ( | struct ast_filestream * | fs | ) | [static] |
Definition at line 462 of file format_wav.c.
References ast_filestream::f.
00463 { 00464 off_t offset; 00465 offset = ftello(fs->f); 00466 /* subtract header size to get samples, then divide by 2 for 16 bit samples */ 00467 return (offset - 44)/2; 00468 }
static int wav_trunc | ( | struct ast_filestream * | fs | ) | [static] |
Definition at line 455 of file format_wav.c.
References ast_filestream::f, and update_header().
00456 { 00457 if (ftruncate(fileno(fs->f), ftello(fs->f))) 00458 return -1; 00459 return update_header(fs->f); 00460 }
static int wav_write | ( | struct ast_filestream * | fs, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 387 of file format_wav.c.
References ast_filestream::_private, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), errno, ast_filestream::f, f, fwrite, LOG_WARNING, and s.
00388 { 00389 #if __BYTE_ORDER == __BIG_ENDIAN 00390 int x; 00391 short tmp[8000], *tmpi; 00392 #endif 00393 struct wav_desc *s = (struct wav_desc *)fs->_private; 00394 int res; 00395 00396 if (f->frametype != AST_FRAME_VOICE) { 00397 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); 00398 return -1; 00399 } 00400 if (f->subclass != AST_FORMAT_SLINEAR) { 00401 ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass); 00402 return -1; 00403 } 00404 if (!f->datalen) 00405 return -1; 00406 00407 #if __BYTE_ORDER == __BIG_ENDIAN 00408 /* swap and write */ 00409 if (f->datalen > sizeof(tmp)) { 00410 ast_log(LOG_WARNING, "Data length is too long\n"); 00411 return -1; 00412 } 00413 tmpi = f->data.ptr; 00414 for (x=0; x < f->datalen/2; x++) 00415 tmp[x] = (tmpi[x] << 8) | ((tmpi[x] & 0xff00) >> 8); 00416 00417 if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) { 00418 #else 00419 /* just write */ 00420 if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen ) { 00421 #endif 00422 ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno)); 00423 return -1; 00424 } 00425 00426 s->bytes += f->datalen; 00427 00428 return 0; 00429 00430 }
static int write_header | ( | FILE * | f | ) | [static] |
Definition at line 242 of file format_wav.c.
References ast_log(), fwrite, and LOG_WARNING.
00243 { 00244 unsigned int hz=htoll(8000); 00245 unsigned int bhz = htoll(16000); 00246 unsigned int hs = htoll(16); 00247 unsigned short fmt = htols(1); 00248 unsigned short chans = htols(1); 00249 unsigned short bysam = htols(2); 00250 unsigned short bisam = htols(16); 00251 unsigned int size = htoll(0); 00252 /* Write a wav header, ignoring sizes which will be filled in later */ 00253 fseek(f,0,SEEK_SET); 00254 if (fwrite("RIFF", 1, 4, f) != 4) { 00255 ast_log(LOG_WARNING, "Unable to write header\n"); 00256 return -1; 00257 } 00258 if (fwrite(&size, 1, 4, f) != 4) { 00259 ast_log(LOG_WARNING, "Unable to write header\n"); 00260 return -1; 00261 } 00262 if (fwrite("WAVEfmt ", 1, 8, f) != 8) { 00263 ast_log(LOG_WARNING, "Unable to write header\n"); 00264 return -1; 00265 } 00266 if (fwrite(&hs, 1, 4, f) != 4) { 00267 ast_log(LOG_WARNING, "Unable to write header\n"); 00268 return -1; 00269 } 00270 if (fwrite(&fmt, 1, 2, f) != 2) { 00271 ast_log(LOG_WARNING, "Unable to write header\n"); 00272 return -1; 00273 } 00274 if (fwrite(&chans, 1, 2, f) != 2) { 00275 ast_log(LOG_WARNING, "Unable to write header\n"); 00276 return -1; 00277 } 00278 if (fwrite(&hz, 1, 4, f) != 4) { 00279 ast_log(LOG_WARNING, "Unable to write header\n"); 00280 return -1; 00281 } 00282 if (fwrite(&bhz, 1, 4, f) != 4) { 00283 ast_log(LOG_WARNING, "Unable to write header\n"); 00284 return -1; 00285 } 00286 if (fwrite(&bysam, 1, 2, f) != 2) { 00287 ast_log(LOG_WARNING, "Unable to write header\n"); 00288 return -1; 00289 } 00290 if (fwrite(&bisam, 1, 2, f) != 2) { 00291 ast_log(LOG_WARNING, "Unable to write header\n"); 00292 return -1; 00293 } 00294 if (fwrite("data", 1, 4, f) != 4) { 00295 ast_log(LOG_WARNING, "Unable to write header\n"); 00296 return -1; 00297 } 00298 if (fwrite(&size, 1, 4, f) != 4) { 00299 ast_log(LOG_WARNING, "Unable to write header\n"); 00300 return -1; 00301 } 00302 return 0; 00303 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Microsoft WAV format (8000Hz 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .load_pri = 10, } [static] |
Definition at line 502 of file format_wav.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 502 of file format_wav.c.
struct ast_format wav_f [static] |