mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Start work on python wrapper for espeak-ng
This commit is contained in:
parent
18f3a8893a
commit
3dd31eae0b
@ -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";
|
||||||
|
39
src/calibre/utils/tts/espeak.py
Normal file
39
src/calibre/utils/tts/espeak.py
Normal 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))
|
Loading…
x
Reference in New Issue
Block a user