Wed Aug 18 22:34:23 2010

Asterisk developer's documentation


format_wav.c File Reference

Work with WAV in the proprietary Microsoft format. Microsoft WAV format (8000hz Signed Linear). More...

#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_framewav_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_ORDER , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .load_pri = 10, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_format wav_f


Detailed Description

Work with WAV in the proprietary Microsoft format. Microsoft WAV format (8000hz Signed Linear).

Definition in file format_wav.c.


Define Documentation

#define BLOCKSIZE   160

Definition at line 48 of file format_wav.c.

#define WAV_BUF_SIZE   320

Definition at line 39 of file format_wav.c.

Referenced by wav_read().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 502 of file format_wav.c.

static void __unreg_module ( void   )  [static]

Definition at line 502 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 486 of file format_wav.c.

References ast_format_register, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, and wav_f.

00487 {
00488    if (ast_format_register(&wav_f))
00489       return AST_MODULE_LOAD_FAILURE;
00490    return AST_MODULE_LOAD_SUCCESS;
00491 }

static int unload_module ( void   )  [static]

Definition at line 493 of file format_wav.c.

References ast_format_unregister(), ast_format::name, and wav_f.

00494 {
00495    return ast_format_unregister(wav_f.name);
00496 }  

static int update_header ( FILE *  f  )  [static]

Definition at line 201 of file format_wav.c.

References ast_log(), fwrite, 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, fwrite, LOG_WARNING, s, and update_header().

00328 {
00329    char zero = 0;
00330    struct wav_desc *fs = (struct wav_desc *)s->_private;
00331 
00332    if (s->filename) {
00333       update_header(s->f);
00334    }
00335 
00336    /* Pad to even length */
00337    if (fs->bytes & 0x1) {
00338       if (!fwrite(&zero, 1, 1, s->f)) {
00339          ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
00340       }
00341    }
00342 }

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 344 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.

00345 {
00346    int res;
00347    int samples;   /* actual samples read */
00348 #if __BYTE_ORDER == __BIG_ENDIAN
00349    int x;
00350 #endif
00351    short *tmp;
00352    int bytes = WAV_BUF_SIZE;  /* in bytes */
00353    off_t here;
00354    /* Send a frame from the file to the appropriate channel */
00355    struct wav_desc *fs = (struct wav_desc *)s->_private;
00356 
00357    here = ftello(s->f);
00358    if (fs->maxlen - here < bytes)      /* truncate if necessary */
00359       bytes = fs->maxlen - here;
00360    if (bytes < 0)
00361       bytes = 0;
00362 /*    ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */
00363    s->fr.frametype = AST_FRAME_VOICE;
00364    s->fr.subclass = AST_FORMAT_SLINEAR;
00365    s->fr.mallocd = 0;
00366    AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes);
00367    
00368    if ( (res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) <= 0 ) {
00369       if (res)
00370          ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00371       return NULL;
00372    }
00373    s->fr.datalen = res;
00374    s->fr.samples = samples = res / 2;
00375 
00376    tmp = (short *)(s->fr.data.ptr);
00377 #if __BYTE_ORDER == __BIG_ENDIAN
00378    /* file format is little endian so we need to swap */
00379    for( x = 0; x < samples; x++)
00380       tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
00381 #endif
00382 
00383    *whennext = samples;
00384    return &s->fr;
00385 }

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 432 of file format_wav.c.

References ast_filestream::f, and SEEK_FORCECUR.

00433 {
00434    off_t min, max, cur, offset = 0, samples;
00435 
00436    samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */
00437    min = 44; /* wav header is 44 bytes */
00438    cur = ftello(fs->f);
00439    fseeko(fs->f, 0, SEEK_END);
00440    max = ftello(fs->f);
00441    if (whence == SEEK_SET)
00442       offset = samples + min;
00443    else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
00444       offset = samples + cur;
00445    else if (whence == SEEK_END)
00446       offset = max - samples;
00447         if (whence != SEEK_FORCECUR) {
00448       offset = (offset > max)?max:offset;
00449    }
00450    /* always protect the header space. */
00451    offset = (offset < min)?min:offset;
00452    return fseeko(fs->f, offset, SEEK_SET);
00453 }

static off_t wav_tell ( struct ast_filestream fs  )  [static]

Definition at line 462 of file format_wav.c.

References ast_filestream::f.

00463 {
00464    off_t offset;
00465    offset = ftello(fs->f);
00466    /* subtract header size to get samples, then divide by 2 for 16 bit samples */
00467    return (offset - 44)/2;
00468 }

static int wav_trunc ( struct ast_filestream fs  )  [static]

Definition at line 455 of file format_wav.c.

References ast_filestream::f, and update_header().

00456 {
00457    if (ftruncate(fileno(fs->f), ftello(fs->f)))
00458       return -1;
00459    return update_header(fs->f);
00460 }

static int wav_write ( struct ast_filestream fs,
struct ast_frame f 
) [static]

Definition at line 387 of file format_wav.c.

References ast_filestream::_private, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), errno, ast_filestream::f, f, fwrite, LOG_WARNING, and s.

00388 {
00389 #if __BYTE_ORDER == __BIG_ENDIAN
00390    int x;
00391    short tmp[8000], *tmpi;
00392 #endif
00393    struct wav_desc *s = (struct wav_desc *)fs->_private;
00394    int res;
00395 
00396    if (f->frametype != AST_FRAME_VOICE) {
00397       ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00398       return -1;
00399    }
00400    if (f->subclass != AST_FORMAT_SLINEAR) {
00401       ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass);
00402       return -1;
00403    }
00404    if (!f->datalen)
00405       return -1;
00406 
00407 #if __BYTE_ORDER == __BIG_ENDIAN
00408    /* swap and write */
00409    if (f->datalen > sizeof(tmp)) {
00410       ast_log(LOG_WARNING, "Data length is too long\n");
00411       return -1;
00412    }
00413    tmpi = f->data.ptr;
00414    for (x=0; x < f->datalen/2; x++) 
00415       tmp[x] = (tmpi[x] << 8) | ((tmpi[x] & 0xff00) >> 8);
00416 
00417    if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) {
00418 #else
00419    /* just write */
00420    if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen ) {
00421 #endif
00422       ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno));
00423       return -1;
00424    }
00425 
00426    s->bytes += f->datalen;
00427       
00428    return 0;
00429 
00430 }

static int write_header ( FILE *  f  )  [static]

Definition at line 242 of file format_wav.c.

References ast_log(), fwrite, 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 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .load_pri = 10, } [static]

Definition at line 502 of file format_wav.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 502 of file format_wav.c.

struct ast_format wav_f [static]

Definition at line 470 of file format_wav.c.

Referenced by load_module(), and unload_module().


Generated on Wed Aug 18 22:34:23 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7