Mercurial > otakunoraifu
annotate music2/koedec.cc @ 47:5f548e5957a8
* get rid of the "deprecated conversion from string constant to ‘char*’" warnings
author | thib |
---|---|
date | Wed, 15 Apr 2009 20:26:32 +0000 |
parents | 53a311ea8289 |
children | 35ce1a30f3f9 |
rev | line source |
---|---|
0 | 1 /* |
2 * Copyright (c) 2004-2006 Kazunori "jagarl" Ueno | |
3 * All rights reserved. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions | |
7 * are met: | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * 3. The name of the author may not be used to endorse or promote products | |
14 * derived from this software without specific prior written permission. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 */ | |
27 | |
28 #include<stdio.h> | |
29 #include<stdlib.h> | |
30 #include<string.h> | |
31 #include <vector> | |
32 #include <list> | |
33 #include <algorithm> | |
34 #include"music.h" | |
35 #include"system/file.h" | |
2
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
36 #include"system/file_impl.h" |
0 | 37 |
38 using namespace std; | |
39 | |
40 /********************************************* | |
41 ** | |
42 ** FindKoe -- RealLive¤Î²»À¼¥¢¡¼¥«¥¤¥Ö½èÍý | |
43 ** | |
44 */ | |
45 | |
46 /* À¼¥Õ¥¡¥¤¥ë¤Î¥¢¡¼¥«¥¤¥ÖÍѤΥ¥ã¥Ã¥·¥å */ | |
47 #define koe_cache_size 7 | |
48 struct AvgKoeTable { | |
49 int koe_num; | |
50 int length; | |
51 int offset; | |
52 AvgKoeTable(int _num, int _len, int _off) : | |
53 koe_num(_num), length(_len), offset(_off) {} | |
54 bool operator <(int number) const { | |
55 return koe_num < number; | |
56 } | |
57 bool operator <(const AvgKoeTable& to) const { | |
58 return koe_num < to.koe_num; | |
59 } | |
60 bool operator ==(const AvgKoeTable& to) const { | |
61 return koe_num == to.koe_num; | |
62 } | |
63 bool operator ==(const int to) const { | |
64 return koe_num == to; | |
65 } | |
66 }; | |
67 struct AvgKoeHead { | |
68 FILE* stream; | |
69 int file_number; | |
70 int rate; | |
71 KoeType type; | |
72 vector<AvgKoeTable> table; | |
73 AvgKoeHead(FILE* stream, int file_number, KoeType type); | |
74 AvgKoeHead(const AvgKoeHead& from); | |
75 ~AvgKoeHead(); | |
76 AvgKoeTable* Find(int koe_num); | |
77 bool operator !=(int num) const { return file_number != num; } | |
78 bool operator ==(int num) const { return file_number == num; } | |
79 }; | |
80 struct AvgKoeCache { | |
81 list<AvgKoeHead> cache; | |
82 AvgKoeInfo Find(int file_number, int index); | |
83 }; | |
84 static AvgKoeCache koe_cache; | |
85 | |
86 AvgKoeInfo FindKoe(int file_number, int index) { | |
87 return koe_cache.Find(file_number, index); | |
88 }; | |
45
53a311ea8289
Patched an old patch of mine (OGG koe files handling)... It's a bit less ugly, and it works with tremor!
thib
parents:
43
diff
changeset
|
89 |
0 | 90 AvgKoeInfo AvgKoeCache::Find(int file_number, int index) { |
91 AvgKoeInfo info; | |
92 info.stream = 0; info.length = 0; info.offset = 0; | |
93 | |
94 list<AvgKoeHead>::iterator it; | |
95 it = find(cache.begin(), cache.end(), file_number); | |
96 if (it == cache.end()) { | |
97 /* ¿·¤¿¤Ë head ¤òºî¤ë */ | |
98 char fname[100]; | |
99 KoeType type = koe_unknown; | |
100 sprintf(fname, "z%03d.koe", file_number); | |
101 ARCINFO* arcinfo = file_searcher.Find(FILESEARCH::KOE,fname,".koe"); | |
102 if (arcinfo == 0) { | |
103 type = koe_nwk; | |
104 sprintf(fname, "z%04d.nwk", file_number); | |
105 arcinfo = file_searcher.Find(FILESEARCH::KOE,fname,".nwk"); | |
106 } | |
107 if (arcinfo == 0) { | |
108 type = koe_ovk; | |
109 sprintf(fname, "z%04d.ovk", file_number); | |
110 arcinfo = file_searcher.Find(FILESEARCH::KOE,fname,".ovk"); | |
111 } | |
24 | 112 #if HAVE_LIBVORBISFILE || HAVE_LIBVORBISIDEC |
2
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
113 if (arcinfo == 0) { |
45
53a311ea8289
Patched an old patch of mine (OGG koe files handling)... It's a bit less ugly, and it works with tremor!
thib
parents:
43
diff
changeset
|
114 //FIXME: OMG that's ugly, improve it as soon as you can! |
2
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
115 DIRFILE* koedir = (DIRFILE*) file_searcher.MakeARCFILE((FILESEARCH::ARCTYPE)0, "koe"); |
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
116 sprintf(fname, "%04d", file_number); |
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
117 koedir = new DIRFILE(koedir->SearchFile(fname)); |
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
118 sprintf(fname, "z%04d%05d.ogg", file_number, index); |
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
119 arcinfo = koedir->Find(fname, ".ogg"); |
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
120 delete koedir; |
45
53a311ea8289
Patched an old patch of mine (OGG koe files handling)... It's a bit less ugly, and it works with tremor!
thib
parents:
43
diff
changeset
|
121 |
2
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
122 if (arcinfo == 0) return info; |
45
53a311ea8289
Patched an old patch of mine (OGG koe files handling)... It's a bit less ugly, and it works with tremor!
thib
parents:
43
diff
changeset
|
123 FILE* stream = arcinfo->OpenFile(&info.length); |
2
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
124 info.type = koe_ogg; |
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
125 info.stream = stream; |
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
126 return info; |
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
127 } |
24 | 128 #endif |
0 | 129 if (arcinfo == 0) return info; |
130 FILE* stream = arcinfo->OpenFile(); | |
131 delete arcinfo; | |
132 if (stream == 0) return info; | |
133 cache.push_front(AvgKoeHead(stream, file_number, type)); | |
134 if (cache.size() >= koe_cache_size) cache.pop_back(); | |
135 it = cache.begin(); | |
136 } | |
137 if (it->file_number != file_number) return info; // Èֹ椬¤ª¤«¤·¤¤ | |
138 AvgKoeTable* table = it->Find(index); | |
139 if (table == 0) return info; // index ¤¬¸«ÉÕ¤«¤é¤Ê¤¤ | |
140 // info ¤òºîÀ®¤¹¤ë | |
141 info.length = table->length; | |
142 info.offset = table->offset; | |
143 info.rate = it->rate; | |
144 info.type = it->type; | |
145 int new_fd = dup(fileno(it->stream)); | |
146 if (new_fd == -1) info.stream = 0; | |
147 else info.stream = fdopen(new_fd, "rb"); | |
148 return info; | |
149 } | |
150 | |
151 AvgKoeHead::AvgKoeHead(const AvgKoeHead& from) { | |
152 if (from.stream) { | |
153 int new_fd = dup(fileno(from.stream)); | |
154 if (new_fd == -1) stream = 0; | |
155 else stream = fdopen(new_fd, "rb"); | |
156 } | |
157 file_number = from.file_number; | |
158 rate = from.rate; | |
159 table = from.table; | |
160 type = from.type; | |
161 } | |
2
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
162 |
0 | 163 AvgKoeHead::AvgKoeHead(FILE* _s, int _file_number, KoeType _type) { |
164 char head[0x20]; | |
165 stream = _s; file_number = _file_number; | |
43
01aa5ddf7dc8
A lot of very minor improvements (deleted some unused variables, and other things like that...)
thib
parents:
24
diff
changeset
|
166 //int offset = ftell(stream); |
0 | 167 rate = 22050; |
168 type = _type; | |
169 if (stream == 0) return; | |
170 /* header Æɤ߹þ¤ß */ | |
171 if (type == koe_nwk) { // ¿·¤·¤¤·Á¼° : .nwk file | |
172 rate = 44100; | |
173 fread(head, 4, 1, stream); | |
174 int table_len = read_little_endian_int(head); | |
175 table.reserve(table_len); | |
176 int i; | |
177 for (i=0; i<table_len; i++) { | |
178 fread(head, 12, 1, stream); | |
179 int sz = read_little_endian_int(head); | |
180 int off = read_little_endian_int(head+4); | |
181 int cnt = read_little_endian_int(head+8); | |
182 table.push_back(AvgKoeTable(cnt, sz, off)); | |
183 } | |
184 } else if (type == koe_ovk) { // Little Busters! : .ovk file | |
185 rate = 44100; | |
186 fread(head, 4, 1, stream); | |
187 int table_len = read_little_endian_int(head); | |
188 table.reserve(table_len); | |
189 int i; | |
190 for (i=0; i<table_len; i++) { | |
191 fread(head, 16, 1, stream); | |
192 int sz = read_little_endian_int(head); | |
193 int off = read_little_endian_int(head+4); | |
194 int cnt = read_little_endian_int(head+8); | |
195 table.push_back(AvgKoeTable(cnt, sz, off)); | |
196 } | |
197 } else { // .koe file | |
198 fread(head, 0x20, 1, stream); | |
199 if (strncmp(head, "KOEPAC", 7) != 0) { // invalid header | |
200 stream = 0; | |
201 return; | |
202 } | |
203 int table_len = read_little_endian_int(head+0x10); | |
204 rate = read_little_endian_int(head+0x18); | |
205 if (rate == 0) rate = 22050; | |
206 /* table Æɤ߹þ¤ß */ | |
207 table.reserve(table_len); | |
208 char* buf = new char[table_len*8]; | |
209 fread(buf, table_len, 8, stream); | |
210 int i; for (i=0; i<table_len; i++) { | |
211 int cnt = read_little_endian_short(buf+i*8); | |
212 int sz = read_little_endian_short(buf+i*8+2); | |
213 int off = read_little_endian_int(buf+i*8+4); | |
214 table.push_back(AvgKoeTable(cnt, sz, off)); | |
215 } | |
216 } | |
217 sort(table.begin(), table.end()); | |
218 } | |
219 | |
220 AvgKoeHead::~AvgKoeHead(void) { | |
221 if (stream) fclose(stream); | |
222 stream = 0; | |
223 } | |
224 AvgKoeTable* AvgKoeHead::Find(int koe_num) { | |
225 if (table.empty()) return 0; | |
226 vector<AvgKoeTable>::iterator it; | |
227 it = lower_bound(table.begin(), table.end(), koe_num); | |
228 if (it == table.end() || it->koe_num != koe_num) return 0; | |
229 return &table[it-table.begin()]; | |
230 } | |
231 | |
232 /********************************************* | |
233 ** | |
234 ** MakeWavHeader : koe ¥Õ¥¡¥¤¥ë¤Ë wave header ¤òÉÕ¤±¤ë | |
235 ** | |
236 */ | |
237 | |
238 static unsigned char orig_header[0x2c] = { | |
239 0x52, 0x49, 0x46, 0x46, /* +00 "RIFF" */ | |
240 0x00, 0x00, 0x00, 0x00, /* +04 file size - 8 */ | |
241 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, /* +08 "WAVEfmt " */ | |
242 0x10, 0x00, 0x00, 0x00, /* +10 fmt size */ | |
243 0x01, 0x00, /* +14 wFormatTag */ | |
244 0x02, 0x00, /* +16 Channels */ | |
245 0x44, 0xac, 0x00, 0x00, /* +18 rate */ | |
246 0x10, 0xb1, 0x02, 0x00, /* +1c BytesPerSec = rate * BlockAlign */ | |
247 0x04, 0x00, /* +20 BlockAlign = channels*BytesPerSample */ | |
248 0x10, 0x00, /* +22 BitsPerSample */ | |
249 0x64, 0x61, 0x74, 0x61, /* +24 "data" */ | |
250 0x00, 0x00, 0x00, 0x00 /* +28 filesize - 0x2c */ | |
251 }; | |
252 | |
253 const char* MakeWavHeader(int rate, int ch, int bps, int size) { | |
254 static char header[0x2c]; | |
255 memcpy(header, (const char*)orig_header, 0x2c); | |
256 write_little_endian_int(header+0x04, size-8); | |
257 write_little_endian_int(header+0x28, size-0x2c); | |
258 write_little_endian_int(header+0x18, rate); | |
259 write_little_endian_int(header+0x1c, rate*ch*bps); | |
260 header[0x16] = ch; | |
261 header[0x20] = ch*bps; | |
262 header[0x22] = bps*8; | |
263 return header; | |
264 } | |
265 | |
266 /********************************************* | |
267 ** | |
268 ** decode_koe -- ²»À¼¥Ç¡¼¥¿Å¸³« | |
269 ** | |
270 */ | |
271 | |
272 extern char* decode_koe(AvgKoeInfo info, int* len); | |
273 | |
274 /* 8bit -> 16bit ¤Ø¤ÎÊÑ´¹¥Æ¡¼¥Ö¥ë¡£ËÜÍè¤Ï signed short ¤À¤¬ | |
275 ** ¤È¤ê¤¢¤¨¤º unsigned ¤Ç°·¤Ã¤Æ¤¤¤ë | |
276 */ | |
277 | |
278 unsigned short koe_8bit_trans_tbl[256] = { | |
279 0x8000,0x81ff,0x83f9,0x85ef,0x87e1,0x89cf,0x8bb9,0x8d9f, | |
280 0x8f81,0x915f,0x9339,0x950f,0x96e1,0x98af,0x9a79,0x9c3f, | |
281 0x9e01,0x9fbf,0xa179,0xa32f,0xa4e1,0xa68f,0xa839,0xa9df, | |
282 0xab81,0xad1f,0xaeb9,0xb04f,0xb1e1,0xb36f,0xb4f9,0xb67f, | |
283 0xb801,0xb97f,0xbaf9,0xbc6f,0xbde1,0xbf4f,0xc0b9,0xc21f, | |
284 0xc381,0xc4df,0xc639,0xc78f,0xc8e1,0xca2f,0xcb79,0xccbf, | |
285 0xce01,0xcf3f,0xd079,0xd1af,0xd2e1,0xd40f,0xd539,0xd65f, | |
286 0xd781,0xd89f,0xd9b9,0xdacf,0xdbe1,0xdcef,0xddf9,0xdeff, | |
287 0xe001,0xe0ff,0xe1f9,0xe2ef,0xe3e1,0xe4cf,0xe5b9,0xe69f, | |
288 0xe781,0xe85f,0xe939,0xea0f,0xeae1,0xebaf,0xec79,0xed3f, | |
289 0xee01,0xeebf,0xef79,0xf02f,0xf0e1,0xf18f,0xf239,0xf2df, | |
290 0xf381,0xf41f,0xf4b9,0xf54f,0xf5e1,0xf66f,0xf6f9,0xf77f, | |
291 0xf801,0xf87f,0xf8f9,0xf96f,0xf9e1,0xfa4f,0xfab9,0xfb1f, | |
292 0xfb81,0xfbdf,0xfc39,0xfc8f,0xfce1,0xfd2f,0xfd79,0xfdbf, | |
293 0xfe01,0xfe3f,0xfe79,0xfeaf,0xfee1,0xff0f,0xff39,0xff5f, | |
294 0xff81,0xff9f,0xffb9,0xffcf,0xffe1,0xffef,0xfff9,0xffff, | |
295 0x0000,0x0001,0x0007,0x0011,0x001f,0x0031,0x0047,0x0061, | |
296 0x007f,0x00a1,0x00c7,0x00f1,0x011f,0x0151,0x0187,0x01c1, | |
297 0x01ff,0x0241,0x0287,0x02d1,0x031f,0x0371,0x03c7,0x0421, | |
298 0x047f,0x04e1,0x0547,0x05b1,0x061f,0x0691,0x0707,0x0781, | |
299 0x07ff,0x0881,0x0907,0x0991,0x0a1f,0x0ab1,0x0b47,0x0be1, | |
300 0x0c7f,0x0d21,0x0dc7,0x0e71,0x0f1f,0x0fd1,0x1087,0x1141, | |
301 0x11ff,0x12c1,0x1387,0x1451,0x151f,0x15f1,0x16c7,0x17a1, | |
302 0x187f,0x1961,0x1a47,0x1b31,0x1c1f,0x1d11,0x1e07,0x1f01, | |
303 0x1fff,0x2101,0x2207,0x2311,0x241f,0x2531,0x2647,0x2761, | |
304 0x287f,0x29a1,0x2ac7,0x2bf1,0x2d1f,0x2e51,0x2f87,0x30c1, | |
305 0x31ff,0x3341,0x3487,0x35d1,0x371f,0x3871,0x39c7,0x3b21, | |
306 0x3c7f,0x3de1,0x3f47,0x40b1,0x421f,0x4391,0x4507,0x4681, | |
307 0x47ff,0x4981,0x4b07,0x4c91,0x4e1f,0x4fb1,0x5147,0x52e1, | |
308 0x547f,0x5621,0x57c7,0x5971,0x5b1f,0x5cd1,0x5e87,0x6041, | |
309 0x61ff,0x63c1,0x6587,0x6751,0x691f,0x6af1,0x6cc7,0x6ea1, | |
310 0x707f,0x7261,0x7447,0x7631,0x781f,0x7a11,0x7c07,0x7fff | |
311 }; | |
312 | |
313 /* ADPCM¡¦¡¦¡¦¤¸¤ã¤Ê¤¤¤é¤·¤¤¡£¤¿¤À¤ÎDPCM¤Î¥Ê¤á¤¿¥Æ¡¼¥Ö¥ë¡£ | |
314 ** ¼«Æ°À¸À®¤¹¤ê¤ã¤¤¤¤¤ó¤À¤±¤É256byte¤À¤Ã¤¿¤é | |
315 ** ¥Æ¡¼¥Ö¥ë¤Ç¤âÌäÂê¤Ê¤¤¤Ç¤·¤ç | |
316 */ | |
317 | |
318 char koe_ad_trans_tbl[256] = { | |
319 0x00,0xff,0x01,0xfe,0x02,0xfd,0x03,0xfc,0x04,0xfb,0x05,0xfa,0x06,0xf9,0x07,0xf8, | |
320 0x08,0xf7,0x09,0xf6,0x0a,0xf5,0x0b,0xf4,0x0c,0xf3,0x0d,0xf2,0x0e,0xf1,0x0f,0xf0, | |
321 0x10,0xef,0x11,0xee,0x12,0xed,0x13,0xec,0x14,0xeb,0x15,0xea,0x16,0xe9,0x17,0xe8, | |
322 0x18,0xe7,0x19,0xe6,0x1a,0xe5,0x1b,0xe4,0x1c,0xe3,0x1d,0xe2,0x1e,0xe1,0x1f,0xe0, | |
323 0x20,0xdf,0x21,0xde,0x22,0xdd,0x23,0xdc,0x24,0xdb,0x25,0xda,0x26,0xd9,0x27,0xd8, | |
324 0x28,0xd7,0x29,0xd6,0x2a,0xd5,0x2b,0xd4,0x2c,0xd3,0x2d,0xd2,0x2e,0xd1,0x2f,0xd0, | |
325 0x30,0xcf,0x31,0xce,0x32,0xcd,0x33,0xcc,0x34,0xcb,0x35,0xca,0x36,0xc9,0x37,0xc8, | |
326 0x38,0xc7,0x39,0xc6,0x3a,0xc5,0x3b,0xc4,0x3c,0xc3,0x3d,0xc2,0x3e,0xc1,0x3f,0xc0, | |
327 0x40,0xbf,0x41,0xbe,0x42,0xbd,0x43,0xbc,0x44,0xbb,0x45,0xba,0x46,0xb9,0x47,0xb8, | |
328 0x48,0xb7,0x49,0xb6,0x4a,0xb5,0x4b,0xb4,0x4c,0xb3,0x4d,0xb2,0x4e,0xb1,0x4f,0xb0, | |
329 0x50,0xaf,0x51,0xae,0x52,0xad,0x53,0xac,0x54,0xab,0x55,0xaa,0x56,0xa9,0x57,0xa8, | |
330 0x58,0xa7,0x59,0xa6,0x5a,0xa5,0x5b,0xa4,0x5c,0xa3,0x5d,0xa2,0x5e,0xa1,0x5f,0xa0, | |
331 0x60,0x9f,0x61,0x9e,0x62,0x9d,0x63,0x9c,0x64,0x9b,0x65,0x9a,0x66,0x99,0x67,0x98, | |
332 0x68,0x97,0x69,0x96,0x6a,0x95,0x6b,0x94,0x6c,0x93,0x6d,0x92,0x6e,0x91,0x6f,0x90, | |
333 0x70,0x8f,0x71,0x8e,0x72,0x8d,0x73,0x8c,0x74,0x8b,0x75,0x8a,0x76,0x89,0x77,0x88, | |
334 0x78,0x87,0x79,0x86,0x7a,0x85,0x7b,0x84,0x7c,0x83,0x7d,0x82,0x7e,0x81,0x7f,0x80 | |
335 }; | |
336 | |
337 extern int is_koe_ogg(char* head); | |
338 extern char* decode_koe_ogg(AvgKoeInfo info, int* dest_len); | |
339 | |
340 char* decode_koe(AvgKoeInfo info, int* dest_len) { | |
341 char buf[1024]; char* table; | |
342 unsigned char* src_orig, *src; | |
343 unsigned short* dest_orig, *dest; | |
344 int all_len; int i,j; | |
345 if (info.stream == NULL) { | |
346 return NULL; | |
347 } | |
348 fseek(info.stream, info.offset, 0); | |
349 if (info.type == koe_nwk) { | |
350 return decode_koe_nwa(info, dest_len); | |
351 } | |
352 fread(buf, 1, 0x20, info.stream); | |
353 if (is_koe_ogg(buf)) { | |
354 fseek(info.stream, -20, 1); | |
355 return decode_koe_ogg(info, dest_len); | |
356 } | |
357 /* avg32 ¤ÎÀ¼¥Ç¡¼¥¿Å¸³« */ | |
358 table = (char*)malloc(info.length*2); | |
359 fseek(info.stream, info.offset, 0); | |
360 fread(table, 2, info.length, info.stream); | |
361 | |
362 all_len = 0; | |
363 for (i=0; i<info.length; i++) | |
364 all_len += read_little_endian_short(table + i*2); | |
365 /* ¥Ç¡¼¥¿Æɤ߹þ¤ß */ | |
366 src_orig = (unsigned char*) malloc(all_len); | |
367 dest_orig = (unsigned short*)malloc(info.length * 0x1000 + 0x2c); | |
368 if (src_orig == NULL || dest_orig == NULL) return NULL; | |
369 src = src_orig; | |
370 fread(src, 1, all_len, info.stream); | |
371 *dest_len = info.length * 0x400 * 4; | |
372 const char* header = MakeWavHeader(info.rate, 2, 2, *dest_len); | |
373 memcpy(dest_orig, header, 0x2c); | |
374 dest = dest_orig + 0x2c; | |
375 /* memset(dest_data, 0, table_len * 0x1000); */ | |
376 | |
377 /* Ÿ³« */ | |
378 for (i=0; i<info.length; i++) { | |
379 int slen = read_little_endian_short(table+i*2); | |
380 if (slen == 0) { // do nothing | |
381 memset(dest, 0, 0x1000); | |
382 dest += 0x800; src += 0; | |
383 } else if (slen == 0x400) { // table ÊÑ´¹ | |
384 for (j=0; j<0x400; j++) { | |
385 write_little_endian_short((char*)(dest+0), koe_8bit_trans_tbl[*src]); | |
386 write_little_endian_short((char*)(dest+1), koe_8bit_trans_tbl[*src]); | |
387 dest += 2; src++; | |
388 } | |
389 } else { // DPCM | |
390 char d = 0; short o2; | |
391 int k,j; for (j=0, k=0; j<slen && k < 0x800; j++) { | |
392 unsigned char s = src[j]; | |
393 if ( (s+1) & 0x0f) { | |
394 d -= koe_ad_trans_tbl[s & 0x0f]; | |
395 } else { | |
396 unsigned char s2; | |
397 s >>= 4; s &= 0x0f; s2 = s; | |
398 s = src[++j]; s2 |= (s<<4) & 0xf0; | |
399 d -= koe_ad_trans_tbl[s2]; | |
400 } | |
401 o2 = koe_8bit_trans_tbl[ (unsigned char)d]; | |
402 write_little_endian_short((char*)(dest+k), o2); | |
403 write_little_endian_short((char*)(dest+k+1), o2); | |
404 k+=2; | |
405 s >>= 4; | |
406 if ((s+1) & 0x0f) { | |
407 d -= koe_ad_trans_tbl[s & 0x0f]; | |
408 } else { | |
409 d -= koe_ad_trans_tbl[ src[++j] ]; | |
410 } | |
411 o2 = koe_8bit_trans_tbl[ (unsigned char)d]; | |
412 write_little_endian_short((char*)(dest+k), o2); | |
413 write_little_endian_short((char*)(dest+k+1), o2); | |
414 k+=2; | |
415 } | |
416 dest += 0x800; src += slen; | |
417 } | |
418 } | |
419 free( (void*) table); | |
420 free( (void*) src_orig); | |
421 return (char*)dest_orig; | |
422 } | |
423 | |
424 |