Mercurial > otakunoraifu
comparison music2/koedec.cc @ 52:15a18fbe6f21
* Known bugs added to the README
* Code cleaning (0 -> NULL when needed, indentation, spaces, ...)
author | thib |
---|---|
date | Sat, 18 Apr 2009 18:35:39 +0000 |
parents | 35ce1a30f3f9 |
children | ddbcbd000206 |
comparison
equal
deleted
inserted
replaced
51:cbb301016a4e | 52:15a18fbe6f21 |
---|---|
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 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 | 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. | 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 | 27 |
28 #include<stdio.h> | 28 #include <stdio.h> |
29 #include<stdlib.h> | 29 #include <stdlib.h> |
30 #include<string.h> | 30 #include <string.h> |
31 #include <vector> | 31 #include <vector> |
32 #include <list> | 32 #include <list> |
33 #include <algorithm> | 33 #include <algorithm> |
34 #include"music.h" | 34 #include "music.h" |
35 #include"system/file.h" | 35 #include "system/file.h" |
36 #include"system/file_impl.h" | 36 #include "system/file_impl.h" |
37 | 37 |
38 using namespace std; | 38 using namespace std; |
39 | 39 |
40 /********************************************* | 40 /********************************************* |
41 ** | 41 ** |
62 } | 62 } |
63 bool operator ==(const int to) const { | 63 bool operator ==(const int to) const { |
64 return koe_num == to; | 64 return koe_num == to; |
65 } | 65 } |
66 }; | 66 }; |
67 | |
67 struct AvgKoeHead { | 68 struct AvgKoeHead { |
68 FILE* stream; | 69 FILE* stream; |
69 int file_number; | 70 int file_number; |
70 int rate; | 71 int rate; |
71 KoeType type; | 72 KoeType type; |
75 ~AvgKoeHead(); | 76 ~AvgKoeHead(); |
76 AvgKoeTable* Find(int koe_num); | 77 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; } |
78 bool operator ==(int num) const { return file_number == num; } | 79 bool operator ==(int num) const { return file_number == num; } |
79 }; | 80 }; |
81 | |
80 struct AvgKoeCache { | 82 struct AvgKoeCache { |
81 list<AvgKoeHead> cache; | 83 list<AvgKoeHead> cache; |
82 AvgKoeInfo Find(int file_number, int index); | 84 AvgKoeInfo Find(int file_number, int index); |
83 }; | 85 }; |
86 | |
84 static AvgKoeCache koe_cache; | 87 static AvgKoeCache koe_cache; |
85 | 88 |
86 AvgKoeInfo FindKoe(int file_number, int index) { | 89 AvgKoeInfo FindKoe(int file_number, int index) { |
87 return koe_cache.Find(file_number, index); | 90 return koe_cache.Find(file_number, index); |
88 }; | 91 } |
89 | 92 |
90 AvgKoeInfo AvgKoeCache::Find(int file_number, int index) { | 93 AvgKoeInfo AvgKoeCache::Find(int file_number, int index) { |
91 AvgKoeInfo info; | 94 AvgKoeInfo info; |
92 info.stream = 0; info.length = 0; info.offset = 0; | 95 info.stream = NULL; |
96 info.length = 0; | |
97 info.offset = 0; | |
93 | 98 |
94 list<AvgKoeHead>::iterator it; | 99 list<AvgKoeHead>::iterator it; |
95 it = find(cache.begin(), cache.end(), file_number); | 100 it = find(cache.begin(), cache.end(), file_number); |
96 if (it == cache.end()) { | 101 if (it == cache.end()) { |
97 /* 新たに head を作る */ | 102 /* 新たに head を作る */ |
98 char fname[100]; | 103 char fname[100]; |
99 KoeType type = koe_unknown; | 104 KoeType type = koe_unknown; |
100 sprintf(fname, "z%03d.koe", file_number); | 105 sprintf(fname, "z%03d.koe", file_number); |
101 ARCINFO* arcinfo = file_searcher.Find(FILESEARCH::KOE,fname,".koe"); | 106 ARCINFO* arcinfo = file_searcher.Find(FILESEARCH::KOE,fname,".koe"); |
102 if (arcinfo == 0) { | 107 if (arcinfo == NULL) { |
103 type = koe_nwk; | 108 type = koe_nwk; |
104 sprintf(fname, "z%04d.nwk", file_number); | 109 sprintf(fname, "z%04d.nwk", file_number); |
105 arcinfo = file_searcher.Find(FILESEARCH::KOE,fname,".nwk"); | 110 arcinfo = file_searcher.Find(FILESEARCH::KOE,fname,".nwk"); |
106 } | 111 } |
107 if (arcinfo == 0) { | 112 if (arcinfo == NULL) { |
108 type = koe_ovk; | 113 type = koe_ovk; |
109 sprintf(fname, "z%04d.ovk", file_number); | 114 sprintf(fname, "z%04d.ovk", file_number); |
110 arcinfo = file_searcher.Find(FILESEARCH::KOE,fname,".ovk"); | 115 arcinfo = file_searcher.Find(FILESEARCH::KOE,fname,".ovk"); |
111 } | 116 } |
112 #if HAVE_LIBVORBISFILE || HAVE_LIBVORBISIDEC | 117 #if HAVE_LIBVORBISFILE || HAVE_LIBVORBISIDEC |
113 if (arcinfo == 0) { | 118 if (arcinfo == NULL) { |
114 //FIXME: OMG that's ugly, improve it as soon as you can! | 119 //FIXME: OMG that's ugly, improve it as soon as you can! |
115 DIRFILE* koedir = (DIRFILE*) file_searcher.MakeARCFILE((FILESEARCH::ARCTYPE)0, "koe"); | 120 DIRFILE* koedir = (DIRFILE*) file_searcher.MakeARCFILE((FILESEARCH::ARCTYPE)0, "koe"); |
116 sprintf(fname, "%04d", file_number); | 121 sprintf(fname, "%04d", file_number); |
117 char* dirname = koedir->SearchFile(fname); | 122 char* dirname = koedir->SearchFile(fname); |
118 delete koedir; | 123 delete koedir; |
120 delete[] dirname; | 125 delete[] dirname; |
121 sprintf(fname, "z%04d%05d.ogg", file_number, index); | 126 sprintf(fname, "z%04d%05d.ogg", file_number, index); |
122 arcinfo = koedir->Find(fname, ".ogg"); | 127 arcinfo = koedir->Find(fname, ".ogg"); |
123 delete koedir; | 128 delete koedir; |
124 | 129 |
125 if (arcinfo == 0) return info; | 130 if (arcinfo == NULL) return info; |
126 FILE* stream = arcinfo->OpenFile(&info.length); | 131 FILE* stream = arcinfo->OpenFile(&info.length); |
127 delete arcinfo; | 132 delete arcinfo; |
128 info.type = koe_ogg; | 133 info.type = koe_ogg; |
129 info.stream = stream; | 134 info.stream = stream; |
130 return info; | 135 return info; |
131 } | 136 } |
132 #endif | 137 #endif |
133 if (arcinfo == 0) return info; | 138 if (arcinfo == NULL) return info; |
134 FILE* stream = arcinfo->OpenFile(); | 139 FILE* stream = arcinfo->OpenFile(); |
135 delete arcinfo; | 140 delete arcinfo; |
136 if (stream == 0) return info; | 141 if (stream == NULL) return info; |
137 cache.push_front(AvgKoeHead(stream, file_number, type)); | 142 cache.push_front(AvgKoeHead(stream, file_number, type)); |
138 if (cache.size() >= koe_cache_size) cache.pop_back(); | 143 if (cache.size() >= koe_cache_size) cache.pop_back(); |
139 it = cache.begin(); | 144 it = cache.begin(); |
140 } | 145 } |
141 if (it->file_number != file_number) return info; // 番号がおかしい | 146 if (it->file_number != file_number) return info; // 番号がおかしい |
142 AvgKoeTable* table = it->Find(index); | 147 AvgKoeTable* table = it->Find(index); |
148 //FIXME: table == NULL ? | |
143 if (table == 0) return info; // index が見付からない | 149 if (table == 0) return info; // index が見付からない |
144 // info を作成する | 150 // info を作成する |
145 info.length = table->length; | 151 info.length = table->length; |
146 info.offset = table->offset; | 152 info.offset = table->offset; |
147 info.rate = it->rate; | 153 info.rate = it->rate; |
148 info.type = it->type; | 154 info.type = it->type; |
149 int new_fd = dup(fileno(it->stream)); | 155 int new_fd = dup(fileno(it->stream)); |
150 if (new_fd == -1) info.stream = 0; | 156 if (new_fd == -1) info.stream = NULL; |
151 else info.stream = fdopen(new_fd, "rb"); | 157 else info.stream = fdopen(new_fd, "rb"); |
152 return info; | 158 return info; |
153 } | 159 } |
154 | 160 |
155 AvgKoeHead::AvgKoeHead(const AvgKoeHead& from) { | 161 AvgKoeHead::AvgKoeHead(const AvgKoeHead& from) { |
156 if (from.stream) { | 162 if (from.stream) { |
157 int new_fd = dup(fileno(from.stream)); | 163 int new_fd = dup(fileno(from.stream)); |
158 if (new_fd == -1) stream = 0; | 164 if (new_fd == -1) stream = NULL; |
159 else stream = fdopen(new_fd, "rb"); | 165 else stream = fdopen(new_fd, "rb"); |
160 } | 166 } |
161 file_number = from.file_number; | 167 file_number = from.file_number; |
162 rate = from.rate; | 168 rate = from.rate; |
163 table = from.table; | 169 table = from.table; |
168 char head[0x20]; | 174 char head[0x20]; |
169 stream = _s; file_number = _file_number; | 175 stream = _s; file_number = _file_number; |
170 //int offset = ftell(stream); | 176 //int offset = ftell(stream); |
171 rate = 22050; | 177 rate = 22050; |
172 type = _type; | 178 type = _type; |
173 if (stream == 0) return; | 179 if (stream == NULL) return; |
174 /* header 読み込み */ | 180 /* header 読み込み */ |
175 if (type == koe_nwk) { // 新しい形式 : .nwk file | 181 if (type == koe_nwk) { // 新しい形式 : .nwk file |
176 rate = 44100; | 182 rate = 44100; |
177 fread(head, 4, 1, stream); | 183 fread(head, 4, 1, stream); |
178 int table_len = read_little_endian_int(head); | 184 int table_len = read_little_endian_int(head); |
199 table.push_back(AvgKoeTable(cnt, sz, off)); | 205 table.push_back(AvgKoeTable(cnt, sz, off)); |
200 } | 206 } |
201 } else { // .koe file | 207 } else { // .koe file |
202 fread(head, 0x20, 1, stream); | 208 fread(head, 0x20, 1, stream); |
203 if (strncmp(head, "KOEPAC", 7) != 0) { // invalid header | 209 if (strncmp(head, "KOEPAC", 7) != 0) { // invalid header |
204 stream = 0; | 210 stream = NULL; |
205 return; | 211 return; |
206 } | 212 } |
207 int table_len = read_little_endian_int(head+0x10); | 213 int table_len = read_little_endian_int(head+0x10); |
208 rate = read_little_endian_int(head+0x18); | 214 rate = read_little_endian_int(head+0x18); |
209 if (rate == 0) rate = 22050; | 215 if (rate == 0) rate = 22050; |
221 sort(table.begin(), table.end()); | 227 sort(table.begin(), table.end()); |
222 } | 228 } |
223 | 229 |
224 AvgKoeHead::~AvgKoeHead(void) { | 230 AvgKoeHead::~AvgKoeHead(void) { |
225 if (stream) fclose(stream); | 231 if (stream) fclose(stream); |
226 stream = 0; | 232 stream = NULL; |
227 } | 233 } |
234 | |
228 AvgKoeTable* AvgKoeHead::Find(int koe_num) { | 235 AvgKoeTable* AvgKoeHead::Find(int koe_num) { |
229 if (table.empty()) return 0; | 236 if (table.empty()) return NULL; |
230 vector<AvgKoeTable>::iterator it; | 237 vector<AvgKoeTable>::iterator it; |
231 it = lower_bound(table.begin(), table.end(), koe_num); | 238 it = lower_bound(table.begin(), table.end(), koe_num); |
232 if (it == table.end() || it->koe_num != koe_num) return 0; | 239 if (it == table.end() || it->koe_num != koe_num) return NULL; |
233 return &table[it-table.begin()]; | 240 return &table[it-table.begin()]; |
234 } | 241 } |
235 | 242 |
236 /********************************************* | 243 /********************************************* |
237 ** | 244 ** |
340 | 347 |
341 extern int is_koe_ogg(char* head); | 348 extern int is_koe_ogg(char* head); |
342 extern char* decode_koe_ogg(AvgKoeInfo info, int* dest_len); | 349 extern char* decode_koe_ogg(AvgKoeInfo info, int* dest_len); |
343 | 350 |
344 char* decode_koe(AvgKoeInfo info, int* dest_len) { | 351 char* decode_koe(AvgKoeInfo info, int* dest_len) { |
345 char buf[1024]; char* table; | 352 char buf[1024]; |
353 char* table; | |
346 unsigned char* src_orig, *src; | 354 unsigned char* src_orig, *src; |
347 unsigned short* dest_orig, *dest; | 355 unsigned short* dest_orig, *dest; |
348 int all_len; int i,j; | 356 int all_len, i, j; |
349 if (info.stream == NULL) { | 357 if (info.stream == NULL) { |
350 return NULL; | 358 return NULL; |
351 } | 359 } |
352 fseek(info.stream, info.offset, 0); | 360 fseek(info.stream, info.offset, SEEK_SET); |
353 if (info.type == koe_nwk) { | 361 if (info.type == koe_nwk) { |
354 return decode_koe_nwa(info, dest_len); | 362 return decode_koe_nwa(info, dest_len); |
355 } | 363 } |
356 fread(buf, 1, 0x20, info.stream); | 364 fread(buf, 1, 0x20, info.stream); |
357 if (is_koe_ogg(buf)) { | 365 if (is_koe_ogg(buf)) { |
358 fseek(info.stream, -20, 1); | 366 fseek(info.stream, -20, SEEK_CUR); |
359 return decode_koe_ogg(info, dest_len); | 367 return decode_koe_ogg(info, dest_len); |
360 } | 368 } |
361 /* avg32 の声データ展開 */ | 369 /* avg32 の声データ展開 */ |
362 table = (char*)malloc(info.length*2); | 370 table = (char*)malloc(info.length*2); |
363 fseek(info.stream, info.offset, 0); | 371 fseek(info.stream, info.offset, SEEK_SET); |
364 fread(table, 2, info.length, info.stream); | 372 fread(table, 2, info.length, info.stream); |
365 | 373 |
366 all_len = 0; | 374 all_len = 0; |
367 for (i=0; i<info.length; i++) | 375 for (i=0; i < info.length; i++) |
368 all_len += read_little_endian_short(table + i*2); | 376 all_len += read_little_endian_short(table + i*2); |
369 /* データ読み込み */ | 377 /* データ読み込み */ |
370 src_orig = (unsigned char*) malloc(all_len); | 378 src_orig = (unsigned char*) malloc(all_len); |
371 dest_orig = (unsigned short*)malloc(info.length * 0x1000 + 0x2c); | 379 dest_orig = (unsigned short*)malloc(info.length * 0x1000 + 0x2c); |
372 if (src_orig == NULL || dest_orig == NULL) return NULL; | 380 if (src_orig == NULL || dest_orig == NULL) return NULL; |