#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_DEFAULT , .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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } |
static const 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 494 of file format_wav.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 494 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 482 of file format_wav.c.
References ast_format_register, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, and wav_f.
00483 { 00484 if (ast_format_register(&wav_f)) 00485 return AST_MODULE_LOAD_FAILURE; 00486 return AST_MODULE_LOAD_SUCCESS; 00487 }
static int unload_module | ( | void | ) | [static] |
Definition at line 489 of file format_wav.c.
References ast_format_unregister(), ast_format::name, and wav_f.
00490 { 00491 return ast_format_unregister(wav_f.name); 00492 }
static int update_header | ( | FILE * | f | ) | [static] |
Definition at line 201 of file format_wav.c.
References ast_log(), 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, LOG_WARNING, and s.
00328 { 00329 char zero = 0; 00330 struct wav_desc *fs = (struct wav_desc *)s->_private; 00331 /* Pad to even length */ 00332 if (fs->bytes & 0x1) { 00333 if (!fwrite(&zero, 1, 1, s->f)) { 00334 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00335 } 00336 } 00337 }
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 339 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.
00340 { 00341 int res; 00342 int samples; /* actual samples read */ 00343 #if __BYTE_ORDER == __BIG_ENDIAN 00344 int x; 00345 #endif 00346 short *tmp; 00347 int bytes = WAV_BUF_SIZE; /* in bytes */ 00348 off_t here; 00349 /* Send a frame from the file to the appropriate channel */ 00350 struct wav_desc *fs = (struct wav_desc *)s->_private; 00351 00352 here = ftello(s->f); 00353 if (fs->maxlen - here < bytes) /* truncate if necessary */ 00354 bytes = fs->maxlen - here; 00355 if (bytes < 0) 00356 bytes = 0; 00357 /* ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */ 00358 s->fr.frametype = AST_FRAME_VOICE; 00359 s->fr.subclass = AST_FORMAT_SLINEAR; 00360 s->fr.mallocd = 0; 00361 AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes); 00362 00363 if ( (res = fread(s->fr.data, 1, s->fr.datalen, s->f)) <= 0 ) { 00364 if (res) 00365 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); 00366 return NULL; 00367 } 00368 s->fr.datalen = res; 00369 s->fr.samples = samples = res / 2; 00370 00371 tmp = (short *)(s->fr.data); 00372 #if __BYTE_ORDER == __BIG_ENDIAN 00373 /* file format is little endian so we need to swap */ 00374 for( x = 0; x < samples; x++) 00375 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8); 00376 #endif 00377 00378 *whennext = samples; 00379 return &s->fr; 00380 }
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 428 of file format_wav.c.
References ast_filestream::f, and SEEK_FORCECUR.
00429 { 00430 off_t min, max, cur, offset = 0, samples; 00431 00432 samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */ 00433 min = 44; /* wav header is 44 bytes */ 00434 cur = ftello(fs->f); 00435 fseeko(fs->f, 0, SEEK_END); 00436 max = ftello(fs->f); 00437 if (whence == SEEK_SET) 00438 offset = samples + min; 00439 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) 00440 offset = samples + cur; 00441 else if (whence == SEEK_END) 00442 offset = max - samples; 00443 if (whence != SEEK_FORCECUR) { 00444 offset = (offset > max)?max:offset; 00445 } 00446 /* always protect the header space. */ 00447 offset = (offset < min)?min:offset; 00448 return fseeko(fs->f, offset, SEEK_SET); 00449 }
static off_t wav_tell | ( | struct ast_filestream * | fs | ) | [static] |
Definition at line 458 of file format_wav.c.
References ast_filestream::f.
00459 { 00460 off_t offset; 00461 offset = ftello(fs->f); 00462 /* subtract header size to get samples, then divide by 2 for 16 bit samples */ 00463 return (offset - 44)/2; 00464 }
static int wav_trunc | ( | struct ast_filestream * | fs | ) | [static] |
Definition at line 451 of file format_wav.c.
References ast_filestream::f, and update_header().
00452 { 00453 if (ftruncate(fileno(fs->f), ftello(fs->f))) 00454 return -1; 00455 return update_header(fs->f); 00456 }
static int wav_write | ( | struct ast_filestream * | fs, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 382 of file format_wav.c.
References ast_filestream::_private, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), errno, ast_filestream::f, f, LOG_WARNING, and s.
00383 { 00384 #if __BYTE_ORDER == __BIG_ENDIAN 00385 int x; 00386 short tmp[8000], *tmpi; 00387 #endif 00388 struct wav_desc *s = (struct wav_desc *)fs->_private; 00389 int res; 00390 00391 if (f->frametype != AST_FRAME_VOICE) { 00392 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); 00393 return -1; 00394 } 00395 if (f->subclass != AST_FORMAT_SLINEAR) { 00396 ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass); 00397 return -1; 00398 } 00399 if (!f->datalen) 00400 return -1; 00401 00402 #if __BYTE_ORDER == __BIG_ENDIAN 00403 /* swap and write */ 00404 if (f->datalen > sizeof(tmp)) { 00405 ast_log(LOG_WARNING, "Data length is too long\n"); 00406 return -1; 00407 } 00408 tmpi = f->data; 00409 for (x=0; x < f->datalen/2; x++) 00410 tmp[x] = (tmpi[x] << 8) | ((tmpi[x] & 0xff00) >> 8); 00411 00412 if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) { 00413 #else 00414 /* just write */ 00415 if ((res = fwrite(f->data, 1, f->datalen, fs->f)) != f->datalen ) { 00416 #endif 00417 ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno)); 00418 return -1; 00419 } 00420 00421 s->bytes += f->datalen; 00422 update_header(fs->f); 00423 00424 return 0; 00425 00426 }
static int write_header | ( | FILE * | f | ) | [static] |
Definition at line 242 of file format_wav.c.
References ast_log(), 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_DEFAULT , .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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 494 of file format_wav.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 494 of file format_wav.c.
struct ast_format wav_f [static] |