Support for writing and reading raw slin files 8khz-192khz.
[asterisk/asterisk.git] / formats / format_sln.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Anthony Minessale
5  * Anthony Minessale (anthmct@yahoo.com)
6  *
7  * See http://www.asterisk.org for more information about
8  * the Asterisk project. Please do not directly contact
9  * any of the maintainers of this project for assistance;
10  * the project provides a web site, mailing lists and IRC
11  * channels for your use.
12  *
13  * This program is free software, distributed under the terms of
14  * the GNU General Public License Version 2. See the LICENSE file
15  * at the top of the source tree.
16  */
17
18 /*! \file
19  *
20  * \brief RAW SLINEAR Formats
21  * \ingroup formats
22  */
23
24 #include "asterisk.h"
25
26 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
27
28 #include "asterisk/mod_format.h"
29 #include "asterisk/module.h"
30 #include "asterisk/endian.h"
31
32 static struct ast_frame *generic_read(struct ast_filestream *s, int *whennext, unsigned int buf_size, enum ast_format_id id)
33 {
34         int res;
35         /* Send a frame from the file to the appropriate channel */
36
37         s->fr.frametype = AST_FRAME_VOICE;
38         ast_format_set(&s->fr.subclass.format, id, 0);
39         s->fr.mallocd = 0;
40         AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, buf_size);
41         if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) {
42                 if (res)
43                         ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
44                 return NULL;
45         }
46         *whennext = s->fr.samples = res/2;
47         s->fr.datalen = res;
48         return &s->fr;
49 }
50
51 static int generic_write(struct ast_filestream *fs, struct ast_frame *f, enum ast_format_id id)
52 {
53         int res;
54         if (f->frametype != AST_FRAME_VOICE) {
55                 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
56                 return -1;
57         }
58         if (f->subclass.format.id != id) {
59                 ast_log(LOG_WARNING, "Asked to write non-slinear frame (%s)!\n", ast_getformatname(&f->subclass.format));
60                 return -1;
61         }
62         if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
63                         ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
64                         return -1;
65         }
66         return 0;
67 }
68
69 static int slinear_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
70 {
71         off_t offset=0,min,cur,max;
72
73         min = 0;
74         sample_offset <<= 1;
75         cur = ftello(fs->f);
76         fseeko(fs->f, 0, SEEK_END);
77         max = ftello(fs->f);
78         if (whence == SEEK_SET)
79                 offset = sample_offset;
80         else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
81                 offset = sample_offset + cur;
82         else if (whence == SEEK_END)
83                 offset = max - sample_offset;
84         if (whence != SEEK_FORCECUR) {
85                 offset = (offset > max)?max:offset;
86         }
87         /* always protect against seeking past begining. */
88         offset = (offset < min)?min:offset;
89         return fseeko(fs->f, offset, SEEK_SET);
90 }
91
92 static int slinear_trunc(struct ast_filestream *fs)
93 {
94         return ftruncate(fileno(fs->f), ftello(fs->f));
95 }
96
97 static off_t slinear_tell(struct ast_filestream *fs)
98 {
99         return ftello(fs->f) / 2;
100 }
101
102 static int slinear_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR);}
103 static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 320, AST_FORMAT_SLINEAR);}
104 static struct ast_format_def slin_f = {
105         .name = "sln",
106         .exts = "sln|raw",
107         .write = slinear_write,
108         .seek = slinear_seek,
109         .trunc = slinear_trunc,
110         .tell = slinear_tell,
111         .read = slinear_read,
112         .buf_size = 320 + AST_FRIENDLY_OFFSET,
113 };
114
115 static int slinear12_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR12);}
116 static struct ast_frame *slinear12_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 480, AST_FORMAT_SLINEAR12);}
117 static struct ast_format_def slin12_f = {
118         .name = "sln12",
119         .exts = "sln12",
120         .write = slinear12_write,
121         .seek = slinear_seek,
122         .trunc = slinear_trunc,
123         .tell = slinear_tell,
124         .read = slinear12_read,
125         .buf_size = 480 + AST_FRIENDLY_OFFSET,
126 };
127
128 static int slinear16_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR16);}
129 static struct ast_frame *slinear16_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 640, AST_FORMAT_SLINEAR16);}
130 static struct ast_format_def slin16_f = {
131         .name = "sln16",
132         .exts = "sln16",
133         .write = slinear16_write,
134         .seek = slinear_seek,
135         .trunc = slinear_trunc,
136         .tell = slinear_tell,
137         .read = slinear16_read,
138         .buf_size = 640 + AST_FRIENDLY_OFFSET,
139 };
140
141 static int slinear24_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR24);}
142 static struct ast_frame *slinear24_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 960, AST_FORMAT_SLINEAR24);}
143 static struct ast_format_def slin24_f = {
144         .name = "sln24",
145         .exts = "sln24",
146         .write = slinear24_write,
147         .seek = slinear_seek,
148         .trunc = slinear_trunc,
149         .tell = slinear_tell,
150         .read = slinear24_read,
151         .buf_size = 960 + AST_FRIENDLY_OFFSET,
152 };
153
154 static int slinear32_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR32);}
155 static struct ast_frame *slinear32_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1280, AST_FORMAT_SLINEAR32);}
156 static struct ast_format_def slin32_f = {
157         .name = "sln32",
158         .exts = "sln32",
159         .write = slinear32_write,
160         .seek = slinear_seek,
161         .trunc = slinear_trunc,
162         .tell = slinear_tell,
163         .read = slinear32_read,
164         .buf_size = 1280 + AST_FRIENDLY_OFFSET,
165 };
166
167 static int slinear44_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR44);}
168 static struct ast_frame *slinear44_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1764, AST_FORMAT_SLINEAR44);}
169 static struct ast_format_def slin44_f = {
170         .name = "sln44",
171         .exts = "sln44",
172         .write = slinear44_write,
173         .seek = slinear_seek,
174         .trunc = slinear_trunc,
175         .tell = slinear_tell,
176         .read = slinear44_read,
177         .buf_size = 1764 + AST_FRIENDLY_OFFSET,
178 };
179
180 static int slinear48_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR48);}
181 static struct ast_frame *slinear48_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 1920, AST_FORMAT_SLINEAR48);}
182 static struct ast_format_def slin48_f = {
183         .name = "sln48",
184         .exts = "sln48",
185         .write = slinear48_write,
186         .seek = slinear_seek,
187         .trunc = slinear_trunc,
188         .tell = slinear_tell,
189         .read = slinear48_read,
190         .buf_size = 1920 + AST_FRIENDLY_OFFSET,
191 };
192
193 static int slinear96_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR96);}
194 static struct ast_frame *slinear96_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 3840, AST_FORMAT_SLINEAR96);}
195 static struct ast_format_def slin96_f = {
196         .name = "sln96",
197         .exts = "sln96",
198         .write = slinear96_write,
199         .seek = slinear_seek,
200         .trunc = slinear_trunc,
201         .tell = slinear_tell,
202         .read = slinear96_read,
203         .buf_size = 3840 + AST_FRIENDLY_OFFSET,
204 };
205
206 static int slinear192_write(struct ast_filestream *fs, struct ast_frame *f){return generic_write(fs, f, AST_FORMAT_SLINEAR192);}
207 static struct ast_frame *slinear192_read(struct ast_filestream *s, int *whennext){return generic_read(s, whennext, 7680, AST_FORMAT_SLINEAR192);}
208 static struct ast_format_def slin192_f = {
209         .name = "sln192",
210         .exts = "sln192",
211         .write = slinear192_write,
212         .seek = slinear_seek,
213         .trunc = slinear_trunc,
214         .tell = slinear_tell,
215         .read = slinear192_read,
216         .buf_size = 7680 + AST_FRIENDLY_OFFSET,
217 };
218
219 static struct ast_format_def *slin_list[] = {
220         &slin_f,
221         &slin12_f,
222         &slin16_f,
223         &slin24_f,
224         &slin32_f,
225         &slin44_f,
226         &slin48_f,
227         &slin96_f,
228         &slin192_f,
229 };
230
231 static int load_module(void)
232 {
233         int i;
234         ast_format_set(&slin_f.format, AST_FORMAT_SLINEAR, 0);
235         ast_format_set(&slin12_f.format, AST_FORMAT_SLINEAR12, 0);
236         ast_format_set(&slin16_f.format, AST_FORMAT_SLINEAR16, 0);
237         ast_format_set(&slin24_f.format, AST_FORMAT_SLINEAR24, 0);
238         ast_format_set(&slin32_f.format, AST_FORMAT_SLINEAR32, 0);
239         ast_format_set(&slin44_f.format, AST_FORMAT_SLINEAR44, 0);
240         ast_format_set(&slin48_f.format, AST_FORMAT_SLINEAR48, 0);
241         ast_format_set(&slin96_f.format, AST_FORMAT_SLINEAR96, 0);
242         ast_format_set(&slin192_f.format, AST_FORMAT_SLINEAR192, 0);
243
244         for (i = 0; i < ARRAY_LEN(slin_list); i++) {
245                 if (ast_format_def_register(slin_list[i])) {
246                         return AST_MODULE_LOAD_FAILURE;
247                 }
248         }
249
250         return AST_MODULE_LOAD_SUCCESS;
251 }
252
253 static int unload_module(void)
254 {
255         int res = 0;
256         int i = 0;
257
258         for (i = 0; i < ARRAY_LEN(slin_list); i++) {
259                 if (ast_format_def_unregister(slin_list[i]->name)) {
260                         res |= AST_MODULE_LOAD_FAILURE;
261                 }
262         }
263         return res;
264 }
265
266 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw Signed Linear Audio support (SLN) 8khz-192khz",
267         .load = load_module,
268         .unload = unload_module,
269         .load_pri = AST_MODPRI_APP_DEPEND
270 );