sphinx: better logging and verbosity handling
[profile/ivi/speech-recognition.git] / src / plugins / speech-to-text / sphinx / decoder-set.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <errno.h>
6
7 #include <sphinxbase/err.h>
8 #include <sphinxbase/ad.h>
9 #include <sphinxbase/cont_ad.h>
10
11 #include <pocketsphinx.h>
12
13 #include <murphy/common/mm.h>
14 #include <murphy/common/log.h>
15
16 #include "decoder-set.h"
17 #include "options.h"
18 #include "utterance.h"
19 #include "logger.h"
20
21
22 int decoder_set_create(context_t *ctx)
23 {
24     options_t *opts;
25     options_decoder_t *dec;
26     decoder_set_t *decset;
27     size_t i;
28     int sts, retval;
29
30     if (!ctx || !(opts = ctx->opts)) {
31         errno = EINVAL;
32         return -1;
33     }
34
35     if (!(decset = mrp_allocz(sizeof(decoder_set_t))))
36         return -1;
37
38     ctx->decset = decset;
39
40     for (i = 0, retval = 0;  i < opts->ndec;  i++) {
41         dec = opts->decs + i;
42
43         sts = decoder_set_add(ctx, dec->name, dec->hmm, dec->lm,
44                               dec->dict, dec->fsg, opts->topn);
45         if (sts  < 0) {
46             mrp_log_error("failed to create '%s' decoder", dec->name);
47             errno = EIO;
48             retval= -1;
49         }
50     }
51
52     decset->curdec = decset->decs;
53
54     return retval;
55 }
56
57 void decoder_set_destroy(context_t *ctx)
58 {
59     decoder_set_t *decset;
60     decoder_t *dec;
61     size_t i,j;
62
63     if (ctx && (decset = ctx->decset)) {
64         ctx->decset = NULL;
65
66         for (i = 0;  i < decset->ndec;  i++) {
67             dec = decset->decs + i;
68
69             mrp_free((void *)dec->name);
70
71             if (dec->ps)
72                 ps_free(dec->ps);
73
74             for (j = 0; j < dec->nfsg; j++)
75                 mrp_free((void *)dec->fsgs[j]);
76             mrp_free((void *)dec->fsgs);
77         }
78
79         mrp_free(decset->decs);
80
81         mrp_free(decset);
82     }
83 }
84
85 int decoder_set_add(context_t *ctx, const char *decoder_name,
86                     const char *hmm, const char *lm,
87                     const char *dict, const char *fsg,
88                     uint32_t topn)
89 {
90 #define FSG_NAMES_MAX 255
91
92     static const arg_t arg_defs[] = {
93         POCKETSPHINX_OPTIONS,
94         CMDLN_EMPTY_OPTION
95     };
96
97     options_t *opts;
98     decoder_set_t *decset;
99     decoder_t *dec;
100     const char *dupnam;
101     cmd_ln_t *cfg;
102     ps_decoder_t *ps;
103     size_t new_size;
104     fsg_set_t *set;
105     fsg_set_iter_t *sit;
106     fsg_model_t *model;
107     const char *modnam;
108     const char *fsgs[FSG_NAMES_MAX + 1];
109     size_t nfsg;
110     size_t curidx;
111
112     if (!ctx || !(opts = ctx->opts) || !(decset = ctx->decset)) {
113         errno = EINVAL;
114         return -1;
115     }
116
117     if (!lm || !dict) {
118         errno = ENOENT;
119         return -1;
120     }
121
122     if (!hmm)
123         hmm = opts->decs[0].hmm;
124
125     curidx = decset->curdec - decset->decs;
126     new_size = sizeof(decoder_t) * (decset->ndec + 2);
127
128     if (!(decset->decs = realloc(decset->decs, new_size)) ||
129         !(dupnam = mrp_strdup(decoder_name)))
130     {
131         return -1;
132     }
133
134     memset(decset->decs + decset->ndec, 0, sizeof(decoder_t) * 2);
135
136     dec = decset->decs + decset->ndec;
137     decset->curdec = decset->decs + curidx;
138
139     if (!(cfg = cmd_ln_init(NULL, arg_defs, 0, NULL))) {
140         mrp_log_error("failed to create cmd line struct");
141         return -1;
142     }
143
144     cmd_ln_set_str_r(cfg, "-hmm", hmm);
145     cmd_ln_set_str_r(cfg, "-lm", lm);
146     cmd_ln_set_str_r(cfg, "-dict", dict);
147     cmd_ln_set_int_r(cfg, "-topn", topn);
148     cmd_ln_set_float_r(cfg, "-samprate", (double)opts->rate);
149     cmd_ln_set_boolean_r(cfg, "-verbose",
150                          (ctx->verbose || opts->logfn != NULL) ? true : false);
151
152     if (opts->logfn != NULL) {
153         if (strcmp(opts->logfn, "srs"))
154             cmd_ln_set_str_r(cfg, "-logfn", opts->logfn);
155     }
156     else {
157         if (ctx->verbose)
158             err_set_logfp(stdout);
159     }
160
161     if (fsg)
162         cmd_ln_set_str_r(cfg, "-fsg", fsg);
163
164     if (!(ps = ps_init(cfg)))
165         return -1;
166
167     if (!fsg)
168         nfsg = 0;
169     else {
170         if (!(set = ps_get_fsgset(ps))) {
171             mrp_log_error("can't find fsg models");
172             ps_free(ps);
173             return -1;
174         }
175
176         mrp_log_info("found fsg models:");
177
178         for (nfsg = 0, sit = fsg_set_iter(set);
179              nfsg < FSG_NAMES_MAX && sit;
180              nfsg++, sit = fsg_set_iter_next(sit))
181         {
182             model = fsg_set_iter_fsg(sit);
183             modnam = fsg_model_name(model);
184             fsgs[nfsg] = mrp_strdup(modnam ? modnam : "<anonymous>");
185
186             mrp_log_info("   %s", fsgs[nfsg]);
187         }
188
189         if (!nfsg) {
190             mrp_log_info("    <none>");
191             ps_free(ps);
192             return -1;
193         }
194     }
195
196     dec->name = dupnam;
197     dec->cfg  = cfg;
198     dec->ps   = ps;
199     dec->fsgs = mrp_allocz(sizeof(const char *) * (nfsg + 1));
200     dec->nfsg = nfsg;
201     dec->utproc = nfsg ? UTTERANCE_PROCESSOR_FSG:UTTERANCE_PROCESSOR_ACOUSTIC;
202     dec->utid = 1;
203
204     if (!dec->fsgs) {
205         mrp_log_error("No memory");
206         return -1;
207     }
208
209     if (nfsg > 0)
210         memcpy((void *)dec->fsgs, (void *)fsgs, sizeof(const char *) * nfsg);
211
212     decset->ndec++;
213
214     return 0;
215
216 #undef FSG_NAMES_MAX
217 }
218
219 bool decoder_set_contains(context_t *ctx, const char *decoder_name)
220 {
221     decoder_set_t *decset;
222     decoder_t *d;
223
224     if (!ctx || !(decset = ctx->decset))
225         return false;
226
227     for (d = decset->decs;  d->name;  d++) {
228         if (!strcmp(decoder_name, d->name))
229             return true;
230     }
231
232     return false;
233 }
234
235 int decoder_set_use(context_t *ctx, const char *decoder_name)
236 {
237     decoder_set_t *decset;
238     decoder_t *d;
239
240     if (!ctx || !(decset = ctx->decset))
241         return -1;
242
243     if (!decoder_name) {
244         decset->curdec = decset->decs;
245         return -1;
246     }
247
248     for (d = decset->decs;  d->name;  d++) {
249         if (!strcmp(decoder_name, d->name)) {
250             if (ctx->verbose)
251                 mrp_debug("switching to decoder '%s'", decoder_name);
252
253             decset->curdec = d;
254
255             return 0;
256         }
257     }
258
259     mrp_log_error("unable to set decoder '%s': can't find it", decoder_name);
260
261     return -1;
262 }
263
264 const char *decoder_set_name(context_t *ctx)
265 {
266     decoder_set_t *decset;
267     decoder_t *dec;
268
269     if (!ctx || !(decset = ctx->decset) || !(dec = decset->curdec))
270         return "<unknown>";
271
272     return dec->name;
273 }
274
275
276 /*
277  * Local Variables:
278  * c-basic-offset: 4
279  * indent-tabs-mode: nil
280  * End:
281  *
282  */