Created
December 6, 2010 08:49
-
-
Save kits/730033 to your computer and use it in GitHub Desktop.
AquesTalk.pm - use AquesTalk library with perl.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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