shithub: flite

ref: 6a2b3b03e3a985937ef609830599572545fce77e
dir: /main/flite_plan9.c/

View raw version
/*************************************************************************/
/*																	   */
/*				  Language Technologies Institute					  */
/*					 Carnegie Mellon University						*/
/*						 Copyright (c) 2001							*/
/*						All Rights Reserved.						   */
/*																	   */
/*  Permission is hereby granted, free of charge, to use and distribute  */
/*  this software and its documentation without restriction, including   */
/*  without limitation the rights to use, copy, modify, merge, publish,  */
/*  distribute, sublicense, and/or sell copies of this work, and to	  */
/*  permit persons to whom this work is furnished to do so, subject to   */
/*  the following conditions:											*/
/*   1. The code must retain the above copyright notice, this list of	*/
/*	  conditions and the following disclaimer.						 */
/*   2. Any modifications must be clearly marked as such.				*/
/*   3. Original authors' names are not deleted.						 */
/*   4. The authors' names are not used to endorse or promote products   */
/*	  derived from this software without specific prior written		*/
/*	  permission.													  */
/*																	   */
/*  CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK		 */
/*  DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING	  */
/*  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT   */
/*  SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE	  */
/*  FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES	*/
/*  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN   */
/*  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,		  */
/*  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF	   */
/*  THIS SOFTWARE.													   */
/*																	   */
/*************************************************************************/
/*			 Author:  Sigrid										   */
/*			   Date:  June 2021										*/
/*************************************************************************/
/*																	   */
/*  Simple top level program for Plan 9								  */
/*																	   */
/*************************************************************************/

#include <flite.h>
#include <bio.h>
#include "flite_version.h"

#pragma lib "../lang/cmu_us_awb/libcmu_us_awb.$M.a"
#pragma lib "../lang/cmu_us_rms/libcmu_us_rms.$M.a"
#pragma lib "../lang/cmu_us_slt/libcmu_us_slt.$M.a"
#pragma lib "../lang/cmulex/libcmulex.$M.a"
#pragma lib "../lang/usenglish/libusenglish.$M.a"
#pragma lib "../src/audio/libaudio.$M.a"
#pragma lib "../src/cg/libcg.$M.a"
#pragma lib "../src/hrg/libhrg.$M.a"
#pragma lib "../src/lexicon/liblexicon.$M.a"
#pragma lib "../src/regex/libregex.$M.a"
#pragma lib "../src/speech/libspeech.$M.a"
#pragma lib "../src/stats/libstats.$M.a"
#pragma lib "../src/synth/libsynth.$M.a"
#pragma lib "../src/utils/libutils.$M.a"
#pragma lib "../src/wavesynth/libwavesynth.$M.a"

void *
flite_set_lang_list(void)
{
	return nil;
}

cst_voice *register_cmu_us_awb(const char *voxdir);
cst_voice *register_cmu_us_rms(const char *voxdir);
cst_voice *register_cmu_us_slt(const char *voxdir);

cst_val *
flite_set_voice_list(const char *voxdir)
{
	flite_voice_list = cons_val(voice_val(register_cmu_us_slt(voxdir)), flite_voice_list);
	flite_voice_list = cons_val(voice_val(register_cmu_us_awb(voxdir)), flite_voice_list);
	flite_voice_list = cons_val(voice_val(register_cmu_us_rms(voxdir)), flite_voice_list);
	flite_voice_list = val_reverse(flite_voice_list);

	return flite_voice_list;
}

static void
usage(void)
{
	cst_voice *voice;
	const cst_val *v;

	fprint(2, "usage: flite [-v VOICE] [>/dev/audio]\n");

	fprint(2, "voices:");
	for(v = flite_voice_list; v; v = val_cdr(v)){
		voice = val_voice(val_car(v));
		fprint(2, " %s", voice->name);
	}
	fprint(2, "\n");

	fprint(2, "  Carnegie Mellon University, Copyright (c) 1999-2021, all rights reserved\n");
	fprint(2, "  version: %s-%s-%s %s (http://cmuflite.org)\n",
		FLITE_PROJECT_PREFIX,
		FLITE_PROJECT_VERSION,
		FLITE_PROJECT_STATE,
		FLITE_PROJECT_DATE);

	exits("usage");
}

static int
runconv(cst_wave *w)
{
	char fmt[16];
	int p[2];

	sprintf(fmt, "s%dr%dc%d", 16, cst_wave_sample_rate(w), cst_wave_num_channels(w));

	pipe(p);
	if(rfork(RFPROC|RFNOTEG|RFFDG|RFCENVG) == 0){
		dup(p[1], 0);
		close(p[0]);
		close(p[1]);
		execl("/bin/audio/pcmconv", "pcmconv", "-i", fmt, nil);
		fprint(2, "%r\n");
		exits("pcmconv");
	}
	close(p[1]);

	return p[0];
}

static int fd = -1;

static int
audiochunk(const cst_wave *w, int start, int size, int last, cst_audio_streaming_info *a)
{
	USED(last, a);

	if(fd < 0)
		fd = runconv(w);

	write(fd, cst_wave_samples(w)+start, 2*size);
	if(last)
		return CST_AUDIO_STREAM_STOP;

	return CST_AUDIO_STREAM_CONT;
}

void
main(int argc, char **argv)
{
    cst_audio_streaming_info *a;
	char *s, *v;
	cst_voice *voice;
	Biobuf in;

	if(Binit(&in, 0, OREAD|OCEXEC) != 0)
		sysfatal("bio: %r");

	flite_init();
	flite_set_lang_list();
	quotefmtinstall();
	flite_set_voice_list(nil);

	v = nil;
	ARGBEGIN{
	case 'v':
		v = EARGF(usage());
		break;
	default:
		usage();
	}ARGEND

	if((voice = flite_voice_select(v)) == nil)
		sysfatal("invalid voice %q", v);

	feat_copy_into(new_features(), voice->features);
	a = new_audio_streaming_info();
	a->asc = audiochunk;
	a->min_buffsize = 4096;
	feat_set(voice->features, "streaming_info", audio_streaming_info_val(a));

	for(;;){
		if((s = Brdstr(&in, '\n', 1)) == nil)
			break;

		flite_text_to_speech(s, voice, "stream");
	}

	close(fd);
	waitpid();

	exits(nil);
}