diff --git a/3rdparty/aques_talk/CMakeLists.txt b/3rdparty/aques_talk/CMakeLists.txt index 56143108f..cd2da2356 100644 --- a/3rdparty/aques_talk/CMakeLists.txt +++ b/3rdparty/aques_talk/CMakeLists.txt @@ -1,71 +1,49 @@ -cmake_minimum_required(VERSION 2.4.6) -include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake) +cmake_minimum_required(VERSION 2.8.3) +project(aques_talk) -# Set the build type. Options are: -# Coverage : w/ debug symbols, w/o optimization, w/ code-coverage -# Debug : w/ debug symbols, w/o optimization -# Release : w/o debug symbols, w/ optimization -# RelWithDebInfo : w/ debug symbols, w/ optimization -# MinSizeRel : w/o debug symbols, w/ optimization, stripped binaries -#set(ROS_BUILD_TYPE RelWithDebInfo) +find_package(catkin REQUIRED) -rosbuild_init() +catkin_package() -#set the default path for built executables to the "bin" directory -set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) -#set the default path for built libraries to the "lib" directory -set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) - -#uncomment if you have defined messages -#rosbuild_genmsg() -#uncomment if you have defined services -#rosbuild_gensrv() - -# Generate the file foo -# Create a target that depends on the generation of foo -#add_custom_command( -# OUTPUT include/AquesTalk2.h -# COMMAND mkdir -p include && cp $(SOURCE_DIR)/lib64/*.h include -# ) -#add_custom_target(include_target DEPENDS include/AquesTalk2.h) -#add_dependencies(rosbuild_precompile include/AquesTalk2.h) - -#common commands for building c++ executables and libraries -#rosbuild_add_library(${PROJECT_NAME} src/example.cpp) -#target_link_libraries(${PROJECT_NAME} another_library) -#rosbuild_add_boost_directories() -#rosbuild_link_boost(${PROJECT_NAME} thread) -link_directories(${PROJECT_SOURCE_DIR}/lib) -rosbuild_add_executable(SampleTalk src/SampleTalk.c) -target_link_libraries(SampleTalk AquesTalk2) - -if(${CMAKE_SYSTEM_PROCESSOR} MATCHES x86_64* ) +# Considering the use of docker in addition to the usual use, +# we use dpkg-architecture command instead of ${CMAKE_SYSTEM_PROCESSOR} to get the architecture. +# https://stackoverflow.com/a/58222507 +# http://manpages.ubuntu.com/manpages/bionic/man1/dpkg-architecture.1.html +execute_process(COMMAND dpkg-architecture -qDEB_HOST_GNU_CPU OUTPUT_VARIABLE ARCHITECTURE) +if("${ARCHITECTURE}" MATCHES x86_64* ) set(AQTK2_LNX_LIB_DIR "lib64") else () set(AQTK2_LNX_LIB_DIR "lib") endif () # -rosbuild_download_data(http://www.a-quest.com/download/package/aqtk2-lnx-eva_210.zip build/aqtk2-lnx-eva_210.zip 68029448ecf4d36337e754c6eb3bb5d8) -# Generate the file foo -add_custom_command( - OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/include/AquesTalk2.h - COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && - unzip -u build/aqtk2-lnx-eva_210.zip -d build && - mkdir -p include lib phont && - cp build/aqtk2-lnx-eva/${AQTK2_LNX_LIB_DIR}/*.h include && - cp build/aqtk2-lnx-eva/${AQTK2_LNX_LIB_DIR}/libAquesTalk2Eva.so.2.1 lib/libAquesTalk2.so.2 && - (cd lib && ln -sf libAquesTalk2.so.2 libAquesTalk2.so ) && - cp -r build/aqtk2-lnx-eva/phont ./ - DEPENDS build/aqtk2-lnx-eva_210.zip - ) -# Create a target that depends on the generation of foo -add_custom_target(include_target DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/include/AquesTalk2.h) +include(ExternalProject) +externalproject_add(aqtk2-lnx-eva + PREFIX download + URL https://www.a-quest.com/archive/package/aqtk2-lnx-eva_230.zip + TIMEOUT 120 + CONFIGURE_COMMAND bash -c "echo configure" + BUILD_COMMAND bash -c "(cd ${AQTK2_LNX_LIB_DIR} && ln -sf libAquesTalk2Eva.so.2.3 libAquesTalk2.so && ln -sf libAquesTalk2Eva.so.2.3 libAquesTalk2.so.2)" + INSTALL_COMMAND bash -c "cp -P ${AQTK2_LNX_LIB_DIR}/libAquesTalk2* ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_LIB_DESTINATION} && cp phont/* ${CMAKE_CURRENT_SOURCE_DIR}/phont/" + BUILD_IN_SOURCE 1 +) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}/download/src/aqtk2-lnx-eva/${AQTK2_LNX_LIB_DIR}) +link_directories(${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_LIB_DESTINATION}) +# compile SampleTalk +add_executable(SampleTalk src/SampleTalk.c) +target_link_libraries(SampleTalk AquesTalk2) + # Make compilation depend on our target: -add_dependencies(SampleTalk include_target) +add_dependencies(SampleTalk aqtk2-lnx-eva) +# install +install(FILES text2wave + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) -set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${PROJECT_SOURCE_DIR}/bin;${PROJECT_SOURCE_DIR}/include;${PROJECT_SOURCE_DIR}/lib;${PROJECT_SOURCE_DIR}/phont;${PROJECT_SOURCE_DIR}/wiped;${PROJECT_SOURCE_DIR}/installed") +install(DIRECTORY launch + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} + USE_SOURCE_PERMISSIONS) diff --git a/3rdparty/aques_talk/README.md b/3rdparty/aques_talk/README.md new file mode 100644 index 000000000..f3acb037a --- /dev/null +++ b/3rdparty/aques_talk/README.md @@ -0,0 +1,36 @@ +# aques_talk + +ROS Interface for AqeusTalk2 + +## Usage + +### Launch sound_play with AquesTalk2 Text-to-Speech + +```bash +roslaunch aques_talk aques_talk.launch +``` + +### Say something + +```bash +$ rostopic pub /robotsound_jp sound_play/SoundRequest "{sound: -3, command: 1, volume: 10.0, arg: 'こんにちわ', arg2: ''}" +$ rostopic pub /robotsound_jp sound_play/SoundRequest "{sound: -3, command: 1, volume: 10.0, arg: 'こんにちわピーアールツー', arg2: ''}" +``` + +```python +import rospy +from sound_play.libsoundplay import SoundClient + +rospy.init_node('say_node') + +client = SoundClient(sound_action='robotsound_jp', sound_topic='robotsound_jp') + +client.say('こんにちは') + +# note that +client.say('Hello') +# does not work ! Use +client.say('Hello', voice='en') + + +``` diff --git a/3rdparty/aques_talk/launch/aques_talk.launch b/3rdparty/aques_talk/launch/aques_talk.launch new file mode 100644 index 000000000..8a306d2a5 --- /dev/null +++ b/3rdparty/aques_talk/launch/aques_talk.launch @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + diff --git a/3rdparty/aques_talk/package.xml b/3rdparty/aques_talk/package.xml new file mode 100644 index 000000000..0022ea3c8 --- /dev/null +++ b/3rdparty/aques_talk/package.xml @@ -0,0 +1,19 @@ + + + aques_talk + 2.1.21 + ROS interface aques_talk demo program + + AQUEST Corp, ROS package maintained by Kei Okada + Kei Okada + BSD + http://ros.org/wiki/aques_talk + + catkin + kakasi + nkf + sound_play + + + + diff --git a/3rdparty/aques_talk/phont/.gitignore b/3rdparty/aques_talk/phont/.gitignore new file mode 100644 index 000000000..241e560df --- /dev/null +++ b/3rdparty/aques_talk/phont/.gitignore @@ -0,0 +1,2 @@ +* + diff --git a/3rdparty/aques_talk/src/SampleTalk.c b/3rdparty/aques_talk/src/SampleTalk.c index a23b6c1d7..6c0137da9 100644 --- a/3rdparty/aques_talk/src/SampleTalk.c +++ b/3rdparty/aques_talk/src/SampleTalk.c @@ -71,6 +71,26 @@ int main(int ac, char **av) unsigned char *wav = AquesTalk2_Synthe_Utf8(speak_str, 100, &size, pPhont); if(wav==0) { fprintf(stderr, "ERR %d\n", size); // エラー時は size にエラーコードが返る + switch (size) { + case 100: fprintf(stderr, "その他のエラー\n"); break; + case 101: fprintf(stderr, "メモリ不足\n"); break; + case 102: fprintf(stderr, "音声記号列に未定義の読み記号が指定された\n"); break; + case 103: fprintf(stderr, "韻律データの時間長がマイナスなっている\n"); break; + case 104: fprintf(stderr, "内部エラー(未定義の区切りコード検出)\n"); break; + case 105: fprintf(stderr, "音声記号列に未定義の読み記号が指定された\n"); break; + case 106: fprintf(stderr, "音声記号列のタグの指定が正しくない\n"); break; + case 107: fprintf(stderr, "タグの長さが制限を越えている(または[>]がみつからない)\n"); break; + case 108: fprintf(stderr, "タグ内の値の指定が正しくない\n"); break; + case 109: fprintf(stderr, "WAVE 再生ができない(サウンドドライバ関連の問題)\n"); break; + case 110: fprintf(stderr, "WAVE 再生ができない(サウンドドライバ関連の問題 非同期再生)\n"); break; + case 111: fprintf(stderr, "発声すべきデータがない\n"); break; + case 200: fprintf(stderr, "音声記号列が長すぎる\n"); break; + case 201: fprintf(stderr, "1つのフレーズ中の読み記号が多すぎる\n"); break; + case 202: fprintf(stderr, "音声記号列が長い(内部バッファオーバー1)\n"); break; + case 203: fprintf(stderr, "ヒープメモリ不足\n"); break; + case 204: fprintf(stderr, "音声記号列が長い(内部バッファオーバー1)\n"); break; + } + fprintf(stderr, "Please refer to https://www.a-quest.com/archive/manual/aqtk2_lnx_man.pdf for more info.\n"); return -1; } // Phont データの開放(音声合成が終わったら開放できる) diff --git a/3rdparty/aques_talk/text2wave b/3rdparty/aques_talk/text2wave index 07e3a4ebb..522cf1d10 100755 --- a/3rdparty/aques_talk/text2wave +++ b/3rdparty/aques_talk/text2wave @@ -1,30 +1,41 @@ -#!/bin/bash +#!/usr/bin/env python +# -*- coding: utf-8 -*- -# for festival compaibility -ARGS=`echo $@ | sed 's/\-eval\ ()//' | sed 's/\-eval\ (\(.\+\))\ \(.\+\)$/\2\ \-p\ \1/'` -eval set -- "$ARGS" +import argparse +import os +import rospkg +import rospy +import sys -INPUT_FILE=$1;shift; -OUTPUT_FILE=/tmp/_aques_talk_sound_$$.wav -JPTEXT_FILE=/tmp/_aques_talk_text_$$.txt -PHONT_FILE=aq_f1c.phont -while getopts p:o: OPT -do - case ${OPT} in - "o") - OUTPUT_FILE=${OPTARG};; - "p") - PHONT_FILE=${OPTARG};; - esac -done +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='') + parser.add_argument('-eval', '--evaluate') + parser.add_argument('-o', '--output') + parser.add_argument('text') + args = parser.parse_args() -PHONT_FILE=`rospack find aques_talk`/phont/$PHONT_FILE -PATH=`rospack find aques_talk`/bin:$PATH -nkf -j $INPUT_FILE | kakasi -JH | nkf -w | \ - sed -e 's/,/、/g' | sed -e 's/,/、/g' | \ - sed -e 's/./。/g' | sed -e 's/\./。/g' > \ - $JPTEXT_FILE -cat $JPTEXT_FILE 1>&2 -`rospack find aques_talk`/bin/SampleTalk -p $PHONT_FILE -o $OUTPUT_FILE $JPTEXT_FILE -#rm -f /tmp/_jtalk_{log,input}_$$.* + input_file = args.text + jptext_file = "/tmp/_voice_text_%s.txt"%os.getpid() + output_file = "/tmp/_voice_text_%s.wav"%os.getpid() + phont_file = "aq_f1c.phont" + phont_file ="%s/phont/%s"%(rospkg.RosPack().get_path("aques_talk"), phont_file) + if args.output is not None: + output_file = args.output + if not os.path.exists(input_file): + rospy.logerr("%s not found"%input_file) + sys.exit(1) + + if args.evaluate in ['(en)']: + os.system("/usr/bin/text2wave %s > %s"%(input_file, output_file)) + sys.exit(0) + + # escape invalid code + os.system("nkf -j %s | kakasi -JH | nkf -w | \ + sed -e 's/,/、/g' | sed -e 's/,/、/g' | \ + sed -e 's/./。/g' | sed -e 's/\./。/g' > \ + %s"%(input_file, jptext_file)) + os.system("cat %s 1>&2"%(jptext_file)) + os.system("rosrun aques_talk SampleTalk -p %s -o %s %s"%(phont_file, output_file, jptext_file)) + + os.remove(jptext_file)