📄 adin_tcpip.c
字号:
/** * @file adin_tcpip.c * * <JA> * @brief ネットワ〖ク掐蜗¨adinnet クライアントからの不兰掐蜗 * * 掐蜗ソ〖スとして Julius の adinnet クライアントを蝗脱する你レベル簇眶ですˉ * * adinnet は ネットワ〖ク惧で不兰デ〖タを流慨する Julius 迫极の数及ですˉ * この掐蜗が联ばれた眷圭·Julius はadinnetサ〖バとなり·弹瓢箕に * クライアントの儡鲁を略ちますˉサンプルのadinnetクライアントとして· * adintool が Julius に烧掳していますので徊雇にしてくださいˉ * * Linux, Windows, その戮サポ〖トされているほとんどの OS で瓢侯しますˉ * * 戮にネットワ〖ク惧で不兰デ〖タをやりとりする数恕として, Linux では * EsounD を蝗う数恕がありますˉadin_esd.c をご枉くださいˉ * * @attention サ〖バ娄とクライアント娄でサンプリングレ〖ト * の肋年を办米させる涩妥がありますˉ儡鲁箕に尉荚粗でチェックは乖われませんˉ * * @bug マシンバイトオ〖ダ〖の佰なるマシン票晃で赖しく奶慨できませんˉ * </JA> * <EN> * @brief Audio input from adinnet client * * Low level I/O functions for audio input from adinnet client. * The adinnet server/client is a scheme to transfer speech data via tcp/ip * network with segmentation information, implemented for Julius. * When this input is selected, Julius becomes adinnet server and * wait for a client to connect. * The sample client "adintool" is also included in Julius package. * * This input works on Linux, Windows and most OS where Julius can run. * * "EsounD" is an another method of obtaining audio input from network * on Linux. See adin_esd.c for details. * * @attention The sampling rate setting on both side (server and client) * should be the same. They will not be checked when connected. * * @bug Does not work between different machine byte order. * </EN> * * @author Akinobu LEE * @date Mon Feb 14 14:55:03 2005 * * $Revision: 1.3 $ * *//* * Copyright (c) 1991-2007 Kawahara Lab., Kyoto University * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology * All rights reserved */#include <sent/stddefs.h>#include <sent/adin.h>#include <sent/tcpip.h>static int adinnet_sd = -1; ///< Listen socket for adinservstatic int adinnet_asd = -1; ///< Accept socket for adinserv#ifdef FORK_ADINNETstatic pid_t child; /* child process ID (0 if myself is child) */#endif/** * Initialize as adinnet server: prepare to become server. * * @param freq [in] required sampling frequency * @param port_str [in] port number in string * * @return TRUE on success, FALSE on failure. */booleanadin_tcpip_standby(int freq, void *port_str){ int port; port = atoi((char *)port_str); if ((adinnet_sd = ready_as_server(port)) < 0) { jlog("Error: adin_tcpip: cannot ready for server\n"); return FALSE; } jlog("Stat: adin_tcpip: ready for server\n"); return TRUE;}/** * Wait for connection from adinnet client and begin audio input stream. * * @return TRUE on success, FALSE on failure. */booleanadin_tcpip_begin(){#ifdef FORK_ADINNET /***********************************/ /*** server infinite loop here!! ***/ /***********************************/ for (;;) { /* wait connection */ jlog("Stat: adin_tcpip: waiting connection...\n"); if ((adinnet_asd = accept_from(adinnet_sd)) < 0) { return FALSE; } jlog("Stat: adin_tcpip: connected\n"); /* fork self */ child = fork(); if (child < 0) { /* error */ jlog("Error: adin_tcpip: fork failed\n"); return FALSE; } /* child thread should handle this request */ if (child == 0) { /* child thread */ break; /* proceed */ } else { /* parent thread */ jlog("Stat: adin_tcpip: forked process [%d] handles this request\n", child); } }#else /* ~FORK_ADINNET */ jlog("Stat: adin_tcpip: waiting connection...\n"); if ((adinnet_asd = accept_from(adinnet_sd)) < 0) { return FALSE; } jlog("Stat: adin_tcpip: connected\n");#endif /* FORK_ADINNET */ return TRUE;}/** * @brief End recording. * * If last input segment was segmented by end of connection, close socket * and wait for next connection. Otherwise, it means that the last input * segment was segmented by either end-of-segment signal * from client side or speech detection function in server side, so just * wait for a next input in the current socket. * * @return TRUE on success, FALSE on failure. */booleanadin_tcpip_end(){ /* end of connection */ close_socket(adinnet_asd);#ifdef FORK_ADINNET /* terminate this child process here */ jlog("Stat: adin_tcpip: connection end, child process now exit\n"); exit(0);#else /* wait for the next connection */ jlog("Stat: adin_tcpip: connection end\n");#endif return TRUE;}/** * Try to read @a sampnum samples and returns actual sample num recorded. * This function will not block. * * If data of zero length has been received, it is treated as a end-of-segment * marker from the client. If data below zero length has been received, * it means the client has finished the overall input stream transmission and * want to disconnect. * * @param buf [out] samples obtained in this function * @param sampnum [in] wanted number of samples to be read * * @return actural number of read samples, -1 if EOF, -2 if error. */intadin_tcpip_read(SP16 *buf, int sampnum){ int cnt, ret; fd_set rfds; struct timeval tv; int status; /* check if some commands are waiting in queue */ FD_ZERO(&rfds); FD_SET(adinnet_asd, &rfds); tv.tv_sec = 0; tv.tv_usec = 10000; /* 10msec */ status = select(adinnet_asd+1, &rfds, NULL, NULL, &tv); if (status < 0) { /* error */ jlog("Error: adin_tcpip: failed to poll socket\n"); return -2; /* error return */ } if (status > 0) { /* there are some data */ /* read one data segment, leave rest even if any for avoid blocking */ ret = rd(adinnet_asd, (char *)buf, &cnt, sampnum * sizeof(SP16)); if (ret == 0) { /* end of segment mark */ return -3; } if (ret < 0) { /* end of input, mark */ return -1; } } else { /* time out, no data */ cnt = 0; } cnt /= sizeof(SP16);#ifdef WORDS_BIGENDIAN swap_sample_bytes(buf, cnt);#endif return cnt;}/** * Tell the adinnet client to pause transfer. * * @return TRUE on success, FALSE on failure. */booleanadin_tcpip_send_pause(){ int count; char com; /* send stop command to adinnet client */ com = '0'; count = wt(adinnet_asd, &com, 1); if (count < 0) jlog("Warning: adin_tcpip: cannot send pause command to client\n"); jlog("Stat: adin_tcpip: sent pause command to client\n"); return TRUE;}/** * Tell the adinnet client to resume the paused transfer. * * @return TRUE on success, FALSE on failure. */booleanadin_tcpip_send_resume(){ int count; char com; int cnt, ret; fd_set rfds; struct timeval tv; int status; static char *tmpbuf = NULL; /* check if some commands are waiting in queue */ count = 0; do { FD_ZERO(&rfds); FD_SET(adinnet_asd, &rfds); tv.tv_sec = 0; tv.tv_usec = 0; status = select(adinnet_asd+1, &rfds, NULL, NULL, &tv); if (status < 0) { /* error */ jlog("Error: adin_tcpip: failed to poll socket\n"); return FALSE; /* error return */ } if (status > 0) { /* there are some data */ if (tmpbuf == NULL) tmpbuf = (char *)mymalloc(MAXSPEECHLEN); ret = rd(adinnet_asd, tmpbuf, &cnt, MAXSPEECHLEN * sizeof(SP16)); } if (cnt > 0) count += cnt; } while (status != 0); if (count > 0) { jlog("Stat: %d samples transfered while pause are flushed\n", count); } /* send resume command to adinnet client */ com = '1'; count = wt(adinnet_asd, &com, 1); if (count < 0) jlog("Warning: adin_tcpip: cannot send resume command to client\n"); jlog("Stat: adin_tcpip: sent resume command to client\n"); /* flush current buffer */ return TRUE;}/** * Tell the adinnet client to terminate transfer. * * @return TRUE on success, FALSE on failure. */booleanadin_tcpip_send_terminate(){ int count; char com; /* send terminate command to adinnet client */ com = '2'; count = wt(adinnet_asd, &com, 1); if (count < 0) jlog("Warning: adin_tcpip: cannot send terminate command to client\n"); jlog("Stat: adin_tcpip: sent terminate command to client\n"); return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -