~ubuntu-branches/ubuntu/hoary/eflite/hoary

« back to all changes in this revision

Viewing changes to fs.c

  • Committer: Bazaar Package Importer
  • Author(s): Mario Lang
  • Date: 2004-02-25 13:55:10 UTC
  • Revision ID: james.westby@ubuntu.com-20040225135510-hei3t1pv7rywewhn
Tags: upstream-0.3.8
ImportĀ upstreamĀ versionĀ 0.3.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * brass - Braille and speech server
 
3
 *
 
4
 * Copyright (C) 2001 by Roger Butenuth, All rights reserved.
 
5
 * Copyright 2002 by Michael Gorse.
 
6
 *
 
7
 * This is free software, placed under the terms of the
 
8
 * GNU General Public License, as published by the Free Software
 
9
 * Foundation.  Please see the file COPYING for details.
 
10
 *
 
11
 * $Id: fs.c,v 1.15 2004/02/20 23:47:44 mgorse Exp $
 
12
 */
 
13
 
 
14
#include <stdio.h>
 
15
#include <string.h>
 
16
#include <unistd.h>
 
17
#include <fcntl.h>
 
18
#include <errno.h>
 
19
#include <pthread.h>
 
20
#include <signal.h>     /* tmp. for dbg. */
 
21
#include <assert.h>
 
22
#ifndef STANDALONE
 
23
#include <dlfcn.h>
 
24
#endif
 
25
#include "flite.h"
 
26
#include "flite_version.h"
 
27
 
 
28
#include "synthesizer.h"
 
29
#include <math.h>
 
30
#include "es.h"
 
31
 
 
32
 
 
33
static int  s_close(synth_t *s);
 
34
static int  s_synth(synth_t *s, unsigned char *buffer);
 
35
static int  s_flush(synth_t *s);
 
36
static int  s_clear(synth_t *s);
 
37
#if 0
 
38
static int  s_index_set(struct synth_struct *s);
 
39
static int  s_index_wait(struct synth_struct *s, int id, int timeout);
 
40
#endif
 
41
static int  s_get_param(struct synth_struct *s, synth_par_t par, int *value);
 
42
static int  s_set_param(struct synth_struct *s, synth_par_t par, int value);
 
43
 
 
44
typedef struct synth_state {
 
45
    int  param[S_MAX];
 
46
    int  initialized;
 
47
} synth_state_t;
 
48
 
 
49
static synth_state_t private_state[2];
 
50
 
 
51
static synth_t state[] = {
 
52
    {
 
53
        &private_state[0],
 
54
        &languages[LANG_BRITISH_ENGLISH],
 
55
        "FLite/US English",
 
56
        NULL,
 
57
        s_close,
 
58
        s_synth,
 
59
        s_flush,
 
60
        s_clear,
 
61
        NULL,                   /* s_index_set, */
 
62
        NULL,                   /* s_index_wait, */
 
63
        s_get_param,
 
64
        s_set_param
 
65
    }, {
 
66
        &private_state[1],
 
67
        &languages[LANG_GERMAN],
 
68
        "FLite/German", /* not supported */
 
69
        NULL,
 
70
        s_close,
 
71
        s_synth,
 
72
        s_flush,
 
73
        s_clear,
 
74
        NULL,                   /* s_index_set, */
 
75
        NULL,                   /* s_index_wait, */
 
76
        s_get_param,
 
77
        s_set_param
 
78
    }
 
79
};
 
80
 
 
81
 
 
82
static int     current_language = -1;
 
83
static int     ref_count = 0;
 
84
static FILE    *debug_fp = NULL;
 
85
 
 
86
  typedef enum { NONE, SPEECH, TONE } ac_type;
 
87
 
 
88
typedef struct
 
89
{
 
90
  ac_type type;
 
91
  void *data;
 
92
} AUDIO_COMMAND;
 
93
 
 
94
#if 0   /* tbd - figure out what these variables are supposed to be used for */
 
95
/*static int sync_mark_no = 0;*/        /* currently used number */
 
96
/*static struct timeval mark;*/ /* time the mark has been set */
 
97
#endif
 
98
 
 
99
/* server-specific variables */
 
100
static cst_voice *v = NULL;
 
101
static pthread_t wave_thread;
 
102
static int wave_thread_active;
 
103
static pthread_mutex_t wave_mutex;
 
104
static AUDIO_COMMAND *ac;
 
105
static int ac_size;
 
106
static int ac_head, ac_tail;
 
107
static int ac_synthpos; /* largest index to play + 1 */
 
108
static pthread_t text_thread;
 
109
static int text_thread_active;
 
110
static pthread_mutex_t text_mutex;
 
111
static char *text;
 
112
static int text_size;
 
113
static int text_head, text_tail;
 
114
static int text_synthpos;       /* pointer to beyond last piece to be played */
 
115
cst_audiodev *audiodev = NULL;  /* Sound device */
 
116
static int pas; /* play after synthesizing? */
 
117
static pthread_attr_t ta;       /* for creating threads */
 
118
static float time_left = 0;
 
119
static int s_count = 0;
 
120
 
 
121
extern cst_voice *REGISTER_VOX(const char *voxdir);
 
122
extern int cst_alloc_out;
 
123
 
 
124
#ifndef STANDALONE
 
125
/*
 
126
 * ----------------------------------------------------------------------
 
127
 * Called before library is loaded.
 
128
 * ----------------------------------------------------------------------
 
129
 */
 
130
void _init(void)
 
131
{
 
132
}
 
133
 
 
134
 
 
135
/*
 
136
 * ----------------------------------------------------------------------
 
137
 * Called before library is unloaded.
 
138
 * ----------------------------------------------------------------------
 
139
 */
 
140
void _fini(void)
 
141
{
 
142
}
 
143
#endif
 
144
 
 
145
/*
 
146
 * ----------------------------------------------------------------------
 
147
 * General open function for german and english synthesizer.
 
148
 * Second open increments refcount.
 
149
 * Return 0 on success, 1 on error.
 
150
 * ----------------------------------------------------------------------
 
151
 */
 
152
#ifdef DEBUG
 
153
/* This code seems to cause lingering processes in the event of a crash */
 
154
void segfault(int sig)
 
155
{
 
156
  extern char *sockname;
 
157
  es_log(1, "Got a seg fault -- exiting");
 
158
  printf("Got a seg fault -- exiting.\n");
 
159
  unlink(sockname);
 
160
  _exit(11);
 
161
}
 
162
#endif
 
163
 
 
164
synth_t *synth_open(void *context, lookup_string_t lookup)
 
165
{
 
166
    synth_t *s;
 
167
    char    *language = (*lookup)(context, "language");
 
168
    int     langi;
 
169
 
 
170
    debug_fp = stderr;
 
171
    if (language == NULL) {
 
172
        language = "english";
 
173
    }
 
174
    if (ref_count == 0) {
 
175
      unlink("log");
 
176
 
 
177
#ifdef DEBUG
 
178
      signal(SIGSEGV, segfault);
 
179
#endif
 
180
      flite_init();
 
181
      v = REGISTER_VOX(NULL);
 
182
      pthread_attr_init(&ta);
 
183
      pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_DETACHED);
 
184
      text_thread_active = 0;
 
185
      text_size = 4096;
 
186
      text = (char *)malloc(text_size);
 
187
      text_head = text_tail = text_synthpos = 0;
 
188
      wave_thread_active = 0;
 
189
      ac_size = 64;
 
190
      ac = (AUDIO_COMMAND *)malloc(ac_size * sizeof(AUDIO_COMMAND));
 
191
      ac_head = ac_tail = ac_synthpos = 0;
 
192
      if (!ac || !text) return NULL;
 
193
      pthread_mutex_init(&wave_mutex, NULL);
 
194
      time_left = 0;
 
195
    }
 
196
    ref_count++;
 
197
 
 
198
    if (!strcasecmp(language, "english")) {
 
199
        langi = 0;
 
200
        s = &state[langi];
 
201
    } else if (!strcasecmp(language, "german")) {
 
202
        langi = 1;
 
203
        s = &state[langi];
 
204
    } else {
 
205
        langi = -1;
 
206
        s = NULL;
 
207
    }
 
208
 
 
209
    if (s != NULL && !s->state->initialized) {
 
210
        s->state->param[S_SPEED]  = 1000;
 
211
        s->state->param[S_PITCH]  = 1000;
 
212
        s->state->param[S_VOLUME] = 1000;
 
213
        s->state->initialized = 1;
 
214
    }
 
215
 
 
216
    return s;
 
217
}
 
218
 
 
219
 
 
220
/*
 
221
 * ----------------------------------------------------------------------
 
222
 * General close. Decrement refcount, do real close when count reaches
 
223
 * zero.
 
224
 * ----------------------------------------------------------------------
 
225
 */
 
226
static int s_close(synth_t *s)
 
227
{
 
228
    ref_count--;
 
229
    if (ref_count == 0) {
 
230
        /* Wait for any speech to be spoken */
 
231
        while (text_thread_active || wave_thread_active) usleep(50000);
 
232
        if (text) free(text);
 
233
        if (ac) free(ac);
 
234
        text = NULL;
 
235
        ac = NULL;
 
236
    }
 
237
 
 
238
    return 0;
 
239
}
 
240
 
 
241
 
 
242
/*
 
243
 * ----------------------------------------------------------------------
 
244
 * Verify that the synthesizer is set to the correct language.
 
245
 * Switch if necessary.
 
246
 * ----------------------------------------------------------------------
 
247
 */
 
248
static void verify_language(struct synth_struct *s)
 
249
{
 
250
    int value = -1;
 
251
 
 
252
    if (s->lang->lang == LANG_BRITISH_ENGLISH
 
253
        && current_language != LANG_BRITISH_ENGLISH) {
 
254
        /* tbd */
 
255
    } else if (s->lang->lang == LANG_GERMAN &&
 
256
               current_language != LANG_GERMAN) {
 
257
        /* tbd */
 
258
    }
 
259
    if (value != -1) {
 
260
        /* tbd */
 
261
    }
 
262
}
 
263
 
 
264
static void cst_wave_free(cst_wave *w)
 
265
{
 
266
  es_log(2, "cst_wave_free: %p", w);
 
267
  if (w)
 
268
  {
 
269
    cst_free(w->samples);
 
270
    cst_free(w);
 
271
  }
 
272
}
 
273
 
 
274
static void ac_destroy(AUDIO_COMMAND *ac)
 
275
{
 
276
  switch (ac->type)
 
277
  {
 
278
  case SPEECH: case TONE: cst_wave_free(ac->data); break;
 
279
  default: break;
 
280
  }
 
281
  ac->type = NONE;
 
282
}
 
283
 
 
284
static void close_audiodev()
 
285
{
 
286
  if (audiodev)
 
287
  {
 
288
    audio_close(audiodev);
 
289
    audiodev = NULL;
 
290
  }
 
291
}
 
292
 
 
293
static void play_unlock(void *canceled)
 
294
{
 
295
  es_log(2, "play: unlocking wave mutex");
 
296
  pthread_mutex_unlock(&wave_mutex);
 
297
  es_log(2, "play: unlocked wave mutex");
 
298
}
 
299
 
 
300
#define PLAY_UNLOCK \
 
301
  play_unlock(NULL); \
 
302
  pthread_cleanup_pop(0);
 
303
 
 
304
#define PLAY_LOCK \
 
305
  es_log(2, "play: locking wave mutex"); \
 
306
  pthread_cleanup_push(play_unlock, NULL); \
 
307
  pthread_mutex_lock(&wave_mutex); \
 
308
  es_log(2, "play: got wave mutex"); \
 
309
  pthread_testcancel();
 
310
 
 
311
static void * play(void *s)
 
312
{
 
313
  int playlen;
 
314
  int skip;
 
315
  cst_wave *wptr;
 
316
  int *sparam = ((synth_t *)s)->state->param;
 
317
 
 
318
  //pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
 
319
  es_log(2, "play: init: ac_head=%d ac_tail=%d", ac_head, ac_tail);
 
320
  while (ac_head < ac_synthpos)
 
321
  {
 
322
    for (;!audiodev;)
 
323
    {
 
324
      PLAY_LOCK;
 
325
      if (ac[ac_head].type == NONE)
 
326
      {
 
327
        pas = (ac_synthpos > 0? 1: 0);
 
328
        pthread_exit(NULL);
 
329
      }
 
330
      wptr = ac[ac_head].data;
 
331
      audiodev = audio_open(wptr->sample_rate, wptr->num_channels, CST_AUDIO_LINEAR16);
 
332
      PLAY_UNLOCK;
 
333
      if (!audiodev || (long)audiodev->platform_data == -1)
 
334
      {
 
335
        if (errno == EBUSY)
 
336
        {
 
337
          es_log(2, "Audio device is busy; trying again");
 
338
          close_audiodev();
 
339
          usleep(20000);
 
340
          pthread_testcancel();
 
341
          continue;
 
342
        }
 
343
      terror("audio_open");
 
344
      }
 
345
    }
 
346
    es_log(2, "play: ac_head=%d type=%d", ac_head, ac[ac_head].type);
 
347
    if (ac[ac_head].type == NONE)
 
348
    {
 
349
      /* There will be more data, but it isn't ready yet. */
 
350
      es_log(2, "ac[%d] is inactive, setting pas", ac_head);
 
351
      pas = 1;
 
352
      PLAY_LOCK;
 
353
      close_audiodev();
 
354
      PLAY_UNLOCK;
 
355
      return NULL;
 
356
    }
 
357
    wptr = ac[ac_head].data;
 
358
    if (ac[ac_head].type == SPEECH)
 
359
    {
 
360
      skip = 1500000 / sparam[S_SPEED];
 
361
      playlen = wptr->num_samples - (skip * 2);
 
362
      if (playlen > 0 && playlen < 500) playlen += (skip * 2) / 3;
 
363
    }
 
364
    else
 
365
    {
 
366
      skip = 0;
 
367
      playlen = wptr->num_samples;
 
368
    }
 
369
    if (playlen < 0) playlen = 0;
 
370
    es_log(2, "play: wave=%p, samples=%p, num_samples=%d skip=%d playlen=%d", wptr, wptr->samples, wptr->num_samples, skip, playlen);
 
371
    time_left += (float)playlen / wptr->sample_rate;
 
372
    if (playlen > 0)
 
373
    {
 
374
      if (sparam[S_VOLUME] != 1000)
 
375
        cst_wave_rescale(wptr, (sparam[S_VOLUME] << 16) / 1000);
 
376
      pthread_testcancel();
 
377
      audio_write(audiodev, wptr->samples + skip, playlen * 2);
 
378
      pthread_testcancel();
 
379
    }
 
380
    es_log(2, "play: syncing");
 
381
    audio_flush(audiodev);
 
382
    pthread_testcancel();
 
383
    time_left -= (float)playlen / wptr->sample_rate;
 
384
    PLAY_LOCK;
 
385
    ac_destroy(&ac[ac_head]);
 
386
    close_audiodev();
 
387
    if (++ac_head > (ac_size >> 1))
 
388
    {
 
389
      es_log(1, "play: compacting wave pointers");
 
390
      memmove(ac, ac + ac_head, (ac_tail - ac_head) * sizeof(AUDIO_COMMAND));
 
391
      ac_tail -= ac_head;
 
392
      ac_synthpos -= ac_head;
 
393
      ac_head = 0;
 
394
    }
 
395
    PLAY_UNLOCK;
 
396
  }
 
397
  es_log(2, "play: loop over: ac_head=%d, ac_tail=%d", ac_head, ac_tail);
 
398
  PLAY_LOCK;
 
399
  if (ac_head == ac_tail)
 
400
  {
 
401
    ac_head = ac_tail = wave_thread_active = 0;
 
402
  }
 
403
  else pas = 1; /* there is more data -- need to re-enter */
 
404
  PLAY_UNLOCK;
 
405
  es_log(2, "play: exiting");
 
406
  return NULL;
 
407
}
 
408
 
 
409
/* This kludge works around the race condition where a synthesize thread is
 
410
   started, then speech is silenced, then more speech is added, with the first
 
411
   thread never having been created.  We want to avoid having two synthesize
 
412
   threads running in this situation.  A better solution would be to use
 
413
   thread conditions, but I have been unable to get them to work so far.  If
 
414
   you can help, then send me an email. */
 
415
typedef struct
 
416
{
 
417
  struct synth_t *s;
 
418
  int s_count;
 
419
} SYNTHESIZE_INITIALIZER;
 
420
 
 
421
void *make_initializer(void *s, int s_count)
 
422
{
 
423
  SYNTHESIZE_INITIALIZER *ptr;
 
424
 
 
425
  ptr = (SYNTHESIZE_INITIALIZER *)malloc(sizeof(SYNTHESIZE_INITIALIZER));
 
426
  if (!ptr) return NULL;
 
427
  ptr->s = s;
 
428
  ptr->s_count = s_count;
 
429
  return ptr;
 
430
}
 
431
 
 
432
static void * synthesize(void *initializer)
 
433
{
 
434
  cst_wave *wptr = NULL;
 
435
  int wml = 0;  /* wave mutex locked */
 
436
  struct synth_t *s;
 
437
  int s_count_enter;
 
438
  int command;
 
439
  int just_entered = 1;
 
440
 
 
441
  if (!initializer) return NULL;
 
442
  s = ((SYNTHESIZE_INITIALIZER *)initializer)->s;
 
443
  s_count_enter = ((SYNTHESIZE_INITIALIZER *)initializer)->s_count;
 
444
  free(initializer);
 
445
  if (s_count != s_count_enter) return NULL;
 
446
  es_log(2, "synthesize: entering");
 
447
  while (text[text_head])
 
448
  {
 
449
    es_log(2, "synthesize: %d %d", text_head, text_tail);
 
450
    switch ((command = text[text_head++]))
 
451
    {
 
452
    case 1:     /* text */
 
453
      wptr = flite_text_to_wave(text + text_head, v);
 
454
      break;
 
455
    case 2:     /* tone */
 
456
    {
 
457
      int freq, dur, vol;
 
458
      if (sscanf(text + text_head, "%d %d %d", &freq, &dur, &vol) != 3)
 
459
      {
 
460
        es_log(1, "unable to scan tone: %s", text + text_head);
 
461
        break;
 
462
      }
 
463
      wptr = generate_tone(freq, dur, vol);
 
464
      break;
 
465
      }
 
466
    default:
 
467
      /* snafu - I'm getting the hell out of here */
 
468
      es_log(1, "synthesize: internal error: unknown command: %x", text[text_head - 1]);
 
469
      return NULL;
 
470
    }
 
471
    if (time_left > 3 && !just_entered)
 
472
    {
 
473
      es_log(1, "time_left=%f -- going to sleep\n", time_left);
 
474
      usleep(time_left * 750000);
 
475
    }
 
476
    just_entered = 0;
 
477
    if (s_count != s_count_enter)
 
478
    {
 
479
      es_log(2, "synthesize: canceling");
 
480
      cst_wave_free(wptr);
 
481
      return NULL;
 
482
    }
 
483
    es_log(2, "synthesize: %p %p\n", wptr, wptr->samples);
 
484
    es_log(1, "text=%s", text + text_head);
 
485
    while (text[text_head]) text_head++;
 
486
    text_head++;        /* This is not a bug. */
 
487
    pthread_mutex_lock(&text_mutex);
 
488
    if (wave_thread_active)
 
489
    {
 
490
    wml = 1;
 
491
    es_log(2, "synthesize: locking wave mutex");
 
492
      pthread_mutex_lock(&wave_mutex);
 
493
    es_log(2, "synthesize: got wave mutex");
 
494
    }
 
495
    /* Compact buffer if it seems like a good thing to do */
 
496
    if (text_head > (text_size >> 1))
 
497
    {
 
498
      es_log(1, "synthesizer: compacting buffer");
 
499
      memcpy(text, text + text_head, text_tail - text_head + 1);
 
500
      text_tail -= text_head;
 
501
      if (text_synthpos != -1) text_synthpos -= text_head;
 
502
      text_head = 0;
 
503
    }
 
504
    if (ac_size == ac_tail + 1)
 
505
    {
 
506
      es_log(1, "synthesize: allocating more wave memory");
 
507
      ac_size <<= 1;
 
508
      ac = (AUDIO_COMMAND *)realloc(ac, ac_size * sizeof(AUDIO_COMMAND));
 
509
      if (!ac)
 
510
      {
 
511
        fprintf(stderr, "Out of memory, ac_size=%d\n", ac_size);
 
512
        exit(1);
 
513
      }
 
514
    }
 
515
    ac[ac_tail].type = command;
 
516
    ac[ac_tail++].data = wptr;
 
517
    if (text_head == text_tail) ac_synthpos = ac_tail;
 
518
    es_log(2, "synthesize: after adding: %d %d", ac_head, ac_tail);
 
519
    if (wml)
 
520
    {
 
521
      es_log(2, "synthesize: unlocking wave mutex");
 
522
      pthread_mutex_unlock(&wave_mutex);
 
523
      es_log(2, "synthesize: unlocked wave mutex");
 
524
      wml = 0;
 
525
    }
 
526
    if (pas)
 
527
    {
 
528
      es_log(2, "synthesize: pas set, creating play thread");
 
529
      es_log(2, "synthesize: locking wave mutex");
 
530
      pthread_mutex_lock(&wave_mutex);
 
531
      es_log(2, "synthesize: got wave mutex");
 
532
      wave_thread_active = 1;
 
533
      pthread_create(&wave_thread, &ta, play, (void *)s);
 
534
      pthread_mutex_unlock(&wave_mutex);
 
535
      es_log(2, "synthesize: unlocked wave mutex");
 
536
      pas = 0;
 
537
    }
 
538
    pthread_mutex_unlock(&text_mutex);
 
539
  }
 
540
  pthread_mutex_lock(&text_mutex);
 
541
  text_head = text_tail = text_thread_active = 0;
 
542
  pthread_mutex_unlock(&text_mutex);
 
543
  es_log(2, "synthesize: dying: %d %d", ac_head, ac_tail);
 
544
  return NULL;
 
545
}
 
546
 
 
547
/*
 
548
 * ----------------------------------------------------------------------
 
549
 * Copy Text to server. Text is not spoken until a flush command
 
550
 * arrives.
 
551
 * ----------------------------------------------------------------------
 
552
 */
 
553
static void add_command(struct synth_struct *s, int id, unsigned char *buffer)
 
554
{
 
555
  int len;
 
556
 
 
557
  assert(s->state->initialized);
 
558
  len = strlen(buffer);
 
559
  if (text_thread_active) pthread_mutex_lock(&text_mutex);
 
560
  if (text_tail + len + 3 >= text_size)
 
561
  {
 
562
    text_size <<= 1;
 
563
    text = (char *)realloc(text, text_size);
 
564
    if (!text)
 
565
    {
 
566
      fprintf(stderr, "Out of memory: text_size=%d\n", text_size);
 
567
      exit(1);
 
568
    }
 
569
  }
 
570
  text[text_tail++] = (char)id;
 
571
  strcpy(text + text_tail, buffer);
 
572
  text_tail += len + 1;
 
573
  /* The below line is important.  An extra \0 indicates to the synthesize
 
574
     thread that there is no more data. */
 
575
  text[text_tail] = '\0';
 
576
  if (!text_thread_active)
 
577
  {
 
578
    pthread_mutex_init(&text_mutex, NULL);
 
579
    es_log(2, "s_synth: creating new text thread");
 
580
    text_thread_active = 1;
 
581
    ac_synthpos = 0xffff;
 
582
    pthread_create(&text_thread, &ta, synthesize, make_initializer(s, s_count));
 
583
  }
 
584
  else pthread_mutex_unlock(&text_mutex);
 
585
  return;
 
586
}
 
587
 
 
588
static int s_synth(struct synth_struct *s, unsigned char *buffer)
 
589
{
 
590
  add_command(s, 1, buffer);
 
591
  return 0;
 
592
}
 
593
 
 
594
void add_tone_command(struct synth_struct *s, int freq, int dur, int vol)
 
595
{
 
596
  char buf[40];
 
597
 
 
598
  sprintf(buf, "%d %d %d", freq, dur, vol);
 
599
  add_command(s, 2, buf);
 
600
}
 
601
 
 
602
/*
 
603
 * ----------------------------------------------------------------------
 
604
 * Flush synthesizer. This triggers the synthesizer and starts 
 
605
 * the synthesis.
 
606
 * ----------------------------------------------------------------------
 
607
 */
 
608
static int s_flush(synth_t *s)
 
609
{
 
610
  int result;
 
611
 
 
612
  if (text_tail == 0 && ac_tail == 0) return 0;
 
613
  text_synthpos = text_tail;
 
614
  if (!wave_thread_active)
 
615
  {
 
616
    es_log(2, "s_flush: locking wave mutex");
 
617
    pthread_mutex_lock(&wave_mutex);
 
618
    es_log(2, "s_flush: got wave mutex");
 
619
    wave_thread_active = 1;
 
620
    es_log(2, "es_flush: creating play thread");
 
621
    result = pthread_create(&wave_thread, &ta, play, s);
 
622
  pthread_mutex_unlock(&wave_mutex);
 
623
    es_log(2, "s_flush: unlocked wave mutex");
 
624
  return result;
 
625
  }
 
626
    return 0;
 
627
}
 
628
 
 
629
 
 
630
/*
 
631
 * ----------------------------------------------------------------------
 
632
 * Remove anything in the synthesizer speech queue.
 
633
 * ----------------------------------------------------------------------
 
634
 */
 
635
static int s_clear(synth_t *s)
 
636
{
 
637
  int i;
 
638
 
 
639
  es_log(2, "s_clear: text=%d %d, wave=%d %d", text_head, text_tail, ac_head, ac_tail);
 
640
  es_log(2, "s_clear: locking wave mutex");
 
641
  pthread_mutex_lock(&wave_mutex);
 
642
  es_log(2, "s_clear: got wave mutex");
 
643
  if (text_thread_active)
 
644
  {
 
645
    es_log(2, "canceling text thread: %d %d", text_head, text_tail);
 
646
    s_count++;
 
647
  }
 
648
  if (wave_thread_active)
 
649
  {
 
650
    es_log(2, "canceling wave thread: %d %d", ac_head, ac_tail);
 
651
    pthread_cancel(wave_thread);
 
652
  }
 
653
  pthread_mutex_unlock(&wave_mutex);
 
654
  if (audiodev)
 
655
  {
 
656
    audio_drain(audiodev);
 
657
    close_audiodev();
 
658
    usleep(5000);
 
659
  }
 
660
  /* Free any wave data */
 
661
//es_log("s_clear: freeing wave data: %d", ac_tail);
 
662
  for (i = 0; i < ac_tail; i++)
 
663
  {
 
664
    if (ac[i].type != NONE) ac_destroy(&ac[i]);
 
665
  }
 
666
#if 0
 
667
  //es_log(2, "mem=%d", cst_alloc_out);
 
668
#endif
 
669
  text_head = text_tail = text_synthpos = 0;
 
670
  ac_head = ac_tail = ac_synthpos = 0;
 
671
  text_thread_active = wave_thread_active = 0;
 
672
  pas = 0;
 
673
  time_left = 0;
 
674
    return 0;
 
675
}
 
676
 
 
677
 
 
678
#if 0
 
679
/*
 
680
 * ----------------------------------------------------------------------
 
681
 * ToDo
 
682
 * ----------------------------------------------------------------------
 
683
 */
 
684
static int s_index_set(struct synth_struct *s)
 
685
{
 
686
    return 0;
 
687
}
 
688
 
 
689
/*
 
690
 * ----------------------------------------------------------------------
 
691
 * ToDo
 
692
 * ----------------------------------------------------------------------
 
693
 */
 
694
static int s_index_wait(struct synth_struct *s, int id, int timeout)
 
695
{
 
696
    int res = 0;
 
697
    return res;
 
698
}
 
699
#endif
 
700
 
 
701
 
 
702
/*
 
703
 * ----------------------------------------------------------------------
 
704
 * Get a synthesizer parameter.
 
705
 * ----------------------------------------------------------------------
 
706
 */
 
707
static int s_get_param(struct synth_struct *s, synth_par_t par, int *value)
 
708
{
 
709
    if (par >= 0 && par < S_MAX) {
 
710
        *value = s->state->param[par];
 
711
        return 0;
 
712
    } else
 
713
        return 1;
 
714
}
 
715
 
 
716
 
 
717
/*
 
718
 * ----------------------------------------------------------------------
 
719
 * Set a parameter of the synthesizer.
 
720
 * ----------------------------------------------------------------------
 
721
 */
 
722
static int s_set_param(struct synth_struct *s, synth_par_t par, int value)
 
723
{
 
724
    verify_language(s);
 
725
 
 
726
    switch (par) {
 
727
    case S_SPEED:               /* default: 1 */
 
728
        es_log(2, "Setting duration_stretch to %4.3f", (float)1000 / value);
 
729
        feat_set_float(v->features, "duration_stretch", (float)1000 / value);
 
730
        break;
 
731
    case S_PITCH:               /* default: 100 */
 
732
      es_log(2, "Setting pitch to %3.3f", exp((float)value / 1000) * 100 / exp(1));
 
733
        feat_set_float(v->features, "int_f0_target_mean", exp((float)value / 1000) * 100 / exp(1));
 
734
        /* tbd */
 
735
        break;
 
736
    case S_VOLUME:              /* default: 92, range: 0-100 */
 
737
        /* tbd */
 
738
        break;
 
739
    default:
 
740
        return 1;
 
741
    }
 
742
    s->state->param[par] = value;
 
743
 
 
744
    return 0;
 
745
}
 
746
 
 
747
#ifdef STANDALONE
 
748
lang_descr_t languages[LANGUAGES] = {
 
749
    { LANG_BRITISH_ENGLISH, "British English" },
 
750
    { LANG_GERMAN, "German" },
 
751
    { LANG_DUMMY, "no language" }
 
752
};
 
753
 
 
754
lang_t lang =
 
755
{
 
756
  NULL,
 
757
  &languages[0],
 
758
NULL,
 
759
  NULL,
 
760
  0,
 
761
  0,
 
762
  NULL,
 
763
  NULL,
 
764
  NULL,
 
765
  NULL,
 
766
  NULL
 
767
};
 
768
 
 
769
lang_t *language_open(void *context, lookup_string_t lookup)
 
770
{
 
771
  lang.synth = synth_open(context, lookup);
 
772
  return &lang;
 
773
}
 
774
#endif