cmake_minimum_required(VERSION 3.8) | |||||
project(espeak-ng | |||||
VERSION 1.52.0.1 | |||||
DESCRIPTION "open source speech synthesizer that supports more than hundred languages and accents" | |||||
HOMEPAGE_URL "https://github.com/espeak-ng/espeak-ng" | |||||
) | |||||
include(cmake/deps.cmake) | |||||
include(cmake/config.cmake) | |||||
add_subdirectory(src) | |||||
include(cmake/data.cmake) | |||||
option(BUILD_SHARED_LIBS "Build shared libraries" OFF) | |||||
message(STATUS "Configuration:") | |||||
message(STATUS " shared: ${BUILD_SHARED_LIBS}") | |||||
message(STATUS " mbrola: ${USE_MBROLA} (${MBROLA_BIN})") | |||||
message(STATUS " libsonic: ${USE_LIBSONIC} (${SONIC_LIB} ${SONIC_INC})") | |||||
message(STATUS " libpcaudio: ${USE_LIBPCAUDIO} (${PCAUDIO_LIB} ${PCAUDIO_INC})") | |||||
message(STATUS " klatt: ${USE_KLATT}") | |||||
message(STATUS " speech-player: ${USE_SPEECHPLAYER}") | |||||
message(STATUS " async: ${USE_ASYNC}") |
include(CheckSymbolExists) | |||||
check_symbol_exists(mkstemp "stdlib.h" HAVE_MKSTEMP) | |||||
option(USE_MBROLA "Use mbrola for speech synthesis" ${HAVE_MBROLA}) | |||||
option(USE_LIBSONIC "Use libsonit for faster speech rates" ${HAVE_LIBSONIC}) | |||||
option(USE_LIBPCAUDIO "Use libPcAudio for sound output" ${HAVE_LIBPCAUDIO}) | |||||
option(USE_KLATT "Use klatt for speech synthesis" ON) | |||||
option(USE_SPEECHPLAYER "Use speech-player for speech synthesis" ON) | |||||
option(USE_ASYNC "Support asynchronous speech synthesis" ON) |
list(APPEND _dict_compile_list | |||||
af am an ar as az | |||||
ba be bg bn bpy bs | |||||
ca chr cmn cs cv cy | |||||
da de | |||||
el en eo es et eu | |||||
fa fi fr | |||||
ga gd gn grc gu | |||||
hak haw he hi hr ht hu hy | |||||
ia id io is it | |||||
ja jbo | |||||
ka kk kl kn kok ko ku ky | |||||
la lb lfn lt lv | |||||
mi mk ml mr ms mto mt my | |||||
nci ne nl nog no | |||||
om or | |||||
pap pa piqd pl pt py | |||||
qdb quc qu qya | |||||
ro ru | |||||
sd shn si sjn sk sl smj sq sr sv sw | |||||
ta te th tk tn tr tt | |||||
ug uk ur uz | |||||
vi | |||||
yue | |||||
) | |||||
list(APPEND _mbrola_lang_list | |||||
af1 ar1 ar2 | |||||
ca cmn cr1 cs | |||||
de2 de4 de6 de8 | |||||
ee1 en1 es es3 es4 | |||||
fr | |||||
gr1 gr2 grc-de6 | |||||
he hn1 hu1 | |||||
ic1 id1 in ir1 it1 it3 | |||||
jp | |||||
la1 lt | |||||
ma1 mx1 mx2 | |||||
nl nz1 | |||||
pl1 pt1 ptbr ptbr4 | |||||
ro1 | |||||
sv sv2 | |||||
tl1 tr1 | |||||
us us3 | |||||
vz | |||||
) | |||||
set(DATA_DIST_ROOT ${CMAKE_CURRENT_BINARY_DIR}) | |||||
set(DATA_DIST_DIR ${DATA_DIST_ROOT}/espeak-ng-data) | |||||
set(PHONEME_TMP_DIR ${DATA_DIST_ROOT}/phsource) | |||||
set(DICT_TMP_DIR ${DATA_DIST_ROOT}/dictsource) | |||||
set(DATA_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/espeak-ng-data) | |||||
set(PHONEME_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/phsource) | |||||
set(DICT_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/dictsource) | |||||
file(MAKE_DIRECTORY "${DATA_DIST_DIR}") | |||||
file(MAKE_DIRECTORY "${DICT_TMP_DIR}") | |||||
file(COPY "${DATA_SRC_DIR}/lang" DESTINATION "${DATA_DIST_DIR}") | |||||
file(COPY "${DATA_SRC_DIR}/voices/!v" DESTINATION "${DATA_DIST_DIR}/voices") | |||||
file(COPY "${PHONEME_SRC_DIR}" DESTINATION "${DATA_DIST_ROOT}") | |||||
set(ESPEAK_RUN_ENV ${CMAKE_COMMAND} -E env "ESPEAK_DATA_PATH=${DATA_DIST_ROOT}") | |||||
set(ESPEAK_RUN_CMD ${ESPEAK_RUN_ENV} $ENV{VALGRIND} "$<TARGET_FILE:espeak-ng-bin>") | |||||
add_custom_command( | |||||
OUTPUT "${DATA_DIST_DIR}/intonations" | |||||
COMMAND ${ESPEAK_RUN_CMD} --compile-intonations | |||||
WORKING_DIRECTORY "${PHONEME_SRC_DIR}" | |||||
COMMENT "Compile intonations" | |||||
DEPENDS | |||||
"$<TARGET_FILE:espeak-ng-bin>" | |||||
"${PHONEME_SRC_DIR}/intonation" | |||||
) | |||||
set(_phon_deps "") | |||||
function(check_phon_deps _file) | |||||
set(_file "${PHONEME_SRC_DIR}/${_file}") | |||||
list(APPEND _phon_deps "${_file}") | |||||
file(STRINGS "${_file}" _phon_incs REGEX "include .+") | |||||
list(TRANSFORM _phon_incs REPLACE "^[ \t]*include[ \t]+" "") | |||||
foreach(_inc ${_phon_incs}) | |||||
check_phon_deps(${_inc}) | |||||
endforeach(_inc) | |||||
set(_phon_deps ${_phon_deps} PARENT_SCOPE) | |||||
endfunction(check_phon_deps) | |||||
check_phon_deps("phonemes") | |||||
add_custom_command( | |||||
OUTPUT | |||||
"${DATA_DIST_DIR}/phondata" | |||||
"${DATA_DIST_DIR}/phondata-manifest" | |||||
"${DATA_DIST_DIR}/phonindex" | |||||
"${DATA_DIST_DIR}/phontab" | |||||
COMMAND ${ESPEAK_RUN_CMD} --compile-phonemes | |||||
WORKING_DIRECTORY "${PHONEME_SRC_DIR}" | |||||
COMMENT "Compile phonemes" | |||||
DEPENDS | |||||
"$<TARGET_FILE:espeak-ng-bin>" | |||||
${_phon_deps} | |||||
) | |||||
list(APPEND _dict_targets) | |||||
list(APPEND _mbr_targets) | |||||
foreach(_dict_name ${_dict_compile_list}) | |||||
set(_dict_target "${DATA_DIST_DIR}/${_dict_name}_dict") | |||||
set(_dict_deps "") | |||||
list(APPEND _dict_targets ${_dict_target}) | |||||
list(APPEND _dict_deps | |||||
"${DICT_SRC_DIR}/${_dict_name}_rules" | |||||
"${DICT_SRC_DIR}/${_dict_name}_list" | |||||
) | |||||
if(EXISTS "${DICT_SRC_DIR}/extra/${_dict_name}_listx") | |||||
option(EXTRA_${_dict_name} "Compile extra ${_dict_name} dictionary" ON) | |||||
if(EXTRA_${_dict_name}) | |||||
list(APPEND _dict_deps "${DICT_SRC_DIR}/extra/${_dict_name}_listx") | |||||
else() | |||||
file(REMOVE "${DICT_TMP_DIR}/${_dict_name}_listx") | |||||
endif() | |||||
elseif(EXISTS "${DICT_SRC_DIR}/${_dict_name}_listx") | |||||
list(APPEND _dict_deps "${DICT_SRC_DIR}/${_dict_name}_listx") | |||||
endif() | |||||
if(EXISTS "${DICT_SRC_DIR}/${_dict_name}_emoji") | |||||
list(APPEND _dict_deps "${DICT_SRC_DIR}/${_dict_name}_emoji") | |||||
endif() | |||||
add_custom_command( | |||||
OUTPUT "${_dict_target}" | |||||
COMMAND ${CMAKE_COMMAND} -E copy ${_dict_deps} "${DICT_TMP_DIR}/" | |||||
COMMAND ${ESPEAK_RUN_CMD} --compile=${_dict_name} | |||||
WORKING_DIRECTORY "${DICT_TMP_DIR}" | |||||
DEPENDS | |||||
"$<TARGET_FILE:espeak-ng-bin>" | |||||
"${DATA_DIST_DIR}/phondata" | |||||
"${DATA_DIST_DIR}/intonations" | |||||
${_dict_deps} | |||||
) | |||||
endforeach() | |||||
if (HAVE_MBROLA AND USE_MBROLA) | |||||
file(COPY "${DATA_SRC_DIR}/voices/mb" DESTINATION "${DATA_DIST_DIR}/voices") | |||||
file(MAKE_DIRECTORY "${DATA_DIST_DIR}/mbrola_ph") | |||||
foreach(_mbl ${_mbrola_lang_list}) | |||||
set(_mbl_src "${PHONEME_SRC_DIR}/mbrola/${_mbl}") | |||||
set(_mbl_out "${DATA_DIST_DIR}/mbrola_ph/${_mbl}_phtrans") | |||||
list(APPEND _mbr_targets ${_mbl_out}) | |||||
add_custom_command( | |||||
OUTPUT "${_mbl_out}" | |||||
COMMAND ${ESPEAK_RUN_CMD} --compile-mbrola="${_mbl_src}" | |||||
DEPENDS "$<TARGET_FILE:espeak-ng-bin>" "${_mbl_src}" | |||||
) | |||||
endforeach(_mbl) | |||||
endif() | |||||
add_custom_target( | |||||
data ALL | |||||
DEPENDS | |||||
"${DATA_DIST_DIR}/intonations" | |||||
"${DATA_DIST_DIR}/phondata" | |||||
${_dict_targets} | |||||
${_mbr_targets} | |||||
) | |||||
install(DIRECTORY ${DATA_DIST_DIR} DESTINATION share) |
find_library(SONIC_LIB sonic) | |||||
find_path(SONIC_INC "sonic.h") | |||||
find_library(PCAUDIO_LIB pcaudio) | |||||
find_path(PCAUDIO_INC "pcaudiolib/audio.h") | |||||
find_library(PTHREAD_LIB pthread) | |||||
find_program(MBROLA_BIN mbrola) | |||||
include(FetchContent) | |||||
if (PTHREAD_LIB) | |||||
set(HAVE_PTHREAD ON) | |||||
endif(PTHREAD_LIB) | |||||
if (MBROLA_BIN) | |||||
set(HAVE_MBROLA ON) | |||||
endif(MBROLA_BIN) | |||||
if (SONIC_LIB AND SONIC_INC) | |||||
set(HAVE_LIBSONIC ON) | |||||
else() | |||||
FetchContent_Declare(sonic-git | |||||
GIT_REPOSITORY https://github.com/waywardgeek/sonic.git | |||||
GIT_TAG fbf75c3d6d846bad3bb3d456cbc5d07d9fd8c104 | |||||
) | |||||
FetchContent_MakeAvailable(sonic-git) | |||||
FetchContent_GetProperties(sonic-git) | |||||
add_library(sonic OBJECT ${sonic-git_SOURCE_DIR}/sonic.c) | |||||
target_include_directories(sonic PUBLIC ${sonic-git_SOURCE_DIR}) | |||||
set(HAVE_LIBSONIC ON) | |||||
set(SONIC_LIB sonic) | |||||
set(SONIC_INC ${sonic-git_SOURCE_DIR}) | |||||
endif() | |||||
if (PCAUDIO_LIB AND PCAUDIO_INC) | |||||
set(HAVE_LIBPCAUDIO ON) | |||||
endif() |
add_library(espeak-include INTERFACE) | |||||
target_include_directories(espeak-include INTERFACE include include/compat) | |||||
add_subdirectory(ucd-tools) | |||||
add_subdirectory(speechPlayer) | |||||
add_subdirectory(libespeak-ng) | |||||
add_executable(espeak-ng-bin espeak-ng.c) | |||||
set_target_properties(espeak-ng-bin PROPERTIES OUTPUT_NAME espeak-ng) | |||||
target_link_libraries( | |||||
espeak-ng-bin PRIVATE espeak-ng espeak-ng-config | |||||
) | |||||
add_custom_target( | |||||
speak-ng ALL | |||||
${CMAKE_COMMAND} -E create_symlink espeak-ng ${CMAKE_CURRENT_BINARY_DIR}/speak-ng | |||||
COMMENT "Link espeak-ng to speak-ng" | |||||
DEPENDS espeak-ng-bin | |||||
) | |||||
install(TARGETS espeak-ng-bin) | |||||
install(DIRECTORY include/espeak include/espeak-ng TYPE INCLUDE) |
set(ESPEAK_CONFIG_DIR ${CMAKE_CURRENT_BINARY_DIR}/include) | |||||
set(ESPEAK_CONFIG_H ${ESPEAK_CONFIG_DIR}/config.h) | |||||
configure_file(config.h.in ${ESPEAK_CONFIG_H}) | |||||
add_library(espeak-ng-config INTERFACE) | |||||
target_include_directories(espeak-ng-config INTERFACE ${ESPEAK_CONFIG_DIR}) | |||||
add_library(espeak-ng | |||||
common.c | |||||
mnemonics.c | |||||
error.c | |||||
ieee80.c | |||||
compiledata.c | |||||
compiledict.c | |||||
dictionary.c | |||||
encoding.c | |||||
intonation.c | |||||
langopts.c | |||||
numbers.c | |||||
phoneme.c | |||||
phonemelist.c | |||||
readclause.c | |||||
setlengths.c | |||||
soundicon.c | |||||
spect.c | |||||
ssml.c | |||||
synthdata.c | |||||
synthesize.c | |||||
tr_languages.c | |||||
translate.c | |||||
translateword.c | |||||
voices.c | |||||
wavegen.c | |||||
speech.c | |||||
espeak_api.c | |||||
) | |||||
target_compile_options(espeak-ng PRIVATE | |||||
"-fPIC" | |||||
"-fvisibility=hidden" | |||||
"-fno-exceptions" | |||||
"-fwrapv" | |||||
"-pedantic" | |||||
"-Wunused-parameter" | |||||
"-Wunused" | |||||
"-Wuninitialized" | |||||
"-Wreturn-type" | |||||
"-Wmissing-prototypes" | |||||
"-Wint-conversion" | |||||
"-Wimplicit" | |||||
) | |||||
target_compile_definitions(espeak-ng PRIVATE "LIBESPEAK_NG_EXPORT") | |||||
if (USE_ASYNC) | |||||
target_sources(espeak-ng PRIVATE | |||||
event.c | |||||
fifo.c | |||||
espeak_command.c | |||||
) | |||||
endif(USE_ASYNC) | |||||
if (USE_MBROLA) | |||||
target_sources(espeak-ng PRIVATE | |||||
mbrowrap.c | |||||
compilembrola.c | |||||
synth_mbrola.c | |||||
) | |||||
endif(USE_MBROLA) | |||||
if (USE_KLATT) | |||||
target_sources(espeak-ng PRIVATE klatt.c) | |||||
endif(USE_KLATT) | |||||
if (USE_SPEECHPLAYER) | |||||
target_sources(espeak-ng PRIVATE sPlayer.c) | |||||
target_link_libraries(espeak-ng PRIVATE speechPlayer) | |||||
endif(USE_SPEECHPLAYER) | |||||
if (HAVE_LIBSONIC AND USE_LIBSONIC) | |||||
target_link_libraries(espeak-ng PRIVATE ${SONIC_LIB}) | |||||
target_include_directories(espeak-ng PRIVATE ${SONIC_INC}) | |||||
endif() | |||||
if (HAVE_LIBPCAUDIO AND USE_LIBPCAUDIO) | |||||
target_link_libraries(espeak-ng PRIVATE ${PCAUDIO_LIB}) | |||||
target_include_directories(espeak-ng PRIVATE ${PCAUDIO_INC}) | |||||
endif() | |||||
target_link_libraries(espeak-ng PRIVATE espeak-ng-config ucd m) | |||||
target_link_libraries(espeak-ng PUBLIC espeak-include) | |||||
install(TARGETS espeak-ng LIBRARY) |
#cmakedefine01 HAVE_MKSTEMP | |||||
#cmakedefine01 USE_ASYNC | |||||
#cmakedefine01 USE_KLATT | |||||
#cmakedefine01 USE_LIBPCAUDIO | |||||
#cmakedefine01 USE_LIBSONIC | |||||
#cmakedefine01 USE_MBROLA | |||||
#cmakedefine01 USE_SPEECHPLAYER | |||||
#define PACKAGE_VERSION "${PROJECT_VERSION}" |
add_library(speechPlayer STATIC | |||||
src/frame.cpp | |||||
src/speechPlayer.cpp | |||||
src/speechWaveGenerator.cpp | |||||
) | |||||
target_include_directories(speechPlayer PUBLIC include) | |||||
target_compile_options(speechPlayer PRIVATE "-fPIC") | |||||
install(TARGETS speechPlayer ARCHIVE) |
add_library(ucd STATIC | |||||
src/case.c | |||||
src/categories.c | |||||
src/ctype.c | |||||
src/proplist.c | |||||
src/scripts.c | |||||
src/tostring.c | |||||
) | |||||
target_include_directories(ucd PUBLIC src/include) | |||||
install(TARGETS ucd ARCHIVE) |