comparison music2/nwatowav.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 01aa5ddf7dc8
children 4416cfac86ae
comparison
equal deleted inserted replaced
51:cbb301016a4e 52:15a18fbe6f21
161 ************************************************************** 161 **************************************************************
162 */ 162 */
163 163
164 // #define NDEBUG /* なぜか assertが入った方が速い、、、 */ 164 // #define NDEBUG /* なぜか assertが入った方が速い、、、 */
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 のシステムに対応させる場合
227 return wavheader; 227 return wavheader;
228 } 228 }
229 229
230 /* NWA の bitstream展開に必要となる情報 */ 230 /* NWA の bitstream展開に必要となる情報 */
231 class NWAInfo { 231 class NWAInfo {
232 int channels; 232 private:
233 int bps; 233 int channels;
234 int complevel; 234 int bps;
235 bool use_runlength; 235 int complevel;
236 public: 236 bool use_runlength;
237 NWAInfo(int c,int b,int cl) { 237 public:
238 channels=c; 238 NWAInfo(int c,int b,int cl) {
239 bps=b; 239 channels=c;
240 complevel=cl; 240 bps=b;
241 use_runlength = false; 241 complevel=cl;
242 if (cl == 5) { 242 use_runlength = false;
243 use_runlength = true; // Tomoyo After (.nwk koe file) 243 if (cl == 5) {
244 if (channels == 2) use_runlength = false; // BGM*.nwa in Little Busters! 244 use_runlength = true; // Tomoyo After (.nwk koe file)
245 } 245 if (channels == 2) use_runlength = false; // BGM*.nwa in Little Busters!
246 } 246 }
247 int Channels(void) const{return channels;} 247 }
248 int Bps(void) const { return bps;} 248 int Channels(void) const{return channels;}
249 int CompLevel(void) const { return complevel;} 249 int Bps(void) const { return bps;}
250 int UseRunLength(void) const { return use_runlength; } 250 int CompLevel(void) const { return complevel;}
251 int UseRunLength(void) const { return use_runlength; }
251 }; 252 };
252 253
253 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) {
254 int d[2]; 255 int d[2];
255 int i; 256 int i;
332 outdata += 2; 333 outdata += 2;
333 } 334 }
334 if (info.Channels() == 2) flip_flag ^= 1; /* channel 切り替え */ 335 if (info.Channels() == 2) flip_flag ^= 1; /* channel 切り替え */
335 } 336 }
336 return; 337 return;
337 }; 338 }
338 339
339 class NWAData { 340 class NWAData {
340 public: 341 public:
341 int channels; 342 int channels;
342 int bps; /* bits per sample */ 343 int bps; /* bits per sample */
343 int freq; /* samples per second */ 344 int freq; /* samples per second */
344 private: 345 private:
345 int complevel; /* compression level */ 346 int complevel; /* compression level */
346 int dummy; /* ? : 0x00 */ 347 int dummy; /* ? : 0x00 */
347 public: 348 public:
348 int blocks; /* block count */ 349 int blocks; /* block count */
349 int datasize; /* all data size */ 350 int datasize; /* all data size */
350 private: 351 private:
351 int compdatasize; /* compressed data size */ 352 int compdatasize; /* compressed data size */
352 int samplecount; /* all samples */ 353 int samplecount; /* all samples */
353 int blocksize; /* samples per block */ 354 int blocksize; /* samples per block */
354 int restsize; /* samples of the last block */ 355 int restsize; /* samples of the last block */
355 int dummy2; /* ? : 0x89 */ 356 int dummy2; /* ? : 0x89 */
356 int curblock; 357 int curblock;
357 int* offsets; 358 int* offsets;
358 int offset_start; 359 int offset_start;
359 int filesize; 360 int filesize;
360 char* tmpdata; 361 char* tmpdata;
361 public: 362 public:
362 void ReadHeader(FILE* in, int file_size=-1); 363 void ReadHeader(FILE* in, int file_size=-1);
363 int CheckHeader(void); /* false: invalid true: valid */ 364 int CheckHeader(void); /* false: invalid true: valid */
364 NWAData(void) { 365 NWAData(void) {
365 offsets = 0; 366 offsets = NULL;
366 tmpdata = 0; 367 tmpdata = NULL;
367 } 368 }
368 ~NWAData(void) { 369 ~NWAData(void) {
369 if (offsets) delete[] offsets; 370 if (offsets) delete[] offsets;
370 if (tmpdata) delete[] tmpdata; 371 if (tmpdata) delete[] tmpdata;
371 } 372 }
372 int BlockLength(void) { 373 int BlockLength(void) {
373 if (complevel != -1) { 374 if (complevel != -1) {
374 if (offsets == 0) return false; 375 if (offsets == NULL) return false;
375 if (tmpdata == 0) return false; 376 if (tmpdata == NULL) return false;
376 } 377 }
377 return blocksize * (bps/8); 378 return blocksize * (bps/8);
378 } 379 }
379 /* data は BlockLength 以上の長さを持つこと 380 /* data は BlockLength 以上の長さを持つこと
380 ** 返り値は作成したデータの長さ。終了時は 0。 381 ** 返り値は作成したデータの長さ。終了時は 0。
381 ** エラー時は -1 382 ** エラー時は -1
382 */ 383 */
383 int Decode(FILE* in, char* data, int& skip_count); 384 int Decode(FILE* in, char* data, int& skip_count);
384 void Rewind(FILE* in); 385 void Rewind(FILE* in);
385 }; 386 };
386 387
387 void NWAData::ReadHeader(FILE* in, int _file_size) { 388 void NWAData::ReadHeader(FILE* in, int _file_size) {
388 char header[0x2c]; 389 char header[0x2c];
389 struct stat sb; 390 struct stat sb;
390 int i; 391 int i;
391 if (offsets) delete[] offsets; 392 if (offsets) delete[] offsets;
392 if (tmpdata) delete[] tmpdata; 393 if (tmpdata) delete[] tmpdata;
393 offsets = 0; 394 offsets = NULL;
394 tmpdata = 0; 395 tmpdata = NULL;
395 filesize = 0; 396 filesize = 0;
396 offset_start = ftell(in); 397 offset_start = ftell(in);
397 if (offset_start == -1) offset_start = 0; 398 if (offset_start == -1) offset_start = 0;
398 if (_file_size != -1) filesize = _file_size; 399 if (_file_size != -1) filesize = _file_size;
399 curblock = -1; 400 curblock = -1;
400 /* header 読み込み */ 401 /* header 読み込み */
401 if (in == 0 || feof(in) || ferror(in)) { 402 if (in == NULL || feof(in) || ferror(in)) {
402 fprintf(stderr,"invalid stream\n"); 403 fprintf(stderr,"invalid stream\n");
403 return; 404 return;
404 } 405 }
405 fread(header, 0x2c, 1, in); 406 fread(header, 0x2c, 1, in);
406 if (feof(in) || ferror(in)) { 407 if (feof(in) || ferror(in)) {
431 return; 432 return;
432 } 433 }
433 /* regular file なら filesize 読み込み */ 434 /* regular file なら filesize 読み込み */
434 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) {
435 int pos = ftell(in); 436 int pos = ftell(in);
436 fseek(in, 0, 2); 437 fseek(in, 0, SEEK_END);
437 filesize = ftell(in); 438 filesize = ftell(in);
438 fseek(in, pos, 0); 439 fseek(in, pos, SEEK_SET);
439 if (pos+blocks*4 >= filesize) { 440 if (pos+blocks*4 >= filesize) {
440 fprintf(stderr,"offset block is not exist\n"); 441 fprintf(stderr,"offset block is not exist\n");
441 return; 442 return;
442 } 443 }
443 } 444 }
449 offsets[i] = read_little_endian_int((char*)(offsets+i)); 450 offsets[i] = read_little_endian_int((char*)(offsets+i));
450 } 451 }
451 if (feof(in) || ferror(in)) { 452 if (feof(in) || ferror(in)) {
452 fprintf(stderr,"invalid stream\n"); 453 fprintf(stderr,"invalid stream\n");
453 delete[] offsets; 454 delete[] offsets;
454 offsets = 0; 455 offsets = NULL;
455 return; 456 return;
456 } 457 }
457 return; 458 }
458 } 459
459 void NWAData::Rewind(FILE* in) { 460 void NWAData::Rewind(FILE* in) {
460 curblock = -1; 461 curblock = -1;
461 fseek(in, 0x2c, 0); 462 fseek(in, 0x2c, SEEK_SET);
462 if (offsets) fseek(in, blocks*4, 1); 463 if (offsets) fseek(in, blocks*4, SEEK_CUR);
463 } 464 }
465
464 int NWAData::CheckHeader(void) { 466 int NWAData::CheckHeader(void) {
465 if (complevel != -1 && offsets == 0) return false; 467 if (complevel != -1 && offsets == NULL) return false;
466 /* データそのもののチェック */ 468 /* データそのもののチェック */
467 if (channels != 1 && channels != 2) { 469 if (channels != 1 && channels != 2) {
468 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);
469 return false; 471 return false;
470 } 472 }
511 tmpdata = new char[blocksize*byps*2]; /* これ以上の大きさはないだろう、、、 */ 513 tmpdata = new char[blocksize*byps*2]; /* これ以上の大きさはないだろう、、、 */
512 return true; 514 return true;
513 } 515 }
514 516
515 class NWAInfo_sw2 { 517 class NWAInfo_sw2 {
516 public: 518 public:
517 int Channels(void) const{return 2;} 519 int Channels(void) const{return 2;}
518 int Bps(void) const { return 16;} 520 int Bps(void) const { return 16;}
519 int CompLevel(void) const { return 2;} 521 int CompLevel(void) const { return 2;}
520 int UseRunLength(void) const { return false; } 522 int UseRunLength(void) const { return false; }
521 }; 523 };
524
522 int NWAData::Decode(FILE* in, char* data, int& skip_count) { 525 int NWAData::Decode(FILE* in, char* data, int& skip_count) {
523 if (complevel == -1) { /* 無圧縮時の処理 */ 526 if (complevel == -1) { /* 無圧縮時の処理 */
524 if (feof(in) || ferror(in)) return -1; 527 if (feof(in) || ferror(in)) return -1;
525 if (curblock == -1) { 528 if (curblock == -1) {
526 /* 最初のブロックなら、wave header 出力 */ 529 /* 最初のブロックなら、wave header 出力 */
546 curblock++; 549 curblock++;
547 return err; 550 return err;
548 } 551 }
549 return -1; 552 return -1;
550 } 553 }
551 if (offsets == 0 || tmpdata == 0) return -1; 554 if (offsets == NULL || tmpdata == NULL) return -1;
552 if (blocks == curblock) return 0; 555 if (blocks == curblock) return 0;
553 if (feof(in) || ferror(in)) return -1; 556 if (feof(in) || ferror(in)) return -1;
554 if (curblock == -1) { 557 if (curblock == -1) {
555 /* 最初のブロックなら、wave header 出力 */ 558 /* 最初のブロックなら、wave header 出力 */
556 memcpy(data, make_wavheader(datasize, channels, bps, freq), 0x2c); 559 memcpy(data, make_wavheader(datasize, channels, bps, freq), 0x2c);
608 if (err == -2) continue; 611 if (err == -2) continue;
609 fwrite(d, err, 1, out); 612 fwrite(d, err, 1, out);
610 } 613 }
611 return; 614 return;
612 } 615 }
616
613 int main(int argc, char** argv) { 617 int main(int argc, char** argv) {
614 int skip_count = 0; 618 int skip_count = 0;
615 619
616 if (argc > 2 && strcmp(argv[1], "--skip") == 0) { 620 if (argc > 2 && strcmp(argv[1], "--skip") == 0) {
617 skip_count = atoi(argv[2]); 621 skip_count = atoi(argv[2]);
621 } 625 }
622 if (argc != 2 && argc != 3) { 626 if (argc != 2 && argc != 3) {
623 fprintf(stderr,"usage : nwatowav [inputfile [outputfile]]\n"); 627 fprintf(stderr,"usage : nwatowav [inputfile [outputfile]]\n");
624 return -1; 628 return -1;
625 } 629 }
626 if (strstr(argv[1], ".nwk") != 0 || strstr(argv[1], ".ovk") != 0) { 630 if (strstr(argv[1], ".nwk") != NULL || strstr(argv[1], ".ovk") != NULL) {
627 bool is_ovk; 631 bool is_ovk;
628 int headblk_sz; 632 int headblk_sz;
629 char* out_ext; 633 const char* out_ext;
630 634
631 char* outpath = new char[strlen(argv[1])+10]; 635 char* outpath = new char[strlen(argv[1])+10];
632 char buf[1024]; 636 char buf[1024];
633 memset(buf, 0, 1024); 637 memset(buf, 0, 1024);
634 FILE* in = fopen(argv[1], "rb"); 638 FILE* in = fopen(argv[1], "rb");
635 if (in == 0) { 639 if (in == NULL) {
636 fprintf(stderr,"Cannot open file : %s\n",argv[1]); 640 fprintf(stderr,"Cannot open file : %s\n",argv[1]);
637 return -1; 641 return -1;
638 } 642 }
639 if (strstr(argv[1], ".ovk") != 0) { 643 if (strstr(argv[1], ".ovk") != NULL) {
640 is_ovk = true; 644 is_ovk = true;
641 headblk_sz = 16; 645 headblk_sz = 16;
642 out_ext = "ogg"; 646 out_ext = "ogg";
643 } else { 647 } else {
644 is_ovk = false; 648 is_ovk = false;
664 tbl_siz[i] = read_little_endian_int(buf); 668 tbl_siz[i] = read_little_endian_int(buf);
665 tbl_off[i] = read_little_endian_int(buf+4); 669 tbl_off[i] = read_little_endian_int(buf+4);
666 tbl_cnt[i] = read_little_endian_int(buf+8); 670 tbl_cnt[i] = read_little_endian_int(buf+8);
667 tbl_origsiz[i] = read_little_endian_int(buf+12); 671 tbl_origsiz[i] = read_little_endian_int(buf+12);
668 } 672 }
669 fseek(in, 0, 2); 673 fseek(in, 0, SEEK_END);
670 int fsize = ftell(in); 674 int fsize = ftell(in);
671 for (i=0; i<index; i++) { 675 for (i=0; i<index; i++) {
672 if (tbl_off[i] <= 0 || tbl_siz[i] <= 0 || tbl_off[i]+tbl_siz[i] > fsize) { 676 if (tbl_off[i] <= 0 || tbl_siz[i] <= 0 || tbl_off[i]+tbl_siz[i] > fsize) {
673 fprintf(stderr,"Invalid table[%d] : cnt %d off %d size %d / %d\n",i,tbl_cnt[i],tbl_off[i],tbl_siz[i],fsize); 677 fprintf(stderr,"Invalid table[%d] : cnt %d off %d size %d / %d\n",i,tbl_cnt[i],tbl_off[i],tbl_siz[i],fsize);
674 continue; 678 continue;
676 if (argc == 2) 680 if (argc == 2)
677 sprintf(outpath, "%s-%d.%s", argv[1], tbl_cnt[i],out_ext); 681 sprintf(outpath, "%s-%d.%s", argv[1], tbl_cnt[i],out_ext);
678 else 682 else
679 sprintf(outpath, "%s-%d.%s", argv[2], tbl_cnt[i],out_ext); 683 sprintf(outpath, "%s-%d.%s", argv[2], tbl_cnt[i],out_ext);
680 FILE* out = fopen(outpath, "wb"); 684 FILE* out = fopen(outpath, "wb");
681 if (out == 0) { 685 if (out == NULL) {
682 fprintf(stderr,"Cannot open output file %s\n",outpath); 686 fprintf(stderr,"Cannot open output file %s\n",outpath);
683 continue; 687 continue;
684 } 688 }
685 fprintf(stderr,"Writing file %s...\n",outpath); 689 fprintf(stderr,"Writing file %s...\n",outpath);
686 fseek(in, tbl_off[i], 0); 690 fseek(in, tbl_off[i], SEEK_SET);
687 if (is_ovk) { // copy file 691 if (is_ovk) { // copy file
688 int sz = tbl_siz[i]; 692 int sz = tbl_siz[i];
689 char buf[32*1024]; 693 char buf[32*1024];
690 while(sz > 32*1024) { 694 while(sz > 32*1024) {
691 fread(buf, 32*1024, 1, in); 695 fread(buf, 32*1024, 1, in);
703 } 707 }
704 fclose(in); 708 fclose(in);
705 return 0; 709 return 0;
706 } 710 }
707 FILE* in = fopen(argv[1],"rb"); 711 FILE* in = fopen(argv[1],"rb");
708 if (in == 0) { 712 if (in == NULL) {
709 fprintf(stderr,"Cannot open file : %s\n",argv[1]); 713 fprintf(stderr,"Cannot open file : %s\n",argv[1]);
710 return -1; 714 return -1;
711 } 715 }
712 FILE* out; 716 FILE* out;
713 if (argc != 3 && (!isatty(fileno(stdout)))) { // wave file is written to stdout if stdout is redirected to a file 717 if (argc != 3 && (!isatty(fileno(stdout)))) { // wave file is written to stdout if stdout is redirected to a file
715 } else { // make a new file or use argv[2] for output file name 719 } else { // make a new file or use argv[2] for output file name
716 char* outpath = new char[strlen(argv[1])+10]; 720 char* outpath = new char[strlen(argv[1])+10];
717 sprintf(outpath, "%s.wav",argv[1]); 721 sprintf(outpath, "%s.wav",argv[1]);
718 if (argc == 3) outpath = argv[2]; 722 if (argc == 3) outpath = argv[2];
719 out = fopen(outpath, "wb"); 723 out = fopen(outpath, "wb");
720 if (out == 0) { 724 if (out == NULL) {
721 fprintf(stderr,"Cannot open file : %s\n",outpath); 725 fprintf(stderr,"Cannot open file : %s\n",outpath);
722 return -1; 726 return -1;
723 } 727 }
724 } 728 }
725 conv(in, out, skip_count); 729 conv(in, out, skip_count);
730 #else 734 #else
731 735
732 #include"wavfile.h" 736 #include"wavfile.h"
733 737
734 void NWAFILE::Seek(int count) { 738 void NWAFILE::Seek(int count) {
735 if (data == 0) data = new char[block_size]; 739 if (data == NULL) data = new char[block_size];
736 nwa->Rewind(stream); 740 nwa->Rewind(stream);
737 int dmy = 0; 741 int dmy = 0;
738 nwa->Decode(stream, data, dmy); // skip wav header 742 nwa->Decode(stream, data, dmy); // skip wav header
739 data_len = 0; 743 data_len = 0;
740 skip_count = count; 744 skip_count = count;
741 } 745 }
742 NWAFILE::NWAFILE(FILE* _stream) { 746 NWAFILE::NWAFILE(FILE* _stream) {
743 skip_count = 0; 747 skip_count = 0;
744 data = 0; 748 data = NULL;
745 stream = _stream; 749 stream = _stream;
746 nwa = new NWAData; 750 nwa = new NWAData;
747 nwa->ReadHeader(stream); 751 nwa->ReadHeader(stream);
748 if (!nwa->CheckHeader()) { 752 if (!nwa->CheckHeader()) {
749 return; 753 return;
764 NWAFILE::~NWAFILE() { 768 NWAFILE::~NWAFILE() {
765 if (stream) fclose(stream); 769 if (stream) fclose(stream);
766 if (data) delete[] data; 770 if (data) delete[] data;
767 if (nwa) delete nwa; 771 if (nwa) delete nwa;
768 } 772 }
773
769 int NWAFILE::Read(char* buf, int blksize, int blklen) { 774 int NWAFILE::Read(char* buf, int blksize, int blklen) {
770 if (data == 0) return -1; // end of file 775 if (data == NULL) return -1; // end of file
771 776
772 if (data_len > blksize * blklen) { 777 if (data_len > blksize * blklen) {
773 int len = blksize * blklen; 778 int len = blksize * blklen;
774 memcpy(buf, data, len); 779 memcpy(buf, data, len);
775 memmove(data, data+len, data_len-len); 780 memmove(data, data+len, data_len-len);
778 } 783 }
779 memcpy(buf, data, data_len); 784 memcpy(buf, data, data_len);
780 int copied_length = data_len; 785 int copied_length = data_len;
781 data_len = 0; 786 data_len = 0;
782 787
783 if (stream == 0) { 788 if (stream == NULL) {
784 delete[] data; 789 delete[] data;
785 data = 0; 790 data = NULL;
786 return copied_length / blksize; 791 return copied_length / blksize;
787 } 792 }
788 793
794 //TODO: Rewrite this joke
789 // read 795 // read
790 do { 796 do {
791 int err; 797 int err;
792 retry: 798 retry:
793 err = nwa->Decode(stream, data, skip_count); 799 err = nwa->Decode(stream, data, skip_count);
794 if (err == 0 || err == -1) { // eof or error 800 if (err == 0 || err == -1) { // eof or error
795 delete[] data; 801 delete[] data;
796 data = 0; 802 data = NULL;
797 return copied_length / blksize; 803 return copied_length / blksize;
798 } 804 }
799 if (err == -2) goto retry; // EAGAIN 805 if (err == -2) goto retry; // EAGAIN
800 data_len = err; 806 data_len = err;
801 if (copied_length + data_len < blklen*blksize) { 807 if (copied_length + data_len < blklen*blksize) {
818 return datablks; 824 return datablks;
819 } 825 }
820 826
821 char* NWAFILE::ReadAll(FILE* in, int& total_size) { 827 char* NWAFILE::ReadAll(FILE* in, int& total_size) {
822 NWAData h; 828 NWAData h;
823 if (in == 0) return 0; 829 if (in == NULL) return NULL;
824 h.ReadHeader(in); 830 h.ReadHeader(in);
825 h.CheckHeader(); 831 h.CheckHeader();
826 int bs = h.BlockLength(); 832 int bs = h.BlockLength();
827 total_size = h.datasize+0x2c; 833 total_size = h.datasize+0x2c;
828 char* d = new char[total_size + bs*2]; 834 char* d = new char[total_size + bs*2];
835 dcur += err; 841 dcur += err;
836 } 842 }
837 return d; 843 return d;
838 } 844 }
839 845
840 #include"music.h" 846 #include "music.h"
841 847
842 char* decode_koe_nwa(AvgKoeInfo info, int* data_len) { 848 char* decode_koe_nwa(AvgKoeInfo info, int* data_len) {
843 NWAData h; 849 NWAData h;
844 if (info.stream == 0) return 0; 850 if (info.stream == NULL) return NULL;
845 fseek(info.stream, info.offset, 0); 851 fseek(info.stream, info.offset, SEEK_SET);
846 h.ReadHeader(info.stream, info.length); 852 h.ReadHeader(info.stream, info.length);
847 if (h.CheckHeader() == false) return 0; 853 if (h.CheckHeader() == false) return NULL;
848 int bs = h.BlockLength(); 854 int bs = h.BlockLength();
849 int total = h.datasize + 0x2c; 855 int total = h.datasize + 0x2c;
850 char* d = new char[total + bs*2]; 856 char* d = new char[total + bs*2];
851 int dcur = 0; 857 int dcur = 0;
852 int err; 858 int err;