Update ATIS voice generation scripts
Split voice samples into two separate files (airport and phraseology). Compress voice samples.
This commit is contained in:
parent
2d424062b7
commit
3bf09215b0
7 changed files with 119 additions and 25 deletions
4
scripts/atis/.gitignore
vendored
Normal file
4
scripts/atis/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*.vlist
|
||||
*.vce
|
||||
*.wav.gz
|
||||
snip/*
|
50
scripts/atis/README
Normal file
50
scripts/atis/README
Normal file
|
@ -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/.
|
||||
|
|
@ -1,16 +1,14 @@
|
|||
#! /usr/bin/perl -w
|
||||
|
||||
sub usage {
|
||||
print <<\EoF;
|
||||
print <<EoF;
|
||||
Read the atis_lexicon.hxx file and print
|
||||
the vocabulary words ... plus phonetic digits and letters.
|
||||
|
||||
See also list-airports.pl
|
||||
|
||||
Typical usage:
|
||||
(echo "/"
|
||||
FG_ROOT=/games/$whatever/fgd ATIS_ONLY=yes ./list-airports.pl
|
||||
FG_ROOT=/games/$whatever/fgd ./atis-lex.pl) > $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
|
||||
}
|
||||
|
|
|
@ -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 = <FILE>) ) {
|
||||
$length = length($content);
|
||||
|
|
|
@ -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";
|
||||
|
|
BIN
scripts/atis/quiet0.500.wav
Normal file
BIN
scripts/atis/quiet0.500.wav
Normal file
Binary file not shown.
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue