Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support new VoiceText API #296

Closed
wants to merge 13 commits into from
1 change: 0 additions & 1 deletion 3rdparty/voice_text/.gitignore

This file was deleted.

66 changes: 45 additions & 21 deletions 3rdparty/voice_text/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,57 +20,81 @@ generate_messages()

catkin_package(CATKIN_DEPENDS message_runtime)

# find voice text headers and libraries
file(GLOB VT_ROOT /usr/vt/*/*)
if(NOT VT_ROOT)
message(WARNING "VoiceText directory should be /usr/vt/*/* (e.g., /usr/vt/sayaka/M16) but is not found")
message(WARNING "VoiceText directory should be /usr/vt/*/* (e.g., /usr/vt/sayaka/M16) but it is not found")
set(VT_ROOT /usr/vt/sayaka/M16) # default value for following configure_file
else()
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
set(VT_LIB_PATH_OLD ${VT_ROOT}/bin/x86_32/RAMIO/libvt_jpn.so) # e.g., /usr/vt/sayaka/M16/bin/x86_32/RAMIO/libvt_jpn.so
set(VT_LIB_PATH_NEW ${VT_ROOT}/bin/LINUX32_GLIBC3/RAMIO/libvt_jpn.so) # e.g., /usr/vt/risa/H16/bin/LINUX32_GLIBC3/RAMIO/libvt_jpn.so
set(VT_LIB_PATH_FILEIO ${VT_ROOT}/bin/FILEIO/LINUX32_GLIBC3/libvt_jpn.so) # e.g., /usr/vt/hikari/D16/bin/FILEIO/LINUX32_GLIBC3/libvt_jpn.so
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
set(VT_LIB_PATH_OLD ${VT_ROOT}/bin/x86_64/RAMIO/libvt_jpn.so) # e.g., /usr/vt/sayaka/M16/bin/x86_64/RAMIO/libvt_jpn.so
set(VT_LIB_PATH_NEW ${VT_ROOT}/bin/LINUX64_GLIBC3/RAMIO/libvt_jpn.so) # e.g., /usr/vt/risa/H16/bin/LINUX64_GLIBC3/RAMIO/libvt_jpn.so
set(VT_LIB_PATH_FILEIO ${VT_ROOT}/bin/FILEIO/LINUX64_GLIBC3/libvt_jpn.so) # e.g., /usr/vt/hikari/D16/bin/FILEIO/LINUX64_GLIBC3/libvt_jpn.so
endif()
if(EXISTS ${VT_LIB_PATH_OLD})
set(VT_LIB_PATH ${VT_LIB_PATH_OLD})
else()
if(EXISTS ${VT_LIB_PATH_NEW})
set(VT_LIB_PATH ${VT_LIB_PATH_NEW})
endif()
elseif(EXISTS ${VT_LIB_PATH_NEW})
set(VT_LIB_PATH ${VT_LIB_PATH_NEW})
elseif(EXISTS ${VT_LIB_PATH_FILEIO})
set(VT_LIB_PATH ${VT_LIB_PATH_FILEIO})
endif()
if(VT_LIB_PATH)
message(WARNING "VoiceText library is found at ${VT_LIB_PATH}")
message(WARNING "VoiceText Engine library is found at ${VT_LIB_PATH}")
else()
message(WARNING "VoiceText library is not found at ${VT_LIB_PATH_OLD} or ${VT_LIB_PATH_NEW}")
message(WARNING "VoiceText Engine library is not found at ${VT_LIB_PATH_OLD} or ${VT_LIB_PATH_NEW} or ${VT_LIB_PATH_FILE}")
endif()
endif()
configure_file(src/voice_text.cpp.in ${PROJECT_SOURCE_DIR}/src/voice_text.cpp)

include_directories(
${Boost_INCLUDE_DIRS}
${catkin_INCLUDE_DIRS}
)
add_executable(voice_text src/voice_text.cpp)
add_dependencies(voice_text ${PROJECT_NAME}_generate_messages_cpp ${PROJECT_NAME}_gencfg)
set_target_properties(voice_text PROPERTIES COMPILE_FLAGS -D_REENTRANT)
# use traditional sdk or new api
set(VT_SDK_H ${VT_ROOT}/inc/vt_jpn.h)
set(VT_API_H ${VT_ROOT}/inc/vtapi.h)
if(EXISTS ${VT_SDK_H})
# use traditional sdk
message(WARNING "Using SDK because ${VT_SDK_H} was found.")
set(VT_INCLUDE ${VT_SDK_H})
elseif(EXISTS ${VT_API_H})
# use new api
message(WARNING "Using API because ${VT_SDK_H} was not found but ${VT_API_H} was found.")
string(REPLACE "/" ";" _VT_ROOT_SPLIT ${VT_ROOT})
list(GET _VT_ROOT_SPLIT 3 VT_SPEAKER)
list(GET _VT_ROOT_SPLIT 4 VT_TYPE)
set(VT_API_LIB_PATH ${VT_ROOT}/bin/libvtapi.so)
set(VT_INCLUDE ${VT_API_H})
set(VT_BIN ${VT_ROOT}/bin)
endif()

if(NOT VT_LIB_PATH)
include_directories(
${Boost_INCLUDE_DIRS}
${catkin_INCLUDE_DIRS}
)
add_executable(voice_text src/voice_text.cpp)
add_dependencies(voice_text ${PROJECT_NAME}_generate_messages_cpp ${PROJECT_NAME}_gencfg)
set_target_properties(voice_text PROPERTIES COMPILE_FLAGS -D_REENTRANT)

# build with voice_text engint or dummy
if(VT_LIB_PATH)
message(WARNING "Building with Voice Text library")
set(BUILD_FLAGS "-DVT_ROOT=${VT_ROOT} -DVT_INCLUDE=${VT_INCLUDE} -DVT_SPEAKER=${VT_SPEAKER} -DVT_TYPE=${VT_TYPE}")
set_target_properties(voice_text PROPERTIES COMPILE_OPTIONS ${BUILD_FLAGS})
else()
message(WARNING "Building dummy library")
add_library(vt_dummy src/dummy/vt_dummy.cpp)
set_target_properties(vt_dummy PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
set_target_properties(vt_dummy PROPERTIES LIBRARY_OUTPUT_NAME vt_jpn)
set_target_properties(voice_text PROPERTIES COMPILE_FLAGS -DUSE_DUMMY_INCLUDE)
set(VT_LIB_PATH ${PROJECT_BINARY_DIR}/libvt_jpn.so)
add_dependencies(voice_text vt_dummy)
endif()

target_link_libraries(voice_text
target_link_libraries(voice_text
${catkin_LIBRARIES}
${VT_LIB_PATH} -lm -lpthread
)
if(NOT EXISTS ${VT_LIB_PATH})
add_dependencies(voice_text vt_dummy)
endif()
${VT_API_LIB_PATH} -lm -lpthread -ldl
)

install(TARGETS voice_text # do not install vt_dummy target, that should be installed from voice_text library
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
Expand Down
20 changes: 17 additions & 3 deletions 3rdparty/voice_text/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,23 @@ ROS Interface for HOYA VoiceText Speech Synthesis Engine

## Installation

1. Install VoiceText SDK
2. Put license file
3. Build this package
### 1. Install VoiceText SDK
#### If you have voicetext sdk install binary, please follow the official guide and install both engine and SDK
#### If you don't have the sdk install binary but have voice text API binary, please follow the guide below.
1. Install VoiceText Engine by official guide
2. Copy VoiceText API binaries to VoiceText binary directory
VoiceText API package includes binary libraries and header file. You have to copy those of them to specific directory by executing following commands.
```bash
cd /path_to_api_package_directory # e.g. cd ~/Downloads/RS_VTAPI_SDK_Linux_4.3.0.2/20201113_VTAPI4.3.0.2_LINUX
cd bin/x64 # You have to cd x86 if your system is x86 architecture
# Assuming VoiceText engine's talker is hikari, type is D16. If it is different, please set appropriate directory.
sudo cp -a * /usr/vt/hikari/D16/bin # Don't forget to add -a not to break symbolic link.
cd ../../include/
sudo mkdir /usr/vt/hikari/D16/inc # not include, but inc
sudo cp vtapi.h /usr/vt/hikari/D16/inc
```
### 2. Put license file
### 3. Build this package

```bash
cd /path/to/catkin_workspace
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#ifdef USE_DUMMY_INCLUDE
#include "dummy/vt_dummy.h"
#else
#include "@VT_ROOT@/inc/vt_jpn.h"
#include VT_INCLUDE
#endif

#define PATH_MAX 1024
Expand All @@ -34,7 +34,11 @@ class VoiceText {
typedef voice_text::VoiceTextConfig Config;

VoiceText() : nh_(), pnh_("~"), db_path_(""), license_path_(""), dyn_srv_(pnh_) {
pnh_.param<std::string>("db_path", db_path_, "@VT_ROOT@");
#ifdef USE_DUMMY_INCLUDE
pnh_.param<std::string>("db_path", db_path_, "dummy");
#else
pnh_.param<std::string>("db_path", db_path_, VT_ROOT);
#endif
pnh_.setParam("db_path", db_path_); // for backward compatibility (db_path is usually set previously)
pnh_.param<std::string>("license_path", license_path_, "");

Expand All @@ -45,7 +49,13 @@ class VoiceText {

~VoiceText() {
if (initialized_) {
#ifdef _VTAPI_H_
VTAPI_ReleaseHandle(this->hVTAPI);
VTAPI_UnloadEngine(this->hEngine);
VTAPI_Exit();
#else
VT_UNLOADTTS_JPN(-1);
#endif
}
}

Expand All @@ -64,9 +74,23 @@ class VoiceText {
license_path_char = (char*)calloc(std::strlen(license_path_.c_str())+1, sizeof(char));
std::strcpy(license_path_char, license_path_.c_str());
}
#ifdef _VTAPI_H_
VTAPI_Init(VT_BIN); // set voice_text binary library path because it loads them dynamically
this->hVTAPI = VTAPI_CreateHandle();
if (this->hVTAPI == 0) {
ROS_ERROR("VoiceText API ERROR when creating API handler. : %s\n", VTAPI_GetLastErrorInfo(0)->szMsg);
return false;
}
VTAPI_SetLicenseFolder(license_path_char);
// Load engine
this->hEngine = VTAPI_GetEngine(VT_SPEAKER, VT_TYPE);
ret = VTAPI_SetEngineHandle(this->hVTAPI, this->hEngine);
if(ret < VTAPI_SUCCESS){
ROS_ERROR("VoiceText API ERROR when creating engine handler. CODE: %d, MESSAGE: %s \n", ret, VTAPI_GetLastErrorInfo(this->hVTAPI)->szMsg);
return false;
}
#else
ret = VT_LOADTTS_JPN((int)NULL, -1, db_path_char, license_path_char);
free(db_path_char);
if (!license_path_.empty()) free(license_path_char);
if (ret != VT_LOADTTS_SUCCESS) {
ROS_FATAL("Failed to load TTS engine (code %d)", ret);
if (ret == -1) {
Expand Down Expand Up @@ -101,6 +125,10 @@ class VoiceText {
VT_GetTTSInfo_JPN(VT_CODEPAGE, NULL, &ret, sizeof(int));
sprintf(szTmp2, "VT_GetTTSInfo_JPN(VT_CODEPAGE = %d\n", ret);
ROS_INFO_STREAM(szTmp2);
#endif

free(db_path_char);
if (!license_path_.empty()) free(license_path_char);

// advertise service
srv_ = nh_.advertiseService("text_to_speech", &VoiceText::text_to_speech, this);
Expand Down Expand Up @@ -130,6 +158,27 @@ class VoiceText {
char* wave_char = (char*)calloc(std::strlen(req.wave_path.c_str())+1, sizeof(char));
std::strcpy(wave_char, req.wave_path.c_str());

#ifdef _VTAPI_H_
int ret;
// set attributes
VTAPI_SetAttr(this->hVTAPI, ATTR_PITCH, config_.pitch);
VTAPI_SetAttr(this->hVTAPI, ATTR_SPEED, config_.speed);
VTAPI_SetAttr(this->hVTAPI, ATTR_VOLUME, config_.volume);
VTAPI_SetAttr(this->hVTAPI, ATTR_PAUSE, config_.pause);
ret = VTAPI_SetOutputFile(this->hVTAPI, wave_char, FORMAT_16PCM_WAV);
if(ret != VTAPI_SUCCESS){
ROS_ERROR("VoiceText API ERROR when executing VTAPI_SetOutputFile. STATUS: %s\n", VTAPI_GetLastErrorInfo(this->hVTAPI)->szMsg);
res.ok = false;
}
// set input text file path
ret = VTAPI_TextToFile(this->hVTAPI, text_char, -1, TEXT_FORMAT_DEFAULT);
if(ret != VTAPI_SUCCESS){
ROS_ERROR("VoiceText API ERROR when executing VTAPI_TextToFile. STATUS: %s\n", VTAPI_GetLastErrorInfo(this->hVTAPI)->szMsg);
res.ok = false;
}
free(text_char);
free(wave_char);
#else
int ret = VT_TextToFile_JPN(VT_FILE_API_FMT_S16PCM_WAVE,
text_char,
wave_char,
Expand All @@ -144,12 +193,12 @@ class VoiceText {

free(text_char);
free(wave_char);

if (ret != VT_FILE_API_SUCCESS) {
ROS_ERROR("Failed to execute tts: (code: %d)", ret);
res.ok = false;
return true;
}
#endif

res.ok = true;
return true;
Expand All @@ -162,6 +211,10 @@ class VoiceText {
ros::ServiceServer srv_;
bool initialized_;
std::string db_path_, license_path_;
#ifdef _VTAPI_H_
VTAPI_HANDLE hVTAPI;
VTAPI_ENGINE_HANDLE hEngine;
#endif
};

int main(int argc, char** argv) {
Expand Down