raw(音楽ファイル)データを配列rawに読み込みたいのですが,バイナリファイルの読み込み方がわかりません.
サンプルで以下のようなソース(途中略)があるのですが,
・なぜrawの型としてshortを使っているのか
・データ数の半分(file_size = ftell(fp) / 2)しか読み込んでいない
・fgetc(fp) << 8
あたりの意味がわからないので教えて下さい.
--------------------------------------------------------
short *raw;
if((fp=fopen(argv[1], "rb")) == NULL){
fprintf(stderr, "can't open %s.\n", argv[1]);
exit(1);
}
fseek(fp, 0, SEEK_END);
file_size = ftell(fp) / 2;
fseek(fp, 0, SEEK_SET);
raw = (short *)malloc((size_t)(file_size * sizeof(short)));
if(raw == NULL){
fprintf(stderr, "malloc error\n");
exit(1);
}
for(i=0;i<file_size;i++)
raw[i] = (short)((fgetc(fp) << 8) | fgetc(fp));
-----------------------------------------------------
No.3ベストアンサー
- 回答日時:
動作自体はNo.1,No.2の方のとおりですが、このサンプルには不都合な点が2点あります。
>file_size = ftell(fp) / 2;
2というマジックナンバを使っている、正式にはsizeof(short)でないとまずい。
file_size = ftell(fp) / sizeof(short);
>raw[i] = (short)((fgetc(fp) << 8) | fgetc(fp));
fgetcを式の中で2回呼び出している、C言語規格では未定義の動作で、fgetcを実行する順序がどうなるか分からないので、下のように書かないと駄目。
raw[i] = fgetc(fp) << 8;
raw[i] |= fgetc(fp);
または
raw[i] = fgetc(fp);
raw[i] |= fgetc(fp) << 8;
どちらかになるかは、元データのエンディアンによります。
回答ありがとうございます。
>どちらかになるかは、元データのエンディアンによります。
入力データがリトルエンディアンかビッグエンディアンかでどちらかに決まる、ということですね。
No.4
- 回答日時:
No.3の訂正です。
------ ここから ------
動作自体はNo.1,No.2の方のとおりですが、このサンプルには不都合な点が1点あります。
>raw[i] = (short)((fgetc(fp) << 8) | fgetc(fp));
fgetcを式の中で2回呼び出している、C言語規格では未定義の動作で、fgetcを実行する順序がどうなるか分からないので、下のように書かないと駄目。
ビッグエンディアンのとき
raw[i] = fgetc(fp) << 8;
raw[i] |= fgetc(fp) & 0xff;
または
リトルエンディアンのとき
raw[i] = fgetc(fp) & 0xff;
raw[i] |= fgetc(fp) << 8;
------ ここまで ------
以下は間違えていました。
>>file_size = ftell(fp) / 2;
>2というマジックナンバを使っている、正式にはsizeof(short)でないとまずい。
>file_size = ftell(fp) / sizeof(short);
逆でしたsizeof(short)がまずくて2の方が正式でした。
元ファイル自体が2バイトずつ書かれているのをsizeof(short)で計算するのは間違いでした。
回答ありがとうございます。
>raw[i] = fgetc(fp) & 0xff;
8ビット全てで1とのアンドをとる、ということですよね。
なぜこのような操作をしているのでしょうか?
No.2
- 回答日時:
rawファイルのデータ構造の知識はありませんが、サンプルソースを読むかぎりでは、
16ビットのデータが、リトルエンディアン(上位アドレスに下位バイトのデータが配置されている)
で格納されている、という前提でバイナリファイルを読み込む処理を行っています。
> なぜrawの型としてshortを使っているのか
確実に16ビットのデータとして扱いたいのだと思います。intでは処理系によってサイズが変わってきます。
> データ数の半分(file_size = ftell(fp) / 2)しか読み込んでいない
ftell、fseek、fgetc、などは全て、ファイルを1バイト単位で扱います。
ftellの返す値は、ファイルサイズをバイトで数えた数値です。
これに対し、raw = (short *)malloc((size_t)(file_size * sizeof(short)));
では、2バイト単位で領域を確保しているので、ftellの返す値の半分で十分です。
また、最後のforループでは、1回のループ内でfgetcを2回呼び出して、2バイトづつ読み込んでいますので
ファイル全体を読み込めています。
> fgetc(fp) << 8
バイトオーダーが変わらないように、fgetcで1バイトづつ読み込み、先に取得した8ビットのデータを
8ビット分上位にシフトして、空いた下位8ビットに、次に取得した8ビットをビット演算で格納し、
16ビットのデータにしてから、raw[i] に代入するための処理です。
回答ありがとうございます。
ソースの内容はだいだいわかりましたが、
エンディアンあたりの話がよく分からないのでもう少し勉強してみます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
餃子を食べるとき、何をつけますか?
みんな大好き餃子。 ふと素朴な疑問ですが、餃子には何をつけて食べますか? 王道は醤油とお酢でしょうか。
-
家・車以外で、人生で一番奮発した買い物
どんなものにお金をかけるかは人それぞれの価値観ですが、 誰もが一度は清水の舞台から飛び降りる覚悟で、ちょっと贅沢な買い物をしたことがあるはず。
-
これ何て呼びますか Part2
あなたのお住いの地域で、これ、何て呼びますか?
-
この人頭いいなと思ったエピソード
一緒にいたときに「この人頭いいな」と思ったエピソードを教えてください
-
14歳の自分に衝撃の事実を告げてください
タイムマシンで14歳の自分のところに現れた未来のあなた。 衝撃的な事実を告げて自分に驚かせるとしたら何を告げますか?
-
freadでデータがない場合の読込値は?
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・チョコミントアイス
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・あなたの習慣について教えてください!!
- ・ハマっている「お菓子」を教えて!
- ・高校三年生の合唱祭で何を歌いましたか?
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・家の中でのこだわりスペースはどこですか?
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語について
-
fopenでファイル名に、変数を使...
-
テキストファイルをバイナリフ...
-
エラーがわかりません、、
-
C言語にてXMLファイルから任意...
-
テキストファイル内に対して, ...
-
C言語 共用体の構造体の引数設定
-
隣接行列を読み込んで有向グラ...
-
数値のみ抽出(C言語)
-
複数ファイルの同時読み込みの...
-
信頼区間の1.96や1.65ってどこ...
-
2÷3などの余りについて
-
複数桁10進数の*桁目だけを抽出...
-
プログラミング初心者です。 Py...
-
std::set<int> で、ある値が何...
-
cout関数を使っているのですが...
-
2の補数を計算するプログラム
-
EXCELの分散分析表のP-値が....
-
構造体の宣言でエラーが出ます。
-
C++でRPGを作成する際のステー...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
複数ファイルの同時読み込みの...
-
c言語でのfscanfについて
-
ガンマ変換 C言語でプログラ...
-
fopenでファイル名に、変数を使...
-
エラーがわかりません、、
-
C言語でクロマキー合成をする方法
-
ファイル出力で改行を入れたい!
-
C言語でファイル読み書きを早く...
-
テキストファイル内に対して, ...
-
ファイルが読み込めない・・・
-
ファイルへの書込み処理が異常...
-
fscanfでループしてしまう。
-
音声データを出力するCプログラ...
-
fgets関数の利用 c言語
-
fgets( ) の返り値は何?
-
日本語ファイル名のFTPについて
-
大量の入力ファイルを扱うとき...
-
【C言語】ファイルを読み込んで...
-
二分探索木への挿入
-
C言語でセグメンテーションエ...
おすすめ情報