Skip to content

Instantly share code, notes, and snippets.

@kits
Created December 6, 2010 08:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kits/730033 to your computer and use it in GitHub Desktop.
Save kits/730033 to your computer and use it in GitHub Desktop.
AquesTalk.pm - use AquesTalk library with perl.
package AquesTalk;
use Any::Moose;
use Win32::API;
use Encode ();
our $VERSION = '0.02';
# error messages
my %Error = (
100 => q{Other error},
101 => q{Memory shortage},
102 => q{An undefined phonetic symbol in voice string},
103 => q{Duration of the meter data is a negative value. },
104 => q{Internal error (undefined separator detection)},
105 => q{An undefined phonetic symbol in voice string},
106 => q{The tag in the voice string is incorrect. },
107 => q{The length of tag has exceeded the limitation (or, > is not found)},
108 => q{The value in tag is incorrect},
109 => q{Cannot play WAVE (sound driver's problem)},
110 => q{Cannot play WAVE (sound driver's problem, asynchronous play)},
111 => q{No data that should be uttered},
200 => q{Voice string is too long. },
201 => q{A lot of phonetic symbols in one phrase},
202 => q{Voice string is long (internal buffer over 1)},
203 => q{Heap memory shortage},
204 => q{Voice string is long (internal buffer over 1)},
);
# function in AquesTalk DLL
my $func_Synthe = Win32::API->new(qw{ AquesTalk AquesTalk_Synthe PIP N });
my $func_FreeWave = Win32::API->new(qw{ AquesTalk AquesTalk_FreeWave N V });
my $func_PlaySync = Win32::API->new(qw{ AquesTalkDa AquesTalkDa_PlaySync PI I });
($func_Synthe && $func_FreeWave) or confess 'Cannot load AquesTalk.dll';
$func_PlaySync or confess 'Cannot load AquesTalkDa.dll';
# initial size buffer (int)
my $initial_size_buffer = pack 'I', 0;
# encoding object
my $enc_sj = Encode::find_encoding('shiftjis');
my $enc_u8 = Encode::find_encoding('utf8');
# accessers and methods
has koe => (
is => 'rw',
isa => 'Str',
);
has speed => (
is => 'rw',
isa => 'Int',
default => 100,
);
sub synthe {
my ($self) = @_;
my $size_buffer = $initial_size_buffer;
my $koe_sjis = $enc_sj->encode($self->koe);
my $lp_wav = $func_Synthe->Call( $koe_sjis, $self->speed, $size_buffer );
my $size = unpack 'I', $size_buffer;
if ($lp_wav == 0) {
$self->_split_test;
confess "Cannot get WAVE data";
}
my $wav = unpack "P$size", pack('L!', $lp_wav);
$func_FreeWave->Call($lp_wav);
return $wav;
}
sub play_sync {
my ($self) = @_;
my $ret = $func_PlaySync->Call( $self->koe, $self->speed );
if ($ret != 0) {
$self->_split_test;
confess "Cannot play_sync";
}
}
sub _split_test {
my ($self) = @_;
# \x{3001} = toten, \x{3002} = kuten
my @strs = grep { $_ ne '' } split /[\x{3001}\x{3002}]/, $self->koe;
for my $str (@strs) {
my $size_buffer = $initial_size_buffer;
my $koe_sjis = $enc_sj->encode($str);
my $lp_wav = $func_Synthe->Call($koe_sjis, 300, $size_buffer);
my $size = unpack 'L!', $size_buffer;
if ($lp_wav == 0) {
warn "AquesTalk error: $size: $Error{$size} : ",
$enc_u8->encode($str),
"\n";
}
$func_FreeWave->Call($lp_wav);
}
}
# end
no Any::Moose;
__PACKAGE__->meta->make_immutable;
1;
=pod
=encoding utf8
=head1 NAME
AquesTalk.pm - use AquesTalk library with perl.
=head1 SYNOPSIS
use utf8;
use AquesTalk;
my $talk = AquesTalk->new( koe => 'はろーわーるど', speed => 100 );
# talk
$talk->play_sync;
# output wav data
open my $fh, '>', 'hello.wav';
print $fh $talk->synth;
close $fh;
=head1 SEE ALSO
http://www.a-quest.com/products/aquestalk.html
=head1 AUTHOR
KITAMURA Akatsuki, E<lt>kits@akatsukinishisu.netE<gt>
=cut
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment