#include "asterisk.h"
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/time.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/sched.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 | GAIN 0 |
#define | htoll(b) (b) |
#define | htols(b) (b) |
#define | ltohl(b) (b) |
#define | ltohs(b) (b) |
#define | WAV_BUF_SIZE 320 |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | check_header (FILE *f) |
static int | check_header_fmt (FILE *f, int hsize) |
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_FIRST | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .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 62 of file format_wav.c.
#define GAIN 0 |
#define htoll | ( | b | ) | (b) |
Definition at line 68 of file format_wav.c.
#define htols | ( | b | ) | (b) |
Definition at line 69 of file format_wav.c.
#define ltohl | ( | b | ) | (b) |
Definition at line 70 of file format_wav.c.
#define ltohs | ( | b | ) | (b) |
Definition at line 71 of file format_wav.c.
#define WAV_BUF_SIZE 320 |
static void __reg_module | ( | void | ) | [static] |
Definition at line 528 of file format_wav.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 528 of file format_wav.c.
static int check_header | ( | FILE * | f | ) | [static] |
Definition at line 149 of file format_wav.c.
References ast_log(), check_header_fmt(), LOG_DEBUG, LOG_WARNING, ltohl, and type.
00150 { 00151 int type, size, formtype; 00152 int data; 00153 if (fread(&type, 1, 4, f) != 4) { 00154 ast_log(LOG_WARNING, "Read failed (type)\n"); 00155 return -1; 00156 } 00157 if (fread(&size, 1, 4, f) != 4) { 00158 ast_log(LOG_WARNING, "Read failed (size)\n"); 00159 return -1; 00160 } 00161 size = ltohl(size); 00162 if (fread(&formtype, 1, 4, f) != 4) { 00163 ast_log(LOG_WARNING, "Read failed (formtype)\n"); 00164 return -1; 00165 } 00166 if (memcmp(&type, "RIFF", 4)) { 00167 ast_log(LOG_WARNING, "Does not begin with RIFF\n"); 00168 return -1; 00169 } 00170 if (memcmp(&formtype, "WAVE", 4)) { 00171 ast_log(LOG_WARNING, "Does not contain WAVE\n"); 00172 return -1; 00173 } 00174 /* Skip any facts and get the first data block */ 00175 for(;;) 00176 { 00177 char buf[4]; 00178 00179 /* Begin data chunk */ 00180 if (fread(&buf, 1, 4, f) != 4) { 00181 ast_log(LOG_WARNING, "Read failed (block header format)\n"); 00182 return -1; 00183 } 00184 /* Data has the actual length of data in it */ 00185 if (fread(&data, 1, 4, f) != 4) { 00186 ast_log(LOG_WARNING, "Read failed (block '%.4s' header length)\n", buf); 00187 return -1; 00188 } 00189 data = ltohl(data); 00190 if (memcmp(&buf, "fmt ", 4) == 0) { 00191 if (check_header_fmt(f, data)) 00192 return -1; 00193 continue; 00194 } 00195 if(memcmp(buf, "data", 4) == 0 ) 00196 break; 00197 ast_log(LOG_DEBUG, "Skipping unknown block '%.4s'\n", buf); 00198 if (fseek(f,data,SEEK_CUR) == -1 ) { 00199 ast_log(LOG_WARNING, "Failed to skip '%.4s' block: %d\n", buf, data); 00200 return -1; 00201 } 00202 } 00203 #if 0 00204 curpos = lseek(fd, 0, SEEK_CUR); 00205 truelength = lseek(fd, 0, SEEK_END); 00206 lseek(fd, curpos, SEEK_SET); 00207 truelength -= curpos; 00208 #endif 00209 return data; 00210 }
static int check_header_fmt | ( | FILE * | f, | |
int | hsize | |||
) | [static] |
Definition at line 90 of file format_wav.c.
References ast_log(), DEFAULT_SAMPLE_RATE, format, LOG_WARNING, ltohl, and ltohs.
Referenced by check_header().
00091 { 00092 short format, chans, bysam, bisam; 00093 int bysec; 00094 int freq; 00095 if (hsize < 16) { 00096 ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize)); 00097 return -1; 00098 } 00099 if (fread(&format, 1, 2, f) != 2) { 00100 ast_log(LOG_WARNING, "Read failed (format)\n"); 00101 return -1; 00102 } 00103 if (ltohs(format) != 1) { 00104 ast_log(LOG_WARNING, "Not a wav file %d\n", ltohs(format)); 00105 return -1; 00106 } 00107 if (fread(&chans, 1, 2, f) != 2) { 00108 ast_log(LOG_WARNING, "Read failed (format)\n"); 00109 return -1; 00110 } 00111 if (ltohs(chans) != 1) { 00112 ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans)); 00113 return -1; 00114 } 00115 if (fread(&freq, 1, 4, f) != 4) { 00116 ast_log(LOG_WARNING, "Read failed (freq)\n"); 00117 return -1; 00118 } 00119 if (ltohl(freq) != DEFAULT_SAMPLE_RATE) { 00120 ast_log(LOG_WARNING, "Unexpected frequency %d\n", ltohl(freq)); 00121 return -1; 00122 } 00123 /* Ignore the byte frequency */ 00124 if (fread(&bysec, 1, 4, f) != 4) { 00125 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n"); 00126 return -1; 00127 } 00128 /* Check bytes per sample */ 00129 if (fread(&bysam, 1, 2, f) != 2) { 00130 ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n"); 00131 return -1; 00132 } 00133 if (ltohs(bysam) != 2) { 00134 ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam)); 00135 return -1; 00136 } 00137 if (fread(&bisam, 1, 2, f) != 2) { 00138 ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam)); 00139 return -1; 00140 } 00141 /* Skip any additional header */ 00142 if (fseek(f,ltohl(hsize)-16,SEEK_CUR) == -1 ) { 00143 ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", ltohl(hsize)-16 ); 00144 return -1; 00145 } 00146 return 0; 00147 }
static int load_module | ( | void | ) | [static] |
Definition at line 515 of file format_wav.c.
References ast_format_register, and wav_f.
00516 { 00517 return ast_format_register(&wav_f); 00518 }
static int unload_module | ( | void | ) | [static] |
Definition at line 520 of file format_wav.c.
References ast_format_unregister(), ast_format::name, and wav_f.
00521 { 00522 return ast_format_unregister(wav_f.name); 00523 }
static int update_header | ( | FILE * | f | ) | [static] |
Definition at line 212 of file format_wav.c.
References ast_log(), errno, htoll, and LOG_WARNING.
00213 { 00214 off_t cur,end; 00215 int datalen,filelen,bytes; 00216 00217 cur = ftello(f); 00218 fseek(f, 0, SEEK_END); 00219 end = ftello(f); 00220 /* data starts 44 bytes in */ 00221 bytes = end - 44; 00222 datalen = htoll(bytes); 00223 /* chunk size is bytes of data plus 36 bytes of header */ 00224 filelen = htoll(36 + bytes); 00225 00226 if (cur < 0) { 00227 ast_log(LOG_WARNING, "Unable to find our position: %s\n", strerror(errno)); 00228 return -1; 00229 } 00230 if (fseek(f, 4, SEEK_SET)) { 00231 ast_log(LOG_WARNING, "Unable to set our position: %s\n", strerror(errno)); 00232 return -1; 00233 } 00234 if (fwrite(&filelen, 1, 4, f) != 4) { 00235 ast_log(LOG_WARNING, "Unable to set write file size: %s\n", strerror(errno)); 00236 return -1; 00237 } 00238 if (fseek(f, 40, SEEK_SET)) { 00239 ast_log(LOG_WARNING, "Unable to set our position: %s\n", strerror(errno)); 00240 return -1; 00241 } 00242 if (fwrite(&datalen, 1, 4, f) != 4) { 00243 ast_log(LOG_WARNING, "Unable to set write datalen: %s\n", strerror(errno)); 00244 return -1; 00245 } 00246 if (fseeko(f, cur, SEEK_SET)) { 00247 ast_log(LOG_WARNING, "Unable to return to position: %s\n", strerror(errno)); 00248 return -1; 00249 } 00250 return 0; 00251 }
static void wav_close | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 338 of file format_wav.c.
References ast_log(), wav_desc::bytes, errno, LOG_WARNING, and s.
00339 { 00340 char zero = 0; 00341 struct wav_desc *fs = (struct wav_desc *)s->_private; 00342 /* Pad to even length */ 00343 if (fs->bytes & 0x1) { 00344 if (!fwrite(&zero, 1, 1, s->f)) { 00345 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00346 } 00347 } 00348 }
static int wav_open | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 316 of file format_wav.c.
References check_header(), wav_desc::maxlen, and s.
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)) < 0) 00323 return -1; 00324 return 0; 00325 }
static struct ast_frame* wav_read | ( | struct ast_filestream * | s, | |
int * | whennext | |||
) | [static] |
Definition at line 350 of file format_wav.c.
References AST_FORMAT_SLINEAR, AST_FRAME_SET_BUFFER, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), errno, GAIN, LOG_WARNING, wav_desc::maxlen, wav_desc::needsgain, s, ast_frame::samples, and WAV_BUF_SIZE.
00351 { 00352 int res; 00353 int samples; /* actual samples read */ 00354 int x; 00355 short *tmp; 00356 int bytes = WAV_BUF_SIZE; /* in bytes */ 00357 off_t here; 00358 /* Send a frame from the file to the appropriate channel */ 00359 struct wav_desc *fs = (struct wav_desc *)s->_private; 00360 00361 here = ftello(s->f); 00362 if (fs->maxlen - here < bytes) /* truncate if necessary */ 00363 bytes = fs->maxlen - here; 00364 if (bytes < 0) 00365 bytes = 0; 00366 /* ast_log(LOG_DEBUG, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */ 00367 s->fr.frametype = AST_FRAME_VOICE; 00368 s->fr.subclass = AST_FORMAT_SLINEAR; 00369 s->fr.mallocd = 0; 00370 AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes); 00371 00372 if ( (res = fread(s->fr.data, 1, s->fr.datalen, s->f)) <= 0 ) { 00373 if (res) 00374 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); 00375 return NULL; 00376 } 00377 s->fr.datalen = res; 00378 s->fr.samples = samples = res / 2; 00379 00380 tmp = (short *)(s->fr.data); 00381 #if __BYTE_ORDER == __BIG_ENDIAN 00382 /* file format is little endian so we need to swap */ 00383 for( x = 0; x < samples; x++) 00384 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8); 00385 #endif 00386 00387 if (fs->needsgain) { 00388 for (x=0; x < samples; x++) { 00389 if (tmp[x] & ((1 << GAIN) - 1)) { 00390 /* If it has data down low, then it's not something we've artificially increased gain 00391 on, so we don't need to gain adjust it */ 00392 fs->needsgain = 0; 00393 break; 00394 } 00395 } 00396 if (fs->needsgain) { 00397 for (x=0; x < samples; x++) 00398 tmp[x] = tmp[x] >> GAIN; 00399 } 00400 } 00401 00402 *whennext = samples; 00403 return &s->fr; 00404 }
static int wav_rewrite | ( | struct ast_filestream * | s, | |
const char * | comment | |||
) | [static] |
Definition at line 327 of file format_wav.c.
References s, 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 if (write_header(s->f)) 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 461 of file format_wav.c.
References ast_filestream::f, offset, and SEEK_FORCECUR.
00462 { 00463 off_t min, max, cur, offset = 0, samples; 00464 00465 samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */ 00466 min = 44; /* wav header is 44 bytes */ 00467 cur = ftello(fs->f); 00468 fseeko(fs->f, 0, SEEK_END); 00469 max = ftello(fs->f); 00470 if (whence == SEEK_SET) 00471 offset = samples + min; 00472 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) 00473 offset = samples + cur; 00474 else if (whence == SEEK_END) 00475 offset = max - samples; 00476 if (whence != SEEK_FORCECUR) { 00477 offset = (offset > max)?max:offset; 00478 } 00479 /* always protect the header space. */ 00480 offset = (offset < min)?min:offset; 00481 return fseeko(fs->f, offset, SEEK_SET); 00482 }
static off_t wav_tell | ( | struct ast_filestream * | fs | ) | [static] |
Definition at line 491 of file format_wav.c.
References ast_filestream::f, and offset.
00492 { 00493 off_t offset; 00494 offset = ftello(fs->f); 00495 /* subtract header size to get samples, then divide by 2 for 16 bit samples */ 00496 return (offset - 44)/2; 00497 }
static int wav_trunc | ( | struct ast_filestream * | fs | ) | [static] |
Definition at line 484 of file format_wav.c.
References ast_filestream::f, and update_header().
00485 { 00486 if (ftruncate(fileno(fs->f), ftello(fs->f))) 00487 return -1; 00488 return update_header(fs->f); 00489 }
static int wav_write | ( | struct ast_filestream * | fs, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 406 of file format_wav.c.
References ast_filestream::_private, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), errno, ast_filestream::f, f, GAIN, LOG_WARNING, s, and update_header().
00407 { 00408 int x; 00409 short tmp[8000], *tmpi; 00410 float tmpf; 00411 struct wav_desc *s = (struct wav_desc *)fs->_private; 00412 int res; 00413 00414 if (f->frametype != AST_FRAME_VOICE) { 00415 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); 00416 return -1; 00417 } 00418 if (f->subclass != AST_FORMAT_SLINEAR) { 00419 ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass); 00420 return -1; 00421 } 00422 if (f->datalen > sizeof(tmp)) { 00423 ast_log(LOG_WARNING, "Data length is too long\n"); 00424 return -1; 00425 } 00426 if (!f->datalen) 00427 return -1; 00428 00429 #if 0 00430 printf("Data Length: %d\n", f->datalen); 00431 #endif 00432 00433 tmpi = f->data; 00434 /* Volume adjust here to accomodate */ 00435 for (x=0;x<f->datalen/2;x++) { 00436 tmpf = ((float)tmpi[x]) * ((float)(1 << GAIN)); 00437 if (tmpf > 32767.0) 00438 tmpf = 32767.0; 00439 if (tmpf < -32768.0) 00440 tmpf = -32768.0; 00441 tmp[x] = tmpf; 00442 tmp[x] &= ~((1 << GAIN) - 1); 00443 00444 #if __BYTE_ORDER == __BIG_ENDIAN 00445 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8); 00446 #endif 00447 00448 } 00449 if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) { 00450 ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno)); 00451 return -1; 00452 } 00453 00454 s->bytes += f->datalen; 00455 update_header(fs->f); 00456 00457 return 0; 00458 00459 }
static int write_header | ( | FILE * | f | ) | [static] |
Definition at line 253 of file format_wav.c.
References ast_log(), htoll, htols, and LOG_WARNING.
00254 { 00255 unsigned int hz=htoll(8000); 00256 unsigned int bhz = htoll(16000); 00257 unsigned int hs = htoll(16); 00258 unsigned short fmt = htols(1); 00259 unsigned short chans = htols(1); 00260 unsigned short bysam = htols(2); 00261 unsigned short bisam = htols(16); 00262 unsigned int size = htoll(0); 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_FIRST | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 528 of file format_wav.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 528 of file format_wav.c.
struct ast_format wav_f [static] |