You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
voicebot/extlib/readspeakerstt/src/vstsample_e2e_ast.c

656 lines
16 KiB
C

#include <pthread.h>
#include <dirent.h>
#include <sys/stat.h>
#define MAX_QUEUE_SIZE 65535
#define MAX_LOG_BUFFER_LEN 1024
#define MAX_FILENAME_LEN 256
#define MAX_CHANNEL 100
#define MAX_IP_ADDRESS_LEN 18
#define MAX_LOG_KEY_LEN 17
#define MAX_VOICE_TYPE_LEN 10
#define FILE_PROCESSING 1
#define DIR_PROCESSING 2
#define EMPTY_STATUS 0
#define WAIT_STATUS 1
#define RECOG_STATUS 2
#define FINISH_STATUS 3
#define AUDIO_TYPE_WAV_FORMAT ".wav"
#define AUDIO_TYPE_PCM_FORMAT ".pcm"
#define AUDIO_TYPE_ALAW_FORMAT ".alaw"
#define AUDIO_TYPE_MULAW_FORMAT ".mulaw"
#include "vstapi_e2e_ast.h"
typedef struct _file_list
{
int status;
char filename[MAX_FILENAME_LEN];
char out_name[MAX_FILENAME_LEN];
} FILE_LIST;
typedef struct _recv_arg
{
int sockfd;
int channel;
FILE *output;
} RECV_ARG;
typedef struct _arg
{
int channel;
} ARG;
FILE_LIST fList[MAX_QUEUE_SIZE];
int STT_PORT;
int Channel;
int file_list_count;
int wait_file_count;
char STT_IP_ADDR[MAX_IP_ADDRESS_LEN];
char STT_LOG_KEY[MAX_LOG_KEY_LEN];
char STT_VOICE_TYPE[MAX_VOICE_TYPE_LEN];
char TargetName[MAX_FILENAME_LEN];
char LOG_FILENAME[MAX_FILENAME_LEN];
pthread_mutex_t LIST_LOCK;
pthread_mutex_t COUNT_LOCK;
pthread_mutex_t LOG_LOCK;
FILE *output[MAX_CHANNEL];
void InitData(void);
void file_process(char *Name);
void dir_process(int Ch);
void SaveFileList( char *path, char *filename );
void SearchDirectory( char *dir_name );
void *recv_thread(void *data);
void *recog_thread(void *data);
void create_log_filename(void);
void debug_print_argument(int Ch, int Op);
void print_help_message(char *program);
void write_service_log( const char *format, ... );
int find_audio_file(char *name);
void print_help_message(char *program)
{
printf("\n====================================================================================\n");
printf(" %s [IP Address] [Port] [Channel] [Option] [Filename] [File Type] [Log Key]\n", program);
printf(" - [IP Address] : STT Server IP Address\n");
printf(" - [Port] : STT Server Port Number\n");
printf(" - [Channel] : Multi Processing Channel ( max 100 channel )\n");
printf(" - [Option] : Voice File Option\n");
printf(" > FILE ---------- Processing for each File\n");
printf(" > DIR ----------- Processing for Directory\n");
printf(" - [Filename] : Voice File Name\n");
printf(" - [File Type] : Voice File Yype\n");
printf(" > PCM\n");
printf(" > WAV\n");
printf(" > ALAW\n");
printf(" > MULAW\n");
printf(" - [Log Key] : Primary Key ( max 16 byte )\n");
printf("====================================================================================\n\n");
}
void debug_print_argument(int Ch, int Op)
{
printf("\n--------------------------------------------\n");
printf(" STT IP Address : %s\n", STT_IP_ADDR);
printf(" STT PORT Number : %d\n", STT_PORT);
printf(" STT Client Channel : %d\n", Ch);
printf(" FILE Option : %s\n", (Op == FILE_PROCESSING) ? "FILE" : "DIRECTORY");
printf(" Target Name : %s\n", TargetName);
printf(" FILE Type : %s\n", STT_VOICE_TYPE);
printf(" STT Log Key : %s\n", STT_LOG_KEY);
printf("--------------------------------------------\n\n");
}
void write_service_log( const char *format, ... )
{
FILE *fp;
struct tm tm;
struct timeval tv;
time_t now;
pthread_mutex_lock( &LOG_LOCK );
if (( fp = fopen( LOG_FILENAME, "at" ) ) != NULL )
{
va_list args;
char buffer[MAX_LOG_BUFFER_LEN + 1];
now = time(NULL);
gettimeofday(&tv, NULL);
localtime_r(&now, &tm);
va_start( args, format );
vsnprintf( buffer, MAX_LOG_BUFFER_LEN, format, args );
va_end(args);
fprintf( fp, "[%04d-%02d-%02d:%02d:%02d:%02d.%03ld] %s\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec/1000, buffer);
fflush( fp );
fclose( fp );
}
pthread_mutex_unlock( &LOG_LOCK );
}
void create_log_filename(void)
{
struct tm tm;
struct timeval tv;
time_t now;
char curr_dir_name[MAX_FILENAME_LEN];
bzero( curr_dir_name, MAX_FILENAME_LEN );
getcwd( curr_dir_name, MAX_FILENAME_LEN );
now = time(NULL);
gettimeofday(&tv, NULL);
localtime_r(&now, &tm);
sprintf( LOG_FILENAME, "%s/vstsample_%04d-%02d-%02d.log", curr_dir_name, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday );
}
void InitData(void)
{
int cnt = 0;
STT_PORT = 0;
Channel = 1;
file_list_count = 0;
wait_file_count = 0;
bzero( STT_IP_ADDR, MAX_IP_ADDRESS_LEN );
bzero( STT_LOG_KEY, MAX_LOG_KEY_LEN );
bzero( STT_VOICE_TYPE, MAX_VOICE_TYPE_LEN );
bzero( TargetName, MAX_FILENAME_LEN );
bzero( LOG_FILENAME, MAX_FILENAME_LEN );
for( cnt = 0; cnt < MAX_QUEUE_SIZE; cnt++ )
{
fList[cnt].status = EMPTY_STATUS;
bzero( fList[cnt].filename, MAX_FILENAME_LEN );
bzero( fList[cnt].out_name, MAX_FILENAME_LEN );
}
pthread_mutex_init( &LIST_LOCK, NULL );
pthread_mutex_init( &COUNT_LOCK, NULL );
pthread_mutex_init( &LOG_LOCK, NULL );
}
int main(int argc, char *argv[])
{
int OperationType = FILE_PROCESSING;
//int timeMin, timeSec;
if ( argc != 8 )
{
printf( "Invalid Argument\n\n");
print_help_message(argv[0]);
return EXIT_FAILURE;
}
// Init Data
InitData();
// Create Log Filename
create_log_filename();
// Set Data
sprintf( STT_IP_ADDR, "%s", argv[1] );
STT_PORT = atoi( argv[2] );
sprintf( STT_VOICE_TYPE, "%s", argv[6]);
sprintf( STT_LOG_KEY, "%s", argv[7]);
Channel = atoi( argv[3] );
if ( Channel < 0 || Channel > MAX_CHANNEL )
{
printf( "Invalid Argument\n\n");
print_help_message(argv[0]);
return EXIT_FAILURE;
}
sprintf( TargetName, "%s", argv[5]);
if ( strstr( argv[4], "FILE" ) != NULL )
{
OperationType = FILE_PROCESSING;
//sprintf( TargetName, "%s", argv[5]);
if ( Channel > 1 )
{
write_service_log( "FILE Processing is one file about only one.....( Channel %d --> 1 )\n", Channel);
Channel = 1;
}
wait_file_count = 1;
}
else if ( strstr( argv[4], "DIR" ) != NULL )
{
OperationType = DIR_PROCESSING;
SearchDirectory( TargetName );
wait_file_count = file_list_count - 1;
}
else
{
printf( "Invalid Argument\n\n");
print_help_message(argv[0]);
return EXIT_FAILURE;
}
debug_print_argument(Channel, OperationType);
switch ( OperationType )
{
case FILE_PROCESSING:
file_process(TargetName);
break;
case DIR_PROCESSING:
dir_process(Channel);
break;
default:
break;
}
while ( 1 )
{
if ( wait_file_count == 0 )
{
sleep(1);
break;
}
}
pthread_mutex_destroy( &LOG_LOCK );
pthread_mutex_destroy( &COUNT_LOCK );
pthread_mutex_destroy( &LIST_LOCK );
return EXIT_SUCCESS;
}
void file_process(char *Name)
{
int index = 0;
pthread_t thrd_ID;
fList[0].status = WAIT_STATUS;
sprintf(fList[0].filename, "%s", Name);
sprintf(fList[0].out_name, "%s.recog", Name);
file_list_count += 1;
thrd_ID = index;
pthread_create( &thrd_ID, NULL, recog_thread, &index );
(void) pthread_join( thrd_ID, NULL );
}
void dir_process(int Ch)
{
int index = 0;
ARG *arg = NULL;
pthread_t thrd_ID;
if ( file_list_count <= 0 )
{
fprintf(stdout, "Not Found File....\n");
return;
}
for ( index = 0; index < Ch; index++ )
{
arg = (ARG *)malloc(sizeof(ARG));
arg->channel = index;
thrd_ID = index;
write_service_log( "Create Recog_Thread function #%d", index);
pthread_create( &thrd_ID, NULL, recog_thread, (void *)arg );
sleep(.5);
}
/*
for ( index = 0; index < Ch; index++ )
{
thrd_ID = index;
(void) pthread_join( thrd_ID, NULL );
}
*/
}
void *recog_thread(void *data)
{
int index = 0;
int sample_num = 0;
int frame_num = 0;
int FoundFile = 0;
int channel = 0;
short *speech;
char inFileName[MAX_FILENAME_LEN];
char outFileName[MAX_FILENAME_LEN];
char *resultbuf = NULL;
unsigned char *speech_data = NULL;
FILE *fd = NULL;
RECV_ARG *recvArg;
pthread_t thid;
timeval t_start, t_end;
channel = ((ARG *)data)->channel;
write_service_log("[%04d] [%s] --------------- RECOG-THREAD START ---------------", channel, __func__);
while ( 1 )
{
// Set Receive Argument
recvArg = (RECV_ARG *)malloc(sizeof(RECV_ARG));
recvArg->sockfd = -1;
//recvArg->channel = ((ARG *)data)->channel;
recvArg->channel = channel;
recvArg->output = NULL;
// Get Filename
FoundFile = 0;
bzero( inFileName, MAX_FILENAME_LEN );
bzero( outFileName, MAX_FILENAME_LEN );
pthread_mutex_lock( &LIST_LOCK );
for ( index = 0; index < file_list_count; index++ )
{
if ( fList[index].status == WAIT_STATUS )
{
write_service_log("[%04d] [%s] %s processing", recvArg->channel, __func__, fList[index].filename);
sprintf(inFileName, "%s", fList[index].filename);
sprintf(outFileName, "%s", fList[index].out_name);
fList[index].status = RECOG_STATUS;
FoundFile = 1;
break;
}
}
pthread_mutex_unlock( &LIST_LOCK );
if ( FoundFile == 0 )
{
write_service_log("[%04d] Not Fount Audio File... Thread Exit...", recvArg->channel);
free( recvArg );
break;
}
// Set Start Time
gettimeofday( &t_start, NULL );
// Voice File Open
fd = fopen( inFileName, "rb" );
if ( fd == NULL )
{
write_service_log("[%04d] %s file open error", recvArg->channel, inFileName);
sleep(.5);
continue;
}
write_service_log("[%04d] %s file open sucess", recvArg->channel, inFileName);
sample_num = (int)(VST_Get_filesize( fd ) / (sizeof( short )));
if ( sample_num < 0 )
{
write_service_log("[%04d] EasrFile -- file open error ( %s )", recvArg->channel, inFileName);
fclose( fd );
free(recvArg);
sleep(.5);
continue;
}
speech = (short *)malloc( sample_num * sizeof( short ) );
fread( speech, sizeof( short ), sample_num, fd );
fclose( fd );
write_service_log("[%04d] %s sample number : %d", recvArg->channel, inFileName, sample_num);
// Recog File Open
if ( access( outFileName, F_OK ) != -1 )
{
write_service_log("[%04d] Found Output File ( %s )... Delete & Create", recvArg->channel, inFileName);
unlink( outFileName );
}
recvArg->output = fopen( outFileName, "wb+" );
frame_num = sample_num / ((int)(FRAME_SHIFT));
speech_data = (unsigned char *)malloc(sample_num * sizeof(unsigned char));
if ( frame_num < 10 )
{
write_service_log("[%04d] %s : Too short input frames...", recvArg->channel, inFileName);
free( speech_data );
free( speech );
free( recvArg );
sleep(.5);
continue;
}
// Connect to STT Server
write_service_log("[%04d] VST Server Connect( %s, %d)", recvArg->channel, STT_IP_ADDR, STT_PORT + recvArg->channel);
recvArg->sockfd = VST_Connect_To_Server( STT_IP_ADDR, STT_PORT + recvArg->channel );
if ( recvArg->sockfd < 0 )
{
write_service_log("[%04d] STT Server Connect Error...", recvArg->channel);
if ( recvArg->sockfd )
VST_Disconnect( recvArg->sockfd );
free(recvArg);
sleep(.5);
continue;
}
write_service_log("[%04d] [%s] sockfd : %d", recvArg->channel, __func__, recvArg->sockfd);
// Send Voice Data
write_service_log("[%04d] Send Header Data", recvArg->channel);
if ( VST_Send_Header_Data( recvArg->sockfd, STT_LOG_KEY, STT_VOICE_TYPE ) != SUCCESS_SEND_DATA )
{
write_service_log("[%04d] Send Header Data Error...", recvArg->channel);
if ( recvArg->sockfd )
VST_Disconnect( recvArg->sockfd );
free( recvArg );
sleep(.5);
continue;
}
// Create Recv Thread
write_service_log("[%04d] Create receive thread", recvArg->channel);
pthread_create( &thid, NULL, recv_thread, recvArg );
write_service_log("[%04d] Send Audio data", recvArg->channel);
int sampleByteNum = sample_num * 2;
int send_block_byte = 320 * 20;
int sendBlockX = 0;
int TotalSendByteNum = 0;
int resByteNum;
short sendByteNum;
char sendbuf[20000];
while ( TotalSendByteNum < sampleByteNum )
{
resByteNum = sampleByteNum - TotalSendByteNum;
if ( resByteNum >= send_block_byte )
sendByteNum = (short)send_block_byte;
else
{
sendByteNum = (short)resByteNum;
if ( sendByteNum < 320 ) break;
}
memcpy( sendbuf, &sendBlockX, 4 );
memcpy( sendbuf + 4, &sendByteNum, 2 );
memcpy( sendbuf + 6, speech + (TotalSendByteNum / 2), (int)sendByteNum );
VST_Send_Audio_Data( recvArg->sockfd, sendbuf, sendByteNum );
TotalSendByteNum += sendByteNum;
sendBlockX++;
}
write_service_log("[%04d] Send Audio Final data", recvArg->channel);
VST_Send_Final_Data( recvArg->sockfd, sendbuf, sample_num, AUDIO_TYPE_MULAW );
pthread_join( thid, (void **)&resultbuf );
write_service_log("[%04d] Recog Receive Finish", recvArg->channel);
// Output File Close
fclose( recvArg->output );
// Set End Time
gettimeofday( &t_end, NULL );
double diff_time;
diff_time = ( t_end.tv_sec - t_start.tv_sec ) + (( t_end.tv_usec - t_start.tv_usec ) / 1000000 );
write_service_log("[%04d] %s decording time %f sec", recvArg->channel, inFileName, diff_time);
if ( recvArg->sockfd )
VST_Disconnect( recvArg->sockfd );
free( recvArg );
pthread_mutex_lock( &COUNT_LOCK );
wait_file_count -= 1;
pthread_mutex_unlock( &COUNT_LOCK );
}
pthread_exit(NULL);
}
void *recv_thread(void *data)
{
int ret = 0;
int retry_flag = 0;
int retry_count = 0;
int code, size;
int sockfd = -1;
int prev_new_line = 0;
FILE *output = ((RECV_ARG *)data)->output;
char *result = NULL;
sockfd = ((RECV_ARG *)data)->sockfd;
while ( true )
{
if ( retry_count > 5 )
break;
usleep( 200 * 100 );
ret = VST_Recv_Header_Data(sockfd, &code, &size);
if ( retry_flag == 0)
result = (char *)malloc( sizeof(char) * size + 1 );
ret = VST_Recv_Recog_Data(sockfd, size, result, NULL);
if ( ret == ERR_RECV_RECOG_DATA )
{
retry_flag = 1;
retry_count += 1;
continue;
}
else if ( ret == SUCCESS_RECV_RECOG_DATA )
{
retry_flag = 0;
}
if (code == 600 )
{
write_service_log("[%04d] recv code : 600", ((RECV_ARG *)data)->channel);
}
else if (code == 100 || code == 900 || code == 901)
{
write_service_log("[%04d] Result ( %d ) : %s", ((RECV_ARG *)data)->channel, size, result);
if ( size == 0 && prev_new_line == 0)
{
fprintf(output, "\n");
prev_new_line = 1;
}
else
{
fprintf(output, "%s\n", result);
prev_new_line = 0;
}
fflush(output);
if(code == 100) break;
}
else
{
write_service_log("[%04d] --- ASR DONE [ code : %d ] --- ", ((RECV_ARG *)data)->channel, code);
break;
}
free( result );
result = NULL;
retry_count = 0;
}
return NULL;
}
void SaveFileList( char *path, char *filename )
{
write_service_log( " - %04d : %s/%s ( %d )", file_list_count, path, filename, WAIT_STATUS);
fList[file_list_count].status = WAIT_STATUS;
sprintf( fList[file_list_count].filename, "%s/%s", path, filename );
sprintf( fList[file_list_count].out_name, "%s/%s.recog", path, filename );
file_list_count += 1;
}
void SearchDirectory( char *dir_name )
{
DIR *dp;
struct dirent *entry;
char curr_dir_name[MAX_FILENAME_LEN];
bzero( curr_dir_name, MAX_FILENAME_LEN );
getcwd( curr_dir_name, MAX_FILENAME_LEN );
if( dir_name[strlen( dir_name ) - 1] == '/' )
dir_name[strlen( dir_name ) - 1] = '\0';
if (( dp = opendir( dir_name ) ) == NULL )
{
fprintf( stdout, "\nCan not open directory : %s\n", dir_name );
return;
}
chdir( dir_name );
while (( entry = readdir( dp )) != NULL )
{
if ( strcmp( entry->d_name, "." ) == 0 || strcmp( entry->d_name, ".." ) == 0 )
continue;
else if ( entry->d_type != DT_DIR )
{
if ( find_audio_file( entry->d_name ) == 1 )
{
SaveFileList( dir_name, entry->d_name );
}
}
}
chdir( curr_dir_name );
closedir( dp );
}
int find_audio_file(char *name)
{
char *ext;
ext = strrchr(name, '.');
if ( ext == NULL )
return 0;
if ( ( strcmp( ext, AUDIO_TYPE_WAV_FORMAT ) == 0 ) ||
( strcmp( ext, AUDIO_TYPE_PCM_FORMAT ) == 0 ) ||
( strcmp( ext, AUDIO_TYPE_ALAW_FORMAT ) == 0 ) ||
( strcmp( ext, AUDIO_TYPE_MULAW_FORMAT ) == 0 ) )
return 1;
return 0;
}