|
|
2014/1/7(Tue) 00:32:06|NO.59219
以前、こちら( http://www.hsp.tv/play/pforum.php?mode=all&num=58994)で教えて頂いた者です。
音声合成でまた分からない点が出てきたので質問させて頂きます。
VoiceSpeakが再生処理中か、再生終了したかをHSPから取得することは可能でしょうか。
もし可能なら、その方法を教えて頂けないでしょうか…
以前教えて頂いたモジュールなども参考にして、テキスト読み上げソフトが形になって来ました。
そこで実際に長文を読ませてテストをしているのですが、
同期再生(再生終了まで待つ)で長文を読みあげようとすると、その間、自ウィンドウが操作を受け付けなくなってしまうという問題が出てきました。
自ウィンドウのドラッグなどができず、ボタンも反応しなくなります。
(そういうモードなので当然ですし、たいした実害もないのですが)
非同期再生モードにして、一文づつVoiceSpeakに渡してやれば改善されるのではないかと考えましたが、そのためにはVoiceSpeakが前の文を再生終了したかどうか知る必要があります。
自分なりに調べてみたのですが、ISpVoice::GetStatusというのがそれっぽいのかな、というのがわかったくらいで…この先が分かりません(´・ω・`)
ご教示いただければ幸いです…
|
|
2014/1/7(Tue) 02:13:14|NO.59221
GetVoiceStatus関数を追加しました。
#module SAPI_Speech_Voices
#define global ctype SUCCEEDED(%1) ((%1) >= 0)
/*
#define global SafeRelease(%1) if ((varuse@(%1)) && (vartype@(%1) == 6)){ \
delcom@ %1: \
%1 = 0 \
}
*/
#define IID_ISpVoice "{6C44DF74-72B9-4992-A1EC-EF996E0422D4}"
#define IID_IEnumSpObjectTokens "{06B64F9E-7FDA-11D2-B4F2-00C04F797396}"
#define IID_ISpObjectToken "{14056589-E16C-11D2-BB90-00C04F8EE6C0}"
#define IID_ISpObjectTokenCategory "{2D3D3845-39AF-4850-BBF9-40B49780011D}"
#define CLSID_SpVoice "{96749377-3391-11D2-9EE3-00C04F797396}"
#define CLSID_SpMMAudioEnum "{AB1890A0-E91F-11D2-BB91-00C04F8EE6C0}"
#define CLSID_SpObjectToken "{EF411752-3736-4CB4-9C8C-8EF4CCB58EFE}"
#define CLSID_SpObjectTokenCategory "{A910187F-0C7A-45AC-92CC-59EDAFB77B53}"
#define SPCAT_VOICES "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices"
#usecom ISpVoice IID_ISpVoice CLSID_SpVoice
// IUnknown(3)->ISpNotifySource(7)->ISpEventSource(3)->ISpVoice
#comfunc ISpVoice_Pause 16
#comfunc ISpVoice_Resume 17
#comfunc ISpVoice_SetVoice 18 int
#comfunc ISpVoice_GetVoice 19 var
#comfunc ISpVoice_Speak 20 wstr, int, int
#comfunc ISpVoice_GetStatus 22 sptr, wstr
#comfunc ISpVoice_SetRate 28 int
#comfunc ISpVoice_GetRate 29 var
#comfunc ISpVoice_SetVolume 30 int
#comfunc ISpVoice_GetVolume 31 var
#usecom ISpObjectTokenCategory IID_ISpObjectTokenCategory CLSID_SpObjectTokenCategory
//IUnknown(3)->ISpDataKey(12)->ISpObjectTokenCategory
#comfunc ISpObjectTokenCategory_SetId 15 wstr, int
#comfunc ISpObjectTokenCategory_EnumTokens 18 wstr, wstr, sptr
#usecom IEnumSpObjectTokens IID_IEnumSpObjectTokens CLSID_SpMMAudioEnum
// IUnknown(3)->IEnumSpObjectTokens
#comfunc IEnumSpObjectTokens_Next 3 int, sptr, sptr
#comfunc IEnumSpObjectTokens_Reset 5
#comfunc IEnumSpObjectTokens_Clone 6 sptr
#comfunc IEnumSpObjectTokens_Item 7 int, sptr
#comfunc IEnumSpObjectTokens_GetCount 8 var
#usecom ISpObjectToken IID_ISpObjectToken CLSID_SpObjectToken
// IUnknown(3)->ISpDataKey(12)->ISpObjectToken
#comfunc ISpObjectToken_GetStringValue 6 wstr, sptr
#deffunc SafeRelease var p1
if ((varuse(p1)) && (vartype(p1) == 6)){
delcom p1
p1 = 0
}
return
#deffunc CreateVoice var pSpVoice
newcom pSpVoice, ISpVoice
return
#deffunc GetVoicesList var list
sdim list, 1024
// 話者一覧取得
newcom pSpOTC, ISpObjectTokenCategory
if varuse(pSpOTC){
ISpObjectTokenCategory_SetId pSpOTC, SPCAT_VOICES, 0 : hr = stat
if SUCCEEDED(hr){
ptr = 0
ISpObjectTokenCategory_EnumTokens pSpOTC, "", "", varptr(ptr) : hr = stat
if SUCCEEDED(hr) && ptr != 0{
newcom pSpOTs, IEnumSpObjectTokens, -1, ptr
if varuse(pSpOTs){
Num = 0
IEnumSpObjectTokens_GetCount pSpOTs, Num : hr = stat
if SUCCEEDED(hr){
repeat Num
ptr = 0
IEnumSpObjectTokens_Item pSpOTs, cnt, varptr(ptr) : hr = stat
if SUCCEEDED(hr) && ptr != 0{
newcom pSpT, ISpObjectToken, -1, ptr
ISpObjectToken_GetStringValue pSpT, "", varptr(ptr) : hr = stat
if SUCCEEDED(hr){
dupptr wStr, ptr, 1024, 2
list += cnvwtos(wStr) + "\n"
}
SafeRelease pSpT
}
loop
}
SafeRelease pSpOTs
}
}
}
SafeRelease pSpOTC
}
return hr
#deffunc SetVoice var pSpVoice, int idx
newcom pSpOTC, ISpObjectTokenCategory
if varuse(pSpOTC){
ISpObjectTokenCategory_SetId pSpOTC, SPCAT_VOICES, 0 : hr = stat
if SUCCEEDED(hr){
ptr = 0
ISpObjectTokenCategory_EnumTokens pSpOTC, "", "", varptr(ptr) : hr = stat
if SUCCEEDED(hr) && ptr != 0{
newcom pSpOTs, IEnumSpObjectTokens, -1, ptr
if varuse(pSpOTs){
ptr = 0
IEnumSpObjectTokens_Item pSpOTs, idx, varptr(ptr) : hr = stat
if SUCCEEDED(hr){
ISpVoice_SetVoice pSpVoice, ptr
}
SafeRelease pSpOTs
}
}
}
SafeRelease pSpOTC
}
return hr
#deffunc VoiceSpeek var pSpVoice, str s, int f
ISpVoice_Speak pSpVoice, s, f, 0
return stat
#deffunc DestoryVoice var pSpVoice
SafeRelease pSpVoice
return stat
#defcfunc GetVoiceVolume var pSpVoice
Volume = 0
ISpVoice_GetVolume pSpVoice, Volume
return Volume
#deffunc SetVoiceVolume var pSpVoice, int vol
ISpVoice_SetVolume pSpVoice, vol
return stat
#defcfunc GetVoiceRate var pSpVoice, local Rate
Rate = 0
ISpVoice_GetRate pSpVoice, Rate
return Rate
#deffunc SetVoiceRate var pSpVoice, int rate
ISpVoice_SetRate pSpVoice, rate
return stat
#deffunc VoicePause var pSpVoice
ISpVoice_Pause pSpVoice
return stat
#deffunc VoiceResume var pSpVoice
ISpVoice_Resume pSpVoice
return stat
#defcfunc GetVoiceStatus var pSpVoice
dim SPVOICESTATUS, 13
ISpVoice_GetStatus pSpVoice, varptr(SPVOICESTATUS), ""
return SPVOICESTATUS.3
#global
// 以下サンプル
pSpVoice = 0
// ComObj作成
CreateVoice pSpVoice
if varuse(pSpVoice){
onexit gosub *exit
// 一覧取得
GetVoicesList list
idx = 0
objsize 420, 20
combox idx, 100, list
mes "▼ 文章"
sdim s, 1024 : s = "Hello this is H.S.P. for windows."
input s
mes "▼ 音量(0〜100)"
Volume = 100
input Volume
mes "▼ 速度(-10〜10)"
Rate = 0
input Rate
Async = 1
chkbox "再生終了まで待たない", Async
button gosub "再生", *speak
}else{
dialog "呼び出し失敗"
}
stop
*speak
// 音量設定(0〜100)
SetVoiceVolume pSpVoice, Volume
// 再生速度設定(-10〜10)
SetVoiceRate pSpVoice, Rate
title "音量:"+GetVoiceVolume(pSpVoice)+", 速度"+GetVoiceRate(pSpVoice)
// 音声選択
SetVoice pSpVoice, idx
if stat{
dialog "音声選択に失敗しました"
}
// 同期再生(再生終了まで待つ)
// 1にすると非同期
VoiceSpeek pSpVoice, s, Async
if stat{
dialog "再生失敗しました"
}
// 再生終了までループ
repeat
// 再生終了している場合
// (再生開始時は0, 再生完了の場合は1, 再生中は2を返す様子)
title "Status: "+GetVoiceStatus(pSpVoice)
if GetVoiceStatus(pSpVoice) == 1 : break
wait 12
loop
dialog "再生終了!"
return
*exit
// 終了時にでも破棄する
DestoryVoice pSpVoice
end : end
return

| |
|
2014/1/7(Tue) 02:59:18|NO.59222
もう1つの方法。
comeventを使ったやり方。
#module SAPI_Speech_Voices
#define global ctype SUCCEEDED(%1) ((%1) >= 0)
/*
#define global SafeRelease(%1) if ((varuse@(%1)) && (vartype@(%1) == 6)){ \
delcom@ %1: \
%1 = 0 \
}
*/
#define IID_ISpVoice "{6C44DF74-72B9-4992-A1EC-EF996E0422D4}"
#define IID_IEnumSpObjectTokens "{06B64F9E-7FDA-11D2-B4F2-00C04F797396}"
#define IID_ISpObjectToken "{14056589-E16C-11D2-BB90-00C04F8EE6C0}"
#define IID_ISpObjectTokenCategory "{2D3D3845-39AF-4850-BBF9-40B49780011D}"
#define IID_ISpNotifySource "{5EFF4AEF-8487-11D2-961C-00C04F8EE628}"
#define IID_ISpNotifySink "{259684DC-37C3-11D2-9603-00C04F8EE628}"
#define CLSID_SpVoice "{96749377-3391-11D2-9EE3-00C04F797396}"
#define CLSID_SpMMAudioEnum "{AB1890A0-E91F-11D2-BB91-00C04F8EE6C0}"
#define CLSID_SpObjectToken "{EF411752-3736-4CB4-9C8C-8EF4CCB58EFE}"
#define CLSID_SpObjectTokenCategory "{A910187F-0C7A-45AC-92CC-59EDAFB77B53}"
#define SPCAT_VOICES "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices"
#usecom ISpVoice IID_ISpVoice CLSID_SpVoice
// IUnknown(3)->ISpNotifySource(7)->ISpEventSource(3)->ISpVoice
#comfunc ISpVoice_Pause 16
#comfunc ISpVoice_Resume 17
#comfunc ISpVoice_SetVoice 18 int
#comfunc ISpVoice_GetVoice 19 var
#comfunc ISpVoice_Speak 20 wstr, int, int
#comfunc ISpVoice_GetStatus 22 sptr, wstr
#comfunc ISpVoice_SetRate 28 int
#comfunc ISpVoice_GetRate 29 var
#comfunc ISpVoice_SetVolume 30 int
#comfunc ISpVoice_GetVolume 31 var
#usecom ISpObjectTokenCategory IID_ISpObjectTokenCategory CLSID_SpObjectTokenCategory
//IUnknown(3)->ISpDataKey(12)->ISpObjectTokenCategory
#comfunc ISpObjectTokenCategory_SetId 15 wstr, int
#comfunc ISpObjectTokenCategory_EnumTokens 18 wstr, wstr, sptr
#usecom IEnumSpObjectTokens IID_IEnumSpObjectTokens CLSID_SpMMAudioEnum
// IUnknown(3)->IEnumSpObjectTokens
#comfunc IEnumSpObjectTokens_Next 3 int, sptr, sptr
#comfunc IEnumSpObjectTokens_Reset 5
#comfunc IEnumSpObjectTokens_Clone 6 sptr
#comfunc IEnumSpObjectTokens_Item 7 int, sptr
#comfunc IEnumSpObjectTokens_GetCount 8 var
#usecom ISpObjectToken IID_ISpObjectToken CLSID_SpObjectToken
// IUnknown(3)->ISpDataKey(12)->ISpObjectToken
#comfunc ISpObjectToken_GetStringValue 6 wstr, sptr
#deffunc SafeRelease var p1
if ((varuse(p1)) && (vartype(p1) == 6)){
delcom p1
p1 = 0
}
return
#deffunc CreateVoice var pSpVoice
newcom pSpVoice, ISpVoice
return
#deffunc GetVoicesList var list
sdim list, 1024
// 話者一覧取得
newcom pSpOTC, ISpObjectTokenCategory
if varuse(pSpOTC){
ISpObjectTokenCategory_SetId pSpOTC, SPCAT_VOICES, 0 : hr = stat
if SUCCEEDED(hr){
ptr = 0
ISpObjectTokenCategory_EnumTokens pSpOTC, "", "", varptr(ptr) : hr = stat
if SUCCEEDED(hr) && ptr != 0{
newcom pSpOTs, IEnumSpObjectTokens, -1, ptr
if varuse(pSpOTs){
Num = 0
IEnumSpObjectTokens_GetCount pSpOTs, Num : hr = stat
if SUCCEEDED(hr){
repeat Num
ptr = 0
IEnumSpObjectTokens_Item pSpOTs, cnt, varptr(ptr) : hr = stat
if SUCCEEDED(hr) && ptr != 0{
newcom pSpT, ISpObjectToken, -1, ptr
ISpObjectToken_GetStringValue pSpT, "", varptr(ptr) : hr = stat
if SUCCEEDED(hr){
dupptr wStr, ptr, 1024, 2
list += cnvwtos(wStr) + "\n"
}
SafeRelease pSpT
}
loop
}
SafeRelease pSpOTs
}
}
}
SafeRelease pSpOTC
}
return hr
#deffunc SetVoice var pSpVoice, int idx
newcom pSpOTC, ISpObjectTokenCategory
if varuse(pSpOTC){
ISpObjectTokenCategory_SetId pSpOTC, SPCAT_VOICES, 0 : hr = stat
if SUCCEEDED(hr){
ptr = 0
ISpObjectTokenCategory_EnumTokens pSpOTC, "", "", varptr(ptr) : hr = stat
if SUCCEEDED(hr) && ptr != 0{
newcom pSpOTs, IEnumSpObjectTokens, -1, ptr
if varuse(pSpOTs){
ptr = 0
IEnumSpObjectTokens_Item pSpOTs, idx, varptr(ptr) : hr = stat
if SUCCEEDED(hr){
ISpVoice_SetVoice pSpVoice, ptr
}
SafeRelease pSpOTs
}
}
}
SafeRelease pSpOTC
}
return hr
#deffunc VoiceSpeek var pSpVoice, str s, int f
ISpVoice_Speak pSpVoice, s, f, 0
return stat
#deffunc DestoryVoice var pSpVoice
SafeRelease pSpVoice
return stat
#defcfunc GetVoiceVolume var pSpVoice
Volume = 0
ISpVoice_GetVolume pSpVoice, Volume
return Volume
#deffunc SetVoiceVolume var pSpVoice, int vol
ISpVoice_SetVolume pSpVoice, vol
return stat
#defcfunc GetVoiceRate var pSpVoice, local Rate
Rate = 0
ISpVoice_GetRate pSpVoice, Rate
return Rate
#deffunc SetVoiceRate var pSpVoice, int rate
ISpVoice_SetRate pSpVoice, rate
return stat
#deffunc VoicePause var pSpVoice
ISpVoice_Pause pSpVoice
return stat
#deffunc VoiceResume var pSpVoice
ISpVoice_Resume pSpVoice
return stat
#defcfunc GetVoiceStatus var pSpVoice
dim SPVOICESTATUS, 13
ISpVoice_GetStatus pSpVoice, varptr(SPVOICESTATUS), ""
return SPVOICESTATUS.3
#global
#define DIID_ISpeechVoiceEvents "{A372ACD1-3BEF-4BBD-8FFB-CB3E2B416AF8}"
#define DISPID_SVEStreamStart 0x00000001
#define DISPID_SVEStreamEnd 0x00000002
#define DISPID_SVEVoiceChange 0x00000003
#define DISPID_SVEBookmark 0x00000004
#define DISPID_SVEWord 0x00000005
#define DISPID_SVEPhoneme 0x00000006
#define DISPID_SVESentenceBoundary 0x00000007
#define DISPID_SVEViseme 0x00000008
#define DISPID_SVEAudioLevel 0x00000009
#define DISPID_SVEEnginePrivate 0x0000000A
// 以下サンプル
pSpVoice = 0
// ComObj作成
CreateVoice pSpVoice
if varuse(pSpVoice){
comevent pSpVEvent, pSpVoice, DIID_ISpeechVoiceEvents, *SpVEvent
onexit gosub *exit
// 一覧取得
GetVoicesList list
idx = 0
objsize 420, 20
combox idx, 100, list
mes "▼ 文章"
sdim s, 1024 : s = "Hello this is H.S.P. for windows."
input s
mes "▼ 音量(0〜100)"
Volume = 100
input Volume
mes "▼ 速度(-10〜10)"
Rate = 0
input Rate
Async = 1
chkbox "再生終了まで待たない", Async
button gosub "再生", *speak
}else{
dialog "呼び出し失敗"
}
stop
*SpVEvent
dispid = comevdisp(pSpVEvent)
if dispid == DISPID_SVEStreamStart{
title "再生開始"
}
if dispid == DISPID_SVEStreamEnd{
title "再生終了"
dialog "再生終了"
}
return
*speak
// 音量設定(0〜100)
SetVoiceVolume pSpVoice, Volume
// 再生速度設定(-10〜10)
SetVoiceRate pSpVoice, Rate
title "音量:"+GetVoiceVolume(pSpVoice)+", 速度"+GetVoiceRate(pSpVoice)
// 音声選択
SetVoice pSpVoice, idx
if stat{
dialog "音声選択に失敗しました"
}
// 同期再生(再生終了まで待つ)
// 1にすると非同期
VoiceSpeek pSpVoice, s, Async
if stat{
dialog "再生失敗しました"
}
;wait 50 : VoicePause pSpVoice
// 再生終了までループ
;repeat
// 再生終了している場合
// (再生開始時は0, 再生完了の場合は1, 再生中は2を返す様子)
; title "Status: "+GetVoiceStatus(pSpVoice)
; if GetVoiceStatus(pSpVoice) == 1 : break
; wait 12
;loop
;dialog "再生終了!"
return
*exit
// 終了時にでも破棄する
DestoryVoice pSpVoice
end : end
return

| |
|
2014/1/7(Tue) 09:48:56|NO.59226
素早い回答をありがとうございます!なるほど、こうやるんですか…
おかげさまで、自ウィンドウの操作が改善できました。
想定していたのは一つ目のやり方ですが、ふたつ目のやり方も興味深いですね。
どちらがいいかもうすこし吟味してみたいと思います。
何度も回答していただき、ありがとうございましたm(_ _)m
|
|