1
0
Fork 0

Update ATIS voice generation scripts

Split voice samples into two separate files (airport and phraseology).
Compress voice samples.
This commit is contained in:
ThorstenB 2012-10-13 01:27:52 +02:00
parent 2d424062b7
commit 3bf09215b0
7 changed files with 119 additions and 25 deletions

4
scripts/atis/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
*.vlist
*.vce
*.wav.gz
snip/*

50
scripts/atis/README Normal file
View 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/.

View file

@ -1,16 +1,14 @@
#! /usr/bin/perl -w #! /usr/bin/perl -w
sub usage { sub usage {
print <<\EoF; print <<EoF;
Read the atis_lexicon.hxx file and print Read the atis_lexicon.hxx file and print
the vocabulary words ... plus phonetic digits and letters. the vocabulary words ... plus phonetic digits and letters.
See also list-airports.pl See also list-airports.pl
Typical usage: Typical usage:
(echo "/" FG_ROOT=/home/whatever/fgdata FG_SRC=/home/whatever/flightgear ./atis-lex.pl > phraseology.vlist
FG_ROOT=/games/$whatever/fgd ATIS_ONLY=yes ./list-airports.pl
FG_ROOT=/games/$whatever/fgd ./atis-lex.pl) > $whatever.vlist
EoF EoF
} }
@ -24,13 +22,14 @@ main: {
usage; usage;
exit; exit;
} }
my $mapfn = "$fgroot/../fgs/src/ATCDCL/atis_lexicon.hxx"; my $mapfn = "$ENV{'FG_SRC'}/src/ATCDCL/atis_lexicon.hxx";
my $mapch = Symbol::gensym; my $mapch = Symbol::gensym;
if (!open($mapch, '<', $mapfn)) { if (!open($mapch, '<', $mapfn)) {
print STDERR "Could not open abbreviation file '$mapfn'\n"; print STDERR "Could not open abbreviation file '$mapfn'\n";
print STDERR "Maybe you need to set FG_ROOT\n"; print STDERR "Maybe you need to set FG_ROOT\n";
exit(1); exit(1);
} }
print "/\n";
while (my $line = <$mapch>) { while (my $line = <$mapch>) {
chomp $line; chomp $line;
if ($line =~ s/^[ \t]*Q[(]//) { if ($line =~ s/^[ \t]*Q[(]//) {
@ -76,5 +75,6 @@ whiskey
xray xray
yankee yankee
zulu zulu
decimal
EoF EoF
} }

View file

@ -2,7 +2,7 @@
my($content, $length); 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>) ) { while( chomp($content = <FILE>) ) {
$length = length($content); $length = length($content);

View file

@ -9,14 +9,14 @@ Print airport names, one per line.
Remapping is done by reference to the atis_remap.hxx file. Remapping is done by reference to the atis_remap.hxx file.
Typical usage: 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 EoF
} }
use strict; use strict;
use Symbol; use Symbol;
my $noparen = 1;
my $noparen = 1;
my $verbose = 0; my $verbose = 0;
my $apt_name = ''; my $apt_name = '';
my $lat; my $lat;
@ -38,6 +38,7 @@ my $noparen = 1;
my $fgroot = $ENV{'FG_ROOT'} || '.'; my $fgroot = $ENV{'FG_ROOT'} || '.';
my $atis_only = $ENV{'ATIS_ONLY'} || 0; my $atis_only = $ENV{'ATIS_ONLY'} || 0;
my $mapfn = "$ENV{'FG_SRC'}/src/ATCDCL/atis_remap.hxx";
sub process_apt { sub process_apt {
if ($atis_only && ! $atis) { if ($atis_only && ! $atis) {
@ -60,7 +61,6 @@ sub get_remap {
# Note: in this context, GKI probably stands for Gereja Kristen Indonesia # Note: in this context, GKI probably stands for Gereja Kristen Indonesia
# I guess the church builds lots of airports. # I guess the church builds lots of airports.
my $mapfn = "$fgroot/../fgs/src/ATCDCL/atis_remap.hxx";
my $mapch = Symbol::gensym; my $mapch = Symbol::gensym;
if (!open($mapch, '<', $mapfn)) { if (!open($mapch, '<', $mapfn)) {
print STDERR "Could not open abbreviation file '$mapfn'\n"; print STDERR "Could not open abbreviation file '$mapfn'\n";
@ -84,11 +84,16 @@ sub get_remap {
} }
main: { main: {
if (@ARGV) {
usage;
exit;
}
get_remap; get_remap;
my $delim = '-'; 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; my $inch = Symbol::gensym;
open ($inch, '-|', $incmd) open ($inch, '-|', $incmd)
|| die "Couldn't open pipe from '$incmd'\n"; || die "Couldn't open pipe from '$incmd'\n";

BIN
scripts/atis/quiet0.500.wav Normal file

Binary file not shown.

View file

@ -88,6 +88,7 @@ my %fixup = (
main: { main: {
my $skip = 0; my $skip = 0;
my $fmtcheck = 1;
my $oneword = 0; my $oneword = 0;
my $gripe = 0; my $gripe = 0;
my $out_bits_sample = 8; ## this is what FGFS expects my $out_bits_sample = 8; ## this is what FGFS expects
@ -122,6 +123,10 @@ main: {
$oneword++; $oneword++;
next argx; next argx;
} }
if ($arg eq '-nocheck') {
$fmtcheck=0;
next argx;
}
if ($arg =~ '^-') { if ($arg =~ '^-') {
die "Unrecognized option '$arg'\n"; die "Unrecognized option '$arg'\n";
} }
@ -184,16 +189,24 @@ main: {
|| die "Could not create directory 'snip' : $!\n"; || die "Could not create directory 'snip' : $!\n";
} }
############## system "/bin/cp nothing.wav t1.wav"; my $wav = new Audio::Wav;
my $where = 0; my $waver = $wav -> read("quiet0.500.wav");
my $sample_rate = -1; my $sample_rate = -1;
my $channels = -1; my $channels = -1;
my $bits_sample = -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; my $ii = 0;
snipper: for my $thing (sort keys %list) { snipper: for my $thing (sort keys %list) {
$ii++; $ii++;
my $iix = sprintf('%05d', $ii); my $iix = sprintf('%05d', $ii);
my $xfn = "./snip/x$iix"; my $xfn = "./snip/x$iix";
print( "$xfn\n");
my $fraise = lc($thing); my $fraise = lc($thing);
if (exists $fixup{$fraise}) { if (exists $fixup{$fraise}) {
@ -223,18 +236,27 @@ main: {
next snipper; next snipper;
} }
} }
}
my $wav = new Audio::Wav; $ii = 0;
my $waver = $wav -> read("$xfn.wav"); snipper: for my $thing (sort keys %list) {
if ($sample_rate < 0) { $ii++;
$sample_rate = ${$waver->details()}{'sample_rate'}; my $iix = sprintf('%05d', $ii);
$channels = ${$waver->details()}{'channels'}; my $xfn = "./snip/x$iix";
$bits_sample = ${$waver->details()}{'bits_sample'};
} else { if ($fmtcheck == 1) {
$sample_rate == ${$waver->details()}{'sample_rate'} my $wav = new Audio::Wav;
&& $channels == ${$waver->details()}{'channels'} my $waver = $wav -> read("$xfn.wav");
&& $bits_sample == ${$waver->details()}{'bits_sample'} if ($sample_rate < 0) {
|| die "audio format not the same: $xfn.wav"; $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"; my $statcmd = "2>&1 sox $xfn.wav -n stat";
@ -268,12 +290,16 @@ main: {
if ($size == 0) { if ($size == 0) {
print STDERR "?Warning! Zero-size audio file for $iix '$thing'\n"; 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); printf("%s %6.3f %6d '%s'\n", $iix, $vol, $size, $thing);
my $subsize = int($size/2); my $subsize = int($size/2);
printf $index ("%-45s %10d %10d\n", $thing, $where, $subsize); printf $index ("%-45s %10d %10d\n", $thing, $where, $subsize);
$where += $subsize; $where += $subsize;
my $volume_cmd = sprintf("sox -v %6.3f %s.wav %s.raw", my $volume_cmd = sprintf("sox -v %6.3f %s.wav %s.raw",
$vol*0.9, $xfn, $xfn); $vol*0.9, $xfn, $xfn);
########## print "+ $volume_cmd\n"; ########## print "+ $volume_cmd\n";
@ -300,6 +326,7 @@ main: {
die "Cat command failed: $cat_cmd"; die "Cat command failed: $cat_cmd";
} }
## Convert RAW to WAVE format
my $wav_cmd = "sox --rate $sample_rate --bits $bits_sample" my $wav_cmd = "sox --rate $sample_rate --bits $bits_sample"
. " --encoding signed-integer" . " --encoding signed-integer"
. " ./snip/everything.raw --rate 8000 --bits $out_bits_sample $out_wav"; . " ./snip/everything.raw --rate 8000 --bits $out_bits_sample $out_wav";
@ -311,4 +338,12 @@ main: {
if ($?) { if ($?) {
die ".wav command failed: $wav_cmd"; 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");
} }