Newer
Older
Kevin P. Fleming
committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2008, Anthony Minessale and Digium, Inc.
* Anthony Minessale (anthmct@yahoo.com)
* Kevin P. Fleming <kpfleming@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief RAW SLINEAR 16 Format
* \arg File name extensions: sln16
* \ingroup formats
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/mod_format.h"
#include "asterisk/module.h"
#include "asterisk/endian.h"
#define BUF_SIZE 640 /* 640 bytes, 320 samples */
#define SLIN_SAMPLES 320
static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext)
{
int res;
/* Send a frame from the file to the appropriate channel */
s->fr.frametype = AST_FRAME_VOICE;
s->fr.subclass.codec = AST_FORMAT_SLINEAR16;
Kevin P. Fleming
committed
s->fr.mallocd = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
Michiel van Baak
committed
if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) {
Kevin P. Fleming
committed
if (res)
ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
return NULL;
}
*whennext = s->fr.samples = res/2;
s->fr.datalen = res;
return &s->fr;
}
static int slinear_write(struct ast_filestream *fs, struct ast_frame *f)
{
int res;
if (f->frametype != AST_FRAME_VOICE) {
ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
return -1;
}
if (f->subclass.codec != AST_FORMAT_SLINEAR16) {
ast_log(LOG_WARNING, "Asked to write non-slinear16 frame (%s)!\n", ast_getformatname(f->subclass.codec));
Kevin P. Fleming
committed
return -1;
}
Michiel van Baak
committed
if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
return -1;
Kevin P. Fleming
committed
}
return 0;
}
static int slinear_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
{
Kevin P. Fleming
committed
sample_offset <<= 1;
Kevin P. Fleming
committed
cur = ftello(fs->f);
Kevin P. Fleming
committed
fseeko(fs->f, 0, SEEK_END);
Kevin P. Fleming
committed
max = ftello(fs->f);
Kevin P. Fleming
committed
if (whence == SEEK_SET)
offset = sample_offset;
else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
offset = sample_offset + cur;
else if (whence == SEEK_END)
offset = max - sample_offset;
if (whence != SEEK_FORCECUR)
offset = (offset > max) ? max : offset;
Kevin P. Fleming
committed
/* always protect against seeking past begining. */
Kevin P. Fleming
committed
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
return fseeko(fs->f, offset, SEEK_SET);
}
static int slinear_trunc(struct ast_filestream *fs)
{
return ftruncate(fileno(fs->f), ftello(fs->f));
}
static off_t slinear_tell(struct ast_filestream *fs)
{
return ftello(fs->f) / 2;
}
static const struct ast_format slin_f = {
.name = "sln16",
.exts = "sln16",
.format = AST_FORMAT_SLINEAR16,
.write = slinear_write,
.seek = slinear_seek,
.trunc = slinear_trunc,
.tell = slinear_tell,
.read = slinear_read,
.buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
};
static int load_module(void)
{
if (ast_format_register(&slin_f))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
}
static int unload_module(void)
{
return ast_format_unregister(slin_f.name);
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw Signed Linear 16KHz Audio support (SLN16)",
.load = load_module,
.unload = unload_module,
.load_pri = 10,
);