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