2007年04月29日

C# プロパティの憂鬱

C#のプロパティって便利なようで使えなくないか、微妙な感じ。
名前そのままで、読み込みは public だけど、値を書き換えるのは protected or private でって設定ができないんだよなぁ。
もうちょっと空気を読んで欲しい。。。


//プロパティを利用しない書き形
class Test
{
private int Otakara;

public int GetOtakara()
{
return this.Otakara;
}

public Test(int inOtakara)
{
this.Otakara = inOtakara;
}
};



//プロパティを使ってみよう!!
class Test
{
private int Otakara
{
//読み込みは public で
public get //エラー!!
{
return this.Otakara;
}
//書き込みは private で
set
{
this.Otakara = value;
}
}

public Test(int inOtakara)
{
this.Otakara = inOtakara;
}
};


ちなみに MSのサンプルだとこげな風に書いてある事が多い気がする。


//MS推奨??
class Test
{
//小文字でメンバを定義するよ.
private int otakara;
//外側には見栄えが良い大文字で定義するよ.
public int Otakara
{
get
{
return this.otakara;
}
}

public Test(int inOtakara)
{
//メンバの先頭を小文字にしたくないよね。。。
this.otakara = inOtakara;
}
};


外には見栄えの良い大文字で表現して内部は小文字って感じ。
内部は見えないところだから見栄を張らなくていいらしい。将軍様の国か、どっかの温泉街か。

やっぱ、メンバってクラスの中ではグローバルであって危険な変数だから先頭を大文字にして強調したいよ。


だからといって、

//昔のようなハンガリアン!
this.m_Otakara

ってのはイヤだなー。

そもそも、メンバに m_ をつける癖をつけるぐらいだったら、this. をつける癖をつけたほうが合理的だ。
ローカル変数に this. をつけたらコンパイラが怒ってくれる。
こっちの方が誰が見てもメンバとわかる。

話がズレたけど、つまり、

this.Aaaaaaaa ってな感じになればいいわけよ。

そんで、外からは読み込みのみで書き込みは内部だけって感じにできないかなぁ。

プロハティの発想はいいと思うんだよなぁ。
いちいち、 getXXX setXXX ってアクセッサを定義するのは面倒。
だから、楽チンにかけるようにしたよ!! ってところは十分評価できる。

だけど、実際使ってみると、なかなか思うようには行かないですよ。。。

ふつーアクセッサの大部分は getXXX であって、 setXXX はめったに使われないよね。
setXXX で設定するぐらいなら、初期化ならコンストラクタか初期化用のメソッド呼ぶし、計算したいなら普通にメソッドたたくし。

そう考えると、読み込みは public だけど、値を書き換えるのはprotected or private って設定ができるのが一番楽のような気がするんだが、
どーなんでしょうか。


はっ!!????????


そうか、、、もしかしてプロパティをアクセッサ代わりに使おうという考えが間違っているのかもしれない!

プロパティの起源をよくよく考えてみれば、



private void Form1_Load(object sender, EventArgs e)
{
this.Text = "うがー";
//Builder だと、 this.Cation = "うがー"; ね。
}


ってヤツをやりたかったために プロパティって作ったんぢゃないのかと。

this.Text の実装は WinAPI ベースで行けば、 setWindowText() で値の書き換え。
やっていることは、アクセッサってレベルぢゃねーぞ
立派なメソッドだね。


プロパティは、アクセッサとしても使えるかもしれないが、それはたまたま利用できただけで、本当の目的はメソッドをラップして自然に見せるための機能って考えれば、現在の実装も理解できる。
posted by rti at 08:28| Comment(1) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2007年04月28日

skype + 音声認識

skype-in で電話を受けて、音声認識でなんかできないかなーと、
思っていたら、既にやっている人がいた。

音声認識でハンズフリーレストラン検索「声探」
音声認識でハンズフリーレストラン検索 「声探」


俺的にやりたかったのは、
ニワンゴのサービスのようなやつの音声化。
ケータイ世代ではないので、ケータイのキーが討ちづらくてしかたないため、電話口でしゃべれば結果を返してくれるって感じのサービスがほしい。
本人認証の仕組みとかがあれば、結果をメールで受信もありかなぁ。
音声読み上げだと長い文章は大変だしね。

たとえば、あらかじめ発信者番号(自分の電話番号)をサーバに登録しておけば、簡易本人確認ができるよね。


ついでに、PCの制御とかもできるようになれば、
ラピュタのあのシーンを再現できるかもしれない。

コマンド バルス。

さっと、ケータイを取り出して、バルスってシャウトするとPCが勝手にシャットダウンするって感じかな。
すげーかっこよくないか。

PCをメールで遠隔操作するソフトがあるんだから、ケータイの音声で操作するソフトもありでしょう。
posted by rti at 04:34| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2007年04月23日

自分に火の粉が降りかかるまでは傍観

トリビアの泉でアキバの人たちは電車男のように助けてくれるのか?
って実験で、アキバでは、被験者の約半分の人たちが助けに入ったという結果が出たが、特急にのっている人はそうではないらしい。
アキバが異常なだけか??


大阪府警淀川署は21日、JR北陸線の富山発大阪行きの特急「サンダーバード」の車内で昨年8月、大阪市内の会社員の女性(当時21歳)に暴行したとして、滋賀県湖南市石部南、解体工、植園貴光被告(36)を強姦(ごうかん)容疑で再逮捕した。当時、同じ車両には約40人の乗客がおり、一部の乗客は異変に気付いたものの、植園容疑者にすごまれ、制止できなかったという。
強姦:特急内で暴行、容疑の36歳再逮捕 乗客沈黙



俺様が同じ常態に居たらどうなんだろう、、、やっぱ助けないのかなぁ。
だめぢゃん。


人は自分に火の粉がふりかかってくるまで動かないものだ。
なんで強引に当事者にして火の粉を振り掛けるってのがもっとも簡単な解決法というのを聞いたことがある。

例えば、夜、暴漢に襲われたときに、助けを呼ぶ一番良い方法は、

「助けて!」と叫ぶ

ではなく、

「火事だ!」と叫ぶ

ことらしい。
「助けて!」だと逆に怖がって家から出てこない場合があるそうだ。
しかし、火事の場合は逃げないと自分に危害が加わるために家から出ずにはいられないわけだ。
奴らは目撃者を恐れるから、これで撃退できるということらしい。
#銀河英雄伝説でも似たようなシーンがあったなぁ

実際に効果があるのか? といわれると、幸いなことに一度も試す機会に恵まれなかったので、効果があるか謎。


ついでに、、、この記事のように暴漢に襲われたときも、

「誰か助けて」

ではなくて、

「そこのxx色の服を着ている人、助けを呼んで!」

ってな感じに指名するといいらしい。
ようするに、強引に関係者にしてしまう。
関係者になったからには、もう傍観は出来ない、と。
今まで傍観者Aだったのがいっせいにギャラリーの視線を浴び、関係者になるわけで、
この状態で見殺し(?)にできますか?ってわけだね。

まぁ、指名されたほうは迷惑だろうが(w 、これが一番らしい。

実際に効果があるのか? といわれると、
これも、幸いなことに一度も試す機会に恵まれなかったので、効果があるか謎。

俺様的には、かなり効果があるような気がするんだけどね。


昔、大夜逃げ学ってサイトがあって、
ゴネたり、居留守を利用して借金をなかなか支払ってくれない人に対して、効果的な取立ての方法として、
家を差し押さえるって方法をあげていた。

どんだけくらりくらりと借金取りから逃げる人も自分の住処を追われるのだけ容認できないらしい。
すぐに向こうから怒りの電話がかかってきてコンタクトを取ることが出来るそうな。
恐ろしい。


結局は、人は自分に害が加わるまで問題を先送りするものらしい。
マーチン神父の教えをほとんどの人は、守れていない。

逆にいえば、
他人になんかやって欲しいときは、強引に関係者にして火の粉を振り掛ければOKってことだね。
黙ってて欲しいときには、火の粉を振り掛けないようにするってことかなぁ。
これにかかわってもあなたに得はありませんよって感じに思わせるって感じか。
posted by rti at 17:50| Comment(0) | TrackBack(3) | 日記 | このブログの読者になる | 更新情報をチェックする

2007年04月22日

メモ 為替の過去のデータ

過去のデータがダウンロードできる。

Export of MARKET DATA to CSV

過去のデータを検証したいときに便利かも。
posted by rti at 18:16| Comment(0) | TrackBack(1) | 日記 | このブログの読者になる | 更新情報をチェックする

C# メモ System.XML の憂鬱、というか空気を呼んでくれないところ

System.XML(XmlDocument) でノードから行番号が取得できない。
特定のノードが xml ファイルのどこにあるのか取得できない。

XMLの文法エラーのときだけは 行番号を取得できるんだけどねぇ。


例えば、エロゲ屋の顧客リスト管理プログラムがあったとして、


<data>
<name>上上下下</name>
<age>15</age>
</data>


なんてデータが来たら、15才の未成年に売れないので、データがおかしいよってエラーを出してあげたい。
「ファイル xxx.xml の 128行目 name 上上下下の年齢がおかしいよ」ぐらいは表示してあげたい。

ついでに言えば、 128行目にスクロールしてあげるとかすれば空気を読めているだろう。

だけど、行番号を取得する方法がないのだ。

「name 上上下下の年齢がおかしいよ」ぐらいしか表示できない。
後は、上上下下で全文検索でもして該当データを直すって感じか。
めんどくさ。

もうちょっとMSFTのアーキテクトさんが空気読んで設計してくれていたら良かったのにね。設計は大切だ。

ライブラリに依存すると、ライブラリの手のひらで遊んでいるうちはいいんだけど、それを外れるとどうしようもなくなるところが困ったものだ。

一応、別解して次の方法があるらしいが、、、
面倒だなぁ。。。

Line number information in XmlDocument? - .NET XML
TopXML : Using LINQ to XML Annotations - tracking line numbers, in .NET XML, System.XML
posted by rti at 18:10| Comment(0) | TrackBack(1) | 日記 | このブログの読者になる | 更新情報をチェックする

2007年04月20日

スカイジャガー

うわー懐かしい。

SKYJAGUAR [MSX]


コナミから発売された縦シューですね。

めっちゃいきこんで攻略していたのに、途中で挫折してしまったヨ。
まさか、ループゲームなんて思ってもなかったよ。

俺の記憶が確かなら、デモ画面に背景が黒の宇宙みたいなところで戦っているでもシーンがあって、いつかこのシーンが登場するものだと思っていた。

SCENE8 のハンマーみたいなボスを倒すともう一度最初に戻されるわけ。
でも、 SCENE3 をクリアしても SCENE1 のような市街地に戻されるから、 もう一度ハンマーを倒せば、宇宙にいけるんぢゃねぇ? って淡い期待を抱いて、プレーしていた。

俺が操縦して弟が玉を打つとかやって、分担作業とかやったりして何とか攻略を試みていた。
ゲームセンターCX「高橋名人の冒険島」の課長と東島みたいな感じだ。
それでも、結局2度目のハンマーを撃墜することが出来なかったけどね。

紅白帽 頭にウルトラマン、ウルトラマンな感じに懐かしい思い出です。
posted by rti at 11:04| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

俺のプログラムの師匠を見つけた

BASIC入門

俺様にプログラムってやつを教えてくれたソフトだった。
テラナツカシス。

発売はカシオだったのか。。。
ドット絵で飛行機飛ばしたり、mmlを記述して音楽鳴らしたりしていたもんだ。

基本はファミコンで遊んでいて、親からファミコンを取り上げられたら、「ゲームが無いければ作ればいいんぢゃね?」って感じでMSXで遊んでいた。
posted by rti at 10:39| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2007年04月18日

SAPI Windows音声認識

何か、音声認識ネタが/.に出ていたので、昔書いた SAPI周りのやつでも上げとくか。
数年前に書いたやつなので、もう時代遅れになっている個所もあるかもしれんが何か役に立つといいかもね。




マイクから自由単語で認識するには?


USES_CONVERSION;

HRESULT hr;
CComPtr Engine; // 認識エンジンオブジェクト
CComPtr RecoCtxt; // 認識エンジンオブジェクトの作成

// CLSID_SpSharedRecognizer マイクから録音するとき?
// CLSID_SpInprocRecognizer Waveから変換するとき?
hr = Engine.CoCreateInstance(CLSID_SpSharedRecognizer);
if(FAILED(hr)) throw RComException(hr , "CLSID_SpSharedRecognizer 構築 に失敗");

// 認識コンテクストオブジェクトの作成

hr = Engine->CreateRecoContext(&RecoCtxt);

if(FAILED(hr)) throw RComException(hr , "CreateRecoContext に失敗");
hr = RecoCtxt->SetNotifyWin32Event();

if ( FAILED(hr) ) throw RComException(hr , "SetNotifyWin32Event に失敗");
hr = RecoCtxt->SetInterest(SPFEI(SPEI_RECOGNITION), SPFEI(SPEI_RECOGNITION));

if ( FAILED(hr) ) throw RComException(hr , "SetInterest に失敗");
hr = RecoCtxt->SetAudioOptions(SPAO_RETAIN_AUDIO, NULL, NULL);

if ( FAILED(hr) ) throw RComException(hr , "SetAudioOptions に失敗");
CComPtr dictationGrammar;

//メインとなる文法の作成
hr = RecoCtxt->CreateGrammar(0, &dictationGrammar);
if ( FAILED(hr) ) throw RComException(hr , "CreateGrammar に失敗");

hr = dictationGrammar->LoadDictation(NULL, SPLO_STATIC);
if ( FAILED(hr) ) throw RComException(hr , "LoadDictation に失敗");

//録音開始
hr = dictationGrammar->SetDictationState( SPRS_ACTIVE );
if ( FAILED(hr) ) throw RComException(hr , "SetDictationState に失敗");

puts("go!");
CSpEvent event;

//録音が終わるまで大待機
hr = RecoCtxt->WaitForNotifyEvent(INFINITE);
if ( FAILED(hr) ) throw RComException(hr , "WaitForNotifyEvent に失敗");

hr = event.GetFrom( RecoCtxt );
if ( FAILED(hr) ) throw RComException(hr , "GetFrom に失敗");

//認識した結果
ISpRecoResult* result;
result = event.RecoResult();

//認識した文字列の取得
CSpDynamicString dstrText;

hr = result->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &dstrText, NULL);
if ( FAILED(hr) ) throw RComException(hr , "録音したテキストの取得に失敗しました");
string ResultString = W2A(dstrText);

認識した結果が、ResultString に入ります。


wave から認識させるには?

CLSID_SpSharedRecognizer ではなくて、 CLSID_SpInprocRecognizer からオブジェクトを作成し、 BindToFileします。

USES_CONVERSION;
HRESULT hr;

CComPtr Engine; // 認識エンジンオブジェクト
CComPtr RecoCtxt;
// 認識エンジンオブジェクトの作成

// CLSID_SpSharedRecognizer マイクから録音するとき?
// CLSID_SpInprocRecognizer Waveから変換するとき?

/* これを
hr = Engine.CoCreateInstance(CLSID_SpSharedRecognizer);
if(FAILED(hr)) throw RComException(hr , "CLSID_SpSharedRecognizer 構築 に失敗");
*/
///こういう風に書き換える---------------------
CComPtr cpStream;
hr = Engine.CoCreateInstance(CLSID_SpInprocRecognizer); //CLSID_SpSharedRecognizerではないよ

if(FAILED(hr)) throw RComException(hr , "CLSID_SpInprocRecognizer 構築 に失敗");
hr = cpStream.CoCreateInstance(CLSID_SpStream);

if(FAILED(hr)) throw RComException(hr , "CoCreateInstance CLSID_SpStream に失敗");
hr = cpStream->BindToFile( L"c:\\test.wav" , SPFM_OPEN_READONLY , NULL , NULL, SPFEI_ALL_EVENTS);

if(FAILED(hr)) throw RComException(hr , "BindToFile に失敗");
hr = Engine->SetInput( cpStream, TRUE);

if(FAILED(hr)) throw RComException( Engine , CLSID_SpSharedRecognizer , hr , "SetInput に失敗");
/// ------------------------

// 認識コンテクストオブジェクトの作成

hr = Engine->CreateRecoContext(&RecoCtxt);

if(FAILED(hr)) throw RComException(hr , "CreateRecoContext に失敗");
hr = RecoCtxt->SetNotifyWin32Event();

if ( FAILED(hr) ) throw RComException(hr , "SetNotifyWin32Event に失敗");
hr = RecoCtxt->SetInterest(SPFEI(SPEI_RECOGNITION), SPFEI(SPEI_RECOGNITION));

if ( FAILED(hr) ) throw RComException(hr , "SetInterest に失敗");
hr = RecoCtxt->SetAudioOptions(SPAO_RETAIN_AUDIO, NULL, NULL);

if ( FAILED(hr) ) throw RComException(hr , "SetAudioOptions に失敗");


CComPtr dictationGrammar;
//メインとなる文法の作成

hr = RecoCtxt->CreateGrammar(0, &dictationGrammar);

if ( FAILED(hr) ) throw RComException(hr , "CreateGrammar に失敗");
hr = dictationGrammar->LoadDictation(NULL, SPLO_STATIC);

if ( FAILED(hr) ) throw RComException(hr , "LoadDictation に失敗");
//録音開始

hr = dictationGrammar->SetDictationState( SPRS_ACTIVE );

if ( FAILED(hr) ) throw RComException(hr , "SetDictationState に失敗");

puts("go!");
CSpEvent event;
//録音が終わるまで大待機

hr = RecoCtxt->WaitForNotifyEvent(INFINITE);

if ( FAILED(hr) ) throw RComException(hr , "WaitForNotifyEvent に失敗");
hr = event.GetFrom( RecoCtxt );

if ( FAILED(hr) ) throw RComException(hr , "GetFrom に失敗");
//認識した結果

ISpRecoResult* result;

result = event.RecoResult();
//認識した文字列の取得

CSpDynamicString dstrText;

hr = result->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &dstrText, NULL);

if ( FAILED(hr) ) throw RComException(hr , "録音したテキストの取得に失敗しました");

string ResultString = W2A(dstrText);



認識した結果が、ResultString に入ります。

音声認識のテストは、音がうるさいので、引きこもりが最も活動的になる夜にやりにいくですからねー。

録音した wav を使ってテストすれば、ご近所からも不審者と思われずに大丈夫です。



マイクからXMLで指定したルールにより認識するには?

USES_CONVERSION;
HRESULT hr;

CComPtr Engine; // 認識エンジンオブジェクト
CComPtr RecoCtxt;
// 認識エンジンオブジェクトの作成

// CLSID_SpSharedRecognizer マイクから録音するとき?
// CLSID_SpInprocRecognizer Waveから変換するとき?

hr = Engine.CoCreateInstance(CLSID_SpSharedRecognizer);

if(FAILED(hr)) throw RComException(hr , "CLSID_SpSharedRecognizer 構築 に失敗");

// 認識コンテクストオブジェクトの作成

hr = Engine->CreateRecoContext(&RecoCtxt);

if(FAILED(hr)) throw RComException(hr , "CreateRecoContext に失敗");
hr = RecoCtxt->SetNotifyWin32Event();

if ( FAILED(hr) ) throw RComException(hr , "SetNotifyWin32Event に失敗");
hr = RecoCtxt->SetInterest(SPFEI(SPEI_RECOGNITION), SPFEI(SPEI_RECOGNITION));

if ( FAILED(hr) ) throw RComException(hr , "SetInterest に失敗");
hr = RecoCtxt->SetAudioOptions(SPAO_RETAIN_AUDIO, NULL, NULL);

if ( FAILED(hr) ) throw RComException(hr , "SetAudioOptions に失敗");


CComPtr dictationGrammar;
//メインとなる文法の作成

hr = RecoCtxt->CreateGrammar(0, &dictationGrammar);

if ( FAILED(hr) ) throw RComException(hr , "CreateGrammar に失敗");
//録音開始

/*これを
hr = dictationGrammar->SetDictationState( SPRS_ACTIVE );
if ( FAILED(hr) ) throw RComException(hr , "SetDictationState に失敗");
*/

///こういう風に書き換える---------------------


//ユーザ指定ファイルからのロード

hr = dictationGrammar->LoadCmdFromFile( L"c:\\test.xml" ,SPLO_STATIC);

if ( FAILED(hr) ) throw RComException(hr , "LoadCmdFromFile に失敗");
//録音開始

hr = dictationGrammar->SetRuleState(NULL, NULL, SPRS_ACTIVE );

if ( FAILED(hr) ) throw RComException(hr , "SetRuleState に失敗");

////--------------------------------------




puts("go!");
CSpEvent event;
//録音が終わるまで大待機

hr = RecoCtxt->WaitForNotifyEvent(INFINITE);

if ( FAILED(hr) ) throw RComException(hr , "WaitForNotifyEvent に失敗");
hr = event.GetFrom( RecoCtxt );

if ( FAILED(hr) ) throw RComException(hr , "GetFrom に失敗");
//認識した結果

ISpRecoResult* result;

result = event.RecoResult();
//認識した文字列の取得

CSpDynamicString dstrText;

hr = result->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &dstrText, NULL);

if ( FAILED(hr) ) throw RComException(hr , "録音したテキストの取得に失敗しました");

string ResultString = W2A(dstrText);




//追加------------------------------

//認識に XMLを使用した場合、代入された結果を得る.

map
ResultMap; //これに結果を代入する

SPPHRASE *pPhrase;

event.RecoResult()->GetPhrase(&pPhrase);

const SPPHRASEPROPERTY *pProp;

for (pProp = pPhrase->pProperties; pProp; pProp = pProp->pNextSibling)

{

string a = W2A(pProp->pszName);

ResultMap[ W2A(pProp->pszName) ] = W2A(pProp->pszValue);

}

CoTaskMemFree(pPhrase);

///---------------------------------

認識した結果が、ResultString に入ります。
また、 XML で指定した名前と結果の配列が ResultMap に格納されます。
PHP でいう _POST みたいな感じで格納されるといえばわかりやすいでしょうか。

ここら辺は、http://julius.sourceforge.jp/sapi/index.html を参考にしました。
ありがとうございました。

マイクから自由単語で認識した結果を wav で保存するには?

USES_CONVERSION;
HRESULT hr;

CComPtr Engine; // 認識エンジンオブジェクト
CComPtr RecoCtxt;
// 認識エンジンオブジェクトの作成

// CLSID_SpSharedRecognizer マイクから録音するとき?
// CLSID_SpInprocRecognizer Waveから変換するとき?

hr = Engine.CoCreateInstance(CLSID_SpSharedRecognizer);

if(FAILED(hr)) throw RComException(hr , "CLSID_SpSharedRecognizer 構築 に失敗");

// 認識コンテクストオブジェクトの作成

hr = Engine->CreateRecoContext(&RecoCtxt);

if(FAILED(hr)) throw RComException(hr , "CreateRecoContext に失敗");
hr = RecoCtxt->SetNotifyWin32Event();

if ( FAILED(hr) ) throw RComException(hr , "SetNotifyWin32Event に失敗");
hr = RecoCtxt->SetInterest(SPFEI(SPEI_RECOGNITION), SPFEI(SPEI_RECOGNITION));

if ( FAILED(hr) ) throw RComException(hr , "SetInterest に失敗");
hr = RecoCtxt->SetAudioOptions(SPAO_RETAIN_AUDIO, NULL, NULL);

if ( FAILED(hr) ) throw RComException(hr , "SetAudioOptions に失敗");


CComPtr dictationGrammar;
//メインとなる文法の作成

hr = RecoCtxt->CreateGrammar(0, &dictationGrammar);
if ( FAILED(hr) ) throw RComException(hr , "CreateGrammar に失敗");

hr = dictationGrammar->LoadDictation(NULL, SPLO_STATIC);
if ( FAILED(hr) ) throw RComException(hr , "LoadDictation に失敗");

//録音開始
hr = dictationGrammar->SetDictationState( SPRS_ACTIVE );
if ( FAILED(hr) ) throw RComException(hr , "SetDictationState に失敗");

puts("go!");
CSpEvent event;

//録音が終わるまで大待機
hr = RecoCtxt->WaitForNotifyEvent(INFINITE);
if ( FAILED(hr) ) throw RComException(hr , "WaitForNotifyEvent に失敗");

hr = event.GetFrom( RecoCtxt );
if ( FAILED(hr) ) throw RComException(hr , "GetFrom に失敗");

//認識した結果

ISpRecoResult* result;

result = event.RecoResult();
//認識した文字列の取得

CSpDynamicString dstrText;
hr = result->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &dstrText, NULL);
if ( FAILED(hr) ) throw RComException(hr , "録音したテキストの取得に失敗しました");

string ResultString = W2A(dstrText);


//追加------------------------------

CComPtr ResultStream;
CComPtr voice;

hr = RecoCtxt->GetVoice(&voice);
if(FAILED(hr)) throw RComException(hr , "GetVoice に失敗");

hr = event.RecoResult()->GetAudio( 0, 0, &ResultStream );
if ( FAILED(hr) ) throw RComException(hr , "GetAudio に失敗しました");

CComPtr cpWavStream;
CComPtr cpOldStream;
CSpStreamFormat OriginalFmt;
voice->GetOutputStream( &cpOldStream );
OriginalFmt.AssignFormat(cpOldStream);

hr = SPBindToFile( L"C:\\output.wav",SPFM_CREATE_ALWAYS, &cpWavStream,&OriginalFmt.FormatId(), OriginalFmt.WaveFormatExPtr() )
voice->SetOutput(cpWavStream,TRUE);

hr = voice->SpeakStream( ResultStream , SPF_DEFAULT, 0 );
if ( FAILED(hr) ) throw RComException(hr , "SpeakStream に失敗しました");
///---------------------------------


あなたがコンピュータさまに、話し掛けたキモイ声が、 C:\output.wav に保存されます。




WindowsXPの人は SAPI 5.1 ぐらいが入っているから何もしなくてもいいけど、
Windows2Kの人は、 SAPIが入っていない?? っぽいんで、
http://www.microsoft.com/downloads/details.aspx?FamilyId=5E86EC97-40A7-453F-B0EE-6583171B4530&displaylang=en#filelist
からダウンロードして入れるといいよ。

上のドキュメント書いているときは、 SAPI4 で試しているので、5で動くかは謎。後で確認するかも。
posted by rti at 17:08| Comment(1) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

C# eval先から自分の関数を呼び出させる

あんまりにも面白かったので作ってみた。

動的に 1+1+自分のクラスのAAAの値を求める。
サンプルでは、 AAA=13 なので、 1+1+13=15 と表示される。

自分

動的に作成したルーチン

自分の関数


これ使えば、簡易スクリプト言語なんて不要ぢゃねーの??

参考
文字列の計算式の計算結果を取得する
Evaluating Mathematical Expressions by Compiling C# Code at Runtime


using System;
using System.Collections.Generic;
using System.Text;

using System.CodeDom.Compiler;
using System.Reflection;

namespace @ref
{
//int AAA を保護するクラス
public class Himitsu
{
private int AAA;

public int getAAA()
{
return this.AAA;
}

public Himitsu(int inAAA)
{
this.AAA = inAAA;
}
};

public class Program
{
static private Himitsu HimitsuInstance;

public static int MyCallBack()
{
return HimitsuInstance.getAAA();
}
static void Main(string[] args)
{
//計算するためのコード
string source = @"
public class MainClass
{
public static double EVal()
{
int aaa = @ref.Program.MyCallBack(); //秘密の数字にアクセス
return 1+1+aaa;
}
}";

//秘密の数字13を渡す.
HimitsuInstance = new Himitsu(13);

//コンパイルするための準備
CodeDomProvider cp = new Microsoft.CSharp.CSharpCodeProvider();
ICodeCompiler icc = cp.CreateCompiler();
CompilerParameters cps = new CompilerParameters();
CompilerResults cres;
//メモリ内で出力を生成する
cps.GenerateInMemory = true;
cps.ReferencedAssemblies.Add("system.dll");
cps.ReferencedAssemblies.Add("ref.exe"); //自分自身のexe名
//コンパイルする
cres = icc.CompileAssemblyFromSource(cps, source);
if (cres.Errors.Count > 0)
{
string errors = "Compilation failed:\n";
foreach (CompilerError err in cres.Errors)
{
errors += err.ToString() + "\n";
}
Console.WriteLine(errors);
return;
}
//コンパイルしたアセンブリを取得
Assembly asm = cres.CompiledAssembly;
//MainClassクラスのTypeを取得
Type t = asm.GetType("MainClass");
//EValメソッドを実行し、結果を取得
double d = (double) t.InvokeMember("EVal",
BindingFlags.InvokeMethod,
null,
null,
null);

//結果を表示
Console.WriteLine(d);
}
}
}
posted by rti at 00:55 | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2007年04月17日

メモ プログラムの中でプログラムを実行する

文字列の計算式の計算結果を取得する

面白い。
Microsoft Script Controlを利用する方法については、サクラエディタが実装していると思う(たぶん)。
C++で書くと死ぬほど面倒くさくてまわりっくどい。

こーゆーのを見ていると、
Windows環境での自作スクリプトとか、Luaとかいらなくねぇ?って感じになるね。

自前スクリプトだと文法覚えるの面倒だし。
エラー処理がいい加減で、エラーメッセージが異常にわかりづらかったりするし。
スクリプト自体にバグがあったりしたら地獄だし。
何より、デバッカーがない!! っての最大の問題だ。


Windows環境で、何らかのスクリプトが欲しくて、自前で実装とかしているやつがいたら今すぐそのコードを破棄するべきだ。
その方が世の中平和になるし、何より楽で良い。
posted by rti at 23:26 | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする