summaryrefslogtreecommitdiff
path: root/src/lib/ecore_audio
diff options
context:
space:
mode:
authorDaniel Willmann <d.willmann@samsung.com>2013-04-12 17:45:12 +0100
committerDaniel Willmann <d.willmann@samsung.com>2013-04-18 19:12:17 +0100
commit422d3313e8363017bf96f28f4de33160fc08e5f5 (patch)
tree8ea9d8be0a4f3946d498b0c97c3a274700fbf2ed /src/lib/ecore_audio
parent845aeb5c63fb309041bde94f61a648ceb0504dc4 (diff)
ecore_audio: Add sndfile in- and output
Signed-off-by: Daniel Willmann <d.willmann@samsung.com>
Diffstat (limited to 'src/lib/ecore_audio')
-rw-r--r--src/lib/ecore_audio/ecore_audio_obj_in_sndfile.c196
-rw-r--r--src/lib/ecore_audio/ecore_audio_obj_in_sndfile.h57
-rw-r--r--src/lib/ecore_audio/ecore_audio_obj_out_sndfile.c218
-rw-r--r--src/lib/ecore_audio/ecore_audio_obj_out_sndfile.h57
4 files changed, 528 insertions, 0 deletions
diff --git a/src/lib/ecore_audio/ecore_audio_obj_in_sndfile.c b/src/lib/ecore_audio/ecore_audio_obj_in_sndfile.c
new file mode 100644
index 0000000000..75eafbdf20
--- /dev/null
+++ b/src/lib/ecore_audio/ecore_audio_obj_in_sndfile.c
@@ -0,0 +1,196 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <string.h>
8
9#ifdef HAVE_FEATURES_H
10#include <features.h>
11#endif
12
13#include <Eo.h>
14#include "ecore_audio_private.h"
15#include <sndfile.h>
16
17EAPI Eo_Op ECORE_AUDIO_OBJ_IN_SNDFILE_BASE_ID = EO_NOOP;
18
19#define MY_CLASS ECORE_AUDIO_OBJ_IN_SNDFILE_CLASS
20#define MY_CLASS_NAME "ecore_audio_obj_in_sndfile"
21
22struct _Ecore_Audio_Sndfile
23{
24 SNDFILE *handle;
25 SF_INFO sfinfo;
26 Ecore_Audio_Vio *vio;
27};
28
29typedef struct _Ecore_Audio_Sndfile Ecore_Audio_Sndfile;
30
31static void _read(Eo *eo_obj, void *_pd, va_list *list)
32{
33 Ecore_Audio_Sndfile *obj = _pd;
34 int read;
35 void *data = va_arg(*list, void *);
36 int len = va_arg(*list, int);
37 int *ret = va_arg(*list, int *);
38
39 read = sf_read_float(obj->handle, data, len/4)*4;
40
41 if (ret)
42 *ret = read;
43}
44
45static void _seek(Eo *eo_obj, void *_pd, va_list *list)
46{
47 Ecore_Audio_Sndfile *obj = _pd;
48 sf_count_t count, pos;
49
50 double offs = va_arg(*list, double);
51 int mode = va_arg(*list, int);
52 double *ret = va_arg(*list, double *);
53
54 count = offs * obj->sfinfo.samplerate;
55 pos = sf_seek(obj->handle, count, mode);
56
57 if (ret)
58 *ret = (double)pos / obj->sfinfo.samplerate;
59}
60
61static void _source_set(Eo *eo_obj, void *_pd, va_list *list)
62{
63 Ecore_Audio_Sndfile *obj = _pd;
64
65 Ecore_Audio_Object *ea_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
66 Ecore_Audio_Input *in_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_IN_CLASS);
67
68 const char *source = va_arg(*list, const char *);
69
70 if (obj->handle) {
71 sf_close(obj->handle);
72 obj->handle = NULL;
73 }
74
75 eina_stringshare_replace(&ea_obj->source, source);
76
77 if (!ea_obj->source)
78 return;
79
80 obj->handle = sf_open(ea_obj->source, SFM_READ, &obj->sfinfo);
81
82 if (!obj->handle) {
83 eina_stringshare_del(ea_obj->source);
84 ea_obj->source = NULL;
85 return;
86 }
87
88 in_obj->length = (double)obj->sfinfo.frames / obj->sfinfo.samplerate;
89
90 in_obj->samplerate = obj->sfinfo.samplerate;
91 in_obj->channels = obj->sfinfo.channels;
92
93 if (obj->sfinfo.format& SF_FORMAT_WAV)
94 ea_obj->format = ECORE_AUDIO_FORMAT_WAV;
95 else if (obj->sfinfo.format& SF_FORMAT_OGG)
96 ea_obj->format = ECORE_AUDIO_FORMAT_OGG;
97 else if (obj->sfinfo.format& SF_FORMAT_FLAC)
98 ea_obj->format = ECORE_AUDIO_FORMAT_FLAC;
99 else
100 ea_obj->format = ECORE_AUDIO_FORMAT_AUTO;
101}
102
103static void _source_get(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list)
104{
105 Ecore_Audio_Object *obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
106
107 const char **ret = va_arg(*list, const char **);
108
109 if (ret)
110 *ret = obj->source;
111}
112
113static void _format_set(Eo *eo_obj, void *_pd, va_list *list)
114{
115 Ecore_Audio_Sndfile *obj = _pd;
116 Ecore_Audio_Object *ea_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
117
118 Ecore_Audio_Format format= va_arg(*list, Ecore_Audio_Format);
119
120 if (ea_obj->source) {
121 ERR("Input is already open - cannot change format");
122 return;
123 }
124
125 switch (format) {
126 case ECORE_AUDIO_FORMAT_AUTO:
127 obj->sfinfo.format = 0;
128 case ECORE_AUDIO_FORMAT_WAV:
129 obj->sfinfo.format = SF_FORMAT_WAV|SF_FORMAT_PCM_16;
130 break;
131 case ECORE_AUDIO_FORMAT_OGG:
132 obj->sfinfo.format = SF_FORMAT_OGG|SF_FORMAT_VORBIS;
133 break;
134 case ECORE_AUDIO_FORMAT_FLAC:
135 obj->sfinfo.format = SF_FORMAT_FLAC;
136 break;
137 default:
138 ERR("Format not supported!");
139 return;
140 }
141 ea_obj->format = format;
142}
143
144static void _format_get(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list)
145{
146 Ecore_Audio_Object *obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
147
148 Ecore_Audio_Format *ret = va_arg(*list, Ecore_Audio_Format *);
149
150 if (ret)
151 *ret = obj->format;
152}
153
154static void _constructor(Eo *eo_obj, void *_pd, va_list *list EINA_UNUSED)
155{
156 eo_do_super(eo_obj, MY_CLASS, eo_constructor());
157
158}
159
160static void _class_constructor(Eo_Class *klass)
161{
162 const Eo_Op_Func_Description func_desc[] = {
163 /* Virtual functions of parent class implemented in this class */
164 EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
165 //EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
166
167 EO_OP_FUNC(ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_SOURCE_SET), _source_set),
168 EO_OP_FUNC(ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_SOURCE_GET), _source_get),
169 EO_OP_FUNC(ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_FORMAT_SET), _format_set),
170 EO_OP_FUNC(ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_FORMAT_GET), _format_get),
171
172 EO_OP_FUNC(ECORE_AUDIO_OBJ_IN_ID(ECORE_AUDIO_OBJ_IN_SUB_ID_SEEK), _seek),
173 EO_OP_FUNC(ECORE_AUDIO_OBJ_IN_ID(ECORE_AUDIO_OBJ_IN_SUB_ID_READ_INTERNAL), _read),
174
175 EO_OP_FUNC_SENTINEL
176 };
177
178 eo_class_funcs_set(klass, func_desc);
179}
180
181static const Eo_Op_Description op_desc[] = {
182 EO_OP_DESCRIPTION_SENTINEL
183};
184
185static const Eo_Class_Description class_desc = {
186 EO_VERSION,
187 MY_CLASS_NAME,
188 EO_CLASS_TYPE_REGULAR,
189 EO_CLASS_DESCRIPTION_OPS(&ECORE_AUDIO_OBJ_IN_SNDFILE_BASE_ID, op_desc, ECORE_AUDIO_OBJ_IN_SNDFILE_SUB_ID_LAST),
190 NULL,
191 sizeof(Ecore_Audio_Sndfile),
192 _class_constructor,
193 NULL
194};
195
196EO_DEFINE_CLASS(ecore_audio_obj_in_sndfile_class_get, &class_desc, ECORE_AUDIO_OBJ_IN_CLASS, NULL);
diff --git a/src/lib/ecore_audio/ecore_audio_obj_in_sndfile.h b/src/lib/ecore_audio/ecore_audio_obj_in_sndfile.h
new file mode 100644
index 0000000000..98a56ca66c
--- /dev/null
+++ b/src/lib/ecore_audio/ecore_audio_obj_in_sndfile.h
@@ -0,0 +1,57 @@
1#ifndef ECORE_AUDIO_IN_SNDFILE_H
2#define ECORE_AUDIO_IN_SNDFILE_H
3
4#include <Eina.h>
5#include <Eo.h>
6
7#ifdef EAPI
8#undef EAPI
9#endif
10
11#ifdef __GNUC__
12#if __GNUC__ >= 4
13#define EAPI __attribute__ ((visibility("default")))
14#else
15#define EAPI
16#endif
17#else
18#define EAPI
19#endif
20
21/**
22 * @file ecore_audio_obj_in_sndfile.h
23 * @brief Audio Module
24 */
25
26#ifdef __cplusplus
27extern "C"
28{
29#endif
30
31/**
32 * @addtogroup Ecore_Audio_Group
33 * @{
34 */
35
36#define ECORE_AUDIO_OBJ_IN_SNDFILE_CLASS ecore_audio_obj_in_sndfile_class_get()
37
38const Eo_Class *ecore_audio_obj_in_sndfile_class_get() EINA_CONST;
39
40extern EAPI Eo_Op ECORE_AUDIO_OBJ_IN_SNDFILE_BASE_ID;
41
42enum Ecore_Audio_Obj_In_Sndfile_Sub_Ids
43{
44 ECORE_AUDIO_OBJ_IN_SNDFILE_SUB_ID_LAST
45};
46
47#define ECORE_AUDIO_OBJ_IN_SNDFILE_ID(sub_id) (ECORE_AUDIO_OBJ_IN_SNDFILE_BASE_ID + EO_TYPECHECK(enum Ecore_Audio_Obj_In_Sndfile_Sub_Ids, sub_id)
48
49/**
50 * @}
51 */
52
53#ifdef __cplusplus
54}
55#endif
56
57#endif
diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_sndfile.c b/src/lib/ecore_audio/ecore_audio_obj_out_sndfile.c
new file mode 100644
index 0000000000..b5fd2d59ff
--- /dev/null
+++ b/src/lib/ecore_audio/ecore_audio_obj_out_sndfile.c
@@ -0,0 +1,218 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <string.h>
8
9#ifdef HAVE_FEATURES_H
10#include <features.h>
11#endif
12
13#include <Eo.h>
14#include "ecore_audio_private.h"
15#include <sndfile.h>
16
17EAPI Eo_Op ECORE_AUDIO_OBJ_OUT_SNDFILE_BASE_ID = EO_NOOP;
18
19#define MY_CLASS ECORE_AUDIO_OBJ_OUT_SNDFILE_CLASS
20#define MY_CLASS_NAME "ecore_audio_obj_out_sndfile"
21
22struct _Ecore_Audio_Sndfile
23{
24 SNDFILE *handle;
25 SF_INFO sfinfo;
26 Ecore_Audio_Vio *vio;
27 Ecore_Idler *idler;
28};
29
30typedef struct _Ecore_Audio_Sndfile Ecore_Audio_Sndfile;
31
32static Eina_Bool _write_cb(void *data)
33{
34 Eo *eo_obj = data;
35 Eo *in;
36
37 Ecore_Audio_Sndfile *obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_OUT_SNDFILE_CLASS);
38 Ecore_Audio_Output *out_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_OUT_CLASS);
39
40 int written, bread;
41 float buf[1024];
42
43 /* TODO: Support mixing of multiple inputs */
44 in = eina_list_data_get(out_obj->inputs);
45
46 eo_do(in, ecore_audio_obj_in_read(buf, 4*1024, &bread));
47
48 if (bread == 0) {
49 sf_write_sync(obj->handle);
50 out_obj->paused = EINA_TRUE;
51 obj->idler = NULL;
52 return EINA_FALSE;
53 }
54 written = sf_write_float(obj->handle, buf, bread/4)*4;
55
56 if (written != bread)
57 ERR("Short write! (%s)\n", sf_strerror(obj->handle));
58
59 return EINA_TRUE;
60}
61
62static void _input_attach(Eo *eo_obj, void *_pd, va_list *list)
63{
64 Ecore_Audio_Sndfile *obj = _pd;
65 Ecore_Audio_Object *ea_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
66 Ecore_Audio_Output *out_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_OUT_CLASS);
67
68 Eo *in = va_arg(*list, Eo *);
69
70 eo_do_super(eo_obj, MY_CLASS, ecore_audio_obj_out_input_attach(in));
71
72 eo_do(in, ecore_audio_obj_in_samplerate_get(&obj->sfinfo.samplerate));
73 eo_do(in, ecore_audio_obj_in_channels_get(&obj->sfinfo.channels));
74
75 obj->handle = sf_open(ea_obj->source, SFM_WRITE, &obj->sfinfo);
76
77 if (!obj->handle) {
78 eina_stringshare_del(ea_obj->source);
79 ea_obj->source = NULL;
80 return;
81 }
82
83 if (ea_obj->paused)
84 return;
85
86 if (out_obj->inputs) {
87 obj->idler = ecore_idler_add(_write_cb, eo_obj);
88 }
89}
90
91static void _source_set(Eo *eo_obj, void *_pd, va_list *list)
92{
93 Ecore_Audio_Sndfile *obj = _pd;
94
95 Ecore_Audio_Object *ea_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
96
97 const char *source = va_arg(*list, const char *);
98
99 if (obj->handle) {
100 sf_close(obj->handle);
101 obj->handle = NULL;
102 }
103
104 eina_stringshare_replace(&ea_obj->source, source);
105
106 if (!ea_obj->source)
107 return;
108
109}
110
111static void _source_get(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list)
112{
113 Ecore_Audio_Object *obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
114
115 const char **ret = va_arg(*list, const char **);
116
117 if (ret)
118 *ret = obj->source;
119}
120
121static void _format_set(Eo *eo_obj, void *_pd, va_list *list)
122{
123 Ecore_Audio_Sndfile *obj = _pd;
124 Ecore_Audio_Object *ea_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
125
126 Ecore_Audio_Format format= va_arg(*list, Ecore_Audio_Format);
127
128 if (ea_obj->source) {
129 ERR("Input is already open - cannot change format");
130 return;
131 }
132
133 switch (format) {
134 case ECORE_AUDIO_FORMAT_AUTO:
135 obj->sfinfo.format = 0;
136 case ECORE_AUDIO_FORMAT_WAV:
137 obj->sfinfo.format = SF_FORMAT_WAV|SF_FORMAT_PCM_16;
138 break;
139 case ECORE_AUDIO_FORMAT_OGG:
140 obj->sfinfo.format = SF_FORMAT_OGG|SF_FORMAT_VORBIS;
141 break;
142 case ECORE_AUDIO_FORMAT_FLAC:
143 obj->sfinfo.format = SF_FORMAT_FLAC;
144 break;
145 default:
146 ERR("Format not supported!");
147 return;
148 }
149 ea_obj->format = format;
150}
151
152static void _format_get(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list)
153{
154 Ecore_Audio_Object *obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
155
156 Ecore_Audio_Format *ret = va_arg(*list, Ecore_Audio_Format *);
157
158 if (ret)
159 *ret = obj->format;
160}
161
162static void _constructor(Eo *eo_obj, void *_pd, va_list *list EINA_UNUSED)
163{
164 Ecore_Audio_Sndfile *obj = _pd;
165
166 eo_do_super(eo_obj, MY_CLASS, eo_constructor());
167
168 eo_do(eo_obj, ecore_audio_obj_format_set(ECORE_AUDIO_FORMAT_OGG));
169}
170
171static void _destructor(Eo *eo_obj, void *_pd, va_list *list EINA_UNUSED)
172{
173 Ecore_Audio_Sndfile *obj = _pd;
174
175 if (obj->handle)
176 sf_close(obj->handle);
177 if (obj->idler)
178 ecore_idler_del(obj->idler);
179
180 eo_do_super(eo_obj, MY_CLASS, eo_destructor());
181}
182
183static void _class_constructor(Eo_Class *klass)
184{
185 const Eo_Op_Func_Description func_desc[] = {
186 /* Virtual functions of parent class implemented in this class */
187 EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
188 EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
189
190 EO_OP_FUNC(ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_SOURCE_SET), _source_set),
191 EO_OP_FUNC(ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_SOURCE_GET), _source_get),
192 EO_OP_FUNC(ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_FORMAT_SET), _format_set),
193 EO_OP_FUNC(ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_FORMAT_GET), _format_get),
194
195 EO_OP_FUNC(ECORE_AUDIO_OBJ_OUT_ID(ECORE_AUDIO_OBJ_OUT_SUB_ID_INPUT_ATTACH), _input_attach),
196 //EO_OP_FUNC(ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_OUT_SUB_ID_FORMAT_GET), _format_get),
197 EO_OP_FUNC_SENTINEL
198 };
199
200 eo_class_funcs_set(klass, func_desc);
201}
202
203static const Eo_Op_Description op_desc[] = {
204 EO_OP_DESCRIPTION_SENTINEL
205};
206
207static const Eo_Class_Description class_desc = {
208 EO_VERSION,
209 MY_CLASS_NAME,
210 EO_CLASS_TYPE_REGULAR,
211 EO_CLASS_DESCRIPTION_OPS(&ECORE_AUDIO_OBJ_OUT_SNDFILE_BASE_ID, op_desc, ECORE_AUDIO_OBJ_OUT_SNDFILE_SUB_ID_LAST),
212 NULL,
213 sizeof(Ecore_Audio_Sndfile),
214 _class_constructor,
215 NULL
216};
217
218EO_DEFINE_CLASS(ecore_audio_obj_out_sndfile_class_get, &class_desc, ECORE_AUDIO_OBJ_OUT_CLASS, NULL);
diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_sndfile.h b/src/lib/ecore_audio/ecore_audio_obj_out_sndfile.h
new file mode 100644
index 0000000000..faea33cb0c
--- /dev/null
+++ b/src/lib/ecore_audio/ecore_audio_obj_out_sndfile.h
@@ -0,0 +1,57 @@
1#ifndef ECORE_AUDIO_OUT_SNDFILE_H
2#define ECORE_AUDIO_OUT_SNDFILE_H
3
4#include <Eina.h>
5#include <Eo.h>
6
7#ifdef EAPI
8#undef EAPI
9#endif
10
11#ifdef __GNUC__
12#if __GNUC__ >= 4
13#define EAPI __attribute__ ((visibility("default")))
14#else
15#define EAPI
16#endif
17#else
18#define EAPI
19#endif
20
21/**
22 * @file ecore_audio_obj_out_sndfile.h
23 * @brief Audio Module
24 */
25
26#ifdef __cplusplus
27extern "C"
28{
29#endif
30
31/**
32 * @addtogroup Ecore_Audio_Group
33 * @{
34 */
35
36#define ECORE_AUDIO_OBJ_OUT_SNDFILE_CLASS ecore_audio_obj_out_sndfile_class_get()
37
38const Eo_Class *ecore_audio_obj_out_sndfile_class_get() EINA_CONST;
39
40extern EAPI Eo_Op ECORE_AUDIO_OBJ_OUT_SNDFILE_BASE_ID;
41
42enum _Ecore_Audio_Obj_Out_Sndfile_Sub_Ids
43{
44 ECORE_AUDIO_OBJ_OUT_SNDFILE_SUB_ID_LAST
45};
46
47#define ECORE_AUDIO_OBJ_OUT_SNDFILE_ID(sub_id) (ECORE_AUDIO_OBJ_OUT_SNDFILE_BASE_ID + EO_TYPECHECK(enum _Ecore_Audio_Obj_Out_Sndfile_Sub_Ids, sub_id))
48
49/**
50 * @}
51 */
52
53#ifdef __cplusplus
54}
55#endif
56
57#endif