Mercurial > otakunoraifu
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); |