Show audioclient.c syntax highlighted
/*
*
* Copyright (c) 2003 The Regents of the University of California. All
* rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* a sensor-client-based client for sensor-device
*/
#include "libdev/sensor_dev.h"
#include <stdio.h>
#define _GNU_SOURCE
#include <getopt.h>
#undef _GNU_SOURCE
#include <openssl/bio.h>
#include <openssl/evp.h>
#include "sys/time.h"
#include "time.h"
#include "libmisc/misc_buf.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <curl/curl.h>
#include "libdev/glib_dev.h"
#include <ftw.h>
#include <unistd.h>
// for ecasound
#include <audiofile.h>
#include <ecasoundc.h>
// for sphinx
#include <s2types.h>
#include <fbs.h>
#define BUF_THRESH 1000000
#define CURL_TIMEOUT 60
#define MAX_AGE 300
BIO * bio, *b64;
int counter = 0;
int file_counter = 0;
int fd = 1;
buf_t * state_buf;
g_event_t * upload_timer_context = NULL;
char * file_dir = "/media/cf/soundfiles";
char * wav_dir = "/media/cf/wavfiles";
char * ram_dir = "/media/ram";
int number_of_files = 0;
char curl_error_buf[CURL_ERROR_SIZE];
// This is a blocking call due to curl_easy_perform(.).
// filename is an xml file that you want to HTTP PUT to
// http://131.179.144.42/sensor1/data/data.xml
//
// It opens, reads, uploads, and closes, and cleans up.
CURLcode http_put(const char * filename)
{
CURL * curl;
CURLcode res;
FILE * hd_src;
int hd;
struct stat file_info;
char * url = "http://131.179.144.42/sensor1/data/data.xml";
elog(LOG_INFO,"HTTP_PUT %s to %s",filename, url);
// Get the file size.
hd = open(filename, O_RDONLY);
fstat(hd, &file_info);
elog(LOG_INFO,"File size is: %d", file_info.st_size);
close(hd);
hd_src = fopen(filename, "rb"); // Get a FILE * to the same file.
curl_global_init(CURL_GLOBAL_ALL); // Something we have to do.
curl = curl_easy_init(); // Get a curl handle.
if (curl) {
// Make verbose
// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1); // Enable uploading.
curl_easy_setopt(curl, CURLOPT_PUT, 1); // Specify HTTP PUT.
curl_easy_setopt(curl, CURLOPT_URL, url); // Specify the target url.
curl_easy_setopt(curl, CURLOPT_READDATA, hd_src); // Specify which file to upload
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); // Specify readfunction.
curl_easy_setopt(curl, CURLOPT_INFILESIZE, file_info.st_size); // Size of the upload.
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_error_buf); // Pointer to curl error msg buf.
curl_easy_setopt(curl, CURLOPT_TIMEOUT, CURL_TIMEOUT); // Set the timeout for the transfer.
res = curl_easy_perform(curl); // Do it.
curl_easy_cleanup(curl); // Clean up.
}
fclose(hd_src);
curl_global_cleanup();
elog(LOG_INFO,"Done.");
return res;
}
/* This is the callback passed to ftw.
If it's a non-file, then skip it and go to next item.
If the file is too old, delete it and go to the next item.
Call http_put (file);
If the file was uploaded, delete it and stop.
If there was an error uploading, then go to the next item.
*/
int
upload (const char * file, const struct stat * sb, int flag)
{
// elog (LOG_NOTICE, "%s", file);
if (FTW_F != flag)
{
return 0; // Continue the file tree walk.
}
double age = difftime(time(NULL), sb->st_mtime);
if ((age > MAX_AGE) || (age < -(MAX_AGE)))
{
elog (LOG_INFO, "%s is %f seconds old. Deleting.", file, age);
unlink(file);
return 0; // Continue the file tree walk.
}
int res = http_put (file); // http PUT the file.
// If it was uploaded, then delete the file.
if (res == 0)
{
elog(LOG_INFO,"SUCCESSFUL");
unlink (file);
return 1; // Stop the walk
}
else
{
elog (LOG_ERR,"Error: %s", curl_error_buf);
return 0; // Continue the walk
}
}
/* This is a g_timer callback. It periodically walks the file tree in
file_dir, applying the upload function, defined above.
*/
static int
upload_timer (gpointer data, int interval, g_event_t * ev)
{
// elog (LOG_NOTICE, " ");
if (ftw (file_dir, upload, 4) < 0)
{
elog (LOG_CRIT, "ftw encountered an error %s: %m", file_dir);
}
return TIMER_RENEW;
}
// buf contains raw acoustic data. It's someone else's job to free the
// buf.
void write_out(buf_t * raw_acoustic_buf)
{
//time
struct timeval current_time;
gettimeofday(¤t_time,NULL);
double current_seconds = 1.0 * current_time.tv_sec + current_time.tv_usec / 1000000.0;
// file
FILE * fstream = NULL;
// create file name
char fname[256];
sprintf(fname,"%s/foo%d.xml", file_dir, ++file_counter);
elog(LOG_INFO,"Writing to file: %s", fname);
if ((fstream = fopen(fname, "w")) == NULL)
{
perror("stdout");
exit(-1);
}
// buffer
buf_t * start_buf = buf_new();
bufprintf(start_buf,"<data><datum time=\"%f\" value=\"",current_seconds);
buf_t * end_buf = buf_new();
bufprintf(end_buf,"\"/></data>");
// write start_buf
fwrite(buf_get(start_buf), 1, buf_len(start_buf), fstream);
// write to raw_acoustic_buf in base64
BIO *bio, *b64;
b64 = BIO_new(BIO_f_base64());
bio = BIO_new_fp(fstream, BIO_NOCLOSE);
bio = BIO_push(b64, bio);
BIO_write(bio, buf_get(raw_acoustic_buf), buf_len(raw_acoustic_buf));
BIO_flush(bio);
BIO_free_all(bio);
// write end_buf
fwrite(buf_get(end_buf), 1, buf_len(end_buf), fstream);
// clean up buffers and close file.
buf_free(start_buf);
buf_free(end_buf);
fclose(fstream);
// http_put(fname);
return;
}
// Normalizes the volume of the current WAV file.
void normalize_wav ()
{
elog (LOG_INFO, "Start.");
float multiplier = 1.0;
buf_t * ai_file = buf_new();
buf_t * ao_file = buf_new();
buf_t * ai_tmp = buf_new();
buf_t * ao_tmp = buf_new();
buf_t * ea = buf_new();
bufprintf (ai_file, "ai-add %s/foo%d.wav", wav_dir, file_counter);
bufprintf (ao_file, "ao-add %s/foo%dnormalized.wav", wav_dir, file_counter);
bufprintf (ai_tmp, "ai-add %s/tmp.wav", wav_dir);
bufprintf (ao_tmp, "ao-add %s/tmp.wav", wav_dir);
eci_init();
eci_command ("cs-add default");
eci_command ("c-add default");
eci_command (buf_get(ai_file));
eci_command (buf_get(ao_tmp));
eci_command ("cop-add -ev");
eci_command ("cs-connect");
eci_command ("run");
eci_command ("cop-select 1");
eci_command ("copp-select 2"); // second param of -ev
eci_command ("copp-get");
multiplier = eci_last_float();
elog (LOG_INFO, "Multiplier is %f.", multiplier * 100.0);
//if (multiplier <= 1.0)
// {
// goto done;
// }
eci_command ("cs-disconnect");
eci_command ("cs-select default");
eci_command ("cs-remove");
eci_command ("cs-add default");
eci_command ("c-add default");
eci_command (buf_get(ai_tmp));
eci_command (buf_get(ao_file));
{
bufprintf (ea, "cop-add -ea:%f", multiplier * 100.0);
eci_command (buf_get(ea));
}
eci_command ("cs-connect");
eci_command ("run");
// done:
eci_command ("cs-disconnect");
eci_command ("cop-status");
elog (LOG_INFO, "Chain operator status: %s", eci_last_string());
eci_cleanup();
buf_free (ai_file);
buf_free (ao_file);
buf_free (ai_tmp);
buf_free (ao_tmp);
buf_free (ea);
}
void noise_gate_wav ()
{
elog(LOG_INFO, "Start.");
buf_t * ai_add_buf = buf_new();
bufprintf (ai_add_buf, "ai-add %s/foo%dnormalized.wav", wav_dir, file_counter);
buf_t * ao_add_buf = buf_new();
bufprintf (ao_add_buf, "ao-add %s/foo%dnoise_gate.wav", wav_dir, file_counter);
eci_init();
eci_command("cs-add default");
eci_command("c-add default");
eci_command(buf_get(ai_add_buf));
eci_command(buf_get(ao_add_buf));
eci_command("cop-add -enm:50,100,300,1,0");
eci_command("cop-select 1");
eci_command("cs-connect");
eci_command("start"); // this is non-blocking, which will be useful in the future.
while ( 1 )
{
sleep ( 1 );
eci_command ( "engine-status" );
if ( strcmp ( eci_last_string(), "running") != 0 ) break;
}
eci_command("stop");
eci_command("cs-disconnect");
eci_command("select default");
eci_command("cs-remove");
eci_command("cop-status");
elog (LOG_INFO, "Chain operator status: %s", eci_last_string());
eci_cleanup();
buf_free(ao_add_buf);
buf_free(ai_add_buf);
elog(LOG_INFO, "Done.");
return;
}
void time_gate_wav ()
{
elog(LOG_INFO, "Start.");
buf_t * ai_add_buf = buf_new();
bufprintf (ai_add_buf, "ai-add %s/foo%dnormalized.wav", wav_dir, file_counter);
buf_t * ao_add_buf = buf_new();
bufprintf (ao_add_buf, "ao-add %s/foo%dtime_gate.wav", wav_dir, file_counter);
eci_init();
eci_command("cs-add default");
eci_command("c-add default");
eci_command(buf_get(ai_add_buf));
eci_command(buf_get(ao_add_buf));
eci_command("cop-add -eemp:0.5,20");
eci_command("cop-select 1");
eci_command("cs-connect");
eci_command("start"); // this is non-blocking, which will be useful in the future.
while ( 1 )
{
sleep ( 1 );
eci_command ( "engine-status" );
if ( strcmp ( eci_last_string(), "running") != 0 ) break;
}
eci_command("stop");
eci_command("cs-disconnect");
eci_command("select default");
eci_command("cs-remove");
eci_command("cop-status");
elog (LOG_INFO, "Chain operator status: %s", eci_last_string());
eci_cleanup();
buf_free(ao_add_buf);
buf_free(ai_add_buf);
elog(LOG_INFO, "Done.");
return;
}
void write_wav(buf_t * raw_acoustic_buf)
{
/*********** Create and open a WAVE file ************/
// Create an audio file setup.
AFfilesetup setup = afNewFileSetup ();
// Initialize the audio file format as Waveform Audio File Format (RIFF)
afInitFileFormat ( setup, AF_FILE_WAVE );
afInitByteOrder ( setup, AF_DEFAULT_TRACK, AF_BYTEORDER_LITTLEENDIAN );
afInitChannels ( setup, AF_DEFAULT_TRACK, 1 );
afInitRate ( setup, AF_DEFAULT_TRACK, 16000.0 );
afInitSampleFormat ( setup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
// Opening the audio file;
char fname[256];
sprintf ( fname, "%s/foo%d.wav", wav_dir, file_counter );
AFfilehandle handle = afOpenFile ( fname, "w", setup );
if ( handle == AF_NULL_FILEHANDLE )
{
fprintf ( stderr, "Error opening file %s\n", fname );
exit ( 1 );
}
/************* Write to a WAVE file ****************/
int sample_count = buf_len (raw_acoustic_buf) / 4;
int return_count = afWriteFrames ( handle,
AF_DEFAULT_TRACK,
buf_get(raw_acoustic_buf),
sample_count );
if ( return_count != sample_count )
{
fprintf ( stderr, "ERROR: afWriteFrame returned %d.\n", return_count );
}
/************* Close a WAVE file ****************/
// Close the AFfilehandle
afCloseFile ( handle );
// Free the audio file setup.
afFreeFileSetup ( setup );
return;
}
void
get_phones ()
{
elog (LOG_INFO, "Start.");
buf_t * fname = buf_new();
bufprintf (fname, "%s/foo%dnormalized.wav", wav_dir, file_counter);
search_hyp_t * h = uttproc_allphone_file (buf_get(fname));
for (; h; h = h->next)
{
elog (LOG_INFO, "%4d %4d %s", h->sf, h->ef, h->word);
}
buf_free(fname);
elog (LOG_INFO, "Done.");
return;
}
void
init_phones (char * argv[])
{
char *v[] = { argv[0]
,"-allphone" ,"TRUE"
,"-datadir" ,"./model/lm/turtle"
,"-agcmax" ,"TRUE"
,"-langwt" ,"6.5"
,"-fwdflatlw" ,"8.5"
,"-rescorelw" ,"9.5"
,"-ugwt" ,"0.5"
,"-fillpen" ,"1e-10"
,"-silpen" ,"0.005"
,"-inspen" ,"0.65"
,"-top" ,"1"
,"-topsenfrm" ,"3 "
,"-topsenthresh" ,"-70000"
,"-beam" ,"2e-06"
,"-npbeam" ,"2e-06"
,"-lpbeam" ,"2e-05"
,"-lponlybeam" ,"0.0005"
,"-nwbeam" ,"0.0005"
,"-fwdflat" ,"TRUE"
,"-fwdflatbeam" ,"1e-08"
,"-fwdflatnwbeam" ,"0.0003"
,"-bestpath" ,"TRUE"
,"-kbdumpdir" ,"./model/lm/turtle"
// ,"-lmfn" ,"./model/lm/turtle/turtle.lm"
,"-dictfn" ,"./model/lm/turtle/turtle.dic"
,"-ndictfn" ,"./model/hmm/6k/noisedict"
,"-phnfn" ,"./model/hmm/6k/phone"
,"-mapfn" ,"./model/hmm/6k/map"
,"-kdtreefn" ,"./model/hmm/6k/kdtrees"
,"-hmmdir" ,"./model/hmm/6k"
,"-hmmdirlist" ,"./model/hmm/6k"
,"-8bsen" ,"TRUE"
,"-sendumpfn" ,"./model/hmm/6k/sendump"
,"-cbdir" ,"./model/hmm/6k"
,"-mmap" ,"TRUE"
};
int c = sizeof(v) / sizeof(char*);
fbs_init (c, v);
return;
}
int sce_do_nothing(void* arg, sc_sample_t* sample)
{
bufcat(state_buf, sample->data);
if (buf_len(state_buf) > BUF_THRESH)
{
elog(LOG_INFO,"Writing file.");
write_out(state_buf);
write_wav(state_buf);
normalize_wav();
// time_gate_wav();
// noise_gate_wav ();
get_phones ();
buf_free(state_buf);
state_buf = buf_new();
}
return EVENT_RENEW;
}
// I don't think this function actually gets called.
int sce_series_do_nothing(void* arg, sc_series_t* sample)
{
// int i;
// int16_t tmp_num;
// void *tmp;
bufcat(state_buf, sample->data);
if (buf_len(state_buf) > BUF_THRESH)
{
elog(LOG_INFO,"Writing file.");
write_out(state_buf);
write_wav(state_buf);
normalize_wav();
// time_gate_wav();
// noise_gate_wav();
get_phones();
buf_free(state_buf);
state_buf = buf_new();
}
return EVENT_RENEW;
}
void usage(char *s)
{
fprintf(stderr,
"%s: %s -d devicename [-a <n>]\n\n"
"-d Specify the device name\n"
"-a aggregates data and calls client cb once every n samples\n",
s, s);
exit(1);
}
int main(int argc, char *argv[])
{
char* key;
char devicename[100];
int data_aggregated = 1;
misc_init(&argc, argv, CVSTAG);
if ((key = misc_parse_out_option(&argc, argv, "help", 'h'))) {
usage(argv[0]);
optind++;
}
if ((key = misc_parse_out_option(&argc, argv, "aggregate", 'a'))) {
data_aggregated = atoi(key);
elog(LOG_DEBUG(1),"Set aggregate: %d\n", data_aggregated);
optind++;
}
if ((key = misc_parse_out_option(&argc, argv, "device", 'd'))) {
strcpy(devicename, key);
elog(LOG_DEBUG(3),"Device name: %s\n", devicename);
}
else {
fprintf(stderr, "%s: No device name specified\n", argv[0]);
usage(argv[0]);
exit(1);
}
if (data_aggregated > 1)
{
sc_open_stream(devicename, 0, 0, data_aggregated, sce_series_do_nothing, NULL, NULL);
}
else
{
sc_open_sample_stream(devicename, 0, 0, sce_do_nothing, NULL, NULL);
}
if (g_timer_add (5000, upload_timer, NULL, NULL, &upload_timer_context) < 0)
{
elog (LOG_ERR, "Unable to create timer event.");
exit (1);
}
init_phones(argv);
state_buf = buf_new();
g_main();
return (1);
}
See more files for this project here