fishtalk/tools/phoneme.pl
2026-05-23 10:23:33 +09:00

98 lines
1.6 KiB
Perl
Executable file

#!/usr/bin/env perl
my $err = 0;
my $base = "samples";
my @phon = ();
my @used = ();
if(@ARGV > 0){
$base = $ARGV[0];
}
require("./$base/mapping.pl");
open(my $f, "<", "phonemes.txt");
while(my $l = <$f>){
$l =~ s/\r?\n$//;
my $orig = $l;
while($mapping{$l}){
$l = $mapping{$l};
}
if(!(-f "$base/$l.wav")){
print("sample for phoneme $orig ($orig => $l) was not found\n");
$err = 1;
}
push(@phon, $orig);
if(!grep(/^$l$/, @used)){
push(@used, $l);
}
}
close($f);
if($err){
die;
}
my @phon = ();
open(my $f, ">", "include/fishtalk_phon.h");
foreach my $l (@used){
print($f "extern signed char phon_$l\[];\n");
print($f "extern unsigned int phon_$l\_length;\n");
print($f "\n");
}
print($f "/*** Aliases ***/\n");
foreach my $l (keys(%mapping)){
my $v = $l;
while($mapping{$v}){
$v = $mapping{$v};
}
print($f "#define phon_$l phon_$v\n");
print($f "#define phon_$l\_length phon_$v\_length;\n");
print($f "\n");
}
close($f);
foreach my $l (@used){
open(my $f, ">", "src/phon_$l.c");
open(my $in, "-|", "ffmpeg -i $base/$l.wav -f s8 -ar 2205 -ac 1 - 2>/dev/null") or die "OOPS";
binmode($in);
my $buffer = "";
my $len;
print("$l\n");
print($f "#include <fishtalk.h>\n");
print($f "\n");
print($f "signed char phon_$l\[] = {\n");
my $total = 0;
while(($len = read($in, $buffer, 32)) > 0){
my @data = unpack("C*", $buffer);
my @arr = ();
$total += $len;
for(my $i = 0; $i < $len; $i++){
my $hex = sprintf("%d", $data[$i] - 128);
push(@arr, $hex);
}
print($f " " . join(", ", @arr) . ", /**/\n");
}
print($f "};\n");
print($f "unsigned int phon_$l\_length = $total;\n");
close($in);
close($f);
}