| /* |
| * speak_queue.h - Speak queue helper for Speech Dispatcher modules |
| * |
| * Copyright (C) 2007 Brailcom, o.p.s. |
| * Copyright (C) 2019-2021 Samuel Thibault <samuel.thibault@ens-lyon.org> |
| * |
| * This is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2, or (at your option) |
| * any later version. |
| * |
| * This software is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program. If not, see <https://www.gnu.org/licenses/>. |
| * |
| * Based on espeak.c |
| * |
| * @author Lukas Loehrer |
| * Based on ibmtts.c. |
| */ |
| |
| /* |
| * This provides convenience support for pipeline speech synthesis in modules. |
| * |
| * |
| * In summary, a module will look like this: |
| * |
| * int module_init(char **status_info) { |
| * if (mysynth_init()) { |
| * *status_info = "synth initialization failed"; |
| * return -1; |
| * } |
| * mysynth_set_play_callback(mycallback_play); |
| * mysynth_set_mark_callback(mycallback_mark); |
| * mysynth_set_end_callback(mycallback_end); |
| * |
| * if (module_speak_queue_init(queue_size, status_info)) |
| * return -1; |
| * |
| * *status_info = "initialization succeeded"; |
| * } |
| * |
| * int module_speak(gchar *data, size_t bytes, SPDMessageType msgtype) { |
| * if (!module_speak_queue_before_synth()) |
| * return 0; |
| * |
| * switch (msgtype) { |
| * case SPD_MSGTYPE_TEXT: |
| * mysynth_synth(data, bytes); |
| * break; |
| * ... |
| * } |
| * |
| * int mycallback_play(short *wav, int samples) |
| * { |
| * if (module_speak_queue_stop_requested()) { |
| * return STOP; |
| * } |
| * AudioTrack track = { |
| * .samples = wav, |
| * .num_samples = samples, |
| * .bits = ..., |
| * ... |
| * }; |
| * |
| * module_speak_queue_before_play(); |
| * module_speak_queue_add_audio(&track, SPD_AUDIO_LE); |
| * } |
| * |
| * int mycallback_mark(const char *mark) |
| * { |
| * if (module_speak_queue_stop_requested()) { |
| * return STOP; |
| * } |
| * module_speak_queue_before_play(); |
| * module_speak_queue_add_mark(mark); |
| * } |
| * |
| * int mycallback_end(const char *mark) |
| * { |
| * if (module_speak_queue_stop_requested()) { |
| * return STOP; |
| * } |
| * module_speak_queue_before_play(); |
| * module_speak_queue_add_end(); |
| * } |
| * |
| * void module_speak_queue_cancel(void) |
| * { |
| * mysynth_cancel(); |
| * } |
| * |
| * int module_stop(void) { |
| * module_speak_queue_stop(); |
| * } |
| * |
| * int module_pause(void) { |
| * module_speak_queue_pause(); |
| * } |
| * |
| * int module_close(void) { |
| * module_speak_queue_terminate(); |
| * mysynth_terminate(); |
| * module_speak_queue_free(); |
| * } |
| * |
| * |
| * the module_speak_queue_before_synth() call replaces module_report_event_begin(), |
| * the module_speak_queue_add_end() call replaces module_report_event_end(), |
| * the module_speak_queue_stop() call replaces module_report_event_stop() and spd_audio_stop(), |
| * the module_speak_queue_pause() call replaces module_report_event_pause(), |
| * |
| * The principle is that module_speak_queue_init() starts playback threads which |
| * will handle the audio part. The mysynth_synth() call from module_speak() will |
| * periodically callback into mycallback_*(), which just queues audio to the |
| * playback threads, which can thus start playing immediately, without having to |
| * wait for the whole synth to be completed. |
| */ |
| |
| #ifndef __MODULE_UTILS_SPEAK_QUEUE_H |
| #define __MODULE_UTILS_SPEAK_QUEUE_H |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #include <pthread.h> |
| #include <glib.h> |
| |
| #include "spd_audio_plugin.h" |
| |
| extern AudioID *module_audio_id; |
| |
| typedef enum { |
| SPEAK_QUEUE_QET_AUDIO, /* Chunk of audio. */ |
| SPEAK_QUEUE_QET_INDEX_MARK, /* Index mark event. */ |
| SPEAK_QUEUE_QET_SOUND_ICON, /* A Sound Icon */ |
| SPEAK_QUEUE_QET_BEGIN, /* Beginning of speech. */ |
| SPEAK_QUEUE_QET_END, /* Speech completed. */ |
| SPEAK_QUEUE_QET_PAUSE, /* Speech pause. */ |
| SPEAK_QUEUE_QET_STOP, /* Speech stop. */ |
| SPEAK_QUEUE_QET_BROKEN, /* Speech module is broken. */ |
| } speak_queue_entry_type; |
| |
| typedef struct { |
| AudioTrack track; |
| AudioFormat format; |
| } speak_queue_audio_chunk; |
| |
| typedef struct { |
| speak_queue_entry_type type; |
| union { |
| char *markId; |
| speak_queue_audio_chunk audio; |
| char *sound_icon_filename; |
| } data; |
| } speak_queue_entry; |
| |
| /* To be called in module_init after synth initialization, to start playback |
| * threads. */ |
| int module_speak_queue_init(int maxsize, char **status_info); |
| |
| |
| /* To be called from module_speak before synthesizing the voice. */ |
| int module_speak_queue_before_synth(void); |
| |
| |
| /* To be called from the synth callback before looking through its events. */ |
| int module_speak_queue_before_play(void); |
| |
| /* To be called from the synth callback to push different types of events. */ |
| gboolean module_speak_queue_add_audio(const AudioTrack *track, AudioFormat format); |
| gboolean module_speak_queue_add_mark(const char *markId); |
| gboolean module_speak_queue_add_sound_icon(const char *filename); |
| /* To be called on the last synth callback call. */ |
| gboolean module_speak_queue_add_end(void); |
| |
| /* To be called in the synth callback to look for early stopping. */ |
| int module_speak_queue_stop_requested(void); |
| |
| |
| /* To be called from module_stop. */ |
| void module_speak_queue_stop(void); |
| |
| /* To be called from module_pause. */ |
| void module_speak_queue_pause(void); |
| |
| /* To be called first from module_close to terminate audio early. */ |
| void module_speak_queue_terminate(void); |
| |
| /* To be called last from module_close to release resources. */ |
| void module_speak_queue_free(void); |
| |
| /* Can be called early to quickly discard audio */ |
| void module_speak_queue_flush(void); |
| |
| /* To be provided by the module, shall stop the synthesizer, i.e. make |
| * it stop calling the module callback, and thus make the module stop calling |
| * module_speak_queue_add_*. */ |
| void module_speak_queue_cancel(void); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* #ifndef __MODULE_UTILS_SPEAK_QUEUE_H */ |