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;