error("Missing 'endphoneme' before end-of-file"); // end of file | error("Missing 'endphoneme' before end-of-file"); // end of file | ||||
break; | break; | ||||
} | } | ||||
if (phoneme_add_feature(phoneme_out, item_string, NULL) == ENS_OK) | |||||
phoneme_feature_t feature = phoneme_feature_from_string(item_string); | |||||
if (phoneme_add_feature(phoneme_out, feature) == ENS_OK) | |||||
continue; | continue; | ||||
error("Bad keyword in phoneme definition '%s'", item_string); | error("Bad keyword in phoneme definition '%s'", item_string); | ||||
continue; | continue; |
return ENS_VERSION_MISMATCH; | return ENS_VERSION_MISMATCH; | ||||
} | } | ||||
espeak_ng_STATUS | |||||
create_name_error_context(espeak_ng_ERROR_CONTEXT *context, | |||||
espeak_ng_STATUS status, | |||||
const char *name) | |||||
{ | |||||
if (context) { | |||||
if (*context) { | |||||
free((*context)->name); | |||||
} else { | |||||
*context = malloc(sizeof(espeak_ng_ERROR_CONTEXT_)); | |||||
if (!*context) | |||||
return ENOMEM; | |||||
} | |||||
(*context)->type = ERROR_CONTEXT_NAME; | |||||
(*context)->name = strdup(name); | |||||
(*context)->version = 0; | |||||
(*context)->expected_version = 0; | |||||
} | |||||
return status; | |||||
} | |||||
#pragma GCC visibility push(default) | #pragma GCC visibility push(default) | ||||
ESPEAK_NG_API void | ESPEAK_NG_API void | ||||
fprintf(out, "Error: %s at '%s' (expected 0x%x, got 0x%x).\n", | fprintf(out, "Error: %s at '%s' (expected 0x%x, got 0x%x).\n", | ||||
error, context->name, context->expected_version, context->version); | error, context->name, context->expected_version, context->version); | ||||
break; | break; | ||||
case ERROR_CONTEXT_NAME: | |||||
fprintf(out, "Error: %s (got \"%s\").\n", error, context->name); | |||||
break; | |||||
} | } | ||||
} else | } else | ||||
fprintf(out, "Error: %s.\n", error); | fprintf(out, "Error: %s.\n", error); |
{ | { | ||||
ERROR_CONTEXT_FILE, | ERROR_CONTEXT_FILE, | ||||
ERROR_CONTEXT_VERSION, | ERROR_CONTEXT_VERSION, | ||||
ERROR_CONTEXT_NAME, | |||||
} espeak_ng_CONTEXT_TYPE; | } espeak_ng_CONTEXT_TYPE; | ||||
typedef struct espeak_ng_ERROR_CONTEXT_ | typedef struct espeak_ng_ERROR_CONTEXT_ | ||||
int version, | int version, | ||||
int expected_version); | int expected_version); | ||||
espeak_ng_STATUS | |||||
create_name_error_context(espeak_ng_ERROR_CONTEXT *context, | |||||
espeak_ng_STATUS status, | |||||
const char *name); | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
#endif | #endif |
#include <espeak-ng/speak_lib.h> | #include <espeak-ng/speak_lib.h> | ||||
#include "phoneme.h" | #include "phoneme.h" | ||||
#include "error.h" | |||||
uint32_t lookup_feature(const char *feature) { | |||||
if (strlen(feature) != 3) | |||||
phoneme_feature_t phoneme_feature_from_string(const char *feature) | |||||
{ | |||||
if (!feature || strlen(feature) != 3) | |||||
return inv; | return inv; | ||||
return (feature[0] << 16) | (feature[1] << 8) | feature[2]; | return (feature[0] << 16) | (feature[1] << 8) | feature[2]; | ||||
} | } | ||||
espeak_ng_STATUS | espeak_ng_STATUS | ||||
phoneme_add_feature(PHONEME_TAB *phoneme, | phoneme_add_feature(PHONEME_TAB *phoneme, | ||||
const char *feature, | |||||
espeak_ng_ERROR_CONTEXT *context) | |||||
phoneme_feature_t feature) | |||||
{ | { | ||||
if (!phoneme || !feature) return EINVAL; | |||||
switch (lookup_feature(feature)) | |||||
if (!phoneme) return EINVAL; | |||||
switch (feature) | |||||
{ | { | ||||
// manner of articulation | // manner of articulation | ||||
case nas: | case nas: | ||||
break; | break; | ||||
// invalid phoneme feature | // invalid phoneme feature | ||||
default: | default: | ||||
return create_name_error_context(context, ENS_UNKNOWN_PHONEME_FEATURE, feature); | |||||
return ENS_UNKNOWN_PHONEME_FEATURE; | |||||
} | } | ||||
return ENS_OK; | return ENS_OK; | ||||
} | } |
#endif | #endif | ||||
// See docs/phonemes.md for the list of supported features. | // See docs/phonemes.md for the list of supported features. | ||||
enum feature_t { | |||||
typedef enum { | |||||
# define FEATURE_T(a, b, c) ((a << 16) | (b << 8) | (c)) | # define FEATURE_T(a, b, c) ((a << 16) | (b << 8) | (c)) | ||||
// invalid phoneme feature name | // invalid phoneme feature name | ||||
inv = 0, | inv = 0, | ||||
fts = FEATURE_T('f', 't', 's'), | fts = FEATURE_T('f', 't', 's'), | ||||
lns = FEATURE_T('l', 'n', 's'), | lns = FEATURE_T('l', 'n', 's'), | ||||
# undef FEATURE_T | # undef FEATURE_T | ||||
}; | |||||
} phoneme_feature_t; | |||||
phoneme_feature_t phoneme_feature_from_string(const char *feature); | |||||
// phoneme types | // phoneme types | ||||
#define phPAUSE 0 | #define phPAUSE 0 | ||||
espeak_ng_STATUS | espeak_ng_STATUS | ||||
phoneme_add_feature(PHONEME_TAB *phoneme, | phoneme_add_feature(PHONEME_TAB *phoneme, | ||||
const char *feature, | |||||
espeak_ng_ERROR_CONTEXT *context); | |||||
phoneme_feature_t feature); | |||||
// Several phoneme tables may be loaded into memory. phoneme_tab points to | // Several phoneme tables may be loaded into memory. phoneme_tab points to | ||||
// one for the current voice | // one for the current voice |