ページ 11

バイナリの書き込み読み込み

Posted: 2006年11月27日(月) 17:23
by MML
バイナリの書き込み/読み込みというのはどうすればいいのでしょうか?
実は「MIDIファイルを自分で生産してみよう!」ということを思いついて、
やってみたかったんですが、MIDIファイルの仕組み(ヘッダとか)はわかる...つもりでいるのですが、書き込み/読み込みがどうすればいいのかがわかりません。
テキストファイルはわかるのですが...(^^;

また、書き込み/読み込みというのは
byte型の配列を使ってやるのでしょうか?

それと、ビッグエディアン -> リトルエディアン また、その反対はどうするのでしょうか?

詳しい方、よろしくお願いします。

Posted: 2006年11月27日(月) 18:24
by OverTaker
どの程度説明するかわかりませんが、とりあえずざっと書いてみます。
バイナリの書き込み/読み込みというのはどうすればいいのでしょうか?
ReadFile()やWriteFile()でOKだと思います。ちなみに、CreateFile() -> ReadFile() Or WriteFile() -> CloseHandle()の流れで使用します。
それと、ビッグエディアン -> リトルエディアン また、その反対はどうするのでしょうか?
この辺は、たぶんHIWORD()などでできると思いますが、複雑なものは論理演算(ビット演算)した方がいいかもしれません。
実は「MIDIファイルを自分で生産してみよう!」ということを思いついて、
やってみたかったんですが、MIDIファイルの仕組み(ヘッダとか)はわかる...つもりでいるのですが、書き込み/読み込みがどうすればいいのかがわかりません。
ちなみに、MIDIファイルは私もやろうと思ったことがありますが、その時は構造がうまくつかめなかったので、やりませんでした。
今は、ABではないですが、OS X用のMIDIシーケンサでいいものが見つからないので、作りたいなーとも思っています。


以上簡単な説明なので、分からないところもあるかもしれませんが、その時はまた質問してください。または他のユーザーさんにお願いしたいと思います。

Posted: 2006年11月27日(月) 23:48
by イグトランス
エンディアンの変換を行う関数ならWinSockにあります。
正確にはネットワークエンディアン(ビッグエンディアン)とプログラムが動いているコンピュータで使われているホストエンディアンを変換する関数ですけど。

コード: 全て選択

Declare Function htons Lib "ws2_32.dll" (netShort As Word) As Word 
Declare Function htonl Lib "ws2_32.dll" (netLong As DWord)  As DWord 
Declare Function ntohs Lib "ws2_32.dll" (hostShort As Word) As Word 
Declare Function ntohl Lib "ws2_32.dll" (hostLong As DWord)  As DWord
hton?がネットワークエンディアンへの,ntoh?がホストエンディアンへの変換を行います。

Posted: 2006年11月28日(火) 16:27
by MML
OverTakerさん、イグトランスさんありがとうございます。
WinSock、バイナリ書き込み、試してみます。

MIDIファイルで一番重要なことですが、
(多分これがリトルエディアンって言われてたと思うのですが、)
可変長数値ってありますよね。
あれってどうやればできるんですか?
ビットシフトという言葉だけは聴いたことがあるのですが、
やり方までは知りません(^^;

Posted: 2006年11月28日(火) 19:02
by konisi
AB5のCP2以降のIncludeフォルダ内にある、Stringクラスが参考になると思いますが、malloc/calloc/realloc等の関数でバイト数を指定して長大変数を確保し、free関数で変数領域の開放を行う という方法があります。

Posted: 2006年11月28日(火) 20:52
by OverTaker
MIDIファイルで一番重要なことですが、
(多分これがリトルエディアンって言われてたと思うのですが、)
可変長数値ってありますよね。
あれってどうやればできるんですか?
ビットシフトという言葉だけは聴いたことがあるのですが、
やり方までは知りません(^^;
可変長数値というのは、SMF内部構造のページ末尾に書いてあるやつのことですよね?

とりあえずサンプルとして、配列に格納されている可変長数値のデータを、Long型に変換するものを作ってみました。
ビット演算自体は、オブジェクト指向よりよっぽど具体的な話なので、検索して調べればすぐにわかると思います。ただ、アルゴリズム考えるのがちょっと面倒です。

Posted: 2006年12月31日(日) 13:32
by MML
返信、遅くなってすみません。
OverTakerさん、ありがとうございます。

Longから可変長データに変換するときは↑の処理を逆にするんですか?
もしくは、HIWORD(LOWORD)、HIBYTE(LOBYTE)を使ってもOKなのでしょうか?

Posted: 2006年12月31日(日) 15:05
by OverTaker
まず、ビット演算について調べてみてください。wikipediaにも結構詳しく載っています。
ビット演算(wikipedia)

HIBYTEやLOBYTEというのは、16bitを上位,下位の8bitに分断するものです。しかし、MIDIで使われている可変長数値は、HIBYTEなどよりも、もっと細かいビット操作を必要としています。

例えば、上のコードのIsTopStanding()ですが、これは、先頭のbitが1かどうかを返す関数です。先頭の1bitの状態を取得するには、HIBYTEなどでは8bit単位なので無理なのは分かるでしょう。そこで、ビット演算をうまくつかいます。

コード: 全て選択

Function IsTopStanding(b As Byte) As BOOL 
    If b And &H80 Then 
        Return TRUE 
    Else 
        Return FALSE 
    End If 
End Function
その前に補足です。条件式ですが、ActiveBasicの場合、条件式の結果が0以外だったら、真と判定されます。

条件式のb And &H80が真だったら、先頭のbitは1になっているというわけですが、具体的には、次のようなビット演算になっています。

コード: 全て選択

b = 10110101(2進数)だった場合
&H80は2進数で10000000です。

     10110101
 and)10000000
-----------------
     10000000
and演算をやっていれば分かりますが、and演算の性質は、どちらかの値が0だったら計算結果が0になります。そして、どちらも1だった場合、1になります。andする値が0の場合、その計算結果は必ず0になります。

コード: 全て選択

0 and 0 = 0
1 and 0 = 0
この性質を利用して、計算します。まず、先頭のビットにand 1することによって、bの値が1だった場合1、0だった場合0となります。1つでもビットが1であれば条件式は真になりますので、他の不要な7bitは、and 0して、全て0にしてしまいます。
こうすることにより、先頭のbitがどうなっているかを、条件式で判断することができます。

こんな感じで、他にも、Orやシフト演算をうまく使い、計算していきます。
最初から複雑な演算は難しいと思いますので、まずは、ビット演算に慣れてみてください。

今日は時間がないので、少し雑な説明になってしまいました。