Asterisk - The Open Source Telephony Project  GIT-master-a1fa8df
format_wav.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Work with WAV in the proprietary Microsoft format.
22  * Microsoft WAV format (8000hz Signed Linear)
23  * \arg File name extension: wav (lower case)
24  * \ingroup formats
25  */
26 
27 /*** MODULEINFO
28  <support_level>core</support_level>
29  ***/
30 
31 #include "asterisk.h"
32 
33 #include "asterisk/mod_format.h"
34 #include "asterisk/module.h"
35 #include "asterisk/endian.h"
36 #include "asterisk/format_cache.h"
37 #include "asterisk/format.h"
38 #include "asterisk/codec.h"
39 
40 /* Some Ideas for this code came from makewave.c by Jeffrey Chilton */
41 
42 /* Portions of the conversion code are by guido@sienanet.it */
43 
44 #define WAV_BUF_SIZE 320
45 
46 #define WAV_HEADER_SIZE 44
47 
48 struct wav_desc { /* format-specific parameters */
49  int hz;
50  int bytes;
52  int maxlen;
53  struct timeval last;
54 };
55 
56 #define BLOCKSIZE 160
57 
58 #if __BYTE_ORDER == __LITTLE_ENDIAN
59 #define htoll(b) (b)
60 #define htols(b) (b)
61 #define ltohl(b) (b)
62 #define ltohs(b) (b)
63 #else
64 #if __BYTE_ORDER == __BIG_ENDIAN
65 #define htoll(b) \
66  (((((b) ) & 0xFF) << 24) | \
67  ((( (b) >> 8) & 0xFF) << 16) | \
68  ((( (b) >> 16) & 0xFF) << 8) | \
69  ((( (b) >> 24) & 0xFF) ))
70 #define htols(b) \
71  (((((b) ) & 0xFF) << 8) | \
72  ((( (b) >> 8) & 0xFF) ))
73 #define ltohl(b) htoll(b)
74 #define ltohs(b) htols(b)
75 #else
76 #error "Endianess not defined"
77 #endif
78 #endif
79 
80 
81 static int check_header_fmt(FILE *f, int hsize, int hz)
82 {
83  unsigned short format, chans, bysam, bisam;
84  unsigned int freq, bysec;
85  if (hsize < 16) {
86  ast_log(LOG_WARNING, "Unexpected header size %d\n", hsize);
87  return -1;
88  }
89  if (fread(&format, 1, 2, f) != 2) {
90  ast_log(LOG_WARNING, "Read failed (format)\n");
91  return -1;
92  }
93  if (ltohs(format) != 1) {
94  ast_log(LOG_WARNING, "Not a supported wav file format (%d). Only PCM encoded, 16 bit, mono, 8kHz/16kHz files are supported with a lowercase '.wav' extension.\n", ltohs(format));
95  return -1;
96  }
97  if (fread(&chans, 1, 2, f) != 2) {
98  ast_log(LOG_WARNING, "Read failed (format)\n");
99  return -1;
100  }
101  if (ltohs(chans) != 1) {
102  ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
103  return -1;
104  }
105  if (fread(&freq, 1, 4, f) != 4) {
106  ast_log(LOG_WARNING, "Read failed (freq)\n");
107  return -1;
108  }
109  freq = ltohl(freq);
110  if ((freq != 8000 && freq != 16000) || freq != hz) {
111  ast_log(LOG_WARNING, "Unexpected frequency mismatch %d (expecting %d)\n", freq, hz);
112  return -1;
113  }
114  /* Ignore the byte frequency */
115  if (fread(&bysec, 1, 4, f) != 4) {
116  ast_log(LOG_WARNING, "Read failed (BYTES_PER_SECOND)\n");
117  return -1;
118  }
119  /* Check bytes per sample */
120  if (fread(&bysam, 1, 2, f) != 2) {
121  ast_log(LOG_WARNING, "Read failed (BYTES_PER_SAMPLE)\n");
122  return -1;
123  }
124  if (ltohs(bysam) != 2) {
125  ast_log(LOG_WARNING, "Can only handle 16bits per sample: %d\n", ltohs(bysam));
126  return -1;
127  }
128  if (fread(&bisam, 1, 2, f) != 2) {
129  ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam));
130  return -1;
131  }
132  /* Skip any additional header */
133  if (fseek(f,hsize-16,SEEK_CUR) == -1 ) {
134  ast_log(LOG_WARNING, "Failed to skip remaining header bytes: %d\n", hsize-16 );
135  return -1;
136  }
137  return 0;
138 }
139 
140 static int check_header(FILE *f, int hz)
141 {
142  int type, size, formtype;
143  int data;
144  if (fread(&type, 1, 4, f) != 4) {
145  ast_log(LOG_WARNING, "Read failed (type)\n");
146  return -1;
147  }
148  if (fread(&size, 1, 4, f) != 4) {
149  ast_log(LOG_WARNING, "Read failed (size)\n");
150  return -1;
151  }
152 #if __BYTE_ORDER == __BIG_ENDIAN
153  size = ltohl(size);
154 #endif
155  if (fread(&formtype, 1, 4, f) != 4) {
156  ast_log(LOG_WARNING, "Read failed (formtype)\n");
157  return -1;
158  }
159  if (memcmp(&type, "RIFF", 4)) {
160  ast_log(LOG_WARNING, "Does not begin with RIFF\n");
161  return -1;
162  }
163  if (memcmp(&formtype, "WAVE", 4)) {
164  ast_log(LOG_WARNING, "Does not contain WAVE\n");
165  return -1;
166  }
167  /* Skip any facts and get the first data block */
168  for(;;)
169  {
170  char buf[4];
171 
172  /* Begin data chunk */
173  if (fread(&buf, 1, 4, f) != 4) {
174  ast_log(LOG_WARNING, "Read failed (block header format)\n");
175  return -1;
176  }
177  /* Data has the actual length of data in it */
178  if (fread(&data, 1, 4, f) != 4) {
179  ast_log(LOG_WARNING, "Read failed (block '%.4s' header length)\n", buf);
180  return -1;
181  }
182 #if __BYTE_ORDER == __BIG_ENDIAN
183  data = ltohl(data);
184 #endif
185  if (memcmp(&buf, "fmt ", 4) == 0) {
186  if (check_header_fmt(f, data, hz))
187  return -1;
188  continue;
189  }
190  if(memcmp(buf, "data", 4) == 0 )
191  break;
192  ast_log(LOG_DEBUG, "Skipping unknown block '%.4s'\n", buf);
193  if (fseek(f,data,SEEK_CUR) == -1 ) {
194  ast_log(LOG_WARNING, "Failed to skip '%.4s' block: %d\n", buf, data);
195  return -1;
196  }
197  }
198 #if 0
199  curpos = lseek(fd, 0, SEEK_CUR);
200  truelength = lseek(fd, 0, SEEK_END);
201  lseek(fd, curpos, SEEK_SET);
202  truelength -= curpos;
203 #endif
204  return data;
205 }
206 
207 static int update_header(FILE *f)
208 {
209  off_t cur,end;
210  int datalen,filelen,bytes;
211 
212  cur = ftello(f);
213  fseek(f, 0, SEEK_END);
214  end = ftello(f);
215  /* data starts 44 bytes in */
216  bytes = end - 44;
217  datalen = htoll(bytes);
218  /* chunk size is bytes of data plus 36 bytes of header */
219  filelen = htoll(36 + bytes);
220 
221  if (cur < 0) {
222  ast_log(LOG_WARNING, "Unable to find our position\n");
223  return -1;
224  }
225  if (fseek(f, 4, SEEK_SET)) {
226  ast_log(LOG_WARNING, "Unable to set our position\n");
227  return -1;
228  }
229  if (fwrite(&filelen, 1, 4, f) != 4) {
230  ast_log(LOG_WARNING, "Unable to set write file size\n");
231  return -1;
232  }
233  if (fseek(f, 40, SEEK_SET)) {
234  ast_log(LOG_WARNING, "Unable to set our position\n");
235  return -1;
236  }
237  if (fwrite(&datalen, 1, 4, f) != 4) {
238  ast_log(LOG_WARNING, "Unable to set write datalen\n");
239  return -1;
240  }
241  if (fseeko(f, cur, SEEK_SET)) {
242  ast_log(LOG_WARNING, "Unable to return to position\n");
243  return -1;
244  }
245  return 0;
246 }
247 
248 static int write_header(FILE *f, int writehz)
249 {
250  unsigned int hz;
251  unsigned int bhz;
252  unsigned int hs = htoll(16);
253  unsigned short fmt = htols(1);
254  unsigned short chans = htols(1);
255  unsigned short bysam = htols(2);
256  unsigned short bisam = htols(16);
257  unsigned int size = htoll(0);
258 
259  if (writehz == 16000) {
260  hz = htoll(16000);
261  bhz = htoll(32000);
262  } else {
263  hz = htoll(8000);
264  bhz = htoll(16000);
265  }
266  /* Write a wav header, ignoring sizes which will be filled in later */
267  fseek(f,0,SEEK_SET);
268  if (fwrite("RIFF", 1, 4, f) != 4) {
269  ast_log(LOG_WARNING, "Unable to write header\n");
270  return -1;
271  }
272  if (fwrite(&size, 1, 4, f) != 4) {
273  ast_log(LOG_WARNING, "Unable to write header\n");
274  return -1;
275  }
276  if (fwrite("WAVEfmt ", 1, 8, f) != 8) {
277  ast_log(LOG_WARNING, "Unable to write header\n");
278  return -1;
279  }
280  if (fwrite(&hs, 1, 4, f) != 4) {
281  ast_log(LOG_WARNING, "Unable to write header\n");
282  return -1;
283  }
284  if (fwrite(&fmt, 1, 2, f) != 2) {
285  ast_log(LOG_WARNING, "Unable to write header\n");
286  return -1;
287  }
288  if (fwrite(&chans, 1, 2, f) != 2) {
289  ast_log(LOG_WARNING, "Unable to write header\n");
290  return -1;
291  }
292  if (fwrite(&hz, 1, 4, f) != 4) {
293  ast_log(LOG_WARNING, "Unable to write header\n");
294  return -1;
295  }
296  if (fwrite(&bhz, 1, 4, f) != 4) {
297  ast_log(LOG_WARNING, "Unable to write header\n");
298  return -1;
299  }
300  if (fwrite(&bysam, 1, 2, f) != 2) {
301  ast_log(LOG_WARNING, "Unable to write header\n");
302  return -1;
303  }
304  if (fwrite(&bisam, 1, 2, f) != 2) {
305  ast_log(LOG_WARNING, "Unable to write header\n");
306  return -1;
307  }
308  if (fwrite("data", 1, 4, f) != 4) {
309  ast_log(LOG_WARNING, "Unable to write header\n");
310  return -1;
311  }
312  if (fwrite(&size, 1, 4, f) != 4) {
313  ast_log(LOG_WARNING, "Unable to write header\n");
314  return -1;
315  }
316  return 0;
317 }
318 
319 static int wav_open(struct ast_filestream *s)
320 {
321  /* We don't have any header to read or anything really, but
322  if we did, it would go here. We also might want to check
323  and be sure it's a valid file. */
324  struct wav_desc *tmp = s->_private;
325  unsigned int sample_rate = ast_format_get_sample_rate(s->fmt->format);
326 
327  tmp->maxlen = check_header(s->f, sample_rate);
328  if (tmp->maxlen < 0) {
329  return -1;
330  }
331 
332  tmp->hz = sample_rate;
333  return 0;
334 }
335 
336 static int wav_rewrite(struct ast_filestream *s, const char *comment)
337 {
338  /* We don't have any header to read or anything really, but
339  if we did, it would go here. We also might want to check
340  and be sure it's a valid file. */
341 
342  struct wav_desc *tmp = (struct wav_desc *)s->_private;
344  if (write_header(s->f,tmp->hz))
345  return -1;
346  return 0;
347 }
348 
349 static void wav_close(struct ast_filestream *s)
350 {
351  char zero = 0;
352  struct wav_desc *fs = (struct wav_desc *)s->_private;
353 
354  if (s->mode == O_RDONLY) {
355  return;
356  }
357 
358  if (s->filename) {
359  update_header(s->f);
360  }
361 
362  /* Pad to even length */
363  if (fs->bytes & 0x1) {
364  if (fwrite(&zero, 1, 1, s->f) != 1) {
365  ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
366  }
367  }
368 }
369 
370 static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
371 {
372  size_t res;
373  int samples; /* actual samples read */
374 #if __BYTE_ORDER == __BIG_ENDIAN
375  int x;
376  short *tmp;
377 #endif
378  int bytes;
379  off_t here;
380  /* Send a frame from the file to the appropriate channel */
381  struct wav_desc *fs = (struct wav_desc *)s->_private;
382 
383  bytes = (fs->hz == 16000 ? (WAV_BUF_SIZE * 2) : WAV_BUF_SIZE);
384 
385  here = ftello(s->f);
386  if (fs->maxlen - here < bytes) /* truncate if necessary */
387  bytes = fs->maxlen - here;
388  if (bytes <= 0) {
389  return NULL;
390  }
391 /* ast_debug(1, "here: %d, maxlen: %d, bytes: %d\n", here, s->maxlen, bytes); */
393 
394  if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) == 0) {
395  if (res) {
396  ast_log(LOG_WARNING, "Short read of %s data (expected %d bytes, read %zu): %s\n",
398  strerror(errno));
399  }
400  return NULL;
401  }
402  s->fr.datalen = res;
403  s->fr.samples = samples = res / 2;
404 
405 #if __BYTE_ORDER == __BIG_ENDIAN
406  tmp = (short *)(s->fr.data.ptr);
407  /* file format is little endian so we need to swap */
408  for( x = 0; x < samples; x++)
409  tmp[x] = (tmp[x] << 8) | ((tmp[x] & 0xff00) >> 8);
410 #endif
411 
412  *whennext = samples;
413  return &s->fr;
414 }
415 
416 static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
417 {
418 #if __BYTE_ORDER == __BIG_ENDIAN
419  int x;
420  short tmp[16000], *tmpi;
421 #endif
422  struct wav_desc *s = (struct wav_desc *)fs->_private;
423  int res;
424 
425  if (!f->datalen)
426  return -1;
427 
428 #if __BYTE_ORDER == __BIG_ENDIAN
429  /* swap and write */
430  if (f->datalen > sizeof(tmp)) {
431  ast_log(LOG_WARNING, "Data length is too long\n");
432  return -1;
433  }
434  tmpi = f->data.ptr;
435  for (x=0; x < f->datalen/2; x++)
436  tmp[x] = (tmpi[x] << 8) | ((tmpi[x] & 0xff00) >> 8);
437 
438  if ((res = fwrite(tmp, 1, f->datalen, fs->f)) != f->datalen ) {
439 #else
440  /* just write */
441  if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen ) {
442 #endif
443  ast_log(LOG_WARNING, "Bad write (%d): %s\n", res, strerror(errno));
444  return -1;
445  }
446 
447  s->bytes += f->datalen;
448 
449  return 0;
450 
451 }
452 
453 static int wav_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
454 {
455  off_t min = WAV_HEADER_SIZE, max, cur, offset = 0, samples;
456 
457  samples = sample_offset * 2; /* SLINEAR is 16 bits mono, so sample_offset * 2 = bytes */
458 
459  if ((cur = ftello(fs->f)) < 0) {
460  ast_log(AST_LOG_WARNING, "Unable to determine current position in wav filestream %p: %s\n", fs, strerror(errno));
461  return -1;
462  }
463 
464  if (fseeko(fs->f, 0, SEEK_END) < 0) {
465  ast_log(AST_LOG_WARNING, "Unable to seek to end of wav filestream %p: %s\n", fs, strerror(errno));
466  return -1;
467  }
468 
469  if ((max = ftello(fs->f)) < 0) {
470  ast_log(AST_LOG_WARNING, "Unable to determine max position in wav filestream %p: %s\n", fs, strerror(errno));
471  return -1;
472  }
473 
474  if (whence == SEEK_SET) {
475  offset = samples + min;
476  } else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) {
477  offset = samples + cur;
478  } else if (whence == SEEK_END) {
479  offset = max - samples;
480  }
481  if (whence != SEEK_FORCECUR) {
482  offset = (offset > max)?max:offset;
483  }
484  /* always protect the header space. */
485  offset = (offset < min)?min:offset;
486  return fseeko(fs->f, offset, SEEK_SET);
487 }
488 
489 static int wav_trunc(struct ast_filestream *fs)
490 {
491  int fd;
492  off_t cur;
493 
494  if ((fd = fileno(fs->f)) < 0) {
495  ast_log(AST_LOG_WARNING, "Unable to determine file descriptor for wav filestream %p: %s\n", fs, strerror(errno));
496  return -1;
497  }
498  if ((cur = ftello(fs->f)) < 0) {
499  ast_log(AST_LOG_WARNING, "Unable to determine current position in wav filestream %p: %s\n", fs, strerror(errno));
500  return -1;
501  }
502  /* Truncate file to current length */
503  if (ftruncate(fd, cur)) {
504  return -1;
505  }
506  return update_header(fs->f);
507 }
508 
509 static off_t wav_tell(struct ast_filestream *fs)
510 {
511  off_t offset;
512  offset = ftello(fs->f);
513  /* subtract header size to get samples, then divide by 2 for 16 bit samples */
514  return (offset - 44)/2;
515 }
516 
517 static struct ast_format_def wav16_f = {
518  .name = "wav16",
519  .exts = "wav16",
520  .mime_types = "audio/x-wav;codec=pcm;bit=16;rate=16000",
521  .open = wav_open,
522  .rewrite = wav_rewrite,
523  .write = wav_write,
524  .seek = wav_seek,
525  .trunc = wav_trunc,
526  .tell = wav_tell,
527  .read = wav_read,
528  .close = wav_close,
529  .buf_size = (WAV_BUF_SIZE * 2) + AST_FRIENDLY_OFFSET,
530  .desc_size = sizeof(struct wav_desc),
531 };
532 
533 static struct ast_format_def wav_f = {
534  .name = "wav",
535  .exts = "wav",
536  .mime_types = "audio/wav|audio/x-wav|audio/x-wav;codec=pcm;bit=16;rate=8000",
537  .open = wav_open,
538  .rewrite = wav_rewrite,
539  .write = wav_write,
540  .seek = wav_seek,
541  .trunc = wav_trunc,
542  .tell = wav_tell,
543  .read = wav_read,
544  .close = wav_close,
545  .buf_size = WAV_BUF_SIZE + AST_FRIENDLY_OFFSET,
546  .desc_size = sizeof(struct wav_desc),
547 };
548 
549 static int unload_module(void)
550 {
551  return ast_format_def_unregister(wav_f.name)
552  || ast_format_def_unregister(wav16_f.name);
553 }
554 
555 static int load_module(void)
556 {
557  wav_f.format = ast_format_slin;
558  wav16_f.format = ast_format_slin16;
559  if (ast_format_def_register(&wav_f)
560  || ast_format_def_register(&wav16_f)) {
561  unload_module();
563  }
565 }
566 
567 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Microsoft WAV/WAV16 format (8kHz/16kHz Signed Linear)",
568  .support_level = AST_MODULE_SUPPORT_CORE,
569  .load = load_module,
570  .unload = unload_module,
571  .load_pri = AST_MODPRI_APP_DEPEND
572 );
int lasttimeout
Definition: format_wav.c:51
static const char type[]
Definition: chan_ooh323.c:109
Asterisk main include file. File version handling, generic pbx functions.
static int write_header(FILE *f, int writehz)
Definition: format_wav.c:248
static int wav_write(struct ast_filestream *fs, struct ast_frame *f)
Definition: format_wav.c:416
static int update_header(FILE *f)
Definition: format_wav.c:207
static int check_header_fmt(FILE *f, int hsize, int hz)
Definition: format_wav.c:81
#define WAV_HEADER_SIZE
Definition: format_wav.c:46
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct ast_format_def wav_f
Definition: format_wav.c:533
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
#define AST_LOG_WARNING
Definition: logger.h:279
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
Codec API.
static int wav_rewrite(struct ast_filestream *s, const char *comment)
Definition: format_wav.c:336
static void wav_close(struct ast_filestream *s)
Definition: format_wav.c:349
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
int hz
Definition: format_wav.c:49
#define NULL
Definition: resample.c:96
Each supported file format is described by the following structure.
Definition: mod_format.h:43
char * end
Definition: eagi_proxy.c:73
#define LOG_DEBUG
Definition: logger.h:241
struct timeval last
Definition: format_wav.c:53
struct ast_frame_subclass subclass
Header for providers of file and format handling routines. Clients of these routines should include "...
Media Format API.
int ast_format_def_unregister(const char *name)
Unregisters a file format.
Definition: file.c:162
#define ast_log
Definition: astobj2.c:42
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
Asterisk architecture endianess compatibility definitions.
#define ast_format_def_register(f)
Definition: mod_format.h:136
struct ast_format_def * fmt
Definition: mod_format.h:103
union ast_frame::@250 data
static struct ast_format_def wav16_f
Definition: format_wav.c:517
struct ast_frame fr
frame produced by read, typically
Definition: mod_format.h:122
static int wav_trunc(struct ast_filestream *fs)
Definition: format_wav.c:489
#define WAV_BUF_SIZE
Definition: format_wav.c:44
struct ast_format * format
Definition: mod_format.h:48
int bytes
Definition: format_wav.c:50
static int wav_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
Definition: format_wav.c:453
static int load_module(void)
Definition: format_wav.c:555
void * _private
Definition: mod_format.h:124
#define AST_FRAME_SET_BUFFER(fr, _base, _ofs, _datalen)
int errno
#define comment
Definition: ael_lex.c:976
char name[80]
Definition: mod_format.h:44
#define SEEK_FORCECUR
Definition: file.h:51
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int wav_open(struct ast_filestream *s)
Definition: format_wav.c:319
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
Definition: astman.c:88
char * filename
Definition: mod_format.h:107
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:101
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
Data structure associated with a single frame of data.
struct ast_format * ast_format_slin16
Built-in cached signed linear 16kHz format.
Definition: format_cache.c:51
static int unload_module(void)
Definition: format_wav.c:549
int maxlen
Definition: format_wav.c:52
struct ast_format * format
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
Asterisk module definitions.
static struct ast_frame * wav_read(struct ast_filestream *s, int *whennext)
Definition: format_wav.c:370
static snd_pcm_format_t format
Definition: chan_alsa.c:106
static int check_header(FILE *f, int hz)
Definition: format_wav.c:140
#define min(a, b)
Definition: f2c.h:197
static off_t wav_tell(struct ast_filestream *fs)
Definition: format_wav.c:509
Media Format Cache API.
static struct chans chans
#define max(a, b)
Definition: f2c.h:198