绑定到外部库

模块

自定义 C++ 模块 中的Summator例子对于小型自定义的模块来说是非常好, 但是如果想使用一个更大的外部库呢?来看一个使用 Festival 的例子, 这是一个用C++编写的语音合成库(文本到语音).

要绑定到外部库, 请设置类似于Summator示例的模块目录:

  1. godot/modules/tts/

接下来, 您将使用简单的TTS类创建头文件:

  1. /* tts.h */
  2. #ifndef GODOT_TTS_H
  3. #define GODOT_TTS_H
  4. #include "core/reference.h"
  5. class TTS : public Reference {
  6. GDCLASS(TTS, Reference);
  7. protected:
  8. static void _bind_methods();
  9. public:
  10. bool say_text(String p_txt);
  11. TTS();
  12. };
  13. #endif // GODOT_TTS_H

然后您将添加cpp文件.

  1. /* tts.cpp */
  2. #include "tts.h"
  3. #include <festival.h>
  4. bool TTS::say_text(String p_txt) {
  5. //convert Godot String to Godot CharString to C string
  6. return festival_say_text(p_txt.ascii().get_data());
  7. }
  8. void TTS::_bind_methods() {
  9. ClassDB::bind_method(D_METHOD("say_text", "txt"), &TTS::say_text);
  10. }
  11. TTS::TTS() {
  12. festival_initialize(true, 210000); //not the best way to do it as this should only ever be called once.
  13. }

和以前一样, 需要以某种方式注册新类, 因此还需要创建两个文件:

  1. register_types.h
  2. register_types.cpp

重要

这些文件必须在您的模块的顶层文件夹中( SCsubconfig.py 文件旁边), 这样模块才能被正确注册.

这些文件应包含以下内容:

  1. /* register_types.h */
  2. void register_tts_types();
  3. void unregister_tts_types();
  4. /* yes, the word in the middle must be the same as the module folder name */
  1. /* register_types.cpp */
  2. #include "register_types.h"
  3. #include "core/class_db.h"
  4. #include "tts.h"
  5. void register_tts_types() {
  6. ClassDB::register_class<TTS>();
  7. }
  8. void unregister_tts_types() {
  9. // Nothing to do here in this example.
  10. }

接下来, 需要创建一个 SCsub 文件, 以便构建系统编译此模块:

  1. # SCsub
  2. Import('env')
  3. env_tts = env.Clone()
  4. env_tts.add_source_files(env.modules_sources, "*.cpp") # Add all cpp files to the build

你需要在自己的机器上安装该外部库才能获取 .a 库文件。至于如何在你的操作系统中一步步安装,请参考该库的官方文档。作为参考,我们这里包含了用来在 Linux 下安装命令。

  1. sudo apt-get install festival festival-dev <-- Installs festival and speech_tools libraries
  2. apt-cache search festvox-* <-- Displays list of voice packages
  3. sudo apt-get install festvox-don festvox-rablpc16k festvox-kallpc16k festvox-kdlpc16k <-- Installs voices

重要

Festival使用的声音(以及任何其他潜在的外部/第三方资源)都有不同的许可证和使用条款;其中一些(如果不是大多数)可能会对Godot产生问题, 即使Festival库本身是与MIT许可证兼容. 请务必检查许可证和使用条款.

外部库也需要被安装到你的模块之中,这样编译器就可以访问到源代码,保持模块独立于外界环境。可以使用如下的 git 命令从 modules/tts/ 目录安装 festival 和 speech_tools:

  1. git clone https://github.com/festvox/festival
  2. git clone https://github.com/festvox/speech_tools

如果不希望将外部仓库的源文件提交到您的仓库中,您可以通过将它们添加为子模块(从 modules/tts/ 目录中)来链接它们,如下所示:

  1. git submodule add https://github.com/festvox/festival
  2. git submodule add https://github.com/festvox/speech_tools

重要

请注意,Godot 仓库中不使用 Git 的子模块(submodule)功能。如果你希望让自己开发的模块合并入 Godot 主仓库,请不要使用子模块。如果你的模块没法合并进主仓库,那么还是可以尝试把它实现为 GDNative C++ 插件。

要添加供编译器查看的包含目录, 可以将其追加到环境的路径中:

  1. # These paths are relative to /modules/tts/
  2. env_tts.Append(CPPPATH=["speech_tools/include", "festival/src/include"])
  3. # LIBPATH and LIBS need to be set on the real "env" (not the clone)
  4. # to link the specified libraries to the Godot executable.
  5. # This is a path relative to /modules/tts/ where your .a libraries reside.
  6. # If you are compiling the module externally (not in the godot source tree),
  7. # these will need to be full paths.
  8. env.Append(LIBPATH=['libpath'])
  9. # Check with the documentation of the external library to see which library
  10. # files should be included/linked.
  11. env.Append(LIBS=['Festival', 'estools', 'estbase', 'eststring'])

如果要在构建模块时添加自定义编译器标志, 则需要首先克隆 env, 这样它就不会将这些标志添加到整个Godot构建中(这可能会导致错误). 带有自定义标志的示例 SCsub:

  1. # SCsub
  2. Import('env')
  3. env_tts = env.Clone()
  4. env_tts.add_source_files(env.modules_sources, "*.cpp")
  5. # Append CCFLAGS flags for both C and C++ code.
  6. env_tts.Append(CCFLAGS=['-O2'])
  7. # If you need to, you can:
  8. # - Append CFLAGS for C code only.
  9. # - Append CXXFLAGS for C++ code only.

最终模块应如下所示:

  1. godot/modules/tts/festival/
  2. godot/modules/tts/libpath/libestbase.a
  3. godot/modules/tts/libpath/libestools.a
  4. godot/modules/tts/libpath/libeststring.a
  5. godot/modules/tts/libpath/libFestival.a
  6. godot/modules/tts/speech_tools/
  7. godot/modules/tts/config.py
  8. godot/modules/tts/tts.h
  9. godot/modules/tts/tts.cpp
  10. godot/modules/tts/register_types.h
  11. godot/modules/tts/register_types.cpp
  12. godot/modules/tts/SCsub

使用模块

现在, 您可以通过任何脚本使用新创建的模块:

  1. var t = TTS.new()
  2. var script = "Hello world. This is a test!"
  3. var is_spoken = t.say_text(script)
  4. print('is_spoken: ', is_spoken)

如果说出文本, 输出将是 is_spoken:True .