Compare commits

...

5 Commits

Author SHA1 Message Date
Hoan Luu Huu 33fee93ec7 free maloc variable on mod_audio_fork (#54) 2024-04-23 09:15:11 -04:00
Hoan Luu Huu 41aebafd1c fix eleevnlabs callsession stuck (#55)
* fix eleevnlabs callsession stuck

Signed-off-by: Hoan HL <quan.luuhoang8@gmail.com>

* fix read sample rate from session is not needed

Signed-off-by: Hoan HL <quan.luuhoang8@gmail.com>

---------

Signed-off-by: Hoan HL <quan.luuhoang8@gmail.com>
2024-04-23 09:14:43 -04:00
Andrew Golledge bd69d476e7 Add Error Code Check to Google V1 Implementation (#51)
* Put the check for `grpc` error code 0 in the Google Speech-To-Text v1 as well.

* Distinguish between two types of error object in `grpc_read_thread`

* Improve naming of JSON field

* Correct error in JSON field name.

* Add sign-off to previous commit

Signed-off-by: Andrew Golledge <andreas.golledge@gmail.com>

---------

Signed-off-by: Andrew Golledge <andreas.golledge@gmail.com>
2024-04-22 19:20:15 -04:00
Dave Horton fea51d5ecf initialize variables to avoid possible junk values
Signed-off-by: Dave Horton <daveh@beachdognet.com>
2024-04-22 16:06:32 -04:00
Dave Horton 83a2d1d730 modify cache folder name and various fixes from testing tts streaming (#50) 2024-04-18 11:28:17 -04:00
12 changed files with 99 additions and 118 deletions
+1 -1
View File
@@ -480,7 +480,7 @@ AudioPipe::AudioPipe(const char* uuid, const char* host, unsigned int port, cons
} }
AudioPipe::~AudioPipe() { AudioPipe::~AudioPipe() {
if (m_audio_buffer) delete [] m_audio_buffer; if (m_audio_buffer) delete [] m_audio_buffer;
if (m_recv_buf) delete [] m_recv_buf; if (m_recv_buf) free(m_recv_buf);
} }
void AudioPipe::connect(void) { void AudioPipe::connect(void) {
+9 -17
View File
@@ -59,7 +59,7 @@ extern "C" {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
fullDirPath = std::string(baseDir) + "jambonz-tts-cache-files"; fullDirPath = std::string(baseDir) + "tts-cache-files";
// Create the directory with read, write, and execute permissions for everyone // Create the directory with read, write, and execute permissions for everyone
mode_t oldMask = umask(0); mode_t oldMask = umask(0);
@@ -135,25 +135,14 @@ extern "C" {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
if (a->session_id) { if (a->rate != 8000 /*Hz*/) {
int err; int err;
switch_codec_implementation_t read_impl; a->resampler = speex_resampler_init(1, 8000, a->rate, SWITCH_RESAMPLE_QUALITY, &err);
/* lock and unlock session */
switch_core_session_t *psession = switch_core_session_locate(a->session_id);
switch_core_session_get_read_impl(psession, &read_impl);
switch_core_session_rwunlock(psession);
uint32_t samples_per_second = !strcasecmp(read_impl.iananame, "g722") ? read_impl.actual_samples_per_second : read_impl.samples_per_second;
a->samples_rate = samples_per_second;
if (samples_per_second != 8000 /*Hz*/) {
a->resampler = speex_resampler_init(1, 8000, samples_per_second, SWITCH_RESAMPLE_QUALITY, &err);
if (0 != err) { if (0 != err) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error initializing resampler: %s.\n", speex_resampler_strerror(err)); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error initializing resampler: %s.\n", speex_resampler_strerror(err));
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
} }
}
std::chrono::time_point<std::chrono::high_resolution_clock>* ptr = new std::chrono::time_point<std::chrono::high_resolution_clock>(std::chrono::high_resolution_clock::now()); std::chrono::time_point<std::chrono::high_resolution_clock>* ptr = new std::chrono::time_point<std::chrono::high_resolution_clock>(std::chrono::high_resolution_clock::now());
a->startTime = ptr; a->startTime = ptr;
@@ -179,6 +168,7 @@ extern "C" {
speechConfig->SetEndpointId(a->endpointId); speechConfig->SetEndpointId(a->endpointId);
} }
try {
auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig); auto speechSynthesizer = SpeechSynthesizer::FromConfig(speechConfig);
speechSynthesizer->SynthesisStarted += [a](const SpeechSynthesisEventArgs& e) { speechSynthesizer->SynthesisStarted += [a](const SpeechSynthesisEventArgs& e) {
@@ -245,6 +235,10 @@ extern "C" {
std::thread(start_synthesis, speechSynthesizer, text, a).detach(); std::thread(start_synthesis, speechSynthesizer, text, a).detach();
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "azure_speech_feed_tts sent synthesize request\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "azure_speech_feed_tts sent synthesize request\n");
} catch (const std::exception& e) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_azure_tts: Exception: %s\n", e.what());
return SWITCH_STATUS_FALSE;
}
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@@ -271,9 +265,7 @@ extern "C" {
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
// azure returned 8000hz 16 bit data, we have to take enough data based on call sample rate. // azure returned 8000hz 16 bit data, we have to take enough data based on call sample rate.
size_t size = a->samples_rate ? size_t size = std::min((*datalen/(2 * a->rate / 8000)), bufSize);
std::min((*datalen/(2 * a->samples_rate / 8000)), bufSize) :
std::min((*datalen/2), bufSize);
pcm_data.insert(pcm_data.end(), cBuffer->begin(), cBuffer->begin() + size); pcm_data.insert(pcm_data.end(), cBuffer->begin(), cBuffer->begin() + size);
cBuffer->erase(cBuffer->begin(), cBuffer->begin() + size); cBuffer->erase(cBuffer->begin(), cBuffer->begin() + size);
switch_mutex_unlock(a->mutex); switch_mutex_unlock(a->mutex);
-1
View File
@@ -82,7 +82,6 @@ static switch_status_t a_speech_feed_tts(switch_speech_handle_t *sh, char *text,
a->draining = 0; a->draining = 0;
a->reads = 0; a->reads = 0;
a->flushed = 0; a->flushed = 0;
a->samples_rate = 0;
return azure_speech_feed_tts(a, text, flags); return azure_speech_feed_tts(a, text, flags);
} }
-1
View File
@@ -25,7 +25,6 @@ typedef struct azure_data {
int reads; int reads;
int cache_audio; int cache_audio;
int flushed; int flushed;
uint32_t samples_rate;
void *startTime; void *startTime;
+4 -2
View File
@@ -385,7 +385,7 @@ static size_t write_cb(void *ptr, size_t size, size_t nmemb, ConnInfo_t *conn) {
auto d = conn->deepgram; auto d = conn->deepgram;
CircularBuffer_t *cBuffer = (CircularBuffer_t *) d->circularBuffer; CircularBuffer_t *cBuffer = (CircularBuffer_t *) d->circularBuffer;
if (conn->flushed) { if (conn->flushed || cBuffer == nullptr) {
/* this will abort the transfer */ /* this will abort the transfer */
return 0; return 0;
} }
@@ -641,7 +641,7 @@ extern "C" {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
fullDirPath = std::string(baseDir) + "jambonz-tts-cache-files"; fullDirPath = std::string(baseDir) + "tts-cache-files";
// Create the directory with read, write, and execute permissions for everyone // Create the directory with read, write, and execute permissions for everyone
mode_t oldMask = umask(0); mode_t oldMask = umask(0);
@@ -764,6 +764,8 @@ extern "C" {
conn->file = d->file; conn->file = d->file;
conn->body = json; conn->body = json;
conn->flushed = false; conn->flushed = false;
conn->has_last_byte = false;
conn->last_byte = 0;
d->circularBuffer = (void *) new CircularBuffer_t(BUFFER_GROW_SIZE); d->circularBuffer = (void *) new CircularBuffer_t(BUFFER_GROW_SIZE);
+5 -16
View File
@@ -445,7 +445,7 @@ static size_t write_cb(void *ptr, size_t size, size_t nmemb, ConnInfo_t *conn) {
CircularBuffer_t *cBuffer = (CircularBuffer_t *) el->circularBuffer; CircularBuffer_t *cBuffer = (CircularBuffer_t *) el->circularBuffer;
std::vector<uint16_t> pcm_data; std::vector<uint16_t> pcm_data;
if (conn->flushed) { if (conn->flushed || cBuffer == nullptr) {
/* this will abort the transfer */ /* this will abort the transfer */
return 0; return 0;
} }
@@ -688,7 +688,7 @@ extern "C" {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
fullDirPath = std::string(baseDir) + "jambonz-tts-cache-files"; fullDirPath = std::string(baseDir) + "tts-cache-files";
// Create the directory with read, write, and execute permissions for everyone // Create the directory with read, write, and execute permissions for everyone
mode_t oldMask = umask(0); mode_t oldMask = umask(0);
@@ -841,7 +841,6 @@ extern "C" {
CURL* easy = createEasyHandle(); CURL* easy = createEasyHandle();
el->conn = (void *) conn ; el->conn = (void *) conn ;
el->sample_rate = 0;
conn->elevenlabs = el; conn->elevenlabs = el;
conn->easy = easy; conn->easy = easy;
conn->global = &global; conn->global = &global;
@@ -852,22 +851,14 @@ extern "C" {
el->circularBuffer = (void *) new CircularBuffer_t(8192); el->circularBuffer = (void *) new CircularBuffer_t(8192);
if (el->session_id) { if (el->rate != 8000 /*Hz*/) {
int err; int err;
switch_codec_implementation_t read_impl; el->resampler = speex_resampler_init(1, 8000, el->rate, SWITCH_RESAMPLE_QUALITY, &err);
switch_core_session_t *psession = switch_core_session_locate(el->session_id);
switch_core_session_get_read_impl(psession, &read_impl);
uint32_t samples_per_second = !strcasecmp(read_impl.iananame, "g722") ? read_impl.actual_samples_per_second : read_impl.samples_per_second;
el->sample_rate = samples_per_second;
// elevenlabs output is PCMU 8000
if (samples_per_second != 8000 /*Hz*/) {
el->resampler = speex_resampler_init(1, 8000, samples_per_second, SWITCH_RESAMPLE_QUALITY, &err);
if (0 != err) { if (0 != err) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error initializing resampler: %s.\n", speex_resampler_strerror(err)); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error initializing resampler: %s.\n", speex_resampler_strerror(err));
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
} }
}
std::ostringstream api_key_stream; std::ostringstream api_key_stream;
api_key_stream << "xi-api-key: " << el->api_key; api_key_stream << "xi-api-key: " << el->api_key;
@@ -939,9 +930,7 @@ extern "C" {
switch_mutex_unlock(el->mutex); switch_mutex_unlock(el->mutex);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
size_t size = el->sample_rate ? size_t size = std::min((*datalen/(2 * el->rate / 8000)), cBuffer->size());
std::min((*datalen/(2 * el->sample_rate / 8000)), cBuffer->size()) :
std::min((*datalen/2), cBuffer->size());
pcm_data.insert(pcm_data.end(), cBuffer->begin(), cBuffer->begin() + size); pcm_data.insert(pcm_data.end(), cBuffer->begin(), cBuffer->begin() + size);
cBuffer->erase(cBuffer->begin(), cBuffer->begin() + size); cBuffer->erase(cBuffer->begin(), cBuffer->begin() + size);
switch_mutex_unlock(el->mutex); switch_mutex_unlock(el->mutex);
-1
View File
@@ -31,7 +31,6 @@ struct elevenlabs_data {
char *cache_filename; char *cache_filename;
int rate; int rate;
uint32_t sample_rate;
void *conn; void *conn;
FILE *file; FILE *file;
+3 -1
View File
@@ -236,6 +236,7 @@ static void *SWITCH_THREAD_FUNC grpc_read_thread(switch_thread_t *thread, void *
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "grpc_read_thread: error %s (%d)\n", status.message().c_str(), status.code()) ; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "grpc_read_thread: error %s (%d)\n", status.message().c_str(), status.code()) ;
cJSON* json = cJSON_CreateObject(); cJSON* json = cJSON_CreateObject();
cJSON_AddStringToObject(json, "type", "error"); cJSON_AddStringToObject(json, "type", "error");
cJSON_AddStringToObject(json, "error_cause", "stream_response");
cJSON_AddStringToObject(json, "error", status.message().c_str()); cJSON_AddStringToObject(json, "error", status.message().c_str());
char* jsonString = cJSON_PrintUnformatted(json); char* jsonString = cJSON_PrintUnformatted(json);
cb->responseHandler(session, jsonString, cb->bugname); cb->responseHandler(session, jsonString, cb->bugname);
@@ -339,9 +340,10 @@ static void *SWITCH_THREAD_FUNC grpc_read_thread(switch_thread_t *thread, void *
cb->responseHandler(session, "no_audio", cb->bugname); cb->responseHandler(session, "no_audio", cb->bugname);
} }
} }
else { else if (status.error_code() != 0) {
cJSON* json = cJSON_CreateObject(); cJSON* json = cJSON_CreateObject();
cJSON_AddStringToObject(json, "type", "error"); cJSON_AddStringToObject(json, "type", "error");
cJSON_AddStringToObject(json, "error_cause", "stream_close");
cJSON_AddItemToObject(json, "error_code", cJSON_CreateNumber(status.error_code())); cJSON_AddItemToObject(json, "error_code", cJSON_CreateNumber(status.error_code()));
cJSON_AddStringToObject(json, "error_message", status.error_message().c_str()); cJSON_AddStringToObject(json, "error_message", status.error_message().c_str());
char* jsonString = cJSON_PrintUnformatted(json); char* jsonString = cJSON_PrintUnformatted(json);
+1
View File
@@ -349,6 +349,7 @@ static void *SWITCH_THREAD_FUNC grpc_read_thread(switch_thread_t *thread, void *
else if (status.error_code() != 0) { else if (status.error_code() != 0) {
cJSON* json = cJSON_CreateObject(); cJSON* json = cJSON_CreateObject();
cJSON_AddStringToObject(json, "type", "error"); cJSON_AddStringToObject(json, "type", "error");
cJSON_AddStringToObject(json, "error_cause", "stream_close");
cJSON_AddItemToObject(json, "error_code", cJSON_CreateNumber(status.error_code())); cJSON_AddItemToObject(json, "error_code", cJSON_CreateNumber(status.error_code()));
cJSON_AddStringToObject(json, "error_message", status.error_message().c_str()); cJSON_AddStringToObject(json, "error_message", status.error_message().c_str());
char* jsonString = cJSON_PrintUnformatted(json); char* jsonString = cJSON_PrintUnformatted(json);
+3 -11
View File
@@ -436,7 +436,7 @@ static size_t write_cb(void *ptr, size_t size, size_t nmemb, ConnInfo_t *conn) {
CircularBuffer_t *cBuffer = (CircularBuffer_t *) p->circularBuffer; CircularBuffer_t *cBuffer = (CircularBuffer_t *) p->circularBuffer;
std::vector<uint16_t> pcm_data; std::vector<uint16_t> pcm_data;
if (conn->flushed) { if (conn->flushed || cBuffer == nullptr) {
/* this will abort the transfer */ /* this will abort the transfer */
return 0; return 0;
} }
@@ -648,7 +648,7 @@ extern "C" {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
fullDirPath = std::string(baseDir) + "jambonz-tts-cache-files"; fullDirPath = std::string(baseDir) + "tts-cache-files";
// Create the directory with read, write, and execute permissions for everyone // Create the directory with read, write, and execute permissions for everyone
mode_t oldMask = umask(0); mode_t oldMask = umask(0);
@@ -838,18 +838,10 @@ extern "C" {
p->circularBuffer = (void *) new CircularBuffer_t(8192); p->circularBuffer = (void *) new CircularBuffer_t(8192);
if (p->session_id) { if (mpg123_param(mh, MPG123_FORCE_RATE, p->rate /*Hz*/, 0) != MPG123_OK) {
int err;
switch_codec_implementation_t read_impl;
switch_core_session_t *psession = switch_core_session_locate(p->session_id);
switch_core_session_get_read_impl(psession, &read_impl);
switch_core_session_rwunlock(psession);
uint32_t samples_per_second = !strcasecmp(read_impl.iananame, "g722") ? read_impl.actual_samples_per_second : read_impl.samples_per_second;
if (mpg123_param(mh, MPG123_FORCE_RATE, samples_per_second /*Hz*/, 0) != MPG123_OK) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error mpg123_param!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error mpg123_param!\n");
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
}
std::ostringstream api_key_stream; std::ostringstream api_key_stream;
api_key_stream << "AUTHORIZATION: " << p->api_key; api_key_stream << "AUTHORIZATION: " << p->api_key;
+8 -2
View File
@@ -386,7 +386,7 @@ static size_t write_cb(void *ptr, size_t size, size_t nmemb, ConnInfo_t *conn) {
auto d = conn->rimelabs; auto d = conn->rimelabs;
CircularBuffer_t *cBuffer = (CircularBuffer_t *) d->circularBuffer; CircularBuffer_t *cBuffer = (CircularBuffer_t *) d->circularBuffer;
if (conn->flushed) { if (conn->flushed || cBuffer == nullptr) {
/* this will abort the transfer */ /* this will abort the transfer */
return 0; return 0;
} }
@@ -394,6 +394,8 @@ static size_t write_cb(void *ptr, size_t size, size_t nmemb, ConnInfo_t *conn) {
std::unique_ptr<uint8_t[]> combinedData; std::unique_ptr<uint8_t[]> combinedData;
if (conn->has_last_byte) { if (conn->has_last_byte) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "rimelabs write_cb: processing last byte from previous read\n");
conn->has_last_byte = false; // We'll handle the last_byte now, so toggle the flag off conn->has_last_byte = false; // We'll handle the last_byte now, so toggle the flag off
// Allocate memory for the new data array // Allocate memory for the new data array
@@ -415,6 +417,8 @@ static size_t write_cb(void *ptr, size_t size, size_t nmemb, ConnInfo_t *conn) {
// If we now have an odd total, save the last byte for next time // If we now have an odd total, save the last byte for next time
if ((total_bytes_to_process % sizeof(int16_t)) != 0) { if ((total_bytes_to_process % sizeof(int16_t)) != 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "rimelabs write_cb: got odd number of bytes %d\n", total_bytes_to_process);
conn->last_byte = data[total_bytes_to_process - 1]; conn->last_byte = data[total_bytes_to_process - 1];
conn->has_last_byte = true; conn->has_last_byte = true;
total_bytes_to_process--; total_bytes_to_process--;
@@ -626,7 +630,7 @@ extern "C" {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
fullDirPath = std::string(baseDir) + "jambonz-tts-cache-files"; fullDirPath = std::string(baseDir) + "tts-cache-files";
// Create the directory with read, write, and execute permissions for everyone // Create the directory with read, write, and execute permissions for everyone
mode_t oldMask = umask(0); mode_t oldMask = umask(0);
@@ -758,6 +762,8 @@ extern "C" {
conn->file = d->file; conn->file = d->file;
conn->body = json; conn->body = json;
conn->flushed = false; conn->flushed = false;
conn->has_last_byte = false;
conn->last_byte = 0;
d->circularBuffer = (void *) new CircularBuffer_t(BUFFER_GROW_SIZE); d->circularBuffer = (void *) new CircularBuffer_t(BUFFER_GROW_SIZE);
+2 -2
View File
@@ -436,7 +436,7 @@ static size_t write_cb(void *ptr, size_t size, size_t nmemb, ConnInfo_t *conn) {
CircularBuffer_t *cBuffer = (CircularBuffer_t *) w->circularBuffer; CircularBuffer_t *cBuffer = (CircularBuffer_t *) w->circularBuffer;
std::vector<uint16_t> pcm_data; std::vector<uint16_t> pcm_data;
if (conn->flushed) { if (conn->flushed || cBuffer == nullptr) {
/* this will abort the transfer */ /* this will abort the transfer */
return 0; return 0;
} }
@@ -671,7 +671,7 @@ extern "C" {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
fullDirPath = std::string(baseDir) + "jambonz-tts-cache-files"; fullDirPath = std::string(baseDir) + "tts-cache-files";
// Create the directory with read, write, and execute permissions for everyone // Create the directory with read, write, and execute permissions for everyone
mode_t oldMask = umask(0); mode_t oldMask = umask(0);