音声合成でHello, world!
Posted feedbacks - Nested
Flatten Hidden1 2 3 4 | function say($msg) {
$speaker = new-object -com Sapi.SpVoice
$speaker.Speak($msg, 1)
}
|
僕が用意していたのもこの方法でした。
1 2 | import win32com.client
say = win32com.client.Dispatch("SAPI.SpVoice").Speak
|
1 | Speaker default say: 'Hello, world!'
|
惚れました。
他にも、ランダムに生成されるキャラ顔にセリフをしゃべらせる(発声のタイミングにあわせてそれっぽく口を動かします)…といったこともできます。
see: 実行画面
1 2 3 4 | | speaker |
speaker := Speaker manWithHead.
(speaker findAVoice: GesturalVoice) head openInHand.
speaker say: 'Hello, world!'
|
Microsoft Agent を使ってます。 AxAgent1がAgentコンポーネントオブジェクトです。 Visual Studioでの操作は、Windowsアプリケーションを作り COMコンポーネントの追加で Microsoft Agent Control 2.0を選択、 そしてFormにコンポーネントを貼り付けというふうになります。 ' .NET Frameworkにも音声合成用の抽象クラスだけはあるのね。
see: Microsoft Agent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
AxAgent1.Connected = True
AxAgent1.Characters.Load("A")
End Sub
Private Sub MainForm_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
AxAgent1.Characters.Unload("A")
AxAgent1.Connected = False
End Sub
Sub Say(ByVal message As String)
Dim chr As AgentObjects.IAgentCtlCharacter = AxAgent1.Characters("A")
chr.Show()
chr.Speak(message)
End Sub
|
他力本願 eSpeak のコマンドを呼ぶ。 espeakはおもしろいですね。 ちゃんとそれらしく、聞える
see: eSpeak: Speech Synthesizer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | module Main (main) where
import System.Environment
import System.Cmd
main = system . mkcmd . unwords =<< getArgs
mkcmd s = "espeak '" ++ s ++ "'"
{-
字では表現できませんが、以下でちゃんとしゃべってくれます。
*Main> :main Hello, world!
ExitSuccess
*Main> :main con nitch were
ExitSuccess
*Main> :main daw cat coo org, sole what program mar know tum yen know Colosseum death
ExitSuccess
-}
|
see: どう書く?org 2987 ether: Windows では COM 経由で S...(音声合成でHello, world!) - 投稿の詳細:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | require "rubygems"
require "win32/sapi5" # http://rubyforge.org/projects/win32utils
include Win32
def say(msg)
v = SpVoice.new
v.Speak(msg)
end
if $0 == __FILE__
if ARGV[0]
say(ARGV[0])
else
say("Hello, world!")
say("con nitch were") # 「こんにちは」
say("daw cat coo org, sole what program mar know tum yen know Colosseum death")
end
end
|
自分には難しかったので、シェルからfestivalを呼び出すことにしました。 festivalは内部スクリプティングにshcemeが採用されてるんですねー。 ubuntu/debianでは、パッケージがあったので導入は簡単でした。
see: The Festival Speech Synthesis System
1 2 3 4 5 6 7 8 9 | (defpackage :doukaku-59 (:use :cl :asdf) (:export say))
(in-package :doukaku-59)
(defun say (str)
(let ((exec-str (concatenate 'string "echo " str "|festival --tts")))
(let ((res (run-shell-command exec-str)))
(case res
(0 (values str 0))
(otherwise (values nil res))))))
|
see: Microsoft Agent Downloads
1 2 3 4 5 6 7 8 9 10 11 12 13 | function doukaku59(text, option){ // テキスト [, {language:言語, gender:性別, speed:速度}]
var i = 1, c, l, g, s;
with(new ActiveXObject('TextToSpeech.TextToSpeech')){
c = countEngines;
if(l = option.language) for(; i <= c && !~modeName(i).indexOf(l); i++);
if(g = option.gender) for(; i <= c && !~modeName(i).indexOf(g); i++);
if(s = option.speed) if(95 <= s && s <= 270) speed = s;
try { select(i) } catch(e){ WSH.echo('No engines for the option.'); WSH.quit() }
for(speak(text); isSpeaking; WSH.sleep(590));
}
}
doukaku59('Hello, world!', {language:'English', gender:'Male', speed:160});
doukaku59('こんにちは!', {language:'Japanese', gender:'Female'});
|
eSpeakのライブラリをSML#のFFI機能を使って呼んでいます。 ライブラリの場所は/usr/libに決め打ち。さらに設定はすべて固定。
see: eSpeak: Speech Synthesizer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | fun say text =
let
open DynamicLink
val lib = dlopen "/usr/lib/libespeak.so"
val init = dlsym (lib, "espeak_Initialize")
val synth = dlsym (lib, "espeak_Synth")
val sync = dlsym (lib, "espeak_Synchronize")
val espeakSyncronize = sync : _import () -> int
fun espeakInitialize () =
_ffiapply init (0 : int,
0 : int,
NULL : string ptr,
0 : int) : int
fun espeakSynth () =
_ffiapply synth (text : string,
size text + 1 : int,
0 : int,
1 : int,
0 : int,
0 : int,
NULL : word ptr,
NULL : char ptr) : int
in
espeakInitialize ();
espeakSynth ();
espeakSyncronize ()
end;
say "Hello, world!"
|
同等のコードをpythonで書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 | from ctypes import cdll
def init():
es = cdll.LoadLibrary('libespeak.so.1')
es.espeak_Initialize(0, 0, None, 0)
es.espeak_Synchronize()
return lambda s: es.espeak_Synth(s, len(s)+1, 0, 1, 0, 0, None, None)
say = init()
say('Hello, world!')
say('con nitch were')
say('daw cat coo org, sole what program mar know tum yen know Colosseum death')
|
もう少しましな日本語を喋らせることもできますが、とりあえず投稿
1 2 | say "Hello, world."
say "con itch wha."
|
see: FreeTTS 1.2 - A speech synthesizer written entirely in the Java(TM) programming language
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import com.sun.speech.freetts.Voice;
import com.sun.speech.freetts.VoiceManager;
public class Speaker {
public static void main(String[] args) {
args = args.length == 0 ? new String[] { "Hello world!" } : args;
StringBuffer message = new StringBuffer();
for (int i = 0; i < args.length; i++) {
message.append(args[i]);
message.append(' ');
}
VoiceManager voiceManager = VoiceManager.getInstance();
Voice helloVoice = voiceManager.getVoice("kevin16");
System.out.printf("%s say \"%s\".%n", helloVoice.getName(), message);
helloVoice.allocate();
helloVoice.setVolume(100.0f);
helloVoice.speak(message.toString());
helloVoice.deallocate();
}
}
|
MS Agentを使ってます。 最低限Text-to-speech engines (日本語か英語版)とSAPI 4.0 が必要です。
see: Microsoft Agent download page for end-users
1 2 3 4 5 6 7 8 9 | say(「Hello, world」, "英語")
say(「こんにちは」, "日本語")
say(「どう書くorg、それはプログラマの為のコロシアムです。」, "日本語")
*say(text, lang)
エージェントマーリン召喚
langへエージェント言語変更
textとエージェント言う
エージェント待つ
|
おおお、これはsayの定義の仕方を変えれば 「"日本語"で「こんにちは」と言う」 なんてこともできそうですね!
できました。 でも、標準命令の「言う」が使えなくなってしまいます。 「いう」の方は使えるから問題ないと思いますが。 ちなみに、「言う、いう」はOKボタンだけのダイアログを出す命令です。
1 2 3 4 5 6 7 8 | "英語"で「Hello, world!」と言う
"日本語"で「こんにちは」と言う
*言う(langで, textと)
エージェントマーリン召喚
langへエージェント言語変更
textとエージェント言う
エージェント待つ
|
c-wrapperのホームページに張ってあるサンプルコードそのままです。Objective-CとSchemeが融合した変なコードになっています。
see: c-wrapper
1 2 3 4 5 6 7 8 9 10 11 | (c-load "Cocoa/Cocoa.h"
:libs "-framework Foundation -framework Cocoa")
[[NSAutoreleasePool :alloc] :init]
(define say
(let1 s [[NSSpeechSynthesizer :alloc] :init]
(lambda (str)
[s :startSpeakingString (@ str)])))
(say "Hello, world")
|
しまった、最初の(use objc-wrapper)が抜けていた。正しくは以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 | (use objc-wrapper)
(c-load "Cocoa/Cocoa.h"
:libs "-framework Foundation -framework Cocoa")
[[NSAutoreleasePool :alloc] :init]
(define say
(let1 s [[NSSpeechSynthesizer :alloc] :init]
(lambda (str)
[s :startSpeakingString (@ str)])))
(say "Hello, world")
|
.NET3.0を使いました。 システムの音声合成エンジンに日本語を話せるエージェントが設定してある事を前提。
1 2 3 4 5 6 7 8 9 10 11 12 | using System;
using System.Speech.Synthesis;
class Program {
static void say(string s) {
SpeechSynthesizer syn = new SpeechSynthesizer();
syn.Speak(s);
}
static void Main(string[] args) {
say("Hello, world!");
say("こんにちは");
}
}
|
何のひねりもないのは…すごい反則してる気がしてきます。
1 2 3 | say "Hello, world!"
say "con nitch were" -- 「こんにちは」
say "daw cat coo org, sole what program mar know tum yen know Colosseum death"
|
NSLog(@"%@", [NSSpeechSynthesizer availableVoices]); で使える声の一覧を確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #import <Foundation/Foundation.h>
#import <Appkit/Appkit.h>
int main(int argc, char** argv)
{
NSAutoreleasePool* pool = [NSAutoreleasePool new];
NSSpeechSynthesizer* s = [[[NSSpeechSynthesizer alloc] initWithVoice:@"com.apple.speech.synthesis.voice.Alex"] autorelease];
[s startSpeakingString:@"Hello, world!"];
while ([s isSpeaking]) ;
[s startSpeakingString:@"con nitch were"];
while ([s isSpeaking]) ;
[s startSpeakingString:@"daw cat coo org, sole what program mar know tum yen know Colosseum death"];
while ([s isSpeaking]) ;
[pool release];
return 0;
}
|
既存ライブラリを用いて実現してみました。 アルファベットでHelloWolrdだと読み上げなかったので仕方なく…
see: Aquesライブラリ
1 2 3 4 5 6 7 8 9 | class VoiceHelloWorld
{
[System.Runtime.InteropServices.DllImport("AquesTalkDa.dll")]
private static extern int AquesTalkDa_PlaySync(string voice,int speed);
static void Main(string[] args)
{
AquesTalkDa_PlaySync("はろーわーるど", 100);
}
}
|
個人的にはnipotanと言う発音は神がかってると思う。
see: SAPI.SpVoiceで文字を喋らせる
1 2 3 4 5 6 7 | function say(msg) {
var sprk = new ActiveXObject("SAPI.SpVoice");
sprk.Speak(msg);
}
say("Hello world");
say("nipotan");
|
(say "Hello, world!")
1 2 3 | (def say (mesg)
(system (+ "say " mesg "&"))
mesg)
|
FreeTTSを使って実装してみました。
see: 音声認識/合成のためのAPI - Java Speech APIとJSR 113
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | import java.beans.PropertyVetoException;
import java.util.Locale
import javax.speech.AudioException
import javax.speech.Central
import javax.speech.EngineException
import javax.speech.EngineStateError
import javax.speech.synthesis.Synthesizer
import javax.speech.synthesis.SynthesizerModeDesc
import javax.speech.synthesis.Voice
class HelloWorld {
private var s:Synthesizer = null
val d:SynthesizerModeDesc = new SynthesizerModeDesc(null, "general", Locale.US, null, null)
var v:Voice = null
s = Central.createSynthesizer(d)
if (s == null) {
Console.println("cannot create synthesizer.")
System.exit(1)
}
v = new Voice("kevin16", Voice.GENDER_DONT_CARE, Voice.AGE_DONT_CARE, null)
if (v == null) {
Console.println("cannot create voice.")
System.exit(1)
}
s.allocate
s.resume
s.getSynthesizerProperties().setVoice(v)
def sayHello(m:String):Unit = {
s.speakPlainText(m,null)
s.waitEngineState(Synthesizer.QUEUE_EMPTY)
}
def deallocateSynthesizer:Unit = s.deallocate
}
object HelloWorldMain {
def main(args:Array[String]):Unit = {
try {
val h:HelloWorld = new HelloWorld
args.size match {
case 0 => h.sayHello("Hello World")
case _ => h.sayHello(args(0))
}
h.deallocateSynthesizer
} catch {
case e:Exception => {
e.printStackTrace
System.exit(1)
}
}
}
}
|
uwscのマニュアルには「要SAPI 5.x」とあります。 コントロールパネルに「音声認識」があれば使えるようです。
1 2 3 | SPEAK("Hello, world!")
SPEAK("こんにちは")
SPEAK("どう書くorg、それはプログラマの為のコロシアムです。")
|
LLVMアセンブリ(32bit)で。Mac OS Xのsayコマンドにコマンドライン引数を渡してます。いいのかこんなんで…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ; Usage: ./say message
declare i32 @strlen(i8*)
declare i32 @sprintf(i8*, i8*, ...)
declare i32 @system(i8*)
@cmd = internal constant [9 x i8] c"say \22%s\22\00"
define i32 @main(i32 %argc, i8** %argv) {
%cmdp = getelementptr [9 x i8]* @cmd, i32 0, i32 0
%argv_addr = ptrtoint i8** %argv to i32
%msg_addr = add i32 %argv_addr, 4
%msgp = inttoptr i32 %msg_addr to i8**
%msg = load i8** %msgp
%slen = call i32 @strlen(i8* %msg)
%len = add i32 %slen, 9
%s = malloc i8, i32 %len
call i32 (i8*, i8*, ...)* @sprintf(i8* %s, i8* %cmdp, i8* %msg)
call i32 @system(i8* %s)
ret i32 0
}
|






にしお
#3415()
Rating4/4=1.00
使用したライブラリはタグでつけてください。またOSに依存する場合もタグでつけてください。日本語文字列も発音できることが好ましいですが、必須ではありません。
以下はサンプルです。
>>> say("Hello, world!") >>> say("con nitch were") # 「こんにちは」 >>> say("daw cat coo org, sole what program mar know tum yen know Colosseum death")[ reply ]