#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 | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Microsoft WAV format (8000Hz Signed Linear)") | |
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_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 |
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Microsoft WAV format (8000Hz Signed Linear)" | ||||
) |
static int check_header | ( | FILE * | f | ) | [static] |
Definition at line 90 of file format_wav.c.
References ast_log(), DEFAULT_SAMPLE_RATE, fmt, 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 freqency %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 518 of file format_wav.c.
References ast_format_register.
00519 { 00520 return ast_format_register(&wav_f); 00521 }
static int unload_module | ( | void | ) | [static] |
Definition at line 523 of file format_wav.c.
References ast_format_unregister(), and ast_format::name.
00524 { 00525 return ast_format_unregister(wav_f.name); 00526 }
static int update_header | ( | FILE * | f | ) | [static] |
Definition at line 218 of file format_wav.c.
References ast_log(), 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\n"); 00234 return -1; 00235 } 00236 if (fseek(f, 4, SEEK_SET)) { 00237 ast_log(LOG_WARNING, "Unable to set our position\n"); 00238 return -1; 00239 } 00240 if (fwrite(&filelen, 1, 4, f) != 4) { 00241 ast_log(LOG_WARNING, "Unable to set write file size\n"); 00242 return -1; 00243 } 00244 if (fseek(f, 40, SEEK_SET)) { 00245 ast_log(LOG_WARNING, "Unable to set our position\n"); 00246 return -1; 00247 } 00248 if (fwrite(&datalen, 1, 4, f) != 4) { 00249 ast_log(LOG_WARNING, "Unable to set write datalen\n"); 00250 return -1; 00251 } 00252 if (fseeko(f, cur, SEEK_SET)) { 00253 ast_log(LOG_WARNING, "Unable to return to position\n"); 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 wav_desc::bytes, ast_filestream::f, and ast_filestream::private.
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 fwrite(&zero, 1, 1, s->f); 00351 }
static int wav_open | ( | struct ast_filestream * | s | ) | [static] |
Definition at line 322 of file format_wav.c.
References check_header(), ast_filestream::f, wav_desc::maxlen, and ast_filestream::private.
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, read] |
Definition at line 353 of file format_wav.c.
References AST_FORMAT_SLINEAR, AST_FRAME_SET_BUFFER, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_filestream::buf, ast_frame::data, ast_frame::datalen, ast_filestream::f, ast_filestream::fr, ast_frame::frametype, GAIN, LOG_WARNING, ast_frame::mallocd, wav_desc::maxlen, wav_desc::needsgain, ast_filestream::private, ast_frame::samples, ast_frame::subclass, and WAV_BUF_SIZE.
00354 { 00355 int res; 00356 int samples; /* actual samples read */ 00357 int x; 00358 short *tmp; 00359 int bytes = WAV_BUF_SIZE; /* in bytes */ 00360 off_t here; 00361 /* Send a frame from the file to the appropriate channel */ 00362 struct wav_desc *fs = (struct wav_desc *)s->private; 00363 00364 here = ftello(s->f); 00365 if (fs->maxlen - here < bytes) /* truncate if necessary */ 00366 bytes = fs->maxlen - here; 00367 if (bytes < 0) 00368 bytes = 0; 00369 /* ast_log(LOG_DEBUG, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */ 00370 s->fr.frametype = AST_FRAME_VOICE; 00371 s->fr.subclass = AST_FORMAT_SLINEAR; 00372 s->fr.mallocd = 0; 00373 AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes); 00374 00375 if ( (res = fread(s->fr.data, 1, s->fr.datalen, s->f)) <= 0 ) { 00376 if (res) 00377 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); 00378 return NULL; 00379 } 00380 s->fr.datalen = res; 00381 s->fr.samples = samples = res / 2; 00382 00383 tmp = (short *)(s->fr.data); 00384 #if __BYTE_ORDER == __BIG_ENDIAN 00385 /* file format is little endian so we need to swap */ 00386 for( x = 0; x < samples; x++) 00387 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8); 00388 #endif 00389 00390 if (fs->needsgain) { 00391 for (x=0; x < samples; x++) { 00392 if (tmp[x] & ((1 << GAIN) - 1)) { 00393 /* If it has data down low, then it's not something we've artificially increased gain 00394 on, so we don't need to gain adjust it */ 00395 fs->needsgain = 0; 00396 break; 00397 } 00398 } 00399 if (fs->needsgain) { 00400 for (x=0; x < samples; x++) 00401 tmp[x] = tmp[x] >> GAIN; 00402 } 00403 } 00404 00405 *whennext = samples; 00406 return &s->fr; 00407 }
static int wav_rewrite | ( | struct ast_filestream * | s, | |
const char * | comment | |||
) | [static] |
Definition at line 333 of file format_wav.c.
References ast_filestream::f, 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 464 of file format_wav.c.
References ast_filestream::f, offset, and SEEK_FORCECUR.
00465 { 00466 off_t min, max, cur, offset = 0, samples; 00467 00468 samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */ 00469 min = 44; /* wav header is 44 bytes */ 00470 cur = ftello(fs->f); 00471 fseeko(fs->f, 0, SEEK_END); 00472 max = ftello(fs->f); 00473 if (whence == SEEK_SET) 00474 offset = samples + min; 00475 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) 00476 offset = samples + cur; 00477 else if (whence == SEEK_END) 00478 offset = max - samples; 00479 if (whence != SEEK_FORCECUR) { 00480 offset = (offset > max)?max:offset; 00481 } 00482 /* always protect the header space. */ 00483 offset = (offset < min)?min:offset; 00484 return fseeko(fs->f, offset, SEEK_SET); 00485 }
static off_t wav_tell | ( | struct ast_filestream * | fs | ) | [static] |
Definition at line 494 of file format_wav.c.
References ast_filestream::f, and offset.
00495 { 00496 off_t offset; 00497 offset = ftello(fs->f); 00498 /* subtract header size to get samples, then divide by 2 for 16 bit samples */ 00499 return (offset - 44)/2; 00500 }
static int wav_trunc | ( | struct ast_filestream * | fs | ) | [static] |
Definition at line 487 of file format_wav.c.
References ast_filestream::f, and update_header().
00488 { 00489 if (ftruncate(fileno(fs->f), ftello(fs->f))) 00490 return -1; 00491 return update_header(fs->f); 00492 }
static int wav_write | ( | struct ast_filestream * | fs, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 409 of file format_wav.c.
References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), wav_desc::bytes, ast_frame::data, ast_frame::datalen, ast_filestream::f, ast_frame::frametype, GAIN, LOG_WARNING, ast_filestream::private, s, ast_frame::subclass, and update_header().
00410 { 00411 int x; 00412 short tmp[8000], *tmpi; 00413 float tmpf; 00414 struct wav_desc *s = (struct wav_desc *)fs->private; 00415 int res; 00416 00417 if (f->frametype != AST_FRAME_VOICE) { 00418 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); 00419 return -1; 00420 } 00421 if (f->subclass != AST_FORMAT_SLINEAR) { 00422 ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass); 00423 return -1; 00424 } 00425 if (f->datalen > sizeof(tmp)) { 00426 ast_log(LOG_WARNING, "Data length is too long\n"); 00427 return -1; 00428 } 00429 if (!f->datalen) 00430 return -1; 00431 00432 #if 0 00433 printf("Data Length: %d\n", f->datalen); 00434 #endif 00435 00436 tmpi = f->data; 00437 /* Volume adjust here to accomodate */ 00438 for (x=0;x<f->datalen/2;x++) { 00439 tmpf = ((float)tmpi[x]) * ((float)(1 << GAIN)); 00440 if (tmpf > 32767.0) 00441 tmpf = 32767.0; 00442 if (tmpf < -32768.0) 00443 tmpf = -32768.0; 00444 tmp[x] = tmpf; 00445 tmp[x] &= ~((1 << GAIN) - 1); 00446 00447 #if __BYTE_ORDER == __BIG_ENDIAN 00448 tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8); 00449 #endif 00450 00451 } 00452 if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) { 00453 ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno)); 00454 return -1; 00455 } 00456 00457 s->bytes += f->datalen; 00458 update_header(fs->f); 00459 00460 return 0; 00461 00462 }
static int write_header | ( | FILE * | f | ) | [static] |
Definition at line 259 of file format_wav.c.
References ast_log(), fmt, 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_format wav_f [static] |
Definition at line 502 of file format_wav.c.