绑定到外部库

模块(Modules)

自定义C++模块 中的Summator示例非常适合小型自定义模块,但如果您想使用更大的外部库,该怎么办? 让我们看一个使用Festival的示例,这是一个用C++编写的语音合成(文本到语音)库。

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

godot/modules/tts/

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

/* tts.h */

#ifndef GODOT_TTS_H
#define GODOT_TTS_H

#include "core/reference.h"

class TTS : public Reference {
    GDCLASS(TTS, Reference);

protected:
    static void _bind_methods();

public:
    bool say_text(String p_txt);

    TTS();
};

#endif // GODOT_TTS_H

然后您将添加cpp文件。

/* tts.cpp */

#include "tts.h"

#include <festival.h>

bool TTS::say_text(String p_txt) {

    //convert Godot String to Godot CharString to C string
    return festival_say_text(p_txt.ascii().get_data());
}

void TTS::_bind_methods() {

    ClassDB::bind_method(D_METHOD("say_text", "txt"), &TTS::say_text);
}

TTS::TTS() {
    festival_initialize(true, 210000); //not the best way to do it as this should only ever be called once.
}

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

register_types.h
register_types.cpp

具有以下内容:

/* register_types.h */

void register_tts_types();
void unregister_tts_types();
/* yes, the word in the middle must be the same as the module folder name */
/* register_types.cpp */

#include "register_types.h"

#include "core/class_db.h"
#include "tts.h"

void register_tts_types() {
    ClassDB::register_class<TTS>();
}

void unregister_tts_types() {
    // Nothing to do here in this example.
}

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

# SCsub

Import('env')

env_tts = env.Clone()
env_tts.add_source_files(env.modules_sources, "*.cpp") # Add all cpp files to the build

您需要在计算机上安装外部库才能获取.a库文件。有关如何为您的操作系统执行此操作的特定说明,请参见库的官方文档。我们在下面包含了Linux的安装命令,以供参考。

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

注解

重要: Festival使用的声音(以及任何其他潜在的外部/第三方资源)均具有不同的许可和使用条款;即使Festival库本身是与MIT许可兼容的,但其中的一些(不是大多数)可能与Godot会有问题。请务必检查许可和使用条款。

外部库也需要安装在模块内部,以使编译器可以访问源文件,同时保持模块代码独立。可以通过 git 使用以下命令从 modules/tts/ 目录中安装 FestivalSpeech_tools 库:

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

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

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

注解

重要: 请注意,Godot存储库中未使用Git子模块。如果要开发将要合并到主Godot存储库中的模块,则不应使用子模块。如果您的模块未合并,则始终可以尝试将外部库实现为GDNative C++插件。

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

env_tts.Append(CPPPATH=["speech_tools/include", "festival/src/include"]) # this is a path relative to /modules/tts/
# http://www.cstr.ed.ac.uk/projects/festival/manual/festival_28.html#SEC132 <-- Festival library documentation
env_tts.Append(LIBPATH=['libpath']) # this is a path relative to /modules/tts/ where your .a library files reside
# You should check with the documentation of the external library to see which library files should be included/linked
env_tts.Append(LIBS=['Festival', 'estools', 'estbase', 'eststring'])

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

# SCsub

Import('env')

env_tts = env.Clone()
env_tts.add_source_files(env.modules_sources, "*.cpp")
env_tts.Append(CCFLAGS=['-O2']) # Flags for C and C++ code
env_tts.Append(CXXFLAGS=['-std=c++11']) # Flags for C++ code only

最终模块应如下所示:

godot/modules/tts/festival/
godot/modules/tts/libpath/libestbase.a
godot/modules/tts/libpath/libestools.a
godot/modules/tts/libpath/libeststring.a
godot/modules/tts/libpath/libFestival.a
godot/modules/tts/speech_tools/
godot/modules/tts/config.py
godot/modules/tts/tts.h
godot/modules/tts/tts.cpp
godot/modules/tts/register_types.h
godot/modules/tts/register_types.cpp
godot/modules/tts/SCsub

使用模块

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

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

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