Asterisk - The Open Source Telephony Project  18.5.0
format_wav_gsm.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 <[email protected]>
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 Save GSM in the proprietary Microsoft format.
22  *
23  * Microsoft WAV format (Proprietary GSM)
24  * \arg File name extension: WAV,wav49 (Upper case WAV, lower case is another format)
25  * This format can be played on Windows systems, used for
26  * e-mail attachments mainly.
27  * \ingroup formats
28  */
29 
30 /*** MODULEINFO
31  <support_level>core</support_level>
32  ***/
33 
34 #include "asterisk.h"
35 
36 #include "asterisk/mod_format.h"
37 #include "asterisk/module.h"
38 #include "asterisk/endian.h"
39 #include "asterisk/format_cache.h"
40 
41 #include "msgsm.h"
42 
43 /* Some Ideas for this code came from makewave.c by Jeffrey Chilton */
44 
45 /* Portions of the conversion code are by [email protected] */
46 
47 #define GSM_FRAME_SIZE 33
48 #define MSGSM_FRAME_SIZE 65
49 #define MSGSM_DATA_OFFSET 60 /* offset of data bytes */
50 #define GSM_SAMPLES 160 /* samples in a GSM block */
51 #define MSGSM_SAMPLES (2*GSM_SAMPLES) /* samples in an MSGSM block */
52 
53 /* begin binary data: */
54 static char msgsm_silence[] = /* 65 */
55 {0x48,0x17,0xD6,0x84,0x02,0x80,0x24,0x49,0x92,0x24,0x89,0x02,0x80,0x24,0x49
56 ,0x92,0x24,0x89,0x02,0x80,0x24,0x49,0x92,0x24,0x89,0x02,0x80,0x24,0x49,0x92
57 ,0x24,0x09,0x82,0x74,0x61,0x4D,0x28,0x00,0x48,0x92,0x24,0x49,0x92,0x28,0x00
58 ,0x48,0x92,0x24,0x49,0x92,0x28,0x00,0x48,0x92,0x24,0x49,0x92,0x28,0x00,0x48
59 ,0x92,0x24,0x49,0x92,0x00};
60 /* end binary data. size = 65 bytes */
61 
62 struct wavg_desc {
63  /* Believe it or not, we must decode/recode to account for the
64  weird MS format */
65  int secondhalf; /* Are we on the second half */
66 };
67 
68 #if __BYTE_ORDER == __LITTLE_ENDIAN
69 #define htoll(b) (b)
70 #define htols(b) (b)
71 #define ltohl(b) (b)
72 #define ltohs(b) (b)
73 #else
74 #if __BYTE_ORDER == __BIG_ENDIAN
75 #define htoll(b) \
76  (((((b) ) & 0xFF) << 24) | \
77  ((( (b) >> 8) & 0xFF) << 16) | \
78  ((( (b) >> 16) & 0xFF) << 8) | \
79  ((( (b) >> 24) & 0xFF) ))
80 #define htols(b) \
81  (((((b) ) & 0xFF) << 8) | \
82  ((( (b) >> 8) & 0xFF) ))
83 #define ltohl(b) htoll(b)
84 #define ltohs(b) htols(b)
85 #else
86 #error "Endianess not defined"
87 #endif
88 #endif
89 
90 
91 static int check_header(FILE *f)
92 {
93  int type, size, formtype;
94  int fmt, hsize, fact;
95  short format, chans;
96  int freq;
97  int data;
98  if (fread(&type, 1, 4, f) != 4) {
99  ast_log(LOG_WARNING, "Read failed (type)\n");
100  return -1;
101  }
102  if (fread(&size, 1, 4, f) != 4) {
103  ast_log(LOG_WARNING, "Read failed (size)\n");
104  return -1;
105  }
106 #if __BYTE_ORDER == __BIG_ENDIAN
107  size = ltohl(size);
108 #endif
109  if (fread(&formtype, 1, 4, f) != 4) {
110  ast_log(LOG_WARNING, "Read failed (formtype)\n");
111  return -1;
112  }
113  if (memcmp(&type, "RIFF", 4)) {
114  ast_log(LOG_WARNING, "Does not begin with RIFF\n");
115  return -1;
116  }
117  if (memcmp(&formtype, "WAVE", 4)) {
118  ast_log(LOG_WARNING, "Does not contain WAVE\n");
119  return -1;
120  }
121  if (fread(&fmt, 1, 4, f) != 4) {
122  ast_log(LOG_WARNING, "Read failed (fmt)\n");
123  return -1;
124  }
125  if (memcmp(&fmt, "fmt ", 4)) {
126  ast_log(LOG_WARNING, "Does not say fmt\n");
127  return -1;
128  }
129  if (fread(&hsize, 1, 4, f) != 4) {
130  ast_log(LOG_WARNING, "Read failed (formtype)\n");
131  return -1;
132  }
133  if (ltohl(hsize) != 20) {
134  ast_log(LOG_WARNING, "Unexpected header size %d\n", ltohl(hsize));
135  return -1;
136  }
137  if (fread(&format, 1, 2, f) != 2) {
138  ast_log(LOG_WARNING, "Read failed (format)\n");
139  return -1;
140  }
141  if (ltohs(format) != 49) {
142  ast_log(LOG_WARNING, "Not a GSM file %d\n", ltohs(format));
143  return -1;
144  }
145  if (fread(&chans, 1, 2, f) != 2) {
146  ast_log(LOG_WARNING, "Read failed (format)\n");
147  return -1;
148  }
149  if (ltohs(chans) != 1) {
150  ast_log(LOG_WARNING, "Not in mono %d\n", ltohs(chans));
151  return -1;
152  }
153  if (fread(&freq, 1, 4, f) != 4) {
154  ast_log(LOG_WARNING, "Read failed (freq)\n");
155  return -1;
156  }
157  if (ltohl(freq) != DEFAULT_SAMPLE_RATE) {
158  ast_log(LOG_WARNING, "Unexpected frequency %d\n", ltohl(freq));
159  return -1;
160  }
161  /* Ignore the byte frequency */
162  if (fread(&freq, 1, 4, f) != 4) {
163  ast_log(LOG_WARNING, "Read failed (X_1)\n");
164  return -1;
165  }
166  /* Ignore the two weird fields */
167  if (fread(&freq, 1, 4, f) != 4) {
168  ast_log(LOG_WARNING, "Read failed (X_2/X_3)\n");
169  return -1;
170  }
171  /* Ignore the byte frequency */
172  if (fread(&freq, 1, 4, f) != 4) {
173  ast_log(LOG_WARNING, "Read failed (Y_1)\n");
174  return -1;
175  }
176  /* Check for the word fact */
177  if (fread(&fact, 1, 4, f) != 4) {
178  ast_log(LOG_WARNING, "Read failed (fact)\n");
179  return -1;
180  }
181  if (memcmp(&fact, "fact", 4)) {
182  ast_log(LOG_WARNING, "Does not say fact\n");
183  return -1;
184  }
185  /* Ignore the "fact value" */
186  if (fread(&fact, 1, 4, f) != 4) {
187  ast_log(LOG_WARNING, "Read failed (fact header)\n");
188  return -1;
189  }
190  if (fread(&fact, 1, 4, f) != 4) {
191  ast_log(LOG_WARNING, "Read failed (fact value)\n");
192  return -1;
193  }
194  /* Check for the word data */
195  if (fread(&data, 1, 4, f) != 4) {
196  ast_log(LOG_WARNING, "Read failed (data)\n");
197  return -1;
198  }
199  if (memcmp(&data, "data", 4)) {
200  ast_log(LOG_WARNING, "Does not say data\n");
201  return -1;
202  }
203  /* Ignore the data length */
204  if (fread(&data, 1, 4, f) != 4) {
205  ast_log(LOG_WARNING, "Read failed (data)\n");
206  return -1;
207  }
208  return 0;
209 }
210 
211 static int update_header(FILE *f)
212 {
213  off_t cur,end,bytes;
214  int datalen, filelen, samples;
215 
216  cur = ftello(f);
217  fseek(f, 0, SEEK_END);
218  end = ftello(f);
219  /* in a gsm WAV, data starts 60 bytes in */
220  bytes = end - MSGSM_DATA_OFFSET;
221  samples = htoll(bytes / MSGSM_FRAME_SIZE * MSGSM_SAMPLES);
222  datalen = htoll(bytes);
223  filelen = htoll(MSGSM_DATA_OFFSET - 8 + bytes);
224  if (cur < 0) {
225  ast_log(LOG_WARNING, "Unable to find our position\n");
226  return -1;
227  }
228  if (fseek(f, 4, SEEK_SET)) {
229  ast_log(LOG_WARNING, "Unable to set our position\n");
230  return -1;
231  }
232  if (fwrite(&filelen, 1, 4, f) != 4) {
233  ast_log(LOG_WARNING, "Unable to write file size\n");
234  return -1;
235  }
236  if (fseek(f, 48, SEEK_SET)) {
237  ast_log(LOG_WARNING, "Unable to set our position\n");
238  return -1;
239  }
240  if (fwrite(&samples, 1, 4, f) != 4) {
241  ast_log(LOG_WARNING, "Unable to write samples\n");
242  return -1;
243  }
244  if (fseek(f, 56, SEEK_SET)) {
245  ast_log(LOG_WARNING, "Unable to set our position\n");
246  return -1;
247  }
248  if (fwrite(&datalen, 1, 4, f) != 4) {
249  ast_log(LOG_WARNING, "Unable to write datalen\n");
250  return -1;
251  }
252  if (fseeko(f, cur, SEEK_SET)) {
253  ast_log(LOG_WARNING, "Unable to return to position\n");
254  return -1;
255  }
256  return 0;
257 }
258 
259 static int write_header(FILE *f)
260 {
261  /* Samples per second (always 8000 for this format). */
262  unsigned int sample_rate = htoll(8000);
263  /* Bytes per second (always 1625 for this format). */
264  unsigned int byte_sample_rate = htoll(1625);
265  /* This is the size of the "fmt " subchunk */
266  unsigned int fmtsize = htoll(20);
267  /* WAV #49 */
268  unsigned short fmt = htols(49);
269  /* Mono = 1 channel */
270  unsigned short chans = htols(1);
271  /* Each block of data is exactly 65 bytes in size. */
272  unsigned int block_align = htoll(MSGSM_FRAME_SIZE);
273  /* Not actually 2, but rounded up to the nearest bit */
274  unsigned short bits_per_sample = htols(2);
275  /* Needed for compressed formats */
276  unsigned short extra_format = htols(MSGSM_SAMPLES);
277  /* This is the size of the "fact" subchunk */
278  unsigned int factsize = htoll(4);
279  /* Number of samples in the data chunk */
280  unsigned int num_samples = htoll(0);
281  /* Number of bytes in the data chunk */
282  unsigned int size = htoll(0);
283  /* Write a GSM header, ignoring sizes which will be filled in later */
284 
285  /* 0: Chunk ID */
286  if (fwrite("RIFF", 1, 4, f) != 4) {
287  ast_log(LOG_WARNING, "Unable to write header\n");
288  return -1;
289  }
290  /* 4: Chunk Size */
291  if (fwrite(&size, 1, 4, f) != 4) {
292  ast_log(LOG_WARNING, "Unable to write header\n");
293  return -1;
294  }
295  /* 8: Chunk Format */
296  if (fwrite("WAVE", 1, 4, f) != 4) {
297  ast_log(LOG_WARNING, "Unable to write header\n");
298  return -1;
299  }
300  /* 12: Subchunk 1: ID */
301  if (fwrite("fmt ", 1, 4, f) != 4) {
302  ast_log(LOG_WARNING, "Unable to write header\n");
303  return -1;
304  }
305  /* 16: Subchunk 1: Size (minus 8) */
306  if (fwrite(&fmtsize, 1, 4, f) != 4) {
307  ast_log(LOG_WARNING, "Unable to write header\n");
308  return -1;
309  }
310  /* 20: Subchunk 1: Audio format (49) */
311  if (fwrite(&fmt, 1, 2, f) != 2) {
312  ast_log(LOG_WARNING, "Unable to write header\n");
313  return -1;
314  }
315  /* 22: Subchunk 1: Number of channels */
316  if (fwrite(&chans, 1, 2, f) != 2) {
317  ast_log(LOG_WARNING, "Unable to write header\n");
318  return -1;
319  }
320  /* 24: Subchunk 1: Sample rate */
321  if (fwrite(&sample_rate, 1, 4, f) != 4) {
322  ast_log(LOG_WARNING, "Unable to write header\n");
323  return -1;
324  }
325  /* 28: Subchunk 1: Byte rate */
326  if (fwrite(&byte_sample_rate, 1, 4, f) != 4) {
327  ast_log(LOG_WARNING, "Unable to write header\n");
328  return -1;
329  }
330  /* 32: Subchunk 1: Block align */
331  if (fwrite(&block_align, 1, 4, f) != 4) {
332  ast_log(LOG_WARNING, "Unable to write header\n");
333  return -1;
334  }
335  /* 36: Subchunk 1: Bits per sample */
336  if (fwrite(&bits_per_sample, 1, 2, f) != 2) {
337  ast_log(LOG_WARNING, "Unable to write header\n");
338  return -1;
339  }
340  /* 38: Subchunk 1: Extra format bytes */
341  if (fwrite(&extra_format, 1, 2, f) != 2) {
342  ast_log(LOG_WARNING, "Unable to write header\n");
343  return -1;
344  }
345  /* 40: Subchunk 2: ID */
346  if (fwrite("fact", 1, 4, f) != 4) {
347  ast_log(LOG_WARNING, "Unable to write header\n");
348  return -1;
349  }
350  /* 44: Subchunk 2: Size (minus 8) */
351  if (fwrite(&factsize, 1, 4, f) != 4) {
352  ast_log(LOG_WARNING, "Unable to write header\n");
353  return -1;
354  }
355  /* 48: Subchunk 2: Number of samples */
356  if (fwrite(&num_samples, 1, 4, f) != 4) {
357  ast_log(LOG_WARNING, "Unable to write header\n");
358  return -1;
359  }
360  /* 52: Subchunk 3: ID */
361  if (fwrite("data", 1, 4, f) != 4) {
362  ast_log(LOG_WARNING, "Unable to write header\n");
363  return -1;
364  }
365  /* 56: Subchunk 3: Size */
366  if (fwrite(&size, 1, 4, f) != 4) {
367  ast_log(LOG_WARNING, "Unable to write header\n");
368  return -1;
369  }
370  return 0;
371 }
372 
373 static int wav_open(struct ast_filestream *s)
374 {
375  /* We don't have any header to read or anything really, but
376  if we did, it would go here. We also might want to check
377  and be sure it's a valid file. */
378  struct wavg_desc *fs = (struct wavg_desc *)s->_private;
379 
380  if (check_header(s->f))
381  return -1;
382  fs->secondhalf = 0; /* not strictly necessary */
383  return 0;
384 }
385 
386 static int wav_rewrite(struct ast_filestream *s, const char *comment)
387 {
388  /* We don't have any header to read or anything really, but
389  if we did, it would go here. We also might want to check
390  and be sure it's a valid file. */
391 
392  if (write_header(s->f))
393  return -1;
394  return 0;
395 }
396 
397 static void wav_close(struct ast_filestream *s)
398 {
399  if (s->mode == O_RDONLY) {
400  return;
401  }
402 
403  if (s->filename) {
404  update_header(s->f);
405  }
406 }
407 
408 static struct ast_frame *wav_read(struct ast_filestream *s, int *whennext)
409 {
410  /* Send a frame from the file to the appropriate channel */
411  struct wavg_desc *fs = (struct wavg_desc *)s->_private;
412 
413  s->fr.samples = GSM_SAMPLES;
415  if (fs->secondhalf) {
416  /* Just return a frame based on the second GSM frame */
417  s->fr.data.ptr = (char *)s->fr.data.ptr + GSM_FRAME_SIZE;
418  s->fr.offset += GSM_FRAME_SIZE;
419  } else {
420  /* read and convert */
421  unsigned char msdata[MSGSM_FRAME_SIZE];
422  size_t res;
423 
424  if ((res = fread(msdata, 1, MSGSM_FRAME_SIZE, s->f)) != MSGSM_FRAME_SIZE) {
425  if (res && res != 1) {
426  ast_log(LOG_WARNING, "Short read of %s data (expected %d bytes, read %zu): %s\n",
428  strerror(errno));
429  }
430  return NULL;
431  }
432  /* Convert from MS format to two real GSM frames */
433  conv65(msdata, s->fr.data.ptr);
434  }
435  fs->secondhalf = !fs->secondhalf;
436  *whennext = GSM_SAMPLES;
437  return &s->fr;
438 }
439 
440 static int wav_write(struct ast_filestream *s, struct ast_frame *f)
441 {
442  int len;
443  int size;
444  struct wavg_desc *fs = (struct wavg_desc *)s->_private;
445 
446  /* XXX this might fail... if the input is a multiple of MSGSM_FRAME_SIZE
447  * we assume it is already in the correct format.
448  */
449  if (!(f->datalen % MSGSM_FRAME_SIZE)) {
450  size = MSGSM_FRAME_SIZE;
451  fs->secondhalf = 0;
452  } else {
453  size = GSM_FRAME_SIZE;
454  }
455  for (len = 0; len < f->datalen ; len += size) {
456  int res;
457  unsigned char *src, msdata[MSGSM_FRAME_SIZE];
458  if (fs->secondhalf) { /* second half of raw gsm to be converted */
459  memcpy(s->buf + GSM_FRAME_SIZE, f->data.ptr + len, GSM_FRAME_SIZE);
460  conv66((unsigned char *) s->buf, msdata);
461  src = msdata;
462  fs->secondhalf = 0;
463  } else if (size == GSM_FRAME_SIZE) { /* first half of raw gsm */
464  memcpy(s->buf, f->data.ptr + len, GSM_FRAME_SIZE);
465  src = NULL; /* nothing to write */
466  fs->secondhalf = 1;
467  } else { /* raw msgsm data */
468  src = f->data.ptr + len;
469  }
470  if (src && (res = fwrite(src, 1, MSGSM_FRAME_SIZE, s->f)) != MSGSM_FRAME_SIZE) {
471  ast_log(LOG_WARNING, "Bad write (%d/65): %s\n", res, strerror(errno));
472  return -1;
473  }
474  }
475  return 0;
476 }
477 
478 static int wav_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
479 {
480  off_t offset = 0, min = MSGSM_DATA_OFFSET, distance, max, cur;
481  struct wavg_desc *s = (struct wavg_desc *)fs->_private;
482 
483  if ((cur = ftello(fs->f)) < 0) {
484  ast_log(AST_LOG_WARNING, "Unable to determine current position in WAV filestream %p: %s\n", fs, strerror(errno));
485  return -1;
486  }
487 
488  if (fseeko(fs->f, 0, SEEK_END) < 0) {
489  ast_log(AST_LOG_WARNING, "Unable to seek to end of WAV filestream %p: %s\n", fs, strerror(errno));
490  return -1;
491  }
492 
493  /* XXX ideally, should round correctly */
494  if ((max = ftello(fs->f)) < 0) {
495  ast_log(AST_LOG_WARNING, "Unable to determine max position in WAV filestream %p: %s\n", fs, strerror(errno));
496  return -1;
497  }
498 
499  /* Compute the distance in bytes, rounded to the block size */
500  distance = (sample_offset/MSGSM_SAMPLES) * MSGSM_FRAME_SIZE;
501  if (whence == SEEK_SET)
502  offset = distance + min;
503  else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
504  offset = distance + cur;
505  else if (whence == SEEK_END)
506  offset = max - distance;
507  /* always protect against seeking past end of header */
508  if (offset < min)
509  offset = min;
510  if (whence != SEEK_FORCECUR) {
511  if (offset > max)
512  offset = max;
513  } else if (offset > max) {
514  int i;
515  fseek(fs->f, 0, SEEK_END);
516  for (i=0; i< (offset - max) / MSGSM_FRAME_SIZE; i++) {
517  if (fwrite(msgsm_silence, 1, MSGSM_FRAME_SIZE, fs->f) != MSGSM_FRAME_SIZE) {
518  ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
519  }
520  }
521  }
522  s->secondhalf = 0;
523  return fseeko(fs->f, offset, SEEK_SET);
524 }
525 
526 static int wav_trunc(struct ast_filestream *fs)
527 {
528  int fd;
529  off_t cur;
530 
531  if ((fd = fileno(fs->f)) < 0) {
532  ast_log(AST_LOG_WARNING, "Unable to determine file descriptor for WAV filestream %p: %s\n", fs, strerror(errno));
533  return -1;
534  }
535  if ((cur = ftello(fs->f)) < 0) {
536  ast_log(AST_LOG_WARNING, "Unable to determine current position in WAV filestream %p: %s\n", fs, strerror(errno));
537  return -1;
538  }
539  /* Truncate file to current length */
540  if (ftruncate(fd, cur)) {
541  return -1;
542  }
543  return update_header(fs->f);
544 }
545 
546 static off_t wav_tell(struct ast_filestream *fs)
547 {
548  off_t offset;
549  offset = ftello(fs->f);
550  /* since this will most likely be used later in play or record, lets stick
551  * to that level of resolution, just even frames boundaries */
553 }
554 
555 static struct ast_format_def wav49_f = {
556  .name = "wav49",
557  .exts = "WAV|wav49",
558  .open = wav_open,
559  .rewrite = wav_rewrite,
560  .write = wav_write,
561  .seek = wav_seek,
562  .trunc = wav_trunc,
563  .tell = wav_tell,
564  .read = wav_read,
565  .close = wav_close,
566  .buf_size = 2*GSM_FRAME_SIZE + AST_FRIENDLY_OFFSET,
567  .desc_size = sizeof(struct wavg_desc),
568 };
569 
570 static int load_module(void)
571 {
572  wav49_f.format = ast_format_gsm;
573  if (ast_format_def_register(&wav49_f))
576 }
577 
578 static int unload_module(void)
579 {
580  return ast_format_def_unregister(wav49_f.name);
581 }
582 
583 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Microsoft WAV format (Proprietary GSM)",
584  .support_level = AST_MODULE_SUPPORT_CORE,
585  .load = load_module,
586  .unload = unload_module,
587  .load_pri = AST_MODPRI_APP_DEPEND
588 );
static const char type[]
Definition: chan_ooh323.c:109
static int update_header(FILE *f)
static int load_module(void)
Asterisk main include file. File version handling, generic pbx functions.
#define DEFAULT_SAMPLE_RATE
Definition: asterisk.h:46
static int wav_rewrite(struct ast_filestream *s, const char *comment)
static off_t wav_tell(struct ast_filestream *fs)
#define LOG_WARNING
Definition: logger.h:274
#define AST_LOG_WARNING
Definition: logger.h:279
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
#define MSGSM_SAMPLES
static struct ast_frame * wav_read(struct ast_filestream *s, int *whennext)
#define MSGSM_DATA_OFFSET
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#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
struct ast_frame_subclass subclass
Header for providers of file and format handling routines. Clients of these routines should include "...
static int wav_open(struct ast_filestream *s)
#define GSM_FRAME_SIZE
int ast_format_def_unregister(const char *name)
Unregisters a file format.
Definition: file.c:162
static int check_header(FILE *f)
static int wav_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
#define ast_log
Definition: astobj2.c:42
static void wav_close(struct ast_filestream *s)
#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 * ast_format_gsm
Built-in cached gsm format.
Definition: format_cache.c:101
struct ast_frame fr
frame produced by read, typically
Definition: mod_format.h:122
static void conv65(wav_byte *c, gsm_byte *d)
Definition: msgsm.h:457
struct ast_format * format
Definition: mod_format.h:48
void * _private
Definition: mod_format.h:124
#define MSGSM_FRAME_SIZE
#define AST_FRAME_SET_BUFFER(fr, _base, _ofs, _datalen)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int errno
#define comment
Definition: ael_lex.c:976
static struct ast_format_def wav49_f
char name[80]
Definition: mod_format.h:44
static int wav_write(struct ast_filestream *s, struct ast_frame *f)
#define SEEK_FORCECUR
Definition: file.h:51
static int wav_trunc(struct ast_filestream *fs)
static void conv66(gsm_byte *d, wav_byte *c)
Definition: msgsm.h:116
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static char msgsm_silence[]
#define GSM_SAMPLES
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
static int unload_module(void)
Data structure associated with a single frame of data.
union ast_frame::@263 data
struct ast_format * format
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#define min(a, b)
Definition: f2c.h:197
static int write_header(FILE *f)
Media Format Cache API.
static struct chans chans
#define max(a, b)
Definition: f2c.h:198