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

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
MML
記事: 154
登録日時: 2006年5月02日(火) 16:27

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

#1 投稿記事 by MML »

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

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

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

詳しい方、よろしくお願いします。
OverTaker
記事: 231
登録日時: 2005年5月31日(火) 17:14
お住まい: 茨城県

#2 投稿記事 by OverTaker »

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


以上簡単な説明なので、分からないところもあるかもしれませんが、その時はまた質問してください。または他のユーザーさんにお願いしたいと思います。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#3 投稿記事 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?がホストエンディアンへの変換を行います。
MML
記事: 154
登録日時: 2006年5月02日(火) 16:27

#4 投稿記事 by MML »

OverTakerさん、イグトランスさんありがとうございます。
WinSock、バイナリ書き込み、試してみます。

MIDIファイルで一番重要なことですが、
(多分これがリトルエディアンって言われてたと思うのですが、)
可変長数値ってありますよね。
あれってどうやればできるんですか?
ビットシフトという言葉だけは聴いたことがあるのですが、
やり方までは知りません(^^;
konisi
記事: 893
登録日時: 2005年7月25日(月) 13:27
お住まい: 埼玉県東松山市
連絡する:

#5 投稿記事 by konisi »

AB5のCP2以降のIncludeフォルダ内にある、Stringクラスが参考になると思いますが、malloc/calloc/realloc等の関数でバイト数を指定して長大変数を確保し、free関数で変数領域の開放を行う という方法があります。
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
OverTaker
記事: 231
登録日時: 2005年5月31日(火) 17:14
お住まい: 茨城県

#6 投稿記事 by OverTaker »

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

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

#7 投稿記事 by MML »

返信、遅くなってすみません。
OverTakerさん、ありがとうございます。

Longから可変長データに変換するときは↑の処理を逆にするんですか?
もしくは、HIWORD(LOWORD)、HIBYTE(LOBYTE)を使ってもOKなのでしょうか?
OverTaker
記事: 231
登録日時: 2005年5月31日(火) 17:14
お住まい: 茨城県

#8 投稿記事 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やシフト演算をうまく使い、計算していきます。
最初から複雑な演算は難しいと思いますので、まずは、ビット演算に慣れてみてください。

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