- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我再次问这个问题,因为模组决定关闭我的问题 here作为拷贝,在被询问后的几分钟内(也被否决了!!)。现在我已经经历了所有33 answers被认为是我的解决方案的答案,但它没有帮助。所以我再问一次。
I am trying to build a FreeSWITCH module to add text-to-speech functionality using AWS Polly & the AWS C++ SDK.Dev environment is Debian 8, g++ 4.9.2. AWS C++ SDK is built using instructions here except that I turned off shared libs (produces .a lib files).
AWS C++ 开发工具包是按照建议构建的 here (基本上是带有 C++ 链接的 C++ 代码)。 mod_polly.cpp
是使用 C++ 链接构建的,也可以生成 mod_polly.so
。它确实引用了一些 C 头文件和函数。这是构建为 -
g++ -shared -o mod_polly.so -L/usr/local/lib/ -laws-cpp-sdk-polly -laws-cpp-sdk-core -fPIC -g -ggdb -std=c++11 -Wall -Werror -I/usr/src/freeswitch/src/include/ -I/usr/src/freeswitch/libs/libteletone/src/ mod_polly.cpp
来源如下 -
extern "C" {
#include <switch.h>
}
#include <fstream>
#define BIG_ENDIAN_SYSTEM (*(uint16_t *)"\0\xff" < 0x100)
#define REVERSE_BYTES(...) do for(size_t REVERSE_BYTES=0; REVERSE_BYTES<sizeof(__VA_ARGS__)>>1; ++REVERSE_BYTES)\
((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES],\
((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES],\
((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES];\
while(0)
#include <aws/core/Aws.h>
#include <aws/core/auth/AWSCredentials.h>
#include <aws/core/client/ClientConfiguration.h>
#include <aws/core/utils/Outcome.h>
#include <aws/polly/PollyClient.h>
#include <aws/polly/model/SynthesizeSpeechRequest.h>
#include <aws/polly/model/SynthesizeSpeechResult.h>
#include <aws/polly/model/TextType.h>
#include <aws/polly/model/LanguageCode.h>
#include <aws/polly/model/OutputFormat.h>
#include <aws/polly/model/VoiceId.h>
typedef unsigned long DWORD; // 32-bit unsigned integer
typedef unsigned short WORD; // 16-bit unsigned integer
struct riff // Data Bytes Total
{
char chunkID[4]; // "RIFF" 4 4
DWORD riffSize; // file size - 8 4 8
char typeID[4]; // "WAVE" 4 12
char formatChunkID[4]; // "fmt " 4 16
DWORD formatChunkSize; // 16 bytes 4 20
WORD formatTag; // 2 22
WORD noOfChannels; // 2 24
DWORD samplesPerSec; // 4 28
DWORD bytesPerSec; // 4 32
WORD blockAlign; // 2 34
WORD bitsPerSample; // 2 36
char dataChunkID[4]; // "data" 4 40
DWORD dataChunkSize; // not fixed 4 44
};
static struct {
switch_mutex_t *mutex;
switch_thread_rwlock_t *running_rwlock;
switch_memory_pool_t *pool;
int running;
} process;
static struct {
Aws::Auth::AWSCredentials *credentials;
Aws::Client::ClientConfiguration *config;
Aws::SDKOptions *options;
} globals;
switch_loadable_module_interface_t *MODULE_INTERFACE;
static char *supported_formats[SWITCH_MAX_CODECS] = { 0 };
/* Prototypes */
SWITCH_MODULE_LOAD_FUNCTION(mod_polly_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_polly_shutdown);
SWITCH_MODULE_DEFINITION(mod_polly, mod_polly_load, mod_polly_shutdown, NULL);
// ------------------------------------------------------------------------------------------------------------------
/* Implementation */
std::ostream& operator<<(std::ostream& out, const riff& h)
{
if BIG_ENDIAN_SYSTEM {
struct riff hdr = std::move(h);
REVERSE_BYTES(hdr.riffSize);
REVERSE_BYTES(hdr.formatChunkSize);
REVERSE_BYTES(hdr.formatTag);
REVERSE_BYTES(hdr.noOfChannels);
REVERSE_BYTES(hdr.samplesPerSec);
REVERSE_BYTES(hdr.bytesPerSec);
REVERSE_BYTES(hdr.blockAlign);
REVERSE_BYTES(hdr.bitsPerSample);
REVERSE_BYTES(hdr.dataChunkSize);
return out
.write(hdr.chunkID, 4)
.write((const char *)&hdr.riffSize, 4)
.write(hdr.typeID, 4)
.write(hdr.formatChunkID, 4)
.write((const char *)&hdr.formatChunkSize, 4)
.write((const char *)&hdr.formatTag, 2)
.write((const char *)&hdr.noOfChannels, 2)
.write((const char *)&hdr.samplesPerSec, 4)
.write((const char *)&hdr.bytesPerSec, 4)
.write((const char *)&hdr.blockAlign, 2)
.write((const char *)&hdr.bitsPerSample, 2)
.write(hdr.dataChunkID, 4)
.write((const char *)&hdr.dataChunkSize, 4);
} else {
return out
.write(h.chunkID, 4)
.write((const char *)&h.riffSize, 4)
.write(h.typeID, 4)
.write(h.formatChunkID, 4)
.write((const char *)&h.formatChunkSize, 4)
.write((const char *)&h.formatTag, 2)
.write((const char *)&h.noOfChannels, 2)
.write((const char *)&h.samplesPerSec, 4)
.write((const char *)&h.bytesPerSec, 4)
.write((const char *)&h.blockAlign, 2)
.write((const char *)&h.bitsPerSample, 2)
.write(h.dataChunkID, 4)
.write((const char *)&h.dataChunkSize, 4);
}
}
riff init_pcm_header(std::ostream& in)
{
// get length of file
in.seekp(0, in.end);
DWORD sz = in.tellp();
in.seekp(0, in.beg);
struct riff result = {
{'R','I','F','F'}, // chunkID
sz + 0x24, // riffSize (size of stream + 0x24) or (file size - 8)
{'W','A','V','E'}, // typeID
{'f','m','t',' '}, // formatChunkID
16, // formatChunkSize
1, // formatTag (PCM)
1, // noOfChannels (mono)
8000, // samplesPerSec (8KHz)
16000, // bytesPerSec ((Sample Rate * BitsPerSample * Channels) / 8)
2, // blockAlign ((bits per sample * channels) / 8)
16, // bitsPerSample (multiples of 8)
{'d','a','t','a'}, // dataChunkID
sz // dataChunkSize (sample size)
};
return result;
}
struct voice_sync {
char* session_uuid;
Aws::IOStream *audio_stream;
switch_size_t blockAlign;
};
typedef struct voice_sync voice_sync_t;
static switch_status_t polly_file_open(switch_file_handle_t *handle, const char *path)
{
voice_sync_t *sync_info = (voice_sync_t*)malloc(sizeof(voice_sync_t));
sync_info->audio_stream = new Aws::StringStream(std::ios::in | std::ios::out | std::ios::binary);
handle->private_info = sync_info;
handle->samplerate = 8000;
handle->channels = 1;
handle->pos = 0;
handle->format = 0;
handle->sections = 0;
handle->seekable = 0;
handle->speed = 0.5;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "submitting text [%s] to polly", path);
Aws::Polly::PollyClient polly_client(*globals.credentials, *globals.config);
Aws::Polly::Model::SynthesizeSpeechRequest request;
request.SetLanguageCode(Aws::Polly::Model::LanguageCode::en_US);
request.SetOutputFormat(Aws::Polly::Model::OutputFormat::pcm);
request.SetSampleRate("8000");
request.SetTextType(Aws::Polly::Model::TextType::text); // or ssml
request.SetVoiceId(Aws::Polly::Model::VoiceId::Matthew);
request.SetText(path);
if (handle->params) {
// get the session UUID for this channel
// note: this doesnt fire for a standard call session in the audio context; is there a way to make sure it is there?
const char *uuid = switch_event_get_header(handle->params, "session");
if (!zstr(uuid)) {
sync_info->session_uuid = switch_core_strdup(handle->memory_pool, uuid);
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(sync_info->session_uuid), SWITCH_LOG_DEBUG, "Polly linked to session %s\n", sync_info->session_uuid);
}
}
sync_info->audio_stream->clear();
// sync_info->audio_stream.open(filename.c_str(), std::ios::out | std::ios::binary);
auto outcome = polly_client.SynthesizeSpeech(request);
// Output operation status
if (outcome.IsSuccess()) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "received audio response for %s", request.GetServiceRequestName());
Aws::Polly::Model::SynthesizeSpeechResult& result = ((Aws::Polly::Model::SynthesizeSpeechResult&)(outcome));
Aws::IOStream* audio_stream = &result.GetAudioStream();
// this is raw PCM so we need to add a wav header!
riff header = init_pcm_header(*audio_stream);
*sync_info->audio_stream << header;
// tansfer audio data into stream
*sync_info->audio_stream << audio_stream->rdbuf();
sync_info->audio_stream->seekp(0, sync_info->audio_stream->beg);
// update handle information about audio stream
handle->samplerate = header.samplesPerSec;
handle->channels = header.noOfChannels;
handle->format = header.formatTag;
handle->duration = header.dataChunkSize / header.bytesPerSec +1;
handle->samples_in = header.dataChunkSize / header.blockAlign +1;
sync_info->blockAlign = header.blockAlign;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "polly audio stream ready; duration: %ld secs", handle->duration);
return SWITCH_STATUS_SUCCESS;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "something went wrong retrieving audio from polly");
return SWITCH_STATUS_FALSE;
}
static switch_status_t polly_file_close(switch_file_handle_t *handle)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "closiing polly audio stream");
voice_sync_t *sync_info = (voice_sync_t*)handle->private_info;
//sync_info->audio_stream->close(); -- doesnt exist on stringstream
delete sync_info->audio_stream;
if (sync_info->session_uuid) {
switch_safe_free(sync_info->session_uuid);
}
switch_safe_free(sync_info);
handle->private_info = NULL;
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t polly_file_read(switch_file_handle_t *handle, void *data, size_t *len)
{
voice_sync_t *sync_info = (voice_sync_t*)handle->private_info;
switch_size_t bytes;
sync_info->audio_stream->read((char *)data, *len * sync_info->blockAlign);
if ((bytes = sync_info->audio_stream->gcount()) <= 0) {
return SWITCH_STATUS_FALSE;
}
*len = bytes / sync_info->blockAlign;
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_polly_load)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initializing polly audio interface");
supported_formats[0] = (char*)"polly";
/*
switch_application_interface_t *app_interface;
switch_api_interface_t *api_interface;
*/
switch_file_interface_t *file_interface;
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
file_interface = (switch_file_interface_t*)switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
file_interface->interface_name = modname;
file_interface->extens = supported_formats;
file_interface->file_open = polly_file_open;
file_interface->file_close = polly_file_close;
file_interface->file_read = polly_file_read;
MODULE_INTERFACE = *module_interface;
memset(&process, 0, sizeof(process));
memset(&globals, 0, sizeof(globals));
process.pool = pool;
switch_thread_rwlock_create(&process.running_rwlock, pool);
switch_mutex_init(&process.mutex, SWITCH_MUTEX_NESTED, pool);
globals.options = new Aws::SDKOptions();
globals.options->loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Debug;
globals.credentials = new Aws::Auth::AWSCredentials();
globals.credentials->SetAWSAccessKeyId("your aws key");
globals.credentials->SetAWSSecretKey("your aws secret");
globals.config = new Aws::Client::ClientConfiguration();
globals.config->region = "eu-west-1"; // Ireland
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initializing aws api");
Aws::InitAPI(*globals.options);
switch_thread_rwlock_wrlock(process.running_rwlock);
process.running = 1;
switch_thread_rwlock_unlock(process.running_rwlock);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ready to rock!");
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_polly_shutdown)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Shutting down polly polly audio interface");
switch_thread_rwlock_wrlock(process.running_rwlock);
process.running = 0;
switch_thread_rwlock_unlock(process.running_rwlock);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Closing aws api");
Aws::ShutdownAPI(*globals.options);
delete globals.credentials;
delete globals.config;
delete globals.options;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Module shutdown finished");
return SWITCH_STATUS_UNLOAD;
}
现在,当我尝试在 Freeswitch
上加载它时,它会抛出一个错误
2019-07-31 22:00:51.918181 [CRIT] switch_loadable_module.c:1522 Error Loading module /usr/local/freeswitch/mod/mod_polly.so
/usr/local/freeswitch/mod/mod_polly.so: undefined symbol: _ZNK3Aws35AmazonSerializableWebServiceRequest7GetBodyEv
Freeswitch 是在头文件中带有 C++ 保护的 C 代码(外部“C”声明)。
查看 mod_polly.so
中的符号
readelf -Ws mod_polly.so | grep _ZNK3Aws35AmazonSerializableWebServiceRequest7GetBodyEv
66: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _ZNK3Aws35AmazonSerializableWebServiceRequest7GetBodyEv
590: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _ZNK3Aws35AmazonSerializableWebServiceRequest7GetBodyEv
现在我对帖子有了基本的了解here告诉我该符号存在于 so
文件中,但 Freeswitch
无法找到或加载它。
现在这个错误很可能与混合 C/C++ 代码但查看 this 有关和 this没有帮助我弄清楚如何修复它。
我不想构建 Freeswitch
来加载我的模块,我认为我不应该这样做,因为这会使该项目无法扩展。
我在这里错过了什么?
附言:
readelf -Ws libaws-cpp-sdk-core.a | grep AmazonSerializableWebServiceRequest7GetBodyEv
165: 0000000000000000 716 FUNC GLOBAL DEFAULT 42 _ZNK3Aws35AmazonSerializableWebServiceRequest7GetBodyEv
符号在 libaws-cpp-sdk-core.a
中定义,它是 mod_polly.cpp
的编译命令的一部分
最佳答案
@Sam V - 事实证明这是构建时的排序问题。将构建命令的顺序更改为
g++ -shared -o mod_polly.so -fPIC -g -ggdb -std=c++11 -Wall -Werror -I/usr/src/freeswitch/src/include/ -I/usr/src/freeswitch/libs/libteletone/src/ mod_polly.cpp -L/usr/local/lib/ -laws-cpp-sdk-polly -laws-cpp-sdk-core
解决了这个问题。你的第一条评论是关键。谢谢。
关于c++ - 在 Freeswitch 中使用 AWS C++ SDK 加载模块时出现 undefined symbol 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57300756/
我的应用程序从一个有 5 个选项卡的选项卡栏 Controller 开始。一开始,第一个出现了它的名字,但其他四个没有名字,直到我点击它们。然后根据用户使用的语言显示名称。如何在选项卡栏出现之前设置选
我有嵌套数组 json 对象(第 1 层、第 2 层和第 3 层)。我的问题是数据表没有出现。任何相关的 CDN 均已导入。该表仅显示部分。我引用了很多网站,但都没有解决我的问题。 之前我使用标准表来
我正在尝试设置要显示的 Parse PFLoginViewController。这是我的一个 View Controller 的类。 import UIKit import Parse import
我遇到了这个问题,我绘制的对象没有出现在 GUI 中。我知道它正在被处理,因为数据被推送到日志文件。但是,图形没有出现。 这是我的一些代码: public static void main(Strin
我有一个树状图,其中包含出现这样的词...... TreeMap occurrence = new TreeMap (); 字符串 = 单词 整数 = 出现次数。 我如何获得最大出现次数 - 整数,
因此,我提示用户输入变量。如果变量小于 0 且大于 10。如果用户输入 10,我想要求用户再次输入数字。我问时间的时候输入4,它说你输入错误。但在第二次尝试时效果很好。例如:如果我输入 25,它会打印
我已经用 css overflow 属性做了一个例子。在这个例子中我遇到了一个溢出滚动的问题。滚动条出现了,但没有工作意味着每当将光标移动到滚动条时,在这个滚动条不活动的时间。我对此一无所知,所以请帮
我现在正在做一个元素。当您单击一个元素时,会出现以下信息,我想知道如何在您单击下一个元素而不重新单击同一元素时使其消失....例如,我的元素中有披萨,我想单击肉披萨看到浇头然后点击奶酪披萨看到浇头和肉
我有一个路由器模块,它将主题与正则表达式进行比较,并将出现的事件与一致的键掩码链接起来。 (它是一个简单的 url 路由过滤,如 symfony http://symfony.com/doc/curr
这个问题在这里已经有了答案: 9年前关闭。 Possible Duplicate: mysql_fetch_array() expects parameter 1 to be resource, bo
我在底部有一个带有工具栏的 View ,我正在使用 NavigationLink 导航到该 View 。但是当 View 出现时,工具栏显示得有点太低了。大约半秒钟后,它突然跳到位。它只会在应用程序启
我试图在我的应用程序上为背景音乐添加一个 AVAudioPlayer,我正在主屏幕上启动播放器,尝试在应用程序打开时开始播放但出现意外行为... 它播放并立即不断创建新玩家并播放这些玩家,因此同时播放
这是获取一个数字,获取其阶乘并将其加倍,但是由于基本情况,如果您输入 0,它会给出 2 作为答案,因此为了绕过它,我使用了 if 语句,但收到错误输入“if”时解析错误。如果你们能提供帮助,我真的很感
暂停期间抛出异常 android.os.DeadObjectException 在 android.os.BinderProxy.transactNative( native 方法) 在 androi
我已经为猜词游戏编写了一些代码。它从用户输入中读取字符并在单词中搜索该字符;根据字符是否在单词中,程序返回并控制一些变量。 代码如下: import java.util.Random; import
我是自动化领域的新手。这是我的简单 TestNG 登录代码,当我以 TestNG 身份运行该代码时,它会出现 java.lang.NullPointerException,双击它会突出显示我导航到 U
我是c#程序员,我习惯了c#的封装语法和其他东西。但是现在,由于某些原因,我应该用java写一些东西,我现在正在练习java一天!我要创建一个为我自己创建一个虚拟项目,以便让自己更熟悉 Java 的
我正在使用 Intellij,我的源类是 main.com.coding,我的资源文件是 main.com.testing。我将 spring.xml 文件放入资源文件中。 我的测试类位于 test.
我想要我的tests folder separate到我的应用程序代码。我的项目结构是这样的 myproject/ myproject/ myproject.py moduleon
这个问题已经有答案了: What is a NullPointerException, and how do I fix it? (12 个回答) 已关闭 6 年前。 因此,我尝试比较 2 个值,一个
我是一名优秀的程序员,十分优秀!