mirror of
https://github.com/jambonz/freeswitch-modules.git
synced 2026-01-25 02:08:27 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ee08a310a | |||
| d01991ed0f | |||
| eec4df4b77 | |||
| b003ab0875 |
@@ -227,20 +227,21 @@ int AudioPipe::lws_callback(struct lws *wsi,
|
|||||||
// check for text frames to send
|
// check for text frames to send
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(ap->m_text_mutex);
|
std::lock_guard<std::mutex> lk(ap->m_text_mutex);
|
||||||
if (ap->m_metadata.length() > 0) {
|
if (!ap->m_metadata_list.empty()) {
|
||||||
uint8_t buf[ap->m_metadata.length() + LWS_PRE];
|
const std::string& message = ap->m_metadata_list.front();
|
||||||
memcpy(buf + LWS_PRE, ap->m_metadata.c_str(), ap->m_metadata.length());
|
uint8_t buf[message.length() + LWS_PRE];
|
||||||
int n = ap->m_metadata.length();
|
memcpy(buf + LWS_PRE, message.c_str(), message.length());
|
||||||
|
int n = message.length();
|
||||||
int m = lws_write(wsi, buf + LWS_PRE, n, LWS_WRITE_TEXT);
|
int m = lws_write(wsi, buf + LWS_PRE, n, LWS_WRITE_TEXT);
|
||||||
ap->m_metadata.clear();
|
|
||||||
if (m < n) {
|
if (m < n) {
|
||||||
return -1;
|
return -1; // Failed to send the full message
|
||||||
}
|
}
|
||||||
|
|
||||||
// there may be audio data, but only one write per writeable event
|
// Remove the message that was successfully sent
|
||||||
// get it next time
|
ap->m_metadata_list.pop_front();
|
||||||
|
// Request another writable event if there are more messages
|
||||||
lws_callback_on_writable(wsi);
|
lws_callback_on_writable(wsi);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -529,7 +530,7 @@ void AudioPipe::bufferForSending(const char* text) {
|
|||||||
if (m_state != LWS_CLIENT_CONNECTED) return;
|
if (m_state != LWS_CLIENT_CONNECTED) return;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(m_text_mutex);
|
std::lock_guard<std::mutex> lk(m_text_mutex);
|
||||||
m_metadata.append(text);
|
m_metadata_list.emplace_back(text);
|
||||||
}
|
}
|
||||||
addPendingWrite(this);
|
addPendingWrite(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ namespace drachtio {
|
|||||||
std::string m_bugname;
|
std::string m_bugname;
|
||||||
unsigned int m_port;
|
unsigned int m_port;
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
std::string m_metadata;
|
std::list<std::string> m_metadata_list;
|
||||||
std::mutex m_text_mutex;
|
std::mutex m_text_mutex;
|
||||||
std::mutex m_audio_mutex;
|
std::mutex m_audio_mutex;
|
||||||
int m_sslFlags;
|
int m_sslFlags;
|
||||||
|
|||||||
+201
-6
@@ -27,6 +27,8 @@ typedef boost::circular_buffer<uint16_t> CircularBuffer_t;
|
|||||||
#define RTP_PACKETIZATION_PERIOD 20
|
#define RTP_PACKETIZATION_PERIOD 20
|
||||||
#define FRAME_SIZE_8000 320 /*which means each 20ms frame as 320 bytes at 8 khz (1 channel only)*/
|
#define FRAME_SIZE_8000 320 /*which means each 20ms frame as 320 bytes at 8 khz (1 channel only)*/
|
||||||
#define BUFFER_GROW_SIZE (16384)
|
#define BUFFER_GROW_SIZE (16384)
|
||||||
|
#define AUDIO_MARKER 0xFFFF
|
||||||
|
#define MAX_MARKS (30)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
static const char *requestedBufferSecs = std::getenv("MOD_AUDIO_FORK_BUFFER_SECS");
|
static const char *requestedBufferSecs = std::getenv("MOD_AUDIO_FORK_BUFFER_SECS");
|
||||||
@@ -38,6 +40,15 @@ namespace {
|
|||||||
static unsigned int idxCallCount = 0;
|
static unsigned int idxCallCount = 0;
|
||||||
static uint32_t playCount = 0;
|
static uint32_t playCount = 0;
|
||||||
|
|
||||||
|
static bool markCountExceeded(private_t* tech_pvt) {
|
||||||
|
if (nullptr != tech_pvt->pVecMarksInUse) {
|
||||||
|
std::deque<std::string>* pVecMarksInUse = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInUse);
|
||||||
|
std::deque<std::string>* pVecMarksInInventory = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInInventory);
|
||||||
|
return pVecMarksInUse->size()+ pVecMarksInInventory->size() >= MAX_MARKS;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch_status_t processIncomingBinary(private_t* tech_pvt, switch_core_session_t* session, const char* message, size_t dataLength) {
|
switch_status_t processIncomingBinary(private_t* tech_pvt, switch_core_session_t* session, const char* message, size_t dataLength) {
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
|
|
||||||
@@ -65,12 +76,30 @@ namespace {
|
|||||||
// Access the prebuffer
|
// Access the prebuffer
|
||||||
CircularBuffer_t* cBuffer = static_cast<CircularBuffer_t*>(tech_pvt->streamingPreBuffer);
|
CircularBuffer_t* cBuffer = static_cast<CircularBuffer_t*>(tech_pvt->streamingPreBuffer);
|
||||||
|
|
||||||
|
int numMarkers = 0;
|
||||||
|
std::deque<std::string>* pVecMarksInInventory = nullptr;
|
||||||
|
std::deque<std::string>* pVecMarksInUse = nullptr;
|
||||||
|
if (nullptr != tech_pvt->pVecMarksInInventory) {
|
||||||
|
pVecMarksInInventory = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInInventory);
|
||||||
|
pVecMarksInUse = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInUse);
|
||||||
|
numMarkers = pVecMarksInInventory->size();
|
||||||
|
|
||||||
|
// move inventory to in-use
|
||||||
|
pVecMarksInUse->insert(pVecMarksInUse->end(), pVecMarksInInventory->begin(), pVecMarksInInventory->end());
|
||||||
|
pVecMarksInInventory->clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure the prebuffer has enough capacity
|
// Ensure the prebuffer has enough capacity
|
||||||
if (cBuffer->capacity() - cBuffer->size() < numSamples) {
|
if (cBuffer->capacity() - cBuffer->size() < numSamples + numMarkers) {
|
||||||
size_t newCapacity = cBuffer->size() + std::max(numSamples, (size_t)BUFFER_GROW_SIZE);
|
size_t newCapacity = cBuffer->size() + std::max(numSamples + numMarkers, (size_t)BUFFER_GROW_SIZE);
|
||||||
cBuffer->set_capacity(newCapacity);
|
cBuffer->set_capacity(newCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepend any markers
|
||||||
|
while (numMarkers-- > 0) {
|
||||||
|
cBuffer->push_back(AUDIO_MARKER);
|
||||||
|
}
|
||||||
|
|
||||||
// Append the data to the prebuffer
|
// Append the data to the prebuffer
|
||||||
cBuffer->insert(cBuffer->end(), data_uint16, data_uint16 + numSamples);
|
cBuffer->insert(cBuffer->end(), data_uint16, data_uint16 + numSamples);
|
||||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Appended %zu 16-bit samples to the prebuffer.\n", numSamples);
|
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Appended %zu 16-bit samples to the prebuffer.\n", numSamples);
|
||||||
@@ -269,6 +298,63 @@ namespace {
|
|||||||
// this will dump buffered incoming audio
|
// this will dump buffered incoming audio
|
||||||
tech_pvt->clear_bidirectional_audio_buffer = true;
|
tech_pvt->clear_bidirectional_audio_buffer = true;
|
||||||
}
|
}
|
||||||
|
else if (0 == type.compare("mark")) {
|
||||||
|
cJSON* data = cJSON_GetObjectItem(json, "data");
|
||||||
|
if (data) {
|
||||||
|
cJSON* name = cJSON_GetObjectItem(data, "name");
|
||||||
|
if (cJSON_IsString(name) && name->valuestring) {
|
||||||
|
if (markCountExceeded(tech_pvt)) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%u) processIncomingMessage - mark count exceeded, discarding mark %s\n", tech_pvt->id, cJSON_GetStringValue(name));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (nullptr == tech_pvt->pVecMarksInInventory) {
|
||||||
|
tech_pvt->pVecMarksInInventory = static_cast<void *>(new std::deque<std::string>());
|
||||||
|
tech_pvt->pVecMarksInUse = static_cast<void *>(new std::deque<std::string>());
|
||||||
|
tech_pvt->pVecMarksCleared = static_cast<void *>(new std::deque<std::string>());
|
||||||
|
}
|
||||||
|
std::deque<std::string>* pVec = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInInventory);
|
||||||
|
pVec->push_back(name->valuestring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (0 == type.compare("clearMarks")) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%u) processIncomingMessage - received clearMarks\n", tech_pvt->id);
|
||||||
|
if (nullptr != tech_pvt->pVecMarksInInventory) {
|
||||||
|
std::deque<std::string>* pVecMarksInInventory = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInInventory);
|
||||||
|
std::deque<std::string>* pVecMarksInUse = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInUse);
|
||||||
|
std::deque<std::string>* pVecMarksCleared = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksCleared);
|
||||||
|
pVecMarksCleared->insert(pVecMarksCleared->end(), pVecMarksInUse->begin(), pVecMarksInUse->end());
|
||||||
|
pVecMarksCleared->insert(pVecMarksCleared->end(), pVecMarksInInventory->begin(), pVecMarksInInventory->end());
|
||||||
|
pVecMarksInInventory->clear();
|
||||||
|
pVecMarksInUse->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (0 == type.compare("transcription")) {
|
||||||
|
char* jsonString = cJSON_PrintUnformatted(jsonData);
|
||||||
|
tech_pvt->responseHandler(session, EVENT_TRANSCRIPTION, jsonString);
|
||||||
|
free(jsonString);
|
||||||
|
}
|
||||||
|
else if (0 == type.compare("transfer")) {
|
||||||
|
char* jsonString = cJSON_PrintUnformatted(jsonData);
|
||||||
|
tech_pvt->responseHandler(session, EVENT_TRANSFER, jsonString);
|
||||||
|
free(jsonString);
|
||||||
|
}
|
||||||
|
else if (0 == type.compare("disconnect")) {
|
||||||
|
char* jsonString = cJSON_PrintUnformatted(jsonData);
|
||||||
|
tech_pvt->responseHandler(session, EVENT_DISCONNECT, jsonString);
|
||||||
|
free(jsonString);
|
||||||
|
}
|
||||||
|
else if (0 == type.compare("error")) {
|
||||||
|
char* jsonString = cJSON_PrintUnformatted(jsonData);
|
||||||
|
tech_pvt->responseHandler(session, EVENT_ERROR, jsonString);
|
||||||
|
free(jsonString);
|
||||||
|
}
|
||||||
|
else if (0 == type.compare("json")) {
|
||||||
|
char* jsonString = cJSON_PrintUnformatted(json);
|
||||||
|
tech_pvt->responseHandler(session, EVENT_JSON, jsonString);
|
||||||
|
free(jsonString);
|
||||||
|
}
|
||||||
else if (0 == type.compare("transcription")) {
|
else if (0 == type.compare("transcription")) {
|
||||||
char* jsonString = cJSON_PrintUnformatted(jsonData);
|
char* jsonString = cJSON_PrintUnformatted(jsonData);
|
||||||
tech_pvt->responseHandler(session, EVENT_TRANSCRIPTION, jsonString);
|
tech_pvt->responseHandler(session, EVENT_TRANSCRIPTION, jsonString);
|
||||||
@@ -400,6 +486,9 @@ namespace {
|
|||||||
}
|
}
|
||||||
tech_pvt->streamingPreBufSize = 320 * tech_pvt->downscale_factor * 4; // min 80ms prebuffer
|
tech_pvt->streamingPreBufSize = 320 * tech_pvt->downscale_factor * 4; // min 80ms prebuffer
|
||||||
tech_pvt->streamingPreBuffer = (void *) new CircularBuffer_t(8192);
|
tech_pvt->streamingPreBuffer = (void *) new CircularBuffer_t(8192);
|
||||||
|
tech_pvt->pVecMarksInInventory = nullptr;
|
||||||
|
tech_pvt->pVecMarksInUse = nullptr;
|
||||||
|
tech_pvt->pVecMarksCleared = nullptr;
|
||||||
|
|
||||||
strncpy(tech_pvt->bugname, bugname, MAX_BUG_LEN);
|
strncpy(tech_pvt->bugname, bugname, MAX_BUG_LEN);
|
||||||
if (metadata) strncpy(tech_pvt->initialMetadata, metadata, MAX_METADATA_LEN);
|
if (metadata) strncpy(tech_pvt->initialMetadata, metadata, MAX_METADATA_LEN);
|
||||||
@@ -467,6 +556,29 @@ namespace {
|
|||||||
delete cBuffer;
|
delete cBuffer;
|
||||||
tech_pvt->streamingPreBuffer = nullptr;
|
tech_pvt->streamingPreBuffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nullptr == tech_pvt->pVecMarksInInventory) {
|
||||||
|
delete static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInInventory);
|
||||||
|
tech_pvt->pVecMarksInInventory = nullptr;
|
||||||
|
delete static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInUse);
|
||||||
|
tech_pvt->pVecMarksInUse = nullptr;
|
||||||
|
delete static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksCleared);
|
||||||
|
tech_pvt->pVecMarksCleared = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_mark_event(private_t* tech_pvt, const char* name, int cleared = false) {
|
||||||
|
drachtio::AudioPipe *pAudioPipe = static_cast<drachtio::AudioPipe *>(tech_pvt->pAudioPipe);
|
||||||
|
std::ostringstream json;
|
||||||
|
json << "{\"type\": \"mark\", \"data\": {\"name\":\"" << name << "\", ";
|
||||||
|
if (cleared) json << "\"event\": \"cleared\"}}";
|
||||||
|
else json << "\"event\": \"playout\"}}";
|
||||||
|
|
||||||
|
if (pAudioPipe) {
|
||||||
|
std::string str = json.str();
|
||||||
|
pAudioPipe->bufferForSending(str.c_str());
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%u) send_mark_event: %s\n", tech_pvt->id, str.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void lws_logger(int level, const char *line) {
|
void lws_logger(int level, const char *line) {
|
||||||
@@ -826,6 +938,28 @@ extern "C" {
|
|||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%u) dub_speech_frame - clearing buffer\n", tech_pvt->id);
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%u) dub_speech_frame - clearing buffer\n", tech_pvt->id);
|
||||||
cBuffer->clear();
|
cBuffer->clear();
|
||||||
tech_pvt->clear_bidirectional_audio_buffer = false;
|
tech_pvt->clear_bidirectional_audio_buffer = false;
|
||||||
|
|
||||||
|
// send "mark" event for any queued markers
|
||||||
|
if (nullptr != tech_pvt->pVecMarksInInventory) {
|
||||||
|
std::deque<std::string>* pVecMarksInInventory = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInInventory);
|
||||||
|
std::deque<std::string>* pVecMarksInUse = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInUse);
|
||||||
|
if (pVecMarksInInventory->size() + pVecMarksInUse->size() > 0) {
|
||||||
|
std::deque<std::string> vec = *pVecMarksInUse;
|
||||||
|
vec.insert(vec.end(), pVecMarksInInventory->begin(), pVecMarksInInventory->end());
|
||||||
|
for (auto it = vec.begin(); it != vec.end(); ++it) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%u) dub_speech_frame - Marker %s cleared\n",
|
||||||
|
tech_pvt->id, it->c_str());
|
||||||
|
send_mark_event(tech_pvt, it->c_str(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// put the "in-use" ones into the "cleared" queue so we dont notify again when they eventually come through
|
||||||
|
std::deque<std::string>* pVecMarksCleared = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksCleared);
|
||||||
|
pVecMarksCleared->insert(pVecMarksCleared->end(), pVecMarksInUse->begin(), pVecMarksInUse->end());
|
||||||
|
|
||||||
|
pVecMarksInUse->clear();
|
||||||
|
pVecMarksInInventory->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch_frame_t* rframe = switch_core_media_bug_get_write_replace_frame(bug);
|
switch_frame_t* rframe = switch_core_media_bug_get_write_replace_frame(bug);
|
||||||
@@ -841,11 +975,72 @@ extern "C" {
|
|||||||
|
|
||||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%u) dub_speech_frame - samples to copy %u\n", tech_pvt->id, samplesToCopy);
|
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%u) dub_speech_frame - samples to copy %u\n", tech_pvt->id, samplesToCopy);
|
||||||
|
|
||||||
std::copy_n(cBuffer->begin(), samplesToCopy, data);
|
bool hasMarkers = false;
|
||||||
cBuffer->erase(cBuffer->begin(), cBuffer->begin() + samplesToCopy);
|
std::deque<std::string>* pVecInventory = nullptr;
|
||||||
|
std::deque<std::string>* pVecInUse = nullptr;
|
||||||
|
std::deque<std::string>* pVecCleared = nullptr;
|
||||||
|
if (nullptr != tech_pvt->pVecMarksInUse) {
|
||||||
|
pVecInventory = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInInventory);
|
||||||
|
pVecInUse = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksInUse);
|
||||||
|
pVecCleared = static_cast<std::deque<std::string>*>(tech_pvt->pVecMarksCleared);
|
||||||
|
hasMarkers = pVecInUse->size() + pVecCleared->size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (samplesToCopy > 0) {
|
if (hasMarkers) {
|
||||||
vector_add(fp, data, rframe->samples);
|
/* discard markers and send notifications */
|
||||||
|
auto bufferIter = cBuffer->begin();
|
||||||
|
auto dataIter = data;
|
||||||
|
for (int i = 0; i < samplesToCopy; ++i) {
|
||||||
|
if (*bufferIter == AUDIO_MARKER) {
|
||||||
|
// Marker detected, discard it and send a notice unless it was previously cleared
|
||||||
|
auto * pVec = pVecCleared->size() > 0 ? pVecCleared : pVecInUse;
|
||||||
|
if (!pVec->empty()) {
|
||||||
|
auto name = pVec->front();
|
||||||
|
pVec->pop_front();
|
||||||
|
|
||||||
|
if (pVec == pVecInUse) {
|
||||||
|
send_mark_event(tech_pvt, name.c_str());
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%u) dub_speech_frame - Marker %s detected in playout\n",
|
||||||
|
tech_pvt->id, name.c_str());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%u) dub_speech_frame - Marker %s detected in playout but previously cleared\n",
|
||||||
|
tech_pvt->id, name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Copy valid audio samplewhat
|
||||||
|
*dataIter = *bufferIter;
|
||||||
|
++dataIter;
|
||||||
|
}
|
||||||
|
++bufferIter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the processed samples (including discarded markers) from the buffer
|
||||||
|
cBuffer->erase(cBuffer->begin(), cBuffer->begin() + samplesToCopy);
|
||||||
|
|
||||||
|
// Adjust the number of samples copied to the output frame
|
||||||
|
int validSamplesCopied = std::distance(data, dataIter);
|
||||||
|
|
||||||
|
if (validSamplesCopied > 0) {
|
||||||
|
vector_add(fp, data, validSamplesCopied);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::copy_n(cBuffer->begin(), samplesToCopy, data);
|
||||||
|
cBuffer->erase(cBuffer->begin(), cBuffer->begin() + samplesToCopy);
|
||||||
|
|
||||||
|
if (samplesToCopy > 0) {
|
||||||
|
vector_add(fp, data, rframe->samples);
|
||||||
|
} else if (pVecInventory != nullptr && pVecInventory->size()) {
|
||||||
|
// no bidirectional audio to dub but still have some mark in inventory, send them now
|
||||||
|
auto name = pVecInventory->front();
|
||||||
|
pVecInventory->pop_front();
|
||||||
|
|
||||||
|
send_mark_event(tech_pvt, name.c_str());
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%u) dub_speech_frame - Marker %s detected in inventory\n",
|
||||||
|
tech_pvt->id, name.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vector_normalize(fp, rframe->samples);
|
vector_normalize(fp, rframe->samples);
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ struct private_data {
|
|||||||
int graceful_shutdown:1;
|
int graceful_shutdown:1;
|
||||||
char initialMetadata[8192];
|
char initialMetadata[8192];
|
||||||
|
|
||||||
|
// for "mark" feature of bidirectional audio
|
||||||
|
void *pVecMarksInInventory;
|
||||||
|
void *pVecMarksInUse;
|
||||||
|
void *pVecMarksCleared;
|
||||||
|
|
||||||
// bidirectional audio
|
// bidirectional audio
|
||||||
void *streamingPlayoutBuffer;
|
void *streamingPlayoutBuffer;
|
||||||
void *streamingPreBuffer;
|
void *streamingPreBuffer;
|
||||||
|
|||||||
@@ -111,9 +111,6 @@ public:
|
|||||||
if (var = switch_channel_get_variable(channel, "AWS_VOCABULARY_FILTER_METHOD")) {
|
if (var = switch_channel_get_variable(channel, "AWS_VOCABULARY_FILTER_METHOD")) {
|
||||||
m_request.SetVocabularyFilterMethod(VocabularyFilterMethodMapper::GetVocabularyFilterMethodForName(var));
|
m_request.SetVocabularyFilterMethod(VocabularyFilterMethodMapper::GetVocabularyFilterMethodForName(var));
|
||||||
}
|
}
|
||||||
if (var = switch_channel_get_variable(channel, "AWS_LANGUAGE_MODEL_NAME")) {
|
|
||||||
m_request.SetLanguageModelName(var);
|
|
||||||
}
|
|
||||||
switch_core_session_rwunlock(session);
|
switch_core_session_rwunlock(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -378,7 +378,10 @@ switch_status_t playht_parse_text(const std::map<std::string, std::string>& para
|
|||||||
cJSON_AddStringToObject(jResult, "quality", quality.c_str());
|
cJSON_AddStringToObject(jResult, "quality", quality.c_str());
|
||||||
}
|
}
|
||||||
if (!speed.empty()) {
|
if (!speed.empty()) {
|
||||||
cJSON_AddNumberToObject(jResult, "speed", atoi(speed.c_str()));
|
double val = strtod(speed.c_str(), NULL);
|
||||||
|
if (val != 0.0) {
|
||||||
|
cJSON_AddNumberToObject(jResult, "speed", val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!seed.empty()) {
|
if (!seed.empty()) {
|
||||||
cJSON_AddNumberToObject(jResult, "seed", atoi(seed.c_str()));
|
cJSON_AddNumberToObject(jResult, "seed", atoi(seed.c_str()));
|
||||||
|
|||||||
@@ -229,16 +229,6 @@ int AudioPipe::lws_callback(struct lws *wsi,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static members
|
|
||||||
static const lws_retry_bo_t retry = {
|
|
||||||
nullptr, // retry_ms_table
|
|
||||||
0, // retry_ms_table_count
|
|
||||||
0, // conceal_count
|
|
||||||
UINT16_MAX, // secs_since_valid_ping
|
|
||||||
UINT16_MAX, // secs_since_valid_hangup
|
|
||||||
0 // jitter_percent
|
|
||||||
};
|
|
||||||
|
|
||||||
struct lws_context *AudioPipe::context = nullptr;
|
struct lws_context *AudioPipe::context = nullptr;
|
||||||
std::thread AudioPipe::serviceThread;
|
std::thread AudioPipe::serviceThread;
|
||||||
std::mutex AudioPipe::mutex_connects;
|
std::mutex AudioPipe::mutex_connects;
|
||||||
@@ -376,6 +366,28 @@ bool AudioPipe::lws_service_thread() {
|
|||||||
{ NULL, NULL, 0, 0 }
|
{ NULL, NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint16_t secs_sinceq_valid_ping = UINT16_MAX;
|
||||||
|
uint16_t secs_since_valid_hangup = UINT16_MAX;
|
||||||
|
|
||||||
|
char* wsVar = std::getenv("WS_PING_INTERVAL");
|
||||||
|
if (wsVar != nullptr) {
|
||||||
|
secs_sinceq_valid_ping = std::atoi(wsVar);
|
||||||
|
}
|
||||||
|
|
||||||
|
wsVar = std::getenv("WS_NO_PONG_HANGUP_INTERVAL");
|
||||||
|
if (wsVar != nullptr) {
|
||||||
|
secs_since_valid_hangup = std::atoi(wsVar);
|
||||||
|
}
|
||||||
|
|
||||||
|
const lws_retry_bo_t retry = {
|
||||||
|
nullptr, // retry_ms_table
|
||||||
|
0, // retry_ms_table_count
|
||||||
|
0, // conceal_count
|
||||||
|
secs_sinceq_valid_ping, // secs_sinceq_valid_ping
|
||||||
|
secs_since_valid_hangup, // secs_since_valid_hangup
|
||||||
|
0 // jitter_percent
|
||||||
|
};
|
||||||
|
|
||||||
memset(&info, 0, sizeof info);
|
memset(&info, 0, sizeof info);
|
||||||
info.port = CONTEXT_PORT_NO_LISTEN;
|
info.port = CONTEXT_PORT_NO_LISTEN;
|
||||||
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||||
|
|||||||
@@ -774,7 +774,10 @@ extern "C" {
|
|||||||
cJSON_AddStringToObject(jResult, "quality", p->quality);
|
cJSON_AddStringToObject(jResult, "quality", p->quality);
|
||||||
}
|
}
|
||||||
if (p->speed) {
|
if (p->speed) {
|
||||||
cJSON_AddNumberToObject(jResult, "speed", atoi(p->speed));
|
double val = strtod(p->speed, NULL);
|
||||||
|
if (val != 0.0) {
|
||||||
|
cJSON_AddNumberToObject(jResult, "speed", val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (p->seed) {
|
if (p->seed) {
|
||||||
cJSON_AddNumberToObject(jResult, "seed", atoi(p->seed));
|
cJSON_AddNumberToObject(jResult, "seed", atoi(p->seed));
|
||||||
|
|||||||
Reference in New Issue
Block a user