-
Notifications
You must be signed in to change notification settings - Fork 11
Exemple d'utilisation du ASR en C
Joel Matteotti edited this page Apr 26, 2014
·
1 revision
Cet exemple vas permettre de vous montrer comment utiliser le système ASR (Automatic Speech Recognition) de TuxDroidServer et de faire effectuer des actions à un TuxDroid par le biais de la voix.
Le code suivant s'appuie sur celui-ci: Exemple C avec quelques modifications pour l'ASR et vous pourrez donc constater que la gestion de l'ASR de TuxDroidServer est vraiment très simple et ne demande que quelques lignes de code et peut d'effort.
NOTE: Le système ASR (la reconnaissance vocale) existe sur TuxDroidServer qu'a partir de la révision 141, pensez donc à utiliser une révision de TuxDroidServer suffisemment à jour si vous souhaitez utiliser des commandes vocale dans votre programme.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <malloc.h>
#include <string.h>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <netdb.h>
#endif
#include <stdbool.h>
#define BUFFER_MAX_SIZE 8191 /* taille maximal du buffer de lecture de la socket */
int sock; /* socket */
pthread_attr_t sockThread_attr; /* paramètre du thread */
pthread_t sockThread; /* thread */
/* prototypes */
void *ReadServer(void *data);
void ParseMessage(char *msg);
void onRemoteButtonPressed(char *button);
void sendMessage(char *msg);
void manageASRResult(char *asr);
char *trim(char *str);
static bool isRecordingASR=false;
/* suppression des espaces avant et arrière */
char *trim(char *string)
{
char *string_start;
for (string_start = string;
*string_start && isspace(*string_start);
++string_start);
// +1 to include the trailing \0
memmove(string, string_start, strlen(string_start) + 1);
char *string_end;
for (string_end = string + strlen(string);
string_end > string && isspace(*(string_end - 1));
--string_end);
*string_end = '\0';
return string;
}
void manageASRResult(char *asr)
{
isRecordingASR=false;
/* On vérifie que asr contient ouvrir ou ouvre et contient aussi bouche */
if( (strstr(asr,"ouvrir") || strstr(asr,"ouvre")) && strstr(asr,"bouche"))
{
/* et si c'est le cas alors on fait ouvrir la bouch de tux avec tux_Open(Mouth) */
sendMessage("Tux_Open(Mouth)");
}
}
/* appuie sur un bouton de la télécommande */
void onRemoteButtonPressed(char *button)
{
if(!strcmp(button,"K_RECORDING\r")) /* \r car c'est ce qu'envoie le server ! */
{
/* Démarrer l'enregistremnt */
isRecordingASR=true;
sendMessage("Tux_Micro(record,asr.wav)");
}
if(!strcmp(button,"RELEASE\r"))
{
/* si on est en mode ASR */
if(isRecordingASR)
{
/* stopper enregistremnt
puis envoyer commande tux_flac() */
sendMessage("Tux_Micro(stop)");
sendMessage("Tux_Flac(asr.wav)");
}
}
}
/* envoie un message au server */
void sendMessage(char *msg)
{
if(sock) /* si la connexion existe toujours */
send(sock,msg,strlen(msg),0);
}
/* Parse les messages provenant du server */
void ParseMessage(char *msg)
{
char *pch; /* pointeur pour manipuler les chaine de caractères */
char type[18]; /* buffer qui contiendra le type de message (#TUXBUTTON, #TUXREMOTE, ...) */
char param[128]; /* buffer qui conteindra la valeur du message (Ex: le nom du bouton si le message est #TUXREMOTE) */
/*
un message d'appuie sur un bouton se présente sous la forme #TUXBUTTON:HEAD
ou sous la forme #TUXREMOTE:K_DOWN
Il faut donc que le caractère # et le caractère : soit présent, sinon c'est qu'il
s'agit d'un autre type de message
*/
if(strchr(msg,'#') && strchr(msg,':'))
{
pch = NULL; /* initialisation du pointeur */
pch = strtok(msg,":"); /* split sur le cractère : */
if(pch)
{
strcpy(type,pch); /* copi le type de bouton dans le buffer */
pch = strtok(NULL,":"); /* récupère ce qu'il y a après le caractère : */
if(pch)
strcpy(param,pch); /* copi le nom du bouton dans le buffer */
/* on vérifie que l'on a bien récupérer le type de bouton ainsi que le nom du bouton */
if(strcmp(type,"") && strcmp(param,""))
{
if(!strcmp(type,"#TUXREMOTE")) /* c'est un bouton de la télécommande */
onRemoteButtonPressed(param);
}
if(!strcmp(type,"#TUXDROIDSERVER") && !strcmp(param,"FLACFINISH\r"))
{
/*Ici la conversion vers le flac est fini
si on est en mode ASR: */
if(isRecordingASR)
{
/* alors on envoie Tux_ASR() */
sendMessage("Tux_Asr(asr.flac)");
}
}
if(!strcmp(type,"#TUXASRRESULT"))
{
manageASRResult(trim(param));
}
}
}
else /* tout autre type de message */
{
printf("server: %s\n",msg);
}
}
/* Fonction de lecture des données en provenance du server */
void *ReadServer(void *data)
{
char buffer[BUFFER_MAX_SIZE]; /* création du buffer qui contiendra le message du server */
while(sock) /* tant que la connexion existe */
{
recv(sock,buffer,BUFFER_MAX_SIZE,0); /* lecture des messages */
ParseMessage(buffer); /* on parse le message recus */
}
}
int main(void)
{
struct sockaddr_in srv; /* structure d'informations de connexion */
/* Initialisation de la socket pour Windows */
#ifdef _WIN32
WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);
#endif
/* création de la connexion au server */
srv.sin_family = AF_INET;
srv.sin_addr.s_addr = inet_addr("127.0.0.1"); /* connexion au server local, pour un server distant penser à changer l'ip */
srv.sin_port = htons(9595); /* pour sur lequel écoute le server, 9595 est le port par défaut */
/* Création de la socket */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket");
exit(1);
}
/* Connexion au server */
if (connect(sock, (struct sockaddr*) &srv, sizeof(srv)) < 0)
{
perror("connect");
exit(1);
}
/* si on est arrivé jusqu'ici c'est que l'on est connecter ! */
printf("Connecter\n\n");
/*
On envoie la clef d'identification au server
Voir le wiki au sujet de Tux_Key ainsi que la page sur le fichier de configuration
du server pour plus d'informations
*/
send(sock,"Tux_Key(test)",13,0);
/* Lance le thread de lecture des messges en provenance du server */
pthread_attr_init(&sockThread_attr);
pthread_attr_setdetachstate (&sockThread_attr, PTHREAD_CREATE_DETACHED);
pthread_create (&sockThread, &sockThread_attr, ReadServer, NULL);
while(1){}
return 1;
}