Start work on python wrapper for espeak-ng

This commit is contained in:
Kovid Goyal 2020-11-14 11:41:54 +05:30
parent 18f3a8893a
commit 3dd31eae0b
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 52 additions and 9 deletions

View File

@ -53,6 +53,15 @@ class pyobject_raii {
static bool initialize_called = false; static bool initialize_called = false;
static PyObject*
terminate(PyObject *self, PyObject *args) {
if (initialize_called) {
espeak_Terminate();
initialize_called = false;
}
Py_RETURN_NONE;
}
static PyObject* static PyObject*
info(PyObject *self, PyObject *args) { info(PyObject *self, PyObject *args) {
const char *path_data; const char *path_data;
@ -208,7 +217,7 @@ int_as_four_bytes(int32_t value, unsigned char *output) {
static PyObject* static PyObject*
create_recording_wav(PyObject *self, PyObject *args) { create_recording_wav(PyObject *self, PyObject *args) {
int buflength = 1000; int buflength = 0;
unsigned int flags = 0; unsigned int flags = 0;
const char *text; const char *text;
Py_ssize_t text_len; Py_ssize_t text_len;
@ -225,7 +234,7 @@ create_recording_wav(PyObject *self, PyObject *args) {
}; };
int_as_four_bytes(rate, wave_hdr + 24); int_as_four_bytes(rate, wave_hdr + 24);
int_as_four_bytes(rate * 2, wave_hdr + 28); int_as_four_bytes(rate * 2, wave_hdr + 28);
PyObject *ret = PyObject_CallFunction(cbdata.data_callback, "s#", wave_hdr, sizeof(wave_hdr)); PyObject *ret = PyObject_CallFunction(cbdata.data_callback, "y#", wave_hdr, sizeof(wave_hdr));
if (!ret) return NULL; if (!ret) return NULL;
Py_DECREF(ret); Py_DECREF(ret);
@ -241,11 +250,11 @@ create_recording_wav(PyObject *self, PyObject *args) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
// Boilerplate {{{ // Boilerplate {{{
#define M(name, args, doc) { #name, (PyCFunction)name, args, ""} #define M(name, args, doc) { #name, (PyCFunction)name, args, ""}
static PyMethodDef methods[] = { static PyMethodDef methods[] = {
M(info, METH_NOARGS, "version and path"), M(info, METH_NOARGS, "version and path"),
M(terminate, METH_NOARGS, "terminate the library"),
M(cancel, METH_NOARGS, "cancel all ongoing speech activity"), M(cancel, METH_NOARGS, "cancel all ongoing speech activity"),
M(synchronize, METH_NOARGS, "synchronize all ongoing speech activity"), M(synchronize, METH_NOARGS, "synchronize all ongoing speech activity"),
M(is_playing, METH_NOARGS, "True iff speech is happening"), M(is_playing, METH_NOARGS, "True iff speech is happening"),
@ -282,12 +291,7 @@ static PyModuleDef_Slot slots[] = { {Py_mod_exec, (void*)exec_module}, {0, NULL}
static struct PyModuleDef module_def = {PyModuleDef_HEAD_INIT}; static struct PyModuleDef module_def = {PyModuleDef_HEAD_INIT};
static void static void
finalize(void*) { finalize(void*) { terminate(NULL, NULL); }
if (initialize_called) {
espeak_Terminate();
initialize_called = false;
}
}
CALIBRE_MODINIT_FUNC PyInit_espeak(void) { CALIBRE_MODINIT_FUNC PyInit_espeak(void) {
module_def.m_name = "espeak"; module_def.m_name = "espeak";

View File

@ -0,0 +1,39 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
def info():
from calibre_extensions.espeak import info
return info()
def create_recording_wav(text, seekable_file_object_or_path, buflength=0, ssml=False, phonemes=False, endpause=False):
import struct
from calibre_extensions.espeak import (
ENDPAUSE, PHONEMES, SSML, create_recording_wav as doit
)
flags = 0
if ssml:
flags |= SSML
if phonemes:
flags |= PHONEMES
if endpause:
flags |= ENDPAUSE
if isinstance(seekable_file_object_or_path, str):
seekable_file_object = open(seekable_file_object_or_path, 'w+b')
else:
seekable_file_object = seekable_file_object_or_path
w = seekable_file_object.write
def write(data):
w(data)
return False
doit(text, write, buflength, flags)
sz = seekable_file_object.tell()
seekable_file_object.seek(4)
seekable_file_object.write(struct.pack('<I', sz - 8))
seekable_file_object.seek(40)
seekable_file_object.write(struct.pack('<I', sz - 44))