diff --git a/scripts/atis/.gitignore b/scripts/atis/.gitignore new file mode 100644 index 000000000..4a675de98 --- /dev/null +++ b/scripts/atis/.gitignore @@ -0,0 +1,4 @@ +*.vlist +*.vce +*.wav.gz +snip/* diff --git a/scripts/atis/README b/scripts/atis/README new file mode 100644 index 000000000..e5d484b41 --- /dev/null +++ b/scripts/atis/README @@ -0,0 +1,50 @@ +The ATIS Voice Generation HowTo +------------------------------- + +Required packages / installation hints by J. Denker +--------------------------------------------------- + cpan Audio::Wav + apt-get install festival mbrola sox festlex-oald + cd \$tars + wget http://tcts.fpms.ac.be/synthesis/mbrola/dba/en1/en1-980910.zip + wget http://www.cstr.ed.ac.uk/downloads/festival/1.95/festvox_en1.tar.gz + cd /usr/share/festival/voices/english + mkdir en1_mbrola + cd en1_mbrola + unzip \$tars/en1-980910.zip + cd /usr/share/festival + mkdir lib + cd lib + ln -s ../voices ./ + cd /usr/share + tar -xpzvf \$tars/festvox_en1.tar.gz + +Generating Voice Files +---------------------- + + 1. Configure paths to fgdata and flightgear sources + export FG_ROOT=/home/whatever/fgdata + export FG_SRC=/home/whatever/flightgear + + 2. Create phraseology word list + ./atis-lex.pl > phraseology.vlist + + 3. Create airport word list + export ATIS_ONLY=yes + ./list-airports.pl | ./words_per_line.sh > airports.vlist + + 4. Check for and fix non-UTF8 encoded airport names + ./find_nonUTF8.pl + + 5. Generate phraseology voice file + ./synth.pl phraseology.vlist phraseology.vce phraseology.wav + + 6. Generate airport voice file + ./synth.pl airports.vlist airports.vce airports.wav + + 7. Install *.vce and *.wav.gz files in fgdata: + cp phraseology.vce $(FG_ROOT)/ATC/voices/default/. + cp phraseology.wav.gz $(FG_ROOT)/ATC/voices/default/. + cp airports.vce $(FG_ROOT)/ATC/voices/default/. + cp airports.wav.gz $(FG_ROOT)/ATC/voices/default/. + diff --git a/scripts/atis/atis-lex.pl b/scripts/atis/atis-lex.pl index 583080e13..701f1c673 100755 --- a/scripts/atis/atis-lex.pl +++ b/scripts/atis/atis-lex.pl @@ -1,16 +1,14 @@ #! /usr/bin/perl -w sub usage { - print <<\EoF; + print < $whatever.vlist + FG_ROOT=/home/whatever/fgdata FG_SRC=/home/whatever/flightgear ./atis-lex.pl > phraseology.vlist EoF } @@ -24,13 +22,14 @@ main: { usage; exit; } - my $mapfn = "$fgroot/../fgs/src/ATCDCL/atis_lexicon.hxx"; + my $mapfn = "$ENV{'FG_SRC'}/src/ATCDCL/atis_lexicon.hxx"; my $mapch = Symbol::gensym; if (!open($mapch, '<', $mapfn)) { print STDERR "Could not open abbreviation file '$mapfn'\n"; print STDERR "Maybe you need to set FG_ROOT\n"; exit(1); } + print "/\n"; while (my $line = <$mapch>) { chomp $line; if ($line =~ s/^[ \t]*Q[(]//) { @@ -76,5 +75,6 @@ whiskey xray yankee zulu +decimal EoF } diff --git a/scripts/atis/find_nonUTF8.pl b/scripts/atis/find_nonUTF8.pl index a5cf22ebc..dcd45cf73 100755 --- a/scripts/atis/find_nonUTF8.pl +++ b/scripts/atis/find_nonUTF8.pl @@ -2,7 +2,7 @@ my($content, $length); -open(FILE, "< atis.list") || die "Unable to open file small. <$!>\n"; +open(FILE, "< airports.vlist") || die "Unable to open file small. <$!>\n"; while( chomp($content = ) ) { $length = length($content); diff --git a/scripts/atis/list-airports.pl b/scripts/atis/list-airports.pl index a431fca68..347b92842 100755 --- a/scripts/atis/list-airports.pl +++ b/scripts/atis/list-airports.pl @@ -9,14 +9,14 @@ Print airport names, one per line. Remapping is done by reference to the atis_remap.hxx file. Typical usage: - FG_ROOT=whatever ATIS_ONLY=yes ./list-airports.pl | words_per_line.sh > atis.list + FG_ROOT=whatever FG_SRC=whatever ATIS_ONLY=yes ./list-airports.pl | ./words_per_line.sh > airports.vlist EoF } use strict; use Symbol; -my $noparen = 1; + my $noparen = 1; my $verbose = 0; my $apt_name = ''; my $lat; @@ -38,6 +38,7 @@ my $noparen = 1; my $fgroot = $ENV{'FG_ROOT'} || '.'; my $atis_only = $ENV{'ATIS_ONLY'} || 0; + my $mapfn = "$ENV{'FG_SRC'}/src/ATCDCL/atis_remap.hxx"; sub process_apt { if ($atis_only && ! $atis) { @@ -60,7 +61,6 @@ sub get_remap { # Note: in this context, GKI probably stands for Gereja Kristen Indonesia # I guess the church builds lots of airports. - my $mapfn = "$fgroot/../fgs/src/ATCDCL/atis_remap.hxx"; my $mapch = Symbol::gensym; if (!open($mapch, '<', $mapfn)) { print STDERR "Could not open abbreviation file '$mapfn'\n"; @@ -84,11 +84,16 @@ sub get_remap { } main: { + if (@ARGV) { + usage; + exit; + } get_remap; my $delim = '-'; - my $incmd = 'zcat /games/sport/fgd/Airports/apt.dat.gz'; + my $fgroot = $ENV{'FG_ROOT'} || 0; + my $incmd = "zcat $fgroot/Airports/apt.dat.gz"; my $inch = Symbol::gensym; open ($inch, '-|', $incmd) || die "Couldn't open pipe from '$incmd'\n"; diff --git a/scripts/atis/quiet0.500.wav b/scripts/atis/quiet0.500.wav new file mode 100644 index 000000000..bceb4e626 Binary files /dev/null and b/scripts/atis/quiet0.500.wav differ diff --git a/scripts/atis/synth.pl b/scripts/atis/synth.pl index 1cc0d2223..86cbf6764 100755 --- a/scripts/atis/synth.pl +++ b/scripts/atis/synth.pl @@ -88,6 +88,7 @@ my %fixup = ( main: { my $skip = 0; + my $fmtcheck = 1; my $oneword = 0; my $gripe = 0; my $out_bits_sample = 8; ## this is what FGFS expects @@ -122,6 +123,10 @@ main: { $oneword++; next argx; } + if ($arg eq '-nocheck') { + $fmtcheck=0; + next argx; + } if ($arg =~ '^-') { die "Unrecognized option '$arg'\n"; } @@ -184,23 +189,31 @@ main: { || die "Could not create directory 'snip' : $!\n"; } -############## system "/bin/cp nothing.wav t1.wav"; - my $where = 0; + my $wav = new Audio::Wav; + my $waver = $wav -> read("quiet0.500.wav"); my $sample_rate = -1; my $channels = -1; my $bits_sample = -1; + $sample_rate = ${$waver->details()}{'sample_rate'}; + $channels = ${$waver->details()}{'channels'}; + $bits_sample = ${$waver->details()}{'bits_sample'}; + +############## system "/bin/cp nothing.wav t1.wav"; + my $where = 0; my $ii = 0; + snipper: for my $thing (sort keys %list) { $ii++; my $iix = sprintf('%05d', $ii); my $xfn = "./snip/x$iix"; + print( "$xfn\n"); my $fraise = lc($thing); if (exists $fixup{$fraise}) { #xxxx print "fixing $fraise\n"; $fraise = $fixup{$fraise}; } - + ## This turns dashes and other funny stuff into spaces ## in the phrase to be processed: $fraise =~ s%[^a-z']+% %gi; @@ -223,18 +236,27 @@ main: { next snipper; } } + } - my $wav = new Audio::Wav; - my $waver = $wav -> read("$xfn.wav"); - if ($sample_rate < 0) { - $sample_rate = ${$waver->details()}{'sample_rate'}; - $channels = ${$waver->details()}{'channels'}; - $bits_sample = ${$waver->details()}{'bits_sample'}; - } else { - $sample_rate == ${$waver->details()}{'sample_rate'} - && $channels == ${$waver->details()}{'channels'} - && $bits_sample == ${$waver->details()}{'bits_sample'} - || die "audio format not the same: $xfn.wav"; + $ii = 0; + snipper: for my $thing (sort keys %list) { + $ii++; + my $iix = sprintf('%05d', $ii); + my $xfn = "./snip/x$iix"; + + if ($fmtcheck == 1) { + my $wav = new Audio::Wav; + my $waver = $wav -> read("$xfn.wav"); + if ($sample_rate < 0) { + $sample_rate = ${$waver->details()}{'sample_rate'}; + $channels = ${$waver->details()}{'channels'}; + $bits_sample = ${$waver->details()}{'bits_sample'}; + } else { + $sample_rate == ${$waver->details()}{'sample_rate'} + && $channels == ${$waver->details()}{'channels'} + && $bits_sample == ${$waver->details()}{'bits_sample'} + || die "audio format not the same: $xfn.wav"; + } } my $statcmd = "2>&1 sox $xfn.wav -n stat"; @@ -268,12 +290,16 @@ main: { if ($size == 0) { print STDERR "?Warning! Zero-size audio file for $iix '$thing'\n"; } + + if ($vol > 20) { + ## unreasonable volume, happens with 'silent' files + $vol = 0; + } printf("%s %6.3f %6d '%s'\n", $iix, $vol, $size, $thing); my $subsize = int($size/2); printf $index ("%-45s %10d %10d\n", $thing, $where, $subsize); $where += $subsize; - my $volume_cmd = sprintf("sox -v %6.3f %s.wav %s.raw", $vol*0.9, $xfn, $xfn); ########## print "+ $volume_cmd\n"; @@ -300,6 +326,7 @@ main: { die "Cat command failed: $cat_cmd"; } + ## Convert RAW to WAVE format my $wav_cmd = "sox --rate $sample_rate --bits $bits_sample" . " --encoding signed-integer" . " ./snip/everything.raw --rate 8000 --bits $out_bits_sample $out_wav"; @@ -311,4 +338,12 @@ main: { if ($?) { die ".wav command failed: $wav_cmd"; } + + ## Compress WAVE file + my $gz_cmd = "gzip -f $out_wav"; + my $gz_handle = Symbol::gensym; + open ($gz_handle, '|-', $gz_cmd) + || die "Couldn't open pipe to command '$gz_cmd'\n"; + close $gz_handle; + system("rm snip/*; rmdir snip"); }