1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "py/builtin.h"
6 #include "py/mperrno.h"
7 #include "py/obj.h"
8 #include "py/runtime.h"
9 #include "py/stackctrl.h"
10 #include "ulog/ulog.h"
11 #include "utility.h"
12 #include "uvoice_alios.h"
13 #include "uvoice_event.h"
14 #include "uvoice_init.h"
15 #include "uvoice_tts.h"
16 #include "uvoice_types.h"
17
18 #define LOG_TAG "UVOICE_TTS"
19
20 #define TTS_CHECK_PARAMS() \
21 uvocie_tts_obj_t *self = (uvocie_tts_obj_t *)MP_OBJ_TO_PTR(self_in); \
22 do { \
23 if (self == NULL || self->tts_obj == NULL) { \
24 mp_raise_OSError(EINVAL); \
25 return mp_const_none; \
26 } \
27 } while (0)
28
29 #define TTS_RECV_CB_URL (0)
30 #define TTS_RECV_CB_DATA (1)
31 #define TTS_RECV_CB_EVENT (2)
32
33 extern const mp_obj_type_t uvoice_tts_type;
34
35 static mp_obj_t callback_url = mp_const_none;
36 static mp_obj_t callback_data = mp_const_none;
37 static mp_obj_t callback_event = mp_const_none;
38
39 // this is the actual C-structure for our new object
40 typedef struct {
41 // base represents some basic information, like type
42 mp_obj_base_t base;
43
44 // a member created by us
45 char *modName;
46 uvoice_tts_t *tts_obj;
47 } uvocie_tts_obj_t;
48
uvoice_tts_print(const mp_print_t * print,mp_obj_t self_in,mp_print_kind_t kind)49 void uvoice_tts_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
50 {
51 uvocie_tts_obj_t *self = MP_OBJ_TO_PTR(self_in);
52 mp_printf(print, "modName(%s)", self->modName);
53 }
54
uvoice_tts_new(const mp_obj_type_t * type,size_t n_args,size_t n_kw,const mp_obj_t * args)55 STATIC mp_obj_t uvoice_tts_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args)
56 {
57 uvocie_tts_obj_t *uvocie_tts_com_obj = m_new_obj(uvocie_tts_obj_t);
58 if (!uvocie_tts_com_obj) {
59 mp_raise_OSError(MP_ENOMEM);
60 return mp_const_none;
61 }
62 memset(uvocie_tts_com_obj, 0, sizeof(uvocie_tts_obj_t));
63
64 uvocie_tts_com_obj->base.type = &uvoice_tts_type;
65 uvocie_tts_com_obj->modName = "uvoice-tts";
66
67 return MP_OBJ_FROM_PTR(uvocie_tts_com_obj);
68 }
69
alicoud_tts_event(tts_event_e event,char * info)70 STATIC mp_int_t alicoud_tts_event(tts_event_e event, char *info)
71 {
72 if (callback_event != mp_const_none) {
73 mp_obj_t event_dict = mp_obj_new_dict(2);
74 mp_obj_dict_store(event_dict, MP_OBJ_NEW_QSTR(qstr_from_str("event")), mp_obj_new_int(event));
75 mp_obj_dict_store(event_dict, MP_OBJ_NEW_QSTR(qstr_from_str("info")), mp_obj_new_strn(info));
76
77 callback_to_python(callback_event, event_dict);
78 }
79 }
80
alicloud_tts_recv_data(uint8_t * buffer,mp_int_t nbytes,mp_int_t index)81 STATIC mp_int_t alicloud_tts_recv_data(uint8_t *buffer, mp_int_t nbytes, mp_int_t index)
82 {
83 if (callback_data != mp_const_none) {
84 mp_obj_t data_dict = mp_obj_new_dict(3);
85 mp_obj_dict_store(data_dict, MP_OBJ_NEW_QSTR(qstr_from_str("buffer")), mp_obj_new_bytes(buffer, nbytes));
86 mp_obj_dict_store(data_dict, MP_OBJ_NEW_QSTR(qstr_from_str("nbytes")), mp_obj_new_int(nbytes));
87 mp_obj_dict_store(data_dict, MP_OBJ_NEW_QSTR(qstr_from_str("index")), mp_obj_new_int(index));
88
89 callback_to_python(callback_data, data_dict);
90 }
91 }
92
alicloud_tts_recv_url(char * tts_url)93 STATIC mp_int_t alicloud_tts_recv_url(char *tts_url)
94 {
95 if (callback_url != mp_const_none) {
96 callback_to_python(callback_url, mp_obj_new_str(tts_url, strlen(tts_url)));
97 }
98 }
99
uvoice_tts_init(mp_obj_t self_in,mp_obj_t aicloud_type_in,mp_obj_t config_in)100 STATIC mp_obj_t uvoice_tts_init(mp_obj_t self_in, mp_obj_t aicloud_type_in, mp_obj_t config_in)
101 {
102 TTS_CHECK_PARAMS();
103
104 tts_aicloud_type_e aicloud_type = (tts_aicloud_type_e)mp_obj_get_int(aicloud_type_in);
105
106 tts_config_t config = { 0 };
107 config.app_key = (char *)get_str_from_dict(config_in, "app_key");
108 config.token = (char *)get_str_from_dict(config_in, "token");
109 config.format = (media_format_t)get_int_from_dict(config_in, "format");
110 config.sample_rate = get_int_from_dict(config_in, "sample_rate");
111 config.voice = (char *)get_str_from_dict(config_in, "voice");
112 config.volume = get_int_from_dict(config_in, "volume");
113 config.speech_rate = get_int_from_dict(config_in, "speech_rate");
114 config.pitch_rate = get_int_from_dict(config_in, "pitch_rate");
115 config.text_encode_type = (tts_encode_type_e)get_int_from_dict(config_in, "text_encode_type");
116
117 LOGD(LOG_TAG,
118 "app_key=%s, token=%s, format=%d, sample_rate=%d, voice=%s, "
119 "volume=%d, speech_rate=%d, pitch_rate=%d, text_encode_type=%d\n",
120 config.app_key, config.token, config.format, config.sample_rate, config.voice, config.volume,
121 config.speech_rate, config.pitch_rate, config.text_encode_type);
122
123 mp_int_t status = self->tts_obj->tts_init(aicloud_type, &config);
124 return mp_obj_new_int(status);
125 }
126 STATIC MP_DEFINE_CONST_FUN_OBJ_3(uvoice_tts_init_obj, uvoice_tts_init);
127
128 static tts_recv_callback_t recv_cb = {
129 .event = alicoud_tts_event,
130 .recv_data = alicloud_tts_recv_data,
131 .recv_url = alicloud_tts_recv_url,
132 };
133
uvoice_tts_request(size_t n_args,const mp_obj_t * args)134 STATIC mp_obj_t uvoice_tts_request(size_t n_args, const mp_obj_t *args)
135 {
136 if (n_args < 3) {
137 LOGE(LOG_TAG, "%s: args num is illegal :n_args = %d;\n", __func__, n_args);
138 return mp_const_none;
139 }
140
141 mp_obj_t self_in = args[0];
142 TTS_CHECK_PARAMS();
143
144 char *text = (char *)mp_obj_str_get_str(args[1]);
145 int recv_type = mp_obj_get_int(args[2]);
146
147 LOGD(LOG_TAG, "text=%s, recv_type=%d", text, recv_type);
148
149 mp_int_t status = self->tts_obj->tts_request(text, recv_type, &recv_cb);
150 return mp_obj_new_int(status);
151 }
152 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(uvoice_tts_request_obj, 3, uvoice_tts_request);
153
uvoice_tts_stop(mp_obj_t self_in)154 STATIC mp_obj_t uvoice_tts_stop(mp_obj_t self_in)
155 {
156 TTS_CHECK_PARAMS();
157
158 mp_int_t status = self->tts_obj->tts_stop();
159 return mp_obj_new_int(status);
160 }
161 STATIC MP_DEFINE_CONST_FUN_OBJ_1(uvoice_tts_stop_obj, uvoice_tts_stop);
162
uvoice_create(mp_obj_t self_in)163 STATIC mp_obj_t uvoice_create(mp_obj_t self_in)
164 {
165 uvocie_tts_obj_t *self = (uvocie_tts_obj_t *)MP_OBJ_TO_PTR(self_in);
166 if (self == NULL) {
167 LOGE(LOG_TAG, "uvocie_tts_obj_t NULL");
168 return mp_const_none;
169 }
170
171 self->tts_obj = uvoice_tts_create();
172 if (self->tts_obj == NULL) {
173 LOGE(LOG_TAG, "create tts failed !\n");
174 }
175
176 return mp_const_none;
177 }
178 STATIC MP_DEFINE_CONST_FUN_OBJ_1(uvoice_tts_create_obj, uvoice_create);
179
uvoice_release(mp_obj_t self_in)180 STATIC mp_obj_t uvoice_release(mp_obj_t self_in)
181 {
182 TTS_CHECK_PARAMS();
183 mp_int_t status = uvoice_tts_release(self->tts_obj);
184
185 callback_url = mp_const_none;
186 callback_data = mp_const_none;
187 callback_event = mp_const_none;
188
189 return mp_obj_new_int(status);
190 }
191 STATIC MP_DEFINE_CONST_FUN_OBJ_1(uvoice_tts_release_obj, uvoice_release);
192
uvoice_tts_set_callback(mp_obj_t self_in,mp_obj_t type_in,mp_obj_t callback_fun)193 STATIC mp_obj_t uvoice_tts_set_callback(mp_obj_t self_in, mp_obj_t type_in, mp_obj_t callback_fun)
194 {
195 TTS_CHECK_PARAMS();
196
197 if (mp_obj_is_fun(callback_fun) == false) {
198 LOGE(LOG_TAG, "Obj is not function\n");
199 return mp_const_none;
200 }
201
202 int type = mp_obj_get_int(type_in);
203 if (type == TTS_RECV_CB_URL) {
204 callback_url = callback_fun;
205 } else if (type == TTS_RECV_CB_DATA) {
206 callback_data = callback_fun;
207 } else if (type == TTS_RECV_CB_EVENT) {
208 callback_event = callback_fun;
209 }
210
211 return mp_const_none;
212 }
213 STATIC MP_DEFINE_CONST_FUN_OBJ_3(uvoice_tts_set_callback_obj, uvoice_tts_set_callback);
214
uvoice_tts_cb_test(mp_obj_t self_in,mp_obj_t type_in)215 STATIC mp_obj_t uvoice_tts_cb_test(mp_obj_t self_in, mp_obj_t type_in)
216 {
217 TTS_CHECK_PARAMS();
218
219 int type = mp_obj_get_int(type_in);
220 LOGD(LOG_TAG, "type=%d", type);
221
222 if (type == TTS_RECV_CB_URL) {
223 alicloud_tts_recv_url("test_url");
224 } else if (type == TTS_RECV_CB_DATA) {
225 char buf[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
226 alicloud_tts_recv_data(buf, 8, 10);
227 } else if (type == TTS_RECV_CB_EVENT) {
228 alicoud_tts_event(10, "test_info");
229 }
230
231 return mp_const_none;
232 }
233
234 STATIC const mp_rom_map_elem_t uvoice_module_tts_globals_table[] = {
235 { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&uvoice_tts_stop_obj) },
236 { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&uvoice_tts_create_obj) },
237 { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&uvoice_tts_release_obj) },
238 { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&uvoice_tts_set_callback_obj) },
239 { MP_ROM_QSTR(MP_QSTR_prepare), MP_ROM_PTR(&uvoice_tts_init_obj) },
240 { MP_ROM_QSTR(MP_QSTR_request), MP_ROM_PTR(&uvoice_tts_request_obj) },
241 { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&uvoice_tts_stop_obj) },
242
243 { MP_ROM_QSTR(MP_QSTR_CB_ENUM_URL), MP_ROM_INT(TTS_RECV_CB_URL) },
244 { MP_ROM_QSTR(MP_QSTR_CB_ENUM_DATA), MP_ROM_INT(TTS_RECV_CB_DATA) },
245 { MP_ROM_QSTR(MP_QSTR_CB_ENUM_EVENT), MP_ROM_INT(TTS_RECV_CB_EVENT) },
246 };
247 STATIC MP_DEFINE_CONST_DICT(uvoice_module_tts_globals, uvoice_module_tts_globals_table);
248
249 const mp_obj_type_t uvoice_tts_type = {
250 .base = { &mp_type_type },
251 .name = MP_QSTR_Tts,
252 .print = uvoice_tts_print,
253 .make_new = uvoice_tts_new,
254 .locals_dict = (mp_obj_dict_t *)&uvoice_module_tts_globals,
255 };
256