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