|
私の前回のレスのおかげで、この掲示板にDLLブウムが起きた(らしい)ことは、嬉しいことです。
こういう知性系掲示板と言うのは質問以外は、なかなか反応が分かる書き込みが無いものです(ちゃっかり黙ってレスのプログラムだけコピイする者はいるだろーが)。よってちょっとでも反応らしいことが起きると嬉しいものですね♪
さて、このレスの結論から先に言えば、DLL関数使用時、MSO VBA etc.では4バイト小数型変数が使えるが、十進BASICでは使えない。
グルグルSMF内のGGS4SETMASTERTEMPOと言う関数を例に挙げよう。
グルグルSMF(以下GGSと呼ぶ)というのは、MIDI演奏するための無料のDLLであって、その名の通りルウプ演奏に長けたDLLである。そのほかにSMFのヘエドイン、ヘエドアウト演奏、演奏中のボリュウムダウン、テンポ変更、ピッチ変更etc.の機能がある。
このソフトのヘルプによればC系言語向けの実装と言うことになっているが、BASICでも一応使用が可能。
URLは コチラ↓
ttp://gurugurusmf.migmig.net/
問題のGGS4SETMASTERTEMPO関数は以下の仕様となっている。
void GGS4SetMasterTempo(float tempo); // C
再生中にテンポを動的に変化させます。
デバイスを閉じるまで有効です。
float tempo
変化割合を指定します。
1で通常、0.5で半分、2で2倍のテンポになります。
現在、0.1~8までの範囲が有効です。
まず、この関数をEXCEL VBA 2000に適用してみる。float型変数はVBAでは8バイト小数、すなわちdouble型変数(だと思っていた)なのでas doubleを宣言した。なお、BASIC系言語では、GGS4を頭に冠した書式の関数しか使用できない。
Private Declare Function op Lib"c:\gurugurusmf\gurugurusmf4.dll"Alias"GGS4OpenDevice"(Byval q as Long,Byval w as Long) as Long
Private Declare Function al Lib"c:\gurugurusmf\gurugurusmf4.dll"Alias"GGS4AddListFromFileA"(Byval q as String,Byval w as Long,Byval e as Long) as Long
Private Declare Function pl Lib"c:\gurugurusmf\gurugurusmf4.dll"Alias"GGS4Play"(Byval q as Long,Byval w as Long,Byval e as Long,Byval r as Long,Byval t as Long) as Long
Private Declare Sub st Lib"c:\gurugurusmf\gurugurusmf4.dll"Alias"GGS4SetMasterTempo"(Byval q as double)
Private Declare Sub cl Lib"c:\gurugurusmf\gurugurusmf4.dll"Alias "GGS4ClearList"()
Private Declare Sub co Lib"c:\gurugurusmf\gurugurusmf4.dll"Alias "GGS4CloseDevice"()
Sub main()
dim w as double
e=op(-1100,0) 'この行は書き換え禁止!
e=al("ddd.mid",0,0) '""の中は任意のMIDIファイル名
e=pl(0,0,0,0,0)
for w=1to 3step.5
Call st(w)
Application.Wait((Timer+3)/86400) 'EXCELのWAITの引数の単位は丸1日を1とする小数
next
call cl:co:End
End Sub
うなるような音がするだけで、演奏しない。そこで一か八かでdouble型を4バイト型小数変数すなわちsingle型に変えてみると、なんと成功した!
Private Declare Function op Lib"c:\gurugurusmf\gurugurusmf4.dll"Alias"GGS4OpenDevice"(Byval q as Long,Byval w as Long) as Long
Private Declare Function al Lib"c:\gurugurusmf\gurugurusmf4.dll"Alias"GGS4AddListFromFileA"(Byval q as String,Byval w as Long,Byval e as Long) as Long
Private Declare Function pl Lib"c:\gurugurusmf\gurugurusmf4.dll"Alias"GGS4Play"(Byval q as Long,Byval w as Long,Byval e as Long,Byval r as Long,Byval t as Long) as Long
Private Declare Sub st Lib"c:\gurugurusmf\gurugurusmf4.dll"Alias"GGS4SetMasterTempo"(Byval q as single)
Private Declare Sub cl Lib"c:\gurugurusmf\gurugurusmf4.dll"Alias"GGS4ClearList"()
Private Declare Sub co Lib"c:\gurugurusmf\gurugurusmf4.dll"Alias"GGS4CloseDevice"()
Sub main()
dim w as single
e=op(-1100,0) 'この行は書き換え禁止!
e=al("ddd.mid",0,0) '""の中は任意のMIDIファイル名
e=pl(0,0,0,0,0)
for w=1to 3step.5
Call st(w)
Application.Wait((Timer+2)/86400)
next
call cl:co:End
End Sub
次はこれを十進BASICに移植しようと思い、以下のコオドを実行する。
e=op(-1100,0)
e=al("ddd.mid",0,0)
e=pl(0,0,0,0,0)
for w=1to 3step.5
Call st(w)
Wait DELAY 2
next
call cl
CALL co
End
EXTERNAL Function op(Q,W)
ASSIGN"c:\gurugurusmf\gurugurusmf4.dll","GGS4OpenDevice"
END FUNDTION
EXTERNAL FUNCTION al(q$,w,e)
assign"c:\gurugurusmf\gurugurusmf4.dll","GGS4AddListFromFileA"
END FUNCTION
EXTERNAL FUNCTION pl(q,w,e,r,t)
assign"c:\gurugurusmf\gurugurusmf4.dll","GGS4Play"
END FUNCTION
EXTERNAL SUB st(q)
assign"c:\gurugurusmf\gurugurusmf4.dll","GGS4SetMasterTempo"
END SUB
EXTERNAL SUB ci
assign"c:\gurugurusmf\gurugurusmf4.dll","GGS4ClearList"
END SUB
EXTERNAL SUB cl
assign"c:\gurugurusmf\gurugurusmf4.dll","GGS4CloseDevice"
END SUB
ヘルプによると以下のようになっているのでもちろんダメ。
数値型の引数は上位桁を切り捨てた32ビット整数として評価して渡す。
そこで、GGS4SetMasterTempo関数に4バイト小数の引数を渡すため、EXCEL VBAに戻り、簡単な4バイト小数のイメエジハイルを作ってみる。
sub q()
dim w as single
open"f:\tenpuhairu\dum.dat"for binary as 1
for w=1to 3step.5
put #1,,w
next
close #1
end sub
これをバイナリエディッタで参照すれば、間違いなく4バイトのデエタが5個書かれているのが解る。
これを十進Bで読み込んで演奏するためのプログラムを作る。小数イメエジを文字列変数として読み込む。
OPTION CHARACTER byte
DECLARE EXTERNAL FUNCTION op,al,pl
open #1:NAME"f:\tenpuhairu\dum.dat",ACCESS INPUT
INPUT #1:I$
CLOSE #1
LET q=op(-1100,0)
LET q=al("DDD.mid",0,2)
LET q=pl(0,2,0,0,0)
FOR W=0TO 4
LET q$=I$(4*W+1:4*W+4)
CALL ST(q$)
WAIT DELAY 1
q$=""
NEXT
CALL ci
CALL cl
END
EXTERNAL FUNCTION op(q,w)
assign"c:\gurugurusmf\gurugurusmf4.dll","GGS4OpenDevice"
END FUNCTION
EXTERNAL FUNCTION al(q$,w,e)
assign"c:\gurugurusmf\gurugurusmf4.dll","GGS4AddListFromFileA"
END FUNCTION
EXTERNAL FUNCTION pl(q,w,e,r,t)
assign"c:\gurugurusmf\gurugurusmf4.dll","GGS4Play"
END FUNCTION
EXTERNAL SUB ST(q$)
assign"c:\gurugurusmf\gurugurusmf4.dll","GGS4SetMasterTempo"
END SUB
EXTERNAL SUB ci
assign"c:\gurugurusmf\gurugurusmf4.dll","GGS4ClearList"
END SUB
EXTERNAL SUB cl
assign"c:\gurugurusmf\gurugurusmf4.dll","GGS4CloseDevice"
END SUB
矢張り結果は同じだった。もう十進Bの組み込み関数、PACKDBL$を用いて4バイト小数イメエジをを8バイト小数に換えたりしても全くダメ(ソース略)(もっとも十進Bは、普通のDLL関数の整数型変数を当てるべきところに文字列型変数を当てること自体受け付けないのだが...)。
すなわち、MSO VBA では4バイト小数型変数が使えるが、十進Bでは使えない、という結論に終わった(もっともVBAのほうも、GGSの使用はどうにかこうにかというレベルなのだが)。
しかしこれは、十進Bのバグと言うより、十進Bタイプの言語の限界なのだろう。
十進Bが、JIS FULL BASICの機能を実現するために作られたもので、JISに準拠しなければならないんだから仕方ないんですよね、白石先生。
|
|