#include #include #include #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; }