Sat Aug 6 00:39:56 2011

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 <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 check_header_fmt (FILE *f, int hsize)
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_FIRST | 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_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 62 of file format_wav.c.

#define GAIN   0

Definition at line 64 of file format_wav.c.

Referenced by wav_read(), and wav_write().

#define htoll (  )     (b)

Definition at line 68 of file format_wav.c.

#define htols (  )     (b)

Definition at line 69 of file format_wav.c.

#define ltohl (  )     (b)

Definition at line 70 of file format_wav.c.

#define ltohs (  )     (b)

Definition at line 71 of file format_wav.c.

#define WAV_BUF_SIZE   320

Definition at line 52 of file format_wav.c.

Referenced by wav_read().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 528 of file format_wav.c.

static void __unreg_module ( void   )  [static]

Definition at line 528 of file format_wav.c.

static int check_header ( FILE *  f  )  [static]

Definition at line 149 of file format_wav.c.

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

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

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

Definition at line 90 of file format_wav.c.

References ast_log(), DEFAULT_SAMPLE_RATE, format, LOG_WARNING, ltohl, and ltohs.

Referenced by check_header().

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

static int load_module ( void   )  [static]

Definition at line 515 of file format_wav.c.

References ast_format_register, and wav_f.

00516 {
00517    return ast_format_register(&wav_f);
00518 }

static int unload_module ( void   )  [static]

Definition at line 520 of file format_wav.c.

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

00521 {
00522    return ast_format_unregister(wav_f.name);
00523 }  

static int update_header ( FILE *  f  )  [static]

Definition at line 212 of file format_wav.c.

References ast_log(), errno, htoll, and LOG_WARNING.

00213 {
00214    off_t cur,end;
00215    int datalen,filelen,bytes;
00216    
00217    cur = ftello(f);
00218    fseek(f, 0, SEEK_END);
00219    end = ftello(f);
00220    /* data starts 44 bytes in */
00221    bytes = end - 44;
00222    datalen = htoll(bytes);
00223    /* chunk size is bytes of data plus 36 bytes of header */
00224    filelen = htoll(36 + bytes);
00225    
00226    if (cur < 0) {
00227       ast_log(LOG_WARNING, "Unable to find our position: %s\n", strerror(errno));
00228       return -1;
00229    }
00230    if (fseek(f, 4, SEEK_SET)) {
00231       ast_log(LOG_WARNING, "Unable to set our position: %s\n", strerror(errno));
00232       return -1;
00233    }
00234    if (fwrite(&filelen, 1, 4, f) != 4) {
00235       ast_log(LOG_WARNING, "Unable to set write file size: %s\n", strerror(errno));
00236       return -1;
00237    }
00238    if (fseek(f, 40, SEEK_SET)) {
00239       ast_log(LOG_WARNING, "Unable to set our position: %s\n", strerror(errno));
00240       return -1;
00241    }
00242    if (fwrite(&datalen, 1, 4, f) != 4) {
00243       ast_log(LOG_WARNING, "Unable to set write datalen: %s\n", strerror(errno));
00244       return -1;
00245    }
00246    if (fseeko(f, cur, SEEK_SET)) {
00247       ast_log(LOG_WARNING, "Unable to return to position: %s\n", strerror(errno));
00248       return -1;
00249    }
00250    return 0;
00251 }

static void wav_close ( struct ast_filestream s  )  [static]

Definition at line 338 of file format_wav.c.

References ast_log(), wav_desc::bytes, errno, LOG_WARNING, and s.

00339 {
00340    char zero = 0;
00341    struct wav_desc *fs = (struct wav_desc *)s->_private;
00342    /* Pad to even length */
00343    if (fs->bytes & 0x1) {
00344       if (!fwrite(&zero, 1, 1, s->f)) {
00345          ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
00346       }
00347    }
00348 }

static int wav_open ( struct ast_filestream s  )  [static]

Definition at line 316 of file format_wav.c.

References check_header(), wav_desc::maxlen, and s.

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    struct wav_desc *tmp = (struct wav_desc *)s->_private;
00322    if ((tmp->maxlen = check_header(s->f)) < 0)
00323       return -1;
00324    return 0;
00325 }

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

Definition at line 350 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.

00351 {
00352    int res;
00353    int samples;   /* actual samples read */
00354    int x;
00355    short *tmp;
00356    int bytes = WAV_BUF_SIZE;  /* in bytes */
00357    off_t here;
00358    /* Send a frame from the file to the appropriate channel */
00359    struct wav_desc *fs = (struct wav_desc *)s->_private;
00360 
00361    here = ftello(s->f);
00362    if (fs->maxlen - here < bytes)      /* truncate if necessary */
00363       bytes = fs->maxlen - here;
00364    if (bytes < 0)
00365       bytes = 0;
00366 /*    ast_log(LOG_DEBUG, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */
00367    s->fr.frametype = AST_FRAME_VOICE;
00368    s->fr.subclass = AST_FORMAT_SLINEAR;
00369    s->fr.mallocd = 0;
00370    AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, bytes);
00371    
00372    if ( (res = fread(s->fr.data, 1, s->fr.datalen, s->f)) <= 0 ) {
00373       if (res)
00374          ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00375       return NULL;
00376    }
00377    s->fr.datalen = res;
00378    s->fr.samples = samples = res / 2;
00379 
00380    tmp = (short *)(s->fr.data);
00381 #if __BYTE_ORDER == __BIG_ENDIAN
00382    /* file format is little endian so we need to swap */
00383    for( x = 0; x < samples; x++)
00384       tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
00385 #endif
00386 
00387    if (fs->needsgain) {
00388       for (x=0; x < samples; x++) {
00389          if (tmp[x] & ((1 << GAIN) - 1)) {
00390             /* If it has data down low, then it's not something we've artificially increased gain
00391                on, so we don't need to gain adjust it */
00392             fs->needsgain = 0;
00393             break;
00394          }
00395       }
00396       if (fs->needsgain) {
00397          for (x=0; x < samples; x++)
00398             tmp[x] = tmp[x] >> GAIN;
00399       }
00400    }
00401          
00402    *whennext = samples;
00403    return &s->fr;
00404 }

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

Definition at line 327 of file format_wav.c.

References s, and write_header().

00328 {
00329    /* We don't have any header to read or anything really, but
00330       if we did, it would go here.  We also might want to check
00331       and be sure it's a valid file.  */
00332 
00333    if (write_header(s->f))
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 461 of file format_wav.c.

References ast_filestream::f, offset, and SEEK_FORCECUR.

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

static off_t wav_tell ( struct ast_filestream fs  )  [static]

Definition at line 491 of file format_wav.c.

References ast_filestream::f, and offset.

00492 {
00493    off_t offset;
00494    offset = ftello(fs->f);
00495    /* subtract header size to get samples, then divide by 2 for 16 bit samples */
00496    return (offset - 44)/2;
00497 }

static int wav_trunc ( struct ast_filestream fs  )  [static]

Definition at line 484 of file format_wav.c.

References ast_filestream::f, and update_header().

00485 {
00486    if (ftruncate(fileno(fs->f), ftello(fs->f)))
00487       return -1;
00488    return update_header(fs->f);
00489 }

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

Definition at line 406 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().

00407 {
00408    int x;
00409    short tmp[8000], *tmpi;
00410    float tmpf;
00411    struct wav_desc *s = (struct wav_desc *)fs->_private;
00412    int res;
00413 
00414    if (f->frametype != AST_FRAME_VOICE) {
00415       ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00416       return -1;
00417    }
00418    if (f->subclass != AST_FORMAT_SLINEAR) {
00419       ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%d)!\n", f->subclass);
00420       return -1;
00421    }
00422    if (f->datalen > sizeof(tmp)) {
00423       ast_log(LOG_WARNING, "Data length is too long\n");
00424       return -1;
00425    }
00426    if (!f->datalen)
00427       return -1;
00428 
00429 #if 0
00430    printf("Data Length: %d\n", f->datalen);
00431 #endif   
00432 
00433    tmpi = f->data;
00434    /* Volume adjust here to accomodate */
00435    for (x=0;x<f->datalen/2;x++) {
00436       tmpf = ((float)tmpi[x]) * ((float)(1 << GAIN));
00437       if (tmpf > 32767.0)
00438          tmpf = 32767.0;
00439       if (tmpf < -32768.0)
00440          tmpf = -32768.0;
00441       tmp[x] = tmpf;
00442       tmp[x] &= ~((1 << GAIN) - 1);
00443 
00444 #if __BYTE_ORDER == __BIG_ENDIAN
00445       tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
00446 #endif
00447 
00448    }
00449    if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) {
00450       ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno));
00451       return -1;
00452    }
00453 
00454    s->bytes += f->datalen;
00455    update_header(fs->f);
00456       
00457    return 0;
00458 
00459 }

static int write_header ( FILE *  f  )  [static]

Definition at line 253 of file format_wav.c.

References ast_log(), htoll, htols, and LOG_WARNING.

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


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_FIRST | 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 528 of file format_wav.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 528 of file format_wav.c.

struct ast_format wav_f [static]

Definition at line 499 of file format_wav.c.

Referenced by load_module(), and unload_module().


Generated on Sat Aug 6 00:39:56 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7