Sat Mar 10 01:55:24 2012

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, int hz)
static int check_header_fmt (FILE *f, int hsize, int hz)
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, int writehz)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Microsoft WAV/WAV16 format (8kHz/16kHz 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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_format wav16_f
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 53 of file format_wav.c.

#define WAV_BUF_SIZE   320

Definition at line 43 of file format_wav.c.

Referenced by wav_read().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 541 of file format_wav.c.

static void __unreg_module ( void   )  [static]

Definition at line 541 of file format_wav.c.

static int check_header ( FILE *  f,
int  hz 
) [static]

Definition at line 139 of file format_wav.c.

References ast_log(), check_header_fmt(), LOG_DEBUG, LOG_WARNING, and type.

00140 {
00141    int type, size, formtype;
00142    int data;
00143    if (fread(&type, 1, 4, f) != 4) {
00144       ast_log(LOG_WARNING, "Read failed (type)\n");
00145       return -1;
00146    }
00147    if (fread(&size, 1, 4, f) != 4) {
00148       ast_log(LOG_WARNING, "Read failed (size)\n");
00149       return -1;
00150    }
00151    size = ltohl(size);
00152    if (fread(&formtype, 1, 4, f) != 4) {
00153       ast_log(LOG_WARNING, "Read failed (formtype)\n");
00154       return -1;
00155    }
00156    if (memcmp(&type, "RIFF", 4)) {
00157       ast_log(LOG_WARNING, "Does not begin with RIFF\n");
00158       return -1;
00159    }
00160    if (memcmp(&formtype, "WAVE", 4)) {
00161       ast_log(LOG_WARNING, "Does not contain WAVE\n");
00162       return -1;
00163    }
00164    /* Skip any facts and get the first data block */
00165    for(;;)
00166    { 
00167       char buf[4];
00168        
00169        /* Begin data chunk */
00170        if (fread(&buf, 1, 4, f) != 4) {
00171          ast_log(LOG_WARNING, "Read failed (block header format)\n");
00172          return -1;
00173        }
00174        /* Data has the actual length of data in it */
00175        if (fread(&data, 1, 4, f) != 4) {
00176          ast_log(LOG_WARNING, "Read failed (block '%.4s' header length)\n", buf);
00177          return -1;
00178        }
00179        data = ltohl(data);
00180       if (memcmp(&buf, "fmt ", 4) == 0) {
00181          if (check_header_fmt(f, data, hz))
00182             return -1;
00183          continue;
00184       }
00185        if(memcmp(buf, "data", 4) == 0 ) 
00186          break;
00187       ast_log(LOG_DEBUG, "Skipping unknown block '%.4s'\n", buf);
00188        if (fseek(f,data,SEEK_CUR) == -1 ) {
00189          ast_log(LOG_WARNING, "Failed to skip '%.4s' block: %d\n", buf, data);
00190          return -1;
00191        }
00192    }
00193 #if 0
00194    curpos = lseek(fd, 0, SEEK_CUR);
00195    truelength = lseek(fd, 0, SEEK_END);
00196    lseek(fd, curpos, SEEK_SET);
00197    truelength -= curpos;
00198 #endif   
00199    return data;
00200 }

static int check_header_fmt ( FILE *  f,
int  hsize,
int  hz 
) [static]

Definition at line 78 of file format_wav.c.

References ast_log(), format, and LOG_WARNING.

Referenced by check_header().

00079 {
00080    short format, chans, bysam, bisam;
00081    int bysec;
00082    int freq;
00083    if (hsize < 16) {
00084       ast_log(LOG_WARNING, "Unexpected header size %d\n", hsize);
00085       return -1;
00086    }
00087    if (fread(&format, 1, 2, f) != 2) {
00088       ast_log(LOG_WARNING, "Read failed (format)\n");
00089       return -1;
00090    }
00091    if (ltohs(format) != 1) {
00092       ast_log(LOG_WARNING, "Not a wav file %d\n", ltohs(format));
00093       return -1;
00094    }
00095    if (fread(&chans, 1, 2, f) != 2) {
00096       ast_log(LOG_WARNING, "Read failed (format)\n");
00097       return -1;
00098    }
00099    if (ltohs(chans) != 1) {
00100       ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
00101       return -1;
00102    }
00103    if (fread(&freq, 1, 4, f) != 4) {
00104       ast_log(LOG_WARNING, "Read failed (freq)\n");
00105       return -1;
00106    }
00107    if (((ltohl(freq) != 8000) && (ltohl(freq) != 16000)) ||
00108        ((ltohl(freq) == 8000) && (hz != 8000)) ||
00109        ((ltohl(freq) == 16000) && (hz != 16000))) {
00110       ast_log(LOG_WARNING, "Unexpected frequency mismatch %d (expecting %d)\n", ltohl(freq),hz);
00111       return -1;
00112    }
00113    /* Ignore the byte frequency */
00114    if (fread(&bysec, 1, 4, f) != 4) {
00115       ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n");
00116       return -1;
00117    }
00118    /* Check bytes per sample */
00119    if (fread(&bysam, 1, 2, f) != 2) {
00120       ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n");
00121       return -1;
00122    }
00123    if (ltohs(bysam) != 2) {
00124       ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam));
00125       return -1;
00126    }
00127    if (fread(&bisam, 1, 2, f) != 2) {
00128       ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam));
00129       return -1;
00130    }
00131    /* Skip any additional header */
00132    if (fseek(f,hsize-16,SEEK_CUR) == -1 ) {
00133       ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", hsize-16 );
00134       return -1;
00135    }
00136    return 0;
00137 }

static int load_module ( void   )  [static]

Definition at line 523 of file format_wav.c.

References ast_format_register, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, wav16_f, and wav_f.

00524 {
00525    if (ast_format_register(&wav_f)
00526       || ast_format_register(&wav16_f))
00527       return AST_MODULE_LOAD_FAILURE;
00528    return AST_MODULE_LOAD_SUCCESS;
00529 }

static int unload_module ( void   )  [static]

Definition at line 531 of file format_wav.c.

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

00532 {
00533    return ast_format_unregister(wav_f.name)
00534       || ast_format_unregister(wav16_f.name);
00535 }

static int update_header ( FILE *  f  )  [static]

Definition at line 202 of file format_wav.c.

References ast_log(), and LOG_WARNING.

00203 {
00204    off_t cur,end;
00205    int datalen,filelen,bytes;
00206    
00207    cur = ftello(f);
00208    fseek(f, 0, SEEK_END);
00209    end = ftello(f);
00210    /* data starts 44 bytes in */
00211    bytes = end - 44;
00212    datalen = htoll(bytes);
00213    /* chunk size is bytes of data plus 36 bytes of header */
00214    filelen = htoll(36 + bytes);
00215    
00216    if (cur < 0) {
00217       ast_log(LOG_WARNING, "Unable to find our position\n");
00218       return -1;
00219    }
00220    if (fseek(f, 4, SEEK_SET)) {
00221       ast_log(LOG_WARNING, "Unable to set our position\n");
00222       return -1;
00223    }
00224    if (fwrite(&filelen, 1, 4, f) != 4) {
00225       ast_log(LOG_WARNING, "Unable to set write file size\n");
00226       return -1;
00227    }
00228    if (fseek(f, 40, SEEK_SET)) {
00229       ast_log(LOG_WARNING, "Unable to set our position\n");
00230       return -1;
00231    }
00232    if (fwrite(&datalen, 1, 4, f) != 4) {
00233       ast_log(LOG_WARNING, "Unable to set write datalen\n");
00234       return -1;
00235    }
00236    if (fseeko(f, cur, SEEK_SET)) {
00237       ast_log(LOG_WARNING, "Unable to return to position\n");
00238       return -1;
00239    }
00240    return 0;
00241 }

static void wav_close ( struct ast_filestream s  )  [static]

Definition at line 338 of file format_wav.c.

References ast_filestream::_private, ast_log(), wav_desc::bytes, errno, ast_filestream::f, ast_filestream::filename, LOG_WARNING, ast_filestream::mode, and update_header().

00339 {
00340    char zero = 0;
00341    struct wav_desc *fs = (struct wav_desc *)s->_private;
00342 
00343    if (s->mode == O_RDONLY) {
00344       return;
00345    }
00346 
00347    if (s->filename) {
00348       update_header(s->f);
00349    }
00350 
00351    /* Pad to even length */
00352    if (fs->bytes & 0x1) {
00353       if (!fwrite(&zero, 1, 1, s->f)) {
00354          ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
00355       }
00356    }
00357 }

static int wav_open ( struct ast_filestream s  )  [static]

Definition at line 314 of file format_wav.c.

References ast_filestream::_private, AST_FORMAT_SLINEAR16, check_header(), ast_filestream::f, ast_filestream::fmt, ast_format::format, and wav_desc::maxlen.

00315 {
00316    /* We don't have any header to read or anything really, but
00317       if we did, it would go here.  We also might want to check
00318       and be sure it's a valid file.  */
00319    struct wav_desc *tmp = (struct wav_desc *)s->_private;
00320    if ((tmp->maxlen = check_header(s->f, (s->fmt->format == AST_FORMAT_SLINEAR16 ? 16000 : 8000))) < 0)
00321       return -1;
00322    return 0;
00323 }

static struct ast_frame* wav_read ( struct ast_filestream s,
int *  whennext 
) [static]

Definition at line 359 of file format_wav.c.

References ast_filestream::_private, AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_FRAME_SET_BUFFER, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_filestream::buf, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, errno, ast_filestream::f, ast_filestream::fr, ast_frame::frametype, wav_desc::hz, LOG_WARNING, ast_frame::mallocd, wav_desc::maxlen, ast_frame::ptr, ast_frame::samples, ast_frame::subclass, and WAV_BUF_SIZE.

00360 {
00361    int res;
00362    int samples;   /* actual samples read */
00363 #if __BYTE_ORDER == __BIG_ENDIAN
00364    int x;
00365    short *tmp;
00366 #endif
00367    int bytes;
00368    off_t here;
00369    /* Send a frame from the file to the appropriate channel */
00370    struct wav_desc *fs = (struct wav_desc *)s->_private;
00371 
00372    bytes = (fs->hz == 16000 ? (WAV_BUF_SIZE * 2) : WAV_BUF_SIZE);
00373 
00374    here = ftello(s->f);
00375    if (fs->maxlen - here < bytes)      /* truncate if necessary */
00376       bytes = fs->maxlen - here;
00377    if (bytes < 0)
00378       bytes = 0;
00379 /*    ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */
00380    s->fr.frametype = AST_FRAME_VOICE;
00381    s->fr.subclass.codec = (fs->hz == 16000 ? AST_FORMAT_SLINEAR16 : AST_FORMAT_SLINEAR);
00382    s->fr.mallocd = 0;
00383    AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes);
00384    
00385    if ( (res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) <= 0 ) {
00386       if (res)
00387          ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00388       return NULL;
00389    }
00390    s->fr.datalen = res;
00391    s->fr.samples = samples = res / 2;
00392 
00393 #if __BYTE_ORDER == __BIG_ENDIAN
00394    tmp = (short *)(s->fr.data.ptr);
00395    /* file format is little endian so we need to swap */
00396    for( x = 0; x < samples; x++)
00397       tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
00398 #endif
00399 
00400    *whennext = samples;
00401    return &s->fr;
00402 }

static int wav_rewrite ( struct ast_filestream s,
const char *  comment 
) [static]

Definition at line 325 of file format_wav.c.

References ast_filestream::_private, AST_FORMAT_SLINEAR16, ast_filestream::f, ast_filestream::fmt, ast_format::format, wav_desc::hz, and write_header().

00326 {
00327    /* We don't have any header to read or anything really, but
00328       if we did, it would go here.  We also might want to check
00329       and be sure it's a valid file.  */
00330 
00331    struct wav_desc *tmp = (struct wav_desc *)s->_private;
00332    tmp->hz = (s->fmt->format == AST_FORMAT_SLINEAR16 ? 16000 : 8000);
00333    if (write_header(s->f,tmp->hz))
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 453 of file format_wav.c.

References ast_filestream::f, and SEEK_FORCECUR.

00454 {
00455    off_t min, max, cur, offset = 0, samples;
00456 
00457    samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */
00458    min = 44; /* wav header is 44 bytes */
00459    cur = ftello(fs->f);
00460    fseeko(fs->f, 0, SEEK_END);
00461    max = ftello(fs->f);
00462    if (whence == SEEK_SET)
00463       offset = samples + min;
00464    else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
00465       offset = samples + cur;
00466    else if (whence == SEEK_END)
00467       offset = max - samples;
00468         if (whence != SEEK_FORCECUR) {
00469       offset = (offset > max)?max:offset;
00470    }
00471    /* always protect the header space. */
00472    offset = (offset < min)?min:offset;
00473    return fseeko(fs->f, offset, SEEK_SET);
00474 }

static off_t wav_tell ( struct ast_filestream fs  )  [static]

Definition at line 483 of file format_wav.c.

References ast_filestream::f.

00484 {
00485    off_t offset;
00486    offset = ftello(fs->f);
00487    /* subtract header size to get samples, then divide by 2 for 16 bit samples */
00488    return (offset - 44)/2;
00489 }

static int wav_trunc ( struct ast_filestream fs  )  [static]

Definition at line 476 of file format_wav.c.

References ast_filestream::f, and update_header().

00477 {
00478    if (ftruncate(fileno(fs->f), ftello(fs->f)))
00479       return -1;
00480    return update_header(fs->f);
00481 }

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

Definition at line 404 of file format_wav.c.

References ast_filestream::_private, AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_FRAME_VOICE, ast_getformatname(), ast_log(), errno, ast_filestream::f, f, ast_filestream::fmt, ast_format::format, wav_desc::hz, and LOG_WARNING.

00405 {
00406 #if __BYTE_ORDER == __BIG_ENDIAN
00407    int x;
00408    short tmp[16000], *tmpi;
00409 #endif
00410    struct wav_desc *s = (struct wav_desc *)fs->_private;
00411    int res;
00412 
00413    if (f->frametype != AST_FRAME_VOICE) {
00414       ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00415       return -1;
00416    }
00417    if ((f->subclass.codec != AST_FORMAT_SLINEAR) && (f->subclass.codec != AST_FORMAT_SLINEAR16)) {
00418       ast_log(LOG_WARNING, "Asked to write non-SLINEAR%s frame (%s)!\n", s->hz == 16000 ? "16" : "", ast_getformatname(f->subclass.codec));
00419       return -1;
00420    }
00421    if (f->subclass.codec != fs->fmt->format) {
00422       ast_log(LOG_WARNING, "Can't change SLINEAR frequency during write\n");
00423       return -1;
00424    }
00425    if (!f->datalen)
00426       return -1;
00427 
00428 #if __BYTE_ORDER == __BIG_ENDIAN
00429    /* swap and write */
00430    if (f->datalen > sizeof(tmp)) {
00431       ast_log(LOG_WARNING, "Data length is too long\n");
00432       return -1;
00433    }
00434    tmpi = f->data.ptr;
00435    for (x=0; x < f->datalen/2; x++) 
00436       tmp[x] = (tmpi[x] << 8) | ((tmpi[x] & 0xff00) >> 8);
00437 
00438    if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) {
00439 #else
00440    /* just write */
00441    if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen ) {
00442 #endif
00443       ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno));
00444       return -1;
00445    }
00446 
00447    s->bytes += f->datalen;
00448       
00449    return 0;
00450 
00451 }

static int write_header ( FILE *  f,
int  writehz 
) [static]

Definition at line 243 of file format_wav.c.

References ast_log(), and LOG_WARNING.

00244 {
00245    unsigned int hz;
00246    unsigned int bhz;
00247    unsigned int hs = htoll(16);
00248    unsigned short fmt = htols(1);
00249    unsigned short chans = htols(1);
00250    unsigned short bysam = htols(2);
00251    unsigned short bisam = htols(16);
00252    unsigned int size = htoll(0);
00253 
00254    if (writehz == 16000) {
00255       hz = htoll(16000);
00256       bhz = htoll(32000);
00257    } else {
00258       hz = htoll(8000);
00259       bhz = htoll(16000);
00260    }
00261    /* Write a wav header, ignoring sizes which will be filled in later */
00262    fseek(f,0,SEEK_SET);
00263    if (fwrite("RIFF", 1, 4, f) != 4) {
00264       ast_log(LOG_WARNING, "Unable to write header\n");
00265       return -1;
00266    }
00267    if (fwrite(&size, 1, 4, f) != 4) {
00268       ast_log(LOG_WARNING, "Unable to write header\n");
00269       return -1;
00270    }
00271    if (fwrite("WAVEfmt ", 1, 8, f) != 8) {
00272       ast_log(LOG_WARNING, "Unable to write header\n");
00273       return -1;
00274    }
00275    if (fwrite(&hs, 1, 4, f) != 4) {
00276       ast_log(LOG_WARNING, "Unable to write header\n");
00277       return -1;
00278    }
00279    if (fwrite(&fmt, 1, 2, f) != 2) {
00280       ast_log(LOG_WARNING, "Unable to write header\n");
00281       return -1;
00282    }
00283    if (fwrite(&chans, 1, 2, f) != 2) {
00284       ast_log(LOG_WARNING, "Unable to write header\n");
00285       return -1;
00286    }
00287    if (fwrite(&hz, 1, 4, f) != 4) {
00288       ast_log(LOG_WARNING, "Unable to write header\n");
00289       return -1;
00290    }
00291    if (fwrite(&bhz, 1, 4, f) != 4) {
00292       ast_log(LOG_WARNING, "Unable to write header\n");
00293       return -1;
00294    }
00295    if (fwrite(&bysam, 1, 2, f) != 2) {
00296       ast_log(LOG_WARNING, "Unable to write header\n");
00297       return -1;
00298    }
00299    if (fwrite(&bisam, 1, 2, f) != 2) {
00300       ast_log(LOG_WARNING, "Unable to write header\n");
00301       return -1;
00302    }
00303    if (fwrite("data", 1, 4, f) != 4) {
00304       ast_log(LOG_WARNING, "Unable to write header\n");
00305       return -1;
00306    }
00307    if (fwrite(&size, 1, 4, f) != 4) {
00308       ast_log(LOG_WARNING, "Unable to write header\n");
00309       return -1;
00310    }
00311    return 0;
00312 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Microsoft WAV/WAV16 format (8kHz/16kHz 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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND } [static]

Definition at line 541 of file format_wav.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 541 of file format_wav.c.

struct ast_format wav16_f [static]

Definition at line 491 of file format_wav.c.

Referenced by load_module(), and unload_module().

struct ast_format wav_f [static]

Definition at line 507 of file format_wav.c.

Referenced by load_module(), and unload_module().


Generated on Sat Mar 10 01:55:24 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7