comparison music2/nwatowav.cc @ 65:4416cfac86ae

Convert EUC-JP files to UTF8
author Thibaut Girka <thib@sitedethib.com>
date Fri, 26 Nov 2010 10:53:15 +0100
parents 15a18fbe6f21
children
comparison
equal deleted inserted replaced
64:045ca45f9610 65:4416cfac86ae
1 /* nwatowav : Visual Arts 系のゲームのデモで使われる nwa 形式の 1 /* nwatowav : Visual Arts 膤祉蚊若≪т戎 nwa 綵√
2 ** ファイルを wav 形式に変換する 2 ** <ゃ wav 綵√紊
3 ** 3 **
4 ** compile : gcc -O2 -o nwatowav nwatowav.cc 4 ** compile : gcc -O2 -o nwatowav nwatowav.cc
5 ** usage : nwatowav [nwa-file [outfile]] 5 ** usage : nwatowav [nwa-file [outfile]]
6 ** nwatowav [nwk-file [outfile]] 6 ** nwatowav [nwk-file [outfile]]
7 ** example : nwatowav HM06.nwa HM06.wav # BGMファイル。HM06.wav に展開される 7 ** example : nwatowav HM06.nwa HM06.wav # BGM<ゃHM06.wav 絮
8 ** nwatowav z2813.nwk z2813 # 音声ファイル。 z2813-100.wav などのファイル名で展開される 8 ** nwatowav z2813.nwk z2813 # 喝0<ゃ z2813-100.wav <ゃу
9 ** nwatowav z0513.ovk z0513 # 音声ファイル。 z0513-100.ogg などのファイル名で展開される 9 ** nwatowav z0513.ovk z0513 # 喝0<ゃ z0513-100.ogg <ゃу
10 ** 10 **
11 ** 11 **
12 ** 2004.5.19 小松さん<s1100089@u-aizu.ac.jp> から CLANNAD の無圧縮nwa形式に対応する 12 ** 2004.5.19 絨障<s1100089@u-aizu.ac.jp> CLANNAD ≦х軒nwa綵√絲上
13 ** パッチをいただいたので、適用しました。ありがとうございます。 13 ** с障障
14 ** 2006.9.10 「智代アフター」の音声ファイル形式 (complevel = 5) をサポート 14 ** 2006.9.10 坂撮≪帥若喝0<ゃ綵√ (complevel = 5) 泣若
15 ** .nwk という拡張子を持つファイルを受け取ると音声ファイルとして 15 ** .nwk ≦宍絖ゃ<ゃ喝0<ゃ
16 ** 解釈、分割して展開するようにする 16 ** 茹i蚊絮
17 ** 2007.7.28 「リトルバスターズ!」の音声ファイル形式 (*.ovk; ogg 連結型) 17 ** 2007.7.28 鴻帥若削喝0<ゃ綵√ (*.ovk; ogg g)
18 ** をサポート。.ovk という拡張子をもつファイルを受け取ると 18 ** 泣若.ovk ≦宍絖ゃ<ゃ
19 ** 音声ファイルとして解釈、分割して展開するようにする 19 ** 喝0<ゃ茹i蚊絮
20 ** 「リトルバスターズ!」のBGMファイルに多量のノイズが乗る問題も 20 ** 鴻帥若削BGM<ゃ紊ゃ冴箙馹
21 **  解決(ランレングス圧縮の処理が不必要だった) 21 ** 茹f浦鐚潟潟違劫х軒筝綽荀c鐚
22 */ 22 */
23 23
24 /* 24 /*
25 * Copyright 2001-2007 jagarl / Kazunori Ueno <jagarl@creator.club.ne.jp> 25 * Copyright 2001-2007 jagarl / Kazunori Ueno <jagarl@creator.club.ne.jp>
26 * All Rights Reserved. 26 * All Rights Reserved.
27 * 27 *
28 * Redistribution and use in source and binary forms, with or without 28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted. 29 * modification, are permitted.
30 * 30 *
31 * このプログラムの作者は jagarl です。 31 * 違篏 jagarl с
32 * 32 *
33 * このプログラム、及びコンパイルによって生成したバイナリは 33 * 違潟潟潟ゃcゃ
34 * プログラムを変更する、しないにかかわらず再配布可能です。 34 * 違紊眼絽純с
35 * その際、上記 Copyright 表示を保持するなどの条件は課しま 35 * 筝荐 Copyright 茵腓冴篆>散茯蚊
36 * せん。対応が面倒なのでバグ報告を除き、メールで連絡をする 36 * 絲上√с医怨ゃ<若чg機
37 * などの必要もありません。ソースの一部を流用することを含め、 37 * 綽荀障純若鴻筝羌
38 * ご自由にお使いください。 38 * 宴篏帥
39 * 39 *
40 * THIS SOFTWARE IS PROVIDED BY KAZUNORI 'jagarl' UENO ``AS IS'' AND ANY 40 * THIS SOFTWARE IS PROVIDED BY KAZUNORI 'jagarl' UENO ``AS IS'' AND ANY
41 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KAZUNORI UENO BE LIABLE 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KAZUNORI UENO BE LIABLE
52 * 52 *
53 */ 53 */
54 54
55 /******************************************** 55 /********************************************
56 ** 56 **
57 ** nwa フォーマットについて 57 ** nwa 若ゃ
58 ** 58 **
59 ** 全体としては以下の構造を持つ 59 ** 篏篁ヤ罕
60 ** NWA Header 60 ** NWA Header
61 ** data offset index 61 ** data offset index
62 ** data block<0> 62 ** data block<0>
63 ** data block<1> 63 ** data block<1>
64 ** ... 64 ** ...
65 ** data block<N> 65 ** data block<N>
66 ** 66 **
67 ** NWA Header: ファイル先頭から 44 bytes 67 ** NWA Header: <ゃ 44 bytes
68 ** magic number などはないのでnwa ファイルかは 68 ** magic number nwa <ゃ
69 ** データの整合性から判断する必要がある 69 ** 若帥翫сゆ綽荀
70 ** データは全て little endian で、 70 ** 若帥 little endian с
71 ** short(signed 2byte)または int(signed 4byte) である。 71 ** short(signed 2byte)障 int(signed 4byte) с
72 ** 72 **
73 ** +00 short channel 数(1/2) 73 ** +00 short channel (1/2)
74 ** +02 short sample 一つあたりの bit 数(16) 74 ** +02 short sample 筝ゃ bit (16)
75 ** +04 int 周波数(一秒あたりのデータ数) 75 ** +04 int 羈∽(筝腱若炊)
76 ** +08 int 圧縮レベル:-1~5.2で最小のデータ、0で最大の復元度(-1は無圧縮rawデータとみなされる) 76 ** +08 int х軒鐚-1~5.2ф絨若帥0ф紊с緇綺(-1≦х軒raw若帥帥)
77 ** +12 int ? 77 ** +12 int ?
78 ** +16 int ブロック数 78 ** +16 int
79 ** +20 int 展開後のデータの大きさ(バイト単位) 79 ** +20 int 絮緇若帥紊с(ゃ篏)
80 ** +24 int 圧縮時のデータの大きさ(nwa ファイルの大きさ。バイト単位) 80 ** +24 int х軒若帥紊с(nwa <ゃ紊сゃ篏)
81 ** +28 int サンプル数:展開後のデータ数(16bit dataなら short 単位==サンプル単位のデータの大きさ) 81 ** +28 int 泣潟逸絮緇若炊(16bit data short 篏==泣潟篏若帥紊с)
82 ** +32 int データ1ブロックを展開した時のサンプル単位のデータ数 82 ** +32 int 若随絮泣潟篏若炊
83 ** +36 int 最終ブロックを展開した時のサンプル単位のデータ数 83 ** +36 int 腟絮泣潟篏若炊
84 ** +40 int ? 84 ** +40 int ?
85 ** 85 **
86 ** data offset index 86 ** data offset index
87 ** 全ブロック数 x 4 byte のデータ 87 ** x 4 byte 若
88 ** それぞれ int のデータが全ブロック数続いている 88 ** int 若帥亥
89 ** 89 **
90 ** データブロックの先頭を指すファイル先頭からの位置(オフセット) 90 ** 若帥<ゃ篏臀(祉)
91 ** が格納されている 91 ** 主
92 ** 92 **
93 ** data block 93 ** data block
94 ** 長さは可変。展開することで一定の大きさをもつデータに展開される。 94 ** 激紊絮т絎紊сゃ若帥絮
95 ** データはDPCM形式。元 PCM データが a,b,c ならば (a),b-a, c-b と 95 ** 若帥DPCM綵√ PCM 若帥 a,b,c (a),b-a, c-b
96 ** いった差分データが、仮数3-5bit,指数3bitの形式で保存されている。 96 ** c綏若帥篁3-5bit,3bit綵√т絖
97 ** 結果的に、16bit のデータが多くの場合 6-8bit で格納される。 97 ** 腟16bit 若帥紊翫 6-8bit ф主
98 ** 仮数のビット数は圧縮レベル0で5bit、圧縮レベル2で3bitとなる。 98 ** 篁違違х軒05bitх軒23bit
99 ** 以下、圧縮レベル2の場合について話を進める。 99 ** 篁ヤх軒2翫ゃ荅宴蚊
100 ** モノラルの場合: 100 ** ≪翫鐚
101 ** +00 short ブロック内の最初のデータ 101 ** +00 short 若
102 ** +02- bit stream 102 ** +02- bit stream
103 ** ステレオの場合: 103 ** 鴻翫鐚
104 ** +00 short 左(?)チャンネルの最初のデータ 104 ** +00 short 綏(?)c潟若
105 ** +02 short 右(?)チャンネルの最初のデータ 105 ** +02 short (?)c潟若
106 ** +04- bit stream 106 ** +04- bit stream
107 ** 107 **
108 ** 差分データの精度が高くないので各ブロックの先頭で 108 ** 綏若帥膕上墾蕭у
109 ** 正確なデータにより補正される(?) 109 ** 罩g∈若帥茖罩c(鐚)
110 ** 110 **
111 ** bit stream 111 ** bit stream
112 ** little endian 112 ** little endian
113 ** +0 - +2 : 指数 113 ** +0 - +2 :
114 ** +3 - +5 : 仮数 114 ** +3 - +5 : 篁
115 ** の形式。例えば a,b,c という8bitデータがあれば、 115 ** 綵√箴 a,b,c 8bit若帥違
116 ** a&0x07 : データ1の指数 116 ** a&0x07 : 若随
117 ** (a>>3)&0x07 : データ1の仮数(signed ; 117 ** (a>>3)&0x07 : 若随篁(signed ;
118 ** ((b<<2)|(a>>6))&0x07 : データ2の指数 118 ** ((b<<2)|(a>>6))&0x07 : 若随
119 ** (b>>1)&0x07 : データ2の仮数 119 ** (b>>1)&0x07 : 若随篁
120 ** となる。 120 **
121 ** ただし、指数の値により仮数のbit数が変化することがある。 121 ** 違ゃ篁違bit違紊
122 ** 指数 = 1 - 6 の場合: 122 ** = 1 - 6 翫鐚
123 ** a=指数、b=仮数、p=前のデータとして、今回のデータd は 123 ** a=違b=篁違p=若帥篁若d
124 ** bの2bit目が立っている場合: 124 ** b2bit腴c翫鐚
125 ** d = p - (b&3)<<(4+a) 125 ** d = p - (b&3)<<(4+a)
126 ** 立ってない場合: 126 ** 腴c翫鐚
127 ** d = p + (b&3)<<(4+a) 127 ** d = p + (b&3)<<(4+a)
128 ** 指数 = 0 の場合:仮数は存在しない(データは3bitとなる) 128 ** = 0 翫鐚篁違絖(若帥3bit)
129 ** d = p 129 ** d = p
130 ** 「智代アフター」の音声ファイル (complevel == 5) ではランレングス圧縮用に使われている。 130 ** 坂撮≪帥若喝0<ゃ (complevel == 5) с潟潟違劫х軒篏帥
131 ** 指数 = 7 131 ** = 7
132 ** 次の bit が立っている場合: 132 ** 罨< bit 腴c翫鐚
133 ** d = 0 (現在未使用) 133 ** d = 0 (憜篏睡)
134 ** (データは4bitとなる) 134 ** (若帥4bit)
135 ** 次の bit が立ってない場合: 135 ** 罨< bit 腴c翫鐚
136 ** complevel = 0,1,2: 136 ** complevel = 0,1,2:
137 ** 仮数 b = 6bit 137 ** 篁 b = 6bit
138 ** b の 5bit 目が立っている場合: 138 ** b 5bit 腴c翫鐚
139 ** d = p - (b&0x1f)<<(4+7) 139 ** d = p - (b&0x1f)<<(4+7)
140 ** 立ってない場合: 140 ** 腴c翫鐚
141 ** d = p + (b&0x1f)<<(4+7) 141 ** d = p + (b&0x1f)<<(4+7)
142 ** (データは10bitとなる) 142 ** (若帥10bit)
143 ** complevel = 3,4,5: 143 ** complevel = 3,4,5:
144 ** 仮数 b = 8bit 144 ** 篁 b = 8bit
145 ** b の 7bit 目が立っている場合: 145 ** b 7bit 腴c翫鐚
146 ** d = p - (b&0x7f)<<9 146 ** d = p - (b&0x7f)<<9
147 ** 立ってない場合: 147 ** 腴c翫鐚
148 ** d = p + (b&0x1f)<<9 148 ** d = p + (b&0x1f)<<9
149 ** (データは10bitとなる) 149 ** (若帥10bit)
150 ** 150 **
151 ** 圧縮レベルが異なる場合、たとえば圧縮レベル==0で 151 ** х軒違翫医х軒==0
152 ** 指数==1~6でdの最上位bitが立っている場合 152 ** ==1~6d筝篏bit腴c翫
153 ** d = p - (b&0x0f)<<(2+a) 153 ** d = p - (b&0x0f)<<(2+a)
154 ** 指数==7でdの最上位bitが立っている場合 154 ** ==7d筝篏bit腴c翫
155 ** d = p - (b&0x7f)<<(2+7) 155 ** d = p - (b&0x7f)<<(2+7)
156 ** (b : 8bitなのでデータは12bitとなる) 156 ** (b : 8bitс若帥12bit)
157 ** のように、精度だけが変化するようになっている。 157 ** 膕上墾紊c
158 ** 158 **
159 ** ヘッダ読み込みについてはNWAData::ReadHeader()参照 159 ** 茯粋昭帥ゃNWAData::ReadHeader()
160 ** bit stream からのデータ展開については NWADecode()参照 160 ** bit stream 若水ゃ NWADecode()
161 ************************************************************** 161 **************************************************************
162 */ 162 */
163 163
164 // #define NDEBUG /* なぜか assertが入った方が速い、、、 */ 164 // #define NDEBUG /* assertャc鴻 */
165 165
166 #include <stdio.h> 166 #include <stdio.h>
167 #include <stdlib.h> 167 #include <stdlib.h>
168 #include <unistd.h> // for isatty() function 168 #include <unistd.h> // for isatty() function
169 #include <sys/stat.h> 169 #include <sys/stat.h>
170 #include <string.h> 170 #include <string.h>
171 171
172 172
173 #ifdef WORDS_BIGENDIAN 173 #ifdef WORDS_BIGENDIAN
174 #error Sorry, This program does not support BIG-ENDIAN system yet. 174 #error Sorry, This program does not support BIG-ENDIAN system yet.
175 /* もし big endian のシステムに対応させる場合 175 /* big endian 激鴻絲上翫
176 ** 以下の *_little_endian_* 及び 176 ** 篁ヤ *_little_endian_*
177 ** getbits() 関数を変更する必要がある 177 ** getbits() ∽違紊眼綽荀
178 */ 178 */
179 #endif 179 #endif
180 180
181 inline int read_little_endian_int(const char* buf) { 181 inline int read_little_endian_int(const char* buf) {
182 return *(int*)buf; 182 return *(int*)buf;
198 int ret = read_little_endian_short(data)>>shift; 198 int ret = read_little_endian_short(data)>>shift;
199 shift += bits; 199 shift += bits;
200 return ret & ((1<<bits)-1); /* mask */ 200 return ret & ((1<<bits)-1); /* mask */
201 } 201 }
202 202
203 /* 指定された形式のヘッダをつくる */ 203 /* 絎綵√ゃ */
204 const char* make_wavheader(int size, int channels, int bps, int freq) { 204 const char* make_wavheader(int size, int channels, int bps, int freq) {
205 static char wavheader[0x2c] = { 205 static char wavheader[0x2c] = {
206 'R','I','F','F', 206 'R','I','F','F',
207 0,0,0,0, /* +0x04: riff size*/ 207 0,0,0,0, /* +0x04: riff size*/
208 'W','A','V','E', 208 'W','A','V','E',
225 write_little_endian_int(wavheader+0x1c, freq*byps*channels); 225 write_little_endian_int(wavheader+0x1c, freq*byps*channels);
226 write_little_endian_short(wavheader+0x20, byps*channels); 226 write_little_endian_short(wavheader+0x20, byps*channels);
227 return wavheader; 227 return wavheader;
228 } 228 }
229 229
230 /* NWA の bitstream展開に必要となる情報 */ 230 /* NWA bitstream絮綽荀 */
231 class NWAInfo { 231 class NWAInfo {
232 private: 232 private:
233 int channels; 233 int channels;
234 int bps; 234 int bps;
235 int complevel; 235 int complevel;
254 template<class NWAI> void NWADecode(const NWAI& info,const char* data, char* outdata, int datasize, int outdatasize) { 254 template<class NWAI> void NWADecode(const NWAI& info,const char* data, char* outdata, int datasize, int outdatasize) {
255 int d[2]; 255 int d[2];
256 int i; 256 int i;
257 int shift = 0; 257 int shift = 0;
258 const char* dataend = data+datasize; 258 const char* dataend = data+datasize;
259 /* 最初のデータを読み込む */ 259 /* 若帥茯粋昭 */
260 if (info.Bps() == 8) {d[0] = *data++; datasize--;} 260 if (info.Bps() == 8) {d[0] = *data++; datasize--;}
261 else /* info.Bps() == 16 */ {d[0] = read_little_endian_short(data); data+=2; datasize-=2;} 261 else /* info.Bps() == 16 */ {d[0] = read_little_endian_short(data); data+=2; datasize-=2;}
262 if (info.Channels() == 2) { 262 if (info.Channels() == 2) {
263 if (info.Bps() == 8) {d[1] = *data++; datasize--;} 263 if (info.Bps() == 8) {d[1] = *data++; datasize--;}
264 else /* info.Bps() == 16 */ {d[1] = read_little_endian_short(data); data+=2; datasize-=2;} 264 else /* info.Bps() == 16 */ {d[1] = read_little_endian_short(data); data+=2; datasize-=2;}
265 } 265 }
266 int dsize = outdatasize / (info.Bps()/8); 266 int dsize = outdatasize / (info.Bps()/8);
267 int flip_flag = 0; /* stereo 用 */ 267 int flip_flag = 0; /* stereo */
268 int runlength = 0; 268 int runlength = 0;
269 for (i=0; i<dsize; i++) { 269 for (i=0; i<dsize; i++) {
270 if (data >= dataend) break; 270 if (data >= dataend) break;
271 if (runlength == 0) { // コピーループ中でないならデータ読み込み 271 if (runlength == 0) { // 潟若若筝с若粋粋昭
272 int type = getbits(data, shift, 3); 272 int type = getbits(data, shift, 3);
273 /* type により分岐:0, 1-6, 7 */ 273 /* type 絏鐚0, 1-6, 7 */
274 if (type == 7) { 274 if (type == 7) {
275 /* 7 : 大きな差分 */ 275 /* 7 : 紊с綏 */
276 /* RunLength() 有効時(CompLevel==5, 音声ファイル) では無効 */ 276 /* RunLength() 号鐚CompLevel==5, 喝0<ゃ) с≦ */
277 if (getbits(data, shift, 1) == 1) { 277 if (getbits(data, shift, 1) == 1) {
278 d[flip_flag] = 0; /* 未使用 */ 278 d[flip_flag] = 0; /* 篏睡 */
279 } else { 279 } else {
280 int BITS, SHIFT; 280 int BITS, SHIFT;
281 if (info.CompLevel() >= 3) { 281 if (info.CompLevel() >= 3) {
282 BITS = 8; 282 BITS = 8;
283 SHIFT = 9; 283 SHIFT = 9;
292 d[flip_flag] -= (b&MASK2)<<SHIFT; 292 d[flip_flag] -= (b&MASK2)<<SHIFT;
293 else 293 else
294 d[flip_flag] += (b&MASK2)<<SHIFT; 294 d[flip_flag] += (b&MASK2)<<SHIFT;
295 } 295 }
296 } else if (type != 0) { 296 } else if (type != 0) {
297 /* 1-6 : 通常の差分 */ 297 /* 1-6 : 絽吾綏 */
298 int BITS, SHIFT; 298 int BITS, SHIFT;
299 if (info.CompLevel() >= 3) { 299 if (info.CompLevel() >= 3) {
300 BITS = info.CompLevel()+3; 300 BITS = info.CompLevel()+3;
301 SHIFT = 1+type; 301 SHIFT = 1+type;
302 } else { 302 } else {
309 if (b&MASK1) 309 if (b&MASK1)
310 d[flip_flag] -= (b&MASK2)<<SHIFT; 310 d[flip_flag] -= (b&MASK2)<<SHIFT;
311 else 311 else
312 d[flip_flag] += (b&MASK2)<<SHIFT; 312 d[flip_flag] += (b&MASK2)<<SHIFT;
313 } else { /* type == 0 */ 313 } else { /* type == 0 */
314 /* ランレングス圧縮なしの場合はなにもしない */ 314 /* 潟潟違劫х軒翫 */
315 if (info.UseRunLength() == true) { 315 if (info.UseRunLength() == true) {
316 /* ランレングス圧縮ありの場合 */ 316 /* 潟潟違劫х軒翫 */
317 runlength = getbits(data,shift,1); 317 runlength = getbits(data,shift,1);
318 if (runlength==1) { 318 if (runlength==1) {
319 runlength = getbits(data,shift,2); 319 runlength = getbits(data,shift,2);
320 if (runlength == 3) { 320 if (runlength == 3) {
321 runlength = getbits(data, shift, 8); 321 runlength = getbits(data, shift, 8);
330 *outdata++ = d[flip_flag]; 330 *outdata++ = d[flip_flag];
331 } else { 331 } else {
332 write_little_endian_short(outdata, d[flip_flag]); 332 write_little_endian_short(outdata, d[flip_flag]);
333 outdata += 2; 333 outdata += 2;
334 } 334 }
335 if (info.Channels() == 2) flip_flag ^= 1; /* channel 切り替え */ 335 if (info.Channels() == 2) flip_flag ^= 1; /* channel 帥 */
336 } 336 }
337 return; 337 return;
338 } 338 }
339 339
340 class NWAData { 340 class NWAData {
375 if (offsets == NULL) return false; 375 if (offsets == NULL) return false;
376 if (tmpdata == NULL) return false; 376 if (tmpdata == NULL) return false;
377 } 377 }
378 return blocksize * (bps/8); 378 return blocksize * (bps/8);
379 } 379 }
380 /* data は BlockLength 以上の長さを持つこと 380 /* data BlockLength 篁ヤ激ゃ
381 ** 返り値は作成したデータの長さ。終了時は 0。 381 ** 菴ゃ篏若帥激腟篋 0
382 ** エラー時は -1 382 ** 惹 -1
383 */ 383 */
384 int Decode(FILE* in, char* data, int& skip_count); 384 int Decode(FILE* in, char* data, int& skip_count);
385 void Rewind(FILE* in); 385 void Rewind(FILE* in);
386 }; 386 };
387 387
396 filesize = 0; 396 filesize = 0;
397 offset_start = ftell(in); 397 offset_start = ftell(in);
398 if (offset_start == -1) offset_start = 0; 398 if (offset_start == -1) offset_start = 0;
399 if (_file_size != -1) filesize = _file_size; 399 if (_file_size != -1) filesize = _file_size;
400 curblock = -1; 400 curblock = -1;
401 /* header 読み込み */ 401 /* header 茯粋昭 */
402 if (in == NULL || feof(in) || ferror(in)) { 402 if (in == NULL || feof(in) || ferror(in)) {
403 fprintf(stderr,"invalid stream\n"); 403 fprintf(stderr,"invalid stream\n");
404 return; 404 return;
405 } 405 }
406 fread(header, 0x2c, 1, in); 406 fread(header, 0x2c, 1, in);
418 compdatasize = read_little_endian_int(header+0x18); 418 compdatasize = read_little_endian_int(header+0x18);
419 samplecount = read_little_endian_int(header+0x1c); 419 samplecount = read_little_endian_int(header+0x1c);
420 blocksize = read_little_endian_int(header+0x20); 420 blocksize = read_little_endian_int(header+0x20);
421 restsize = read_little_endian_int(header+0x24); 421 restsize = read_little_endian_int(header+0x24);
422 dummy2 = read_little_endian_int(header+0x28); 422 dummy2 = read_little_endian_int(header+0x28);
423 if (complevel == -1) { /* 無圧縮rawデータ */ 423 if (complevel == -1) { /* ≦х軒raw若 */
424 /* 適当に決め打ちする */ 424 /* 綵羆冴< */
425 blocksize = 65536; 425 blocksize = 65536;
426 restsize = (datasize % (blocksize * (bps/8))) / (bps/8); 426 restsize = (datasize % (blocksize * (bps/8))) / (bps/8);
427 blocks = datasize / (blocksize * (bps/8)) + (restsize > 0 ? 1 : 0); 427 blocks = datasize / (blocksize * (bps/8)) + (restsize > 0 ? 1 : 0);
428 } 428 }
429 if (blocks <= 0 || blocks > 1000000) { 429 if (blocks <= 0 || blocks > 1000000) {
430 /* 1時間を超える曲ってのはないでしょ*/ 430 /* 鐚莇蚊cс*/
431 fprintf(stderr,"too large blocks : %d\n",blocks); 431 fprintf(stderr,"too large blocks : %d\n",blocks);
432 return; 432 return;
433 } 433 }
434 /* regular file なら filesize 読み込み */ 434 /* regular file filesize 茯粋昭 */
435 if (filesize == 0 && fstat(fileno(in), &sb)==0 && (sb.st_mode&S_IFMT) == S_IFREG) { 435 if (filesize == 0 && fstat(fileno(in), &sb)==0 && (sb.st_mode&S_IFMT) == S_IFREG) {
436 int pos = ftell(in); 436 int pos = ftell(in);
437 fseek(in, 0, SEEK_END); 437 fseek(in, 0, SEEK_END);
438 filesize = ftell(in); 438 filesize = ftell(in);
439 fseek(in, pos, SEEK_SET); 439 fseek(in, pos, SEEK_SET);
441 fprintf(stderr,"offset block is not exist\n"); 441 fprintf(stderr,"offset block is not exist\n");
442 return; 442 return;
443 } 443 }
444 } 444 }
445 if (complevel == -1) return; 445 if (complevel == -1) return;
446 /* offset index 読み込み */ 446 /* offset index 茯粋昭 */
447 offsets = new int[blocks]; 447 offsets = new int[blocks];
448 fread(offsets, blocks, 4, in); 448 fread(offsets, blocks, 4, in);
449 for (i=0; i<blocks; i++) { 449 for (i=0; i<blocks; i++) {
450 offsets[i] = read_little_endian_int((char*)(offsets+i)); 450 offsets[i] = read_little_endian_int((char*)(offsets+i));
451 } 451 }
463 if (offsets) fseek(in, blocks*4, SEEK_CUR); 463 if (offsets) fseek(in, blocks*4, SEEK_CUR);
464 } 464 }
465 465
466 int NWAData::CheckHeader(void) { 466 int NWAData::CheckHeader(void) {
467 if (complevel != -1 && offsets == NULL) return false; 467 if (complevel != -1 && offsets == NULL) return false;
468 /* データそのもののチェック */ 468 /* 若帥с */
469 if (channels != 1 && channels != 2) { 469 if (channels != 1 && channels != 2) {
470 fprintf(stderr,"This program only supports mono / stereo data : data have %d channels.\n",channels); 470 fprintf(stderr,"This program only supports mono / stereo data : data have %d channels.\n",channels);
471 return false; 471 return false;
472 } 472 }
473 if (bps != 8 && bps != 16) { 473 if (bps != 8 && bps != 16) {
490 //if (complevel < 0 || complevel > 2) { 490 //if (complevel < 0 || complevel > 2) {
491 if (complevel < 0 || complevel > 5) { 491 if (complevel < 0 || complevel > 5) {
492 fprintf(stderr,"This program only supports -1,0,1,2 compression level : the level of data is %d\n",complevel); 492 fprintf(stderr,"This program only supports -1,0,1,2 compression level : the level of data is %d\n",complevel);
493 return false; 493 return false;
494 } 494 }
495 /* 整合性チェック */ 495 /* 翫сс */
496 if (filesize != 0 && filesize != compdatasize) { 496 if (filesize != 0 && filesize != compdatasize) {
497 fprintf(stderr,"file size is invalid : %d != %d\n",filesize,compdatasize); 497 fprintf(stderr,"file size is invalid : %d != %d\n",filesize,compdatasize);
498 return false; 498 return false;
499 } 499 }
500 if (offsets[blocks-1] >= compdatasize) { 500 if (offsets[blocks-1] >= compdatasize) {
508 } 508 }
509 if (samplecount != (blocks-1)*blocksize+restsize ) { 509 if (samplecount != (blocks-1)*blocksize+restsize ) {
510 fprintf(stderr,"total sample count is invalid : samplecount %d != %d*%d+%d(block*blocksize+lastblocksize).\n",samplecount,blocks-1,blocksize,restsize); 510 fprintf(stderr,"total sample count is invalid : samplecount %d != %d*%d+%d(block*blocksize+lastblocksize).\n",samplecount,blocks-1,blocksize,restsize);
511 return false; 511 return false;
512 } 512 }
513 tmpdata = new char[blocksize*byps*2]; /* これ以上の大きさはないだろう、、、 */ 513 tmpdata = new char[blocksize*byps*2]; /* 篁ヤ紊с */
514 return true; 514 return true;
515 } 515 }
516 516
517 class NWAInfo_sw2 { 517 class NWAInfo_sw2 {
518 public: 518 public:
521 int CompLevel(void) const { return 2;} 521 int CompLevel(void) const { return 2;}
522 int UseRunLength(void) const { return false; } 522 int UseRunLength(void) const { return false; }
523 }; 523 };
524 524
525 int NWAData::Decode(FILE* in, char* data, int& skip_count) { 525 int NWAData::Decode(FILE* in, char* data, int& skip_count) {
526 if (complevel == -1) { /* 無圧縮時の処理 */ 526 if (complevel == -1) { /* ≦х軒 */
527 if (feof(in) || ferror(in)) return -1; 527 if (feof(in) || ferror(in)) return -1;
528 if (curblock == -1) { 528 if (curblock == -1) {
529 /* 最初のブロックなら、wave header 出力 */ 529 /* wave header 阪 */
530 memcpy(data, make_wavheader(datasize, channels, bps, freq), 0x2c); 530 memcpy(data, make_wavheader(datasize, channels, bps, freq), 0x2c);
531 curblock++; 531 curblock++;
532 fseek(in, offset_start + 0x2c, SEEK_SET); 532 fseek(in, offset_start + 0x2c, SEEK_SET);
533 return 0x2c; 533 return 0x2c;
534 } 534 }
553 } 553 }
554 if (offsets == NULL || tmpdata == NULL) return -1; 554 if (offsets == NULL || tmpdata == NULL) return -1;
555 if (blocks == curblock) return 0; 555 if (blocks == curblock) return 0;
556 if (feof(in) || ferror(in)) return -1; 556 if (feof(in) || ferror(in)) return -1;
557 if (curblock == -1) { 557 if (curblock == -1) {
558 /* 最初のブロックなら、wave header 出力 */ 558 /* wave header 阪 */
559 memcpy(data, make_wavheader(datasize, channels, bps, freq), 0x2c); 559 memcpy(data, make_wavheader(datasize, channels, bps, freq), 0x2c);
560 curblock++; 560 curblock++;
561 return 0x2c; 561 return 0x2c;
562 } 562 }
563 /* 今回読み込む/デコードするデータの大きさを得る */ 563 /* 篁茯粋昭鐚潟若若帥紊с緇 */
564 int curblocksize, curcompsize; 564 int curblocksize, curcompsize;
565 if (curblock != blocks-1) { 565 if (curblock != blocks-1) {
566 curblocksize = blocksize * (bps/8); 566 curblocksize = blocksize * (bps/8);
567 curcompsize = offsets[curblock+1] - offsets[curblock]; 567 curcompsize = offsets[curblock+1] - offsets[curblock];
568 if (curblocksize >= blocksize*(bps/8)*2) return -1; // Fatal error 568 if (curblocksize >= blocksize*(bps/8)*2) return -1; // Fatal error
574 skip_count -= blocksize/channels; 574 skip_count -= blocksize/channels;
575 fseek(in, curcompsize, SEEK_CUR); 575 fseek(in, curcompsize, SEEK_CUR);
576 curblock++; 576 curblock++;
577 return -2; 577 return -2;
578 } 578 }
579 /* データ読み込み */ 579 /* 若粋粋昭 */
580 fread(tmpdata, 1, curcompsize, in); 580 fread(tmpdata, 1, curcompsize, in);
581 /* 展開 */ 581 /* 絮 */
582 if (channels == 2 && bps == 16 && complevel == 2) { 582 if (channels == 2 && bps == 16 && complevel == 2) {
583 NWAInfo_sw2 info; 583 NWAInfo_sw2 info;
584 NWADecode(info, tmpdata, data, curcompsize, curblocksize); 584 NWADecode(info, tmpdata, data, curcompsize, curblocksize);
585 } else { 585 } else {
586 NWAInfo info(channels, bps, complevel); 586 NWAInfo info(channels, bps, complevel);