Mercurial > otakunoraifu
annotate music2/nwatowav.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 | 01aa5ddf7dc8 |
children | 15a18fbe6f21 |
rev | line source |
---|---|
0 | 1 /* nwatowav : Visual Arts ·Ï¤Î¥²¡¼¥à¤Î¥Ç¥â¤Ç»È¤ï¤ì¤ë nwa ·Á¼°¤Î |
2 ** ¥Õ¥¡¥¤¥ë¤ò wav ·Á¼°¤ËÊÑ´¹¤¹¤ë | |
3 ** | |
4 ** compile : gcc -O2 -o nwatowav nwatowav.cc | |
5 ** usage : nwatowav [nwa-file [outfile]] | |
6 ** nwatowav [nwk-file [outfile]] | |
7 ** example : nwatowav HM06.nwa HM06.wav # BGM¥Õ¥¡¥¤¥ë¡£HM06.wav ¤ËŸ³«¤µ¤ì¤ë | |
8 ** nwatowav z2813.nwk z2813 # ²»À¼¥Õ¥¡¥¤¥ë¡£ z2813-100.wav ¤Ê¤É¤Î¥Õ¥¡¥¤¥ë̾¤ÇŸ³«¤µ¤ì¤ë | |
9 ** nwatowav z0513.ovk z0513 # ²»À¼¥Õ¥¡¥¤¥ë¡£ z0513-100.ogg ¤Ê¤É¤Î¥Õ¥¡¥¤¥ë̾¤ÇŸ³«¤µ¤ì¤ë | |
10 ** | |
11 ** | |
12 ** 2004.5.19 ¾®¾¾¤µ¤ó<s1100089@u-aizu.ac.jp> ¤«¤é CLANNAD ¤Î̵°µ½Ìnwa·Á¼°¤ËÂбþ¤¹¤ë | |
13 ** ¥Ñ¥Ã¥Á¤ò¤¤¤¿¤À¤¤¤¿¤Î¤Ç¡¢Å¬ÍѤ·¤Þ¤·¤¿¡£¤¢¤ê¤¬¤È¤¦¤´¤¶¤¤¤Þ¤¹¡£ | |
14 ** 2006.9.10 ¡ÖÃÒÂ奢¥Õ¥¿¡¼¡×¤Î²»À¼¥Õ¥¡¥¤¥ë·Á¼° (complevel = 5) ¤ò¥µ¥Ý¡¼¥È | |
15 ** .nwk ¤È¤¤¤¦³ÈÄ¥»Ò¤ò»ý¤Ä¥Õ¥¡¥¤¥ë¤ò¼õ¤±¼è¤ë¤È²»À¼¥Õ¥¡¥¤¥ë¤È¤·¤Æ | |
16 ** ²ò¼á¡¢Ê¬³ä¤·¤ÆŸ³«¤¹¤ë¤è¤¦¤Ë¤¹¤ë | |
17 ** 2007.7.28 ¡Ö¥ê¥È¥ë¥Ð¥¹¥¿¡¼¥º¡ª¡×¤Î²»À¼¥Õ¥¡¥¤¥ë·Á¼° (*.ovk; ogg Ï¢·ë·¿) | |
18 ** ¤ò¥µ¥Ý¡¼¥È¡£.ovk ¤È¤¤¤¦³ÈÄ¥»Ò¤ò¤â¤Ä¥Õ¥¡¥¤¥ë¤ò¼õ¤±¼è¤ë¤È | |
19 ** ²»À¼¥Õ¥¡¥¤¥ë¤È¤·¤Æ²ò¼á¡¢Ê¬³ä¤·¤ÆŸ³«¤¹¤ë¤è¤¦¤Ë¤¹¤ë | |
20 ** ¡Ö¥ê¥È¥ë¥Ð¥¹¥¿¡¼¥º¡ª¡×¤ÎBGM¥Õ¥¡¥¤¥ë¤Ë¿Î̤ΥΥ¤¥º¤¬¾è¤ëÌäÂê¤â | |
21 ** ¡¡²ò·è¡Ê¥é¥ó¥ì¥ó¥°¥¹°µ½Ì¤Î½èÍý¤¬ÉÔɬÍפÀ¤Ã¤¿¡Ë | |
22 */ | |
23 | |
24 /* | |
25 * Copyright 2001-2007 jagarl / Kazunori Ueno <jagarl@creator.club.ne.jp> | |
26 * All Rights Reserved. | |
27 * | |
28 * Redistribution and use in source and binary forms, with or without | |
29 * modification, are permitted. | |
30 * | |
31 * ¤³¤Î¥×¥í¥°¥é¥à¤Îºî¼Ô¤Ï jagarl ¤Ç¤¹¡£ | |
32 * | |
33 * ¤³¤Î¥×¥í¥°¥é¥à¡¢µÚ¤Ó¥³¥ó¥Ñ¥¤¥ë¤Ë¤è¤Ã¤ÆÀ¸À®¤·¤¿¥Ð¥¤¥Ê¥ê¤Ï | |
34 * ¥×¥í¥°¥é¥à¤òÊѹ¹¤¹¤ë¡¢¤·¤Ê¤¤¤Ë¤«¤«¤ï¤é¤ººÆÇÛÉÛ²Äǽ¤Ç¤¹¡£ | |
35 * ¤½¤ÎºÝ¡¢¾åµ Copyright ɽ¼¨¤òÊÝ»ý¤¹¤ë¤Ê¤É¤Î¾ò·ï¤Ï²Ý¤·¤Þ | |
36 * ¤»¤ó¡£Âбþ¤¬ÌÌÅݤʤΤǥХ°Êó¹ð¤ò½ü¤¡¢¥á¡¼¥ë¤ÇÏ¢Íí¤ò¤¹¤ë | |
37 * ¤Ê¤É¤ÎɬÍפ⤢¤ê¤Þ¤»¤ó¡£¥½¡¼¥¹¤Î°ìÉô¤òήÍѤ¹¤ë¤³¤È¤ò´Þ¤á¡¢ | |
38 * ¤´¼«Í³¤Ë¤ª»È¤¤¤¯¤À¤µ¤¤¡£ | |
39 * | |
40 * THIS SOFTWARE IS PROVIDED BY KAZUNORI 'jagarl' UENO ``AS IS'' AND ANY | |
41 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KAZUNORI UENO BE LIABLE | |
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
45 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
46 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
47 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
48 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
50 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | |
51 * DAMAGE. | |
52 * | |
53 */ | |
54 | |
55 /******************************************** | |
56 ** | |
57 ** nwa ¥Õ¥©¡¼¥Þ¥Ã¥È¤Ë¤Ä¤¤¤Æ | |
58 ** | |
59 ** Á´ÂΤȤ·¤Æ¤Ï°Ê²¼¤Î¹½Â¤¤ò»ý¤Ä | |
60 ** NWA Header | |
61 ** data offset index | |
62 ** data block<0> | |
63 ** data block<1> | |
64 ** ... | |
65 ** data block<N> | |
66 ** | |
67 ** NWA Header: ¥Õ¥¡¥¤¥ëÀèƬ¤«¤é 44 bytes | |
68 ** magic number ¤Ê¤É¤Ï¤Ê¤¤¤Î¤Çnwa ¥Õ¥¡¥¤¥ë¤«¤Ï | |
69 ** ¥Ç¡¼¥¿¤ÎÀ°¹çÀ¤«¤éȽÃǤ¹¤ëɬÍפ¬¤¢¤ë | |
70 ** ¥Ç¡¼¥¿¤ÏÁ´¤Æ little endian ¤Ç¡¢ | |
71 ** short(signed 2byte)¤Þ¤¿¤Ï int(signed 4byte) ¤Ç¤¢¤ë¡£ | |
72 ** | |
73 ** +00 short channel ¿ô(1/2) | |
74 ** +02 short sample °ì¤Ä¤¢¤¿¤ê¤Î bit ¿ô(16) | |
75 ** +04 int ¼þÇÈ¿ô(°ìÉ䢤¿¤ê¤Î¥Ç¡¼¥¿¿ô) | |
76 ** +08 int °µ½Ì¥ì¥Ù¥ë¡§-1~5.2¤ÇºÇ¾®¤Î¥Ç¡¼¥¿¡¢0¤ÇºÇÂç¤ÎÉü¸µÅÙ(-1¤Ï̵°µ½Ìraw¥Ç¡¼¥¿¤È¤ß¤Ê¤µ¤ì¤ë) | |
77 ** +12 int ? | |
78 ** +16 int ¥Ö¥í¥Ã¥¯¿ô | |
79 ** +20 int Ÿ³«¸å¤Î¥Ç¡¼¥¿¤ÎÂ礤µ(¥Ð¥¤¥Èñ°Ì) | |
80 ** +24 int °µ½Ì»þ¤Î¥Ç¡¼¥¿¤ÎÂ礤µ(nwa ¥Õ¥¡¥¤¥ë¤ÎÂ礤µ¡£¥Ð¥¤¥Èñ°Ì) | |
81 ** +28 int ¥µ¥ó¥×¥ë¿ô¡§Å¸³«¸å¤Î¥Ç¡¼¥¿¿ô(16bit data¤Ê¤é short ñ°Ì==¥µ¥ó¥×¥ëñ°Ì¤Î¥Ç¡¼¥¿¤ÎÂ礤µ) | |
82 ** +32 int ¥Ç¡¼¥¿£±¥Ö¥í¥Ã¥¯¤òŸ³«¤·¤¿»þ¤Î¥µ¥ó¥×¥ëñ°Ì¤Î¥Ç¡¼¥¿¿ô | |
83 ** +36 int ºÇ½ª¥Ö¥í¥Ã¥¯¤òŸ³«¤·¤¿»þ¤Î¥µ¥ó¥×¥ëñ°Ì¤Î¥Ç¡¼¥¿¿ô | |
84 ** +40 int ? | |
85 ** | |
86 ** data offset index | |
87 ** Á´¥Ö¥í¥Ã¥¯¿ô x 4 byte ¤Î¥Ç¡¼¥¿ | |
88 ** ¤½¤ì¤¾¤ì int ¤Î¥Ç¡¼¥¿¤¬Á´¥Ö¥í¥Ã¥¯¿ô³¤¤¤Æ¤¤¤ë | |
89 ** | |
90 ** ¥Ç¡¼¥¿¥Ö¥í¥Ã¥¯¤ÎÀèƬ¤ò»Ø¤¹¥Õ¥¡¥¤¥ëÀèƬ¤«¤é¤Î°ÌÃÖ(¥ª¥Õ¥»¥Ã¥È) | |
91 ** ¤¬³ÊǼ¤µ¤ì¤Æ¤¤¤ë | |
92 ** | |
93 ** data block | |
94 ** Ťµ¤Ï²ÄÊÑ¡£Å¸³«¤¹¤ë¤³¤È¤Ç°ìÄê¤ÎÂ礤µ¤ò¤â¤Ä¥Ç¡¼¥¿¤ËŸ³«¤µ¤ì¤ë¡£ | |
95 ** ¥Ç¡¼¥¿¤ÏDPCM·Á¼°¡£¸µ PCM ¥Ç¡¼¥¿¤¬ a,b,c ¤Ê¤é¤Ð (a),b-a, c-b ¤È | |
96 ** ¤¤¤Ã¤¿º¹Ê¬¥Ç¡¼¥¿¤¬¡¢²¾¿ô3-5bit,»Ø¿ô3bit¤Î·Á¼°¤ÇÊݸ¤µ¤ì¤Æ¤¤¤ë¡£ | |
97 ** ·ë²ÌŪ¤Ë¡¢16bit ¤Î¥Ç¡¼¥¿¤¬Â¿¤¯¤Î¾ì¹ç 6-8bit ¤Ç³ÊǼ¤µ¤ì¤ë¡£ | |
98 ** ²¾¿ô¤Î¥Ó¥Ã¥È¿ô¤Ï°µ½Ì¥ì¥Ù¥ë0¤Ç5bit¡¢°µ½Ì¥ì¥Ù¥ë2¤Ç3bit¤È¤Ê¤ë¡£ | |
99 ** °Ê²¼¡¢°µ½Ì¥ì¥Ù¥ë2¤Î¾ì¹ç¤Ë¤Ä¤¤¤ÆÏäò¿Ê¤á¤ë¡£ | |
100 ** ¥â¥Î¥é¥ë¤Î¾ì¹ç¡§ | |
101 ** +00 short ¥Ö¥í¥Ã¥¯Æâ¤ÎºÇ½é¤Î¥Ç¡¼¥¿ | |
102 ** +02- bit stream | |
103 ** ¥¹¥Æ¥ì¥ª¤Î¾ì¹ç¡§ | |
104 ** +00 short º¸(?)¥Á¥ã¥ó¥Í¥ë¤ÎºÇ½é¤Î¥Ç¡¼¥¿ | |
105 ** +02 short ±¦(?)¥Á¥ã¥ó¥Í¥ë¤ÎºÇ½é¤Î¥Ç¡¼¥¿ | |
106 ** +04- bit stream | |
107 ** | |
108 ** º¹Ê¬¥Ç¡¼¥¿¤ÎÀºÅÙ¤¬¹â¤¯¤Ê¤¤¤Î¤Ç³Æ¥Ö¥í¥Ã¥¯¤ÎÀèƬ¤Ç | |
109 ** Àµ³Î¤Ê¥Ç¡¼¥¿¤Ë¤è¤êÊäÀµ¤µ¤ì¤ë(¡©) | |
110 ** | |
111 ** bit stream | |
112 ** little endian | |
113 ** +0 - +2 : »Ø¿ô | |
114 ** +3 - +5 : ²¾¿ô | |
115 ** ¤Î·Á¼°¡£Î㤨¤Ð a,b,c ¤È¤¤¤¦8bit¥Ç¡¼¥¿¤¬¤¢¤ì¤Ð¡¢ | |
116 ** a&0x07 : ¥Ç¡¼¥¿£±¤Î»Ø¿ô | |
117 ** (a>>3)&0x07 : ¥Ç¡¼¥¿£±¤Î²¾¿ô(signed ; | |
118 ** ((b<<2)|(a>>6))&0x07 : ¥Ç¡¼¥¿£²¤Î»Ø¿ô | |
119 ** (b>>1)&0x07 : ¥Ç¡¼¥¿£²¤Î²¾¿ô | |
120 ** ¤È¤Ê¤ë¡£ | |
121 ** ¤¿¤À¤·¡¢»Ø¿ô¤ÎÃͤˤè¤ê²¾¿ô¤Îbit¿ô¤¬ÊѲ½¤¹¤ë¤³¤È¤¬¤¢¤ë¡£ | |
122 ** »Ø¿ô = 1 - 6 ¤Î¾ì¹ç¡§ | |
123 ** a=»Ø¿ô¡¢b=²¾¿ô¡¢p=Á°¤Î¥Ç¡¼¥¿¤È¤·¤Æ¡¢º£²ó¤Î¥Ç¡¼¥¿d ¤Ï | |
124 ** b¤Î2bitÌܤ¬Î©¤Ã¤Æ¤¤¤ë¾ì¹ç¡§ | |
125 ** d = p - (b&3)<<(4+a) | |
126 ** Ω¤Ã¤Æ¤Ê¤¤¾ì¹ç¡§ | |
127 ** d = p + (b&3)<<(4+a) | |
128 ** »Ø¿ô = 0 ¤Î¾ì¹ç¡§²¾¿ô¤Ï¸ºß¤·¤Ê¤¤(¥Ç¡¼¥¿¤Ï3bit¤È¤Ê¤ë) | |
129 ** d = p | |
130 ** ¡ÖÃÒÂ奢¥Õ¥¿¡¼¡×¤Î²»À¼¥Õ¥¡¥¤¥ë (complevel == 5) ¤Ç¤Ï¥é¥ó¥ì¥ó¥°¥¹°µ½ÌÍѤ˻Ȥï¤ì¤Æ¤¤¤ë¡£ | |
131 ** »Ø¿ô = 7 | |
132 ** ¼¡¤Î bit ¤¬Î©¤Ã¤Æ¤¤¤ë¾ì¹ç¡§ | |
133 ** d = 0 (¸½ºß̤»ÈÍÑ) | |
134 ** (¥Ç¡¼¥¿¤Ï4bit¤È¤Ê¤ë) | |
135 ** ¼¡¤Î bit ¤¬Î©¤Ã¤Æ¤Ê¤¤¾ì¹ç¡§ | |
136 ** complevel = 0,1,2: | |
137 ** ²¾¿ô b = 6bit | |
138 ** b ¤Î 5bit Ìܤ¬Î©¤Ã¤Æ¤¤¤ë¾ì¹ç¡§ | |
139 ** d = p - (b&0x1f)<<(4+7) | |
140 ** Ω¤Ã¤Æ¤Ê¤¤¾ì¹ç¡§ | |
141 ** d = p + (b&0x1f)<<(4+7) | |
142 ** (¥Ç¡¼¥¿¤Ï10bit¤È¤Ê¤ë) | |
143 ** complevel = 3,4,5: | |
144 ** ²¾¿ô b = 8bit | |
145 ** b ¤Î 7bit Ìܤ¬Î©¤Ã¤Æ¤¤¤ë¾ì¹ç¡§ | |
146 ** d = p - (b&0x7f)<<9 | |
147 ** Ω¤Ã¤Æ¤Ê¤¤¾ì¹ç¡§ | |
148 ** d = p + (b&0x1f)<<9 | |
149 ** (¥Ç¡¼¥¿¤Ï10bit¤È¤Ê¤ë) | |
150 ** | |
151 ** °µ½Ì¥ì¥Ù¥ë¤¬°Û¤Ê¤ë¾ì¹ç¡¢¤¿¤È¤¨¤Ð°µ½Ì¥ì¥Ù¥ë==0¤Ç | |
152 ** »Ø¿ô==1~6¤Çd¤ÎºÇ¾å°Ìbit¤¬Î©¤Ã¤Æ¤¤¤ë¾ì¹ç | |
153 ** d = p - (b&0x0f)<<(2+a) | |
154 ** »Ø¿ô==7¤Çd¤ÎºÇ¾å°Ìbit¤¬Î©¤Ã¤Æ¤¤¤ë¾ì¹ç | |
155 ** d = p - (b&0x7f)<<(2+7) | |
156 ** (b : 8bit¤Ê¤Î¤Ç¥Ç¡¼¥¿¤Ï12bit¤È¤Ê¤ë) | |
157 ** ¤Î¤è¤¦¤Ë¡¢ÀºÅÙ¤À¤±¤¬ÊѲ½¤¹¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡£ | |
158 ** | |
159 ** ¥Ø¥Ã¥ÀÆɤ߹þ¤ß¤Ë¤Ä¤¤¤Æ¤ÏNWAData::ReadHeader()»²¾È | |
160 ** bit stream ¤«¤é¤Î¥Ç¡¼¥¿Å¸³«¤Ë¤Ä¤¤¤Æ¤Ï NWADecode()»²¾È | |
161 ************************************************************** | |
162 */ | |
163 | |
164 // #define NDEBUG /* ¤Ê¤¼¤« assert¤¬Æþ¤Ã¤¿Êý¤¬Â®¤¤¡¢¡¢¡¢ */ | |
165 | |
166 #include<stdio.h> | |
167 #include<stdlib.h> | |
168 #include<unistd.h> // for isatty() function | |
169 #include<sys/stat.h> | |
170 #include<string.h> | |
171 | |
172 | |
173 #ifdef WORDS_BIGENDIAN | |
174 #error Sorry, This program does not support BIG-ENDIAN system yet. | |
175 /* ¤â¤· big endian ¤Î¥·¥¹¥Æ¥à¤ËÂбþ¤µ¤»¤ë¾ì¹ç | |
176 ** °Ê²¼¤Î *_little_endian_* µÚ¤Ó | |
177 ** getbits() ´Ø¿ô¤òÊѹ¹¤¹¤ëɬÍפ¬¤¢¤ë | |
178 */ | |
179 #endif | |
180 | |
181 inline int read_little_endian_int(const char* buf) { | |
182 return *(int*)buf; | |
183 } | |
184 | |
185 inline int read_little_endian_short(const char* buf) { | |
186 return *(short*)buf; | |
187 } | |
188 | |
189 inline int write_little_endian_int(char* buf, int number) { | |
190 int c = *(int*)buf; *(int*)buf = number; return c; | |
191 } | |
192 | |
193 inline int write_little_endian_short(char* buf, int number) { | |
194 int c = *(short*)buf; *(short*)buf = number; return c; | |
195 } | |
196 inline int getbits(const char*& data, int& shift, int bits) { | |
197 if (shift > 8) { data++; shift-=8;} | |
198 int ret = read_little_endian_short(data)>>shift; | |
199 shift += bits; | |
200 return ret & ((1<<bits)-1); /* mask */ | |
201 } | |
202 | |
203 /* »ØÄꤵ¤ì¤¿·Á¼°¤Î¥Ø¥Ã¥À¤ò¤Ä¤¯¤ë */ | |
204 const char* make_wavheader(int size, int channels, int bps, int freq) { | |
205 static char wavheader[0x2c] = { | |
206 'R','I','F','F', | |
207 0,0,0,0, /* +0x04: riff size*/ | |
208 'W','A','V','E', | |
209 'f','m','t',' ', | |
210 16,0,0,0, /* +0x10 : fmt size=0x10 */ | |
211 1, 0, /* +0x14 : tag : pcm = 1 */ | |
212 2, 0, /* +0x16 : channels */ | |
213 0,0,0,0, /* +0x18 : samples per second */ | |
214 0,0,0,0, /* +0x1c : average bytes per second */ | |
215 0,0, /* +0x20 : block alignment */ | |
216 0,0, /* +0x22 : bits per sample */ | |
217 'd','a','t','a', | |
218 0,0,0,0};/* +0x28 : data size */ | |
219 write_little_endian_int(wavheader+0x04, size+0x24); | |
220 write_little_endian_int(wavheader+0x28, size); | |
221 write_little_endian_short(wavheader+0x16, channels); | |
222 write_little_endian_short(wavheader+0x22, bps); | |
223 write_little_endian_int(wavheader+0x18, freq); | |
224 int byps = (bps+7)>>3; | |
225 write_little_endian_int(wavheader+0x1c, freq*byps*channels); | |
226 write_little_endian_short(wavheader+0x20, byps*channels); | |
227 return wavheader; | |
228 } | |
229 | |
230 /* NWA ¤Î bitstreamŸ³«¤ËɬÍפȤʤë¾ðÊó */ | |
231 class NWAInfo { | |
232 int channels; | |
233 int bps; | |
234 int complevel; | |
235 bool use_runlength; | |
236 public: | |
237 NWAInfo(int c,int b,int cl) { | |
238 channels=c; | |
239 bps=b; | |
240 complevel=cl; | |
241 use_runlength = false; | |
242 if (cl == 5) { | |
243 use_runlength = true; // Tomoyo After (.nwk koe file) | |
244 if (channels == 2) use_runlength = false; // BGM*.nwa in Little Busters! | |
245 } | |
246 } | |
247 int Channels(void) const{return channels;} | |
248 int Bps(void) const { return bps;} | |
249 int CompLevel(void) const { return complevel;} | |
250 int UseRunLength(void) const { return use_runlength; } | |
251 }; | |
252 | |
253 template<class NWAI> void NWADecode(const NWAI& info,const char* data, char* outdata, int datasize, int outdatasize) { | |
254 int d[2]; | |
43
01aa5ddf7dc8
A lot of very minor improvements (deleted some unused variables, and other things like that...)
thib
parents:
0
diff
changeset
|
255 int i; |
0 | 256 int shift = 0; |
257 const char* dataend = data+datasize; | |
258 /* ºÇ½é¤Î¥Ç¡¼¥¿¤òÆɤ߹þ¤à */ | |
259 if (info.Bps() == 8) {d[0] = *data++; datasize--;} | |
260 else /* info.Bps() == 16 */ {d[0] = read_little_endian_short(data); data+=2; datasize-=2;} | |
261 if (info.Channels() == 2) { | |
262 if (info.Bps() == 8) {d[1] = *data++; datasize--;} | |
263 else /* info.Bps() == 16 */ {d[1] = read_little_endian_short(data); data+=2; datasize-=2;} | |
264 } | |
265 int dsize = outdatasize / (info.Bps()/8); | |
266 int flip_flag = 0; /* stereo ÍÑ */ | |
267 int runlength = 0; | |
268 for (i=0; i<dsize; i++) { | |
269 if (data >= dataend) break; | |
270 if (runlength == 0) { // ¥³¥Ô¡¼¥ë¡¼¥×Ãæ¤Ç¤Ê¤¤¤Ê¤é¥Ç¡¼¥¿Æɤ߹þ¤ß | |
271 int type = getbits(data, shift, 3); | |
272 /* type ¤Ë¤è¤êʬ´ô¡§0, 1-6, 7 */ | |
273 if (type == 7) { | |
274 /* 7 : Â礤ʺ¹Ê¬ */ | |
275 /* RunLength() ͸ú»þ¡ÊCompLevel==5, ²»À¼¥Õ¥¡¥¤¥ë) ¤Ç¤Ï̵¸ú */ | |
276 if (getbits(data, shift, 1) == 1) { | |
277 d[flip_flag] = 0; /* ̤»ÈÍÑ */ | |
278 } else { | |
279 int BITS, SHIFT; | |
280 if (info.CompLevel() >= 3) { | |
281 BITS = 8; | |
282 SHIFT = 9; | |
283 } else { | |
284 BITS = 8-info.CompLevel(); | |
285 SHIFT = 2+7+info.CompLevel(); | |
286 } | |
287 const int MASK1 = (1<<(BITS-1)); | |
288 const int MASK2 = (1<<(BITS-1))-1; | |
289 int b = getbits(data, shift, BITS); | |
290 if (b&MASK1) | |
291 d[flip_flag] -= (b&MASK2)<<SHIFT; | |
292 else | |
293 d[flip_flag] += (b&MASK2)<<SHIFT; | |
294 } | |
295 } else if (type != 0) { | |
296 /* 1-6 : Ä̾ï¤Îº¹Ê¬ */ | |
297 int BITS, SHIFT; | |
298 if (info.CompLevel() >= 3) { | |
299 BITS = info.CompLevel()+3; | |
300 SHIFT = 1+type; | |
301 } else { | |
302 BITS = 5-info.CompLevel(); | |
303 SHIFT = 2+type+info.CompLevel(); | |
304 } | |
305 const int MASK1 = (1<<(BITS-1)); | |
306 const int MASK2 = (1<<(BITS-1))-1; | |
307 int b = getbits(data, shift, BITS); | |
308 if (b&MASK1) | |
309 d[flip_flag] -= (b&MASK2)<<SHIFT; | |
310 else | |
311 d[flip_flag] += (b&MASK2)<<SHIFT; | |
312 } else { /* type == 0 */ | |
313 /* ¥é¥ó¥ì¥ó¥°¥¹°µ½Ì¤Ê¤·¤Î¾ì¹ç¤Ï¤Ê¤Ë¤â¤·¤Ê¤¤ */ | |
314 if (info.UseRunLength() == true) { | |
315 /* ¥é¥ó¥ì¥ó¥°¥¹°µ½Ì¤¢¤ê¤Î¾ì¹ç */ | |
316 runlength = getbits(data,shift,1); | |
317 if (runlength==1) { | |
318 runlength = getbits(data,shift,2); | |
319 if (runlength == 3) { | |
320 runlength = getbits(data, shift, 8); | |
321 } | |
322 } | |
323 } | |
324 } | |
325 } else { | |
326 runlength--; | |
327 } | |
328 if (info.Bps() == 8) { | |
329 *outdata++ = d[flip_flag]; | |
330 } else { | |
331 write_little_endian_short(outdata, d[flip_flag]); | |
332 outdata += 2; | |
333 } | |
334 if (info.Channels() == 2) flip_flag ^= 1; /* channel ÀÚ¤êÂؤ¨ */ | |
335 } | |
336 return; | |
337 }; | |
338 | |
339 class NWAData { | |
340 public: | |
341 int channels; | |
342 int bps; /* bits per sample */ | |
343 int freq; /* samples per second */ | |
344 private: | |
345 int complevel; /* compression level */ | |
346 int dummy; /* ? : 0x00 */ | |
347 public: | |
348 int blocks; /* block count */ | |
349 int datasize; /* all data size */ | |
350 private: | |
351 int compdatasize; /* compressed data size */ | |
352 int samplecount; /* all samples */ | |
353 int blocksize; /* samples per block */ | |
354 int restsize; /* samples of the last block */ | |
355 int dummy2; /* ? : 0x89 */ | |
356 int curblock; | |
357 int* offsets; | |
358 int offset_start; | |
359 int filesize; | |
360 char* tmpdata; | |
361 public: | |
362 void ReadHeader(FILE* in, int file_size=-1); | |
363 int CheckHeader(void); /* false: invalid true: valid */ | |
364 NWAData(void) { | |
365 offsets = 0; | |
366 tmpdata = 0; | |
367 } | |
368 ~NWAData(void) { | |
369 if (offsets) delete[] offsets; | |
370 if (tmpdata) delete[] tmpdata; | |
371 } | |
372 int BlockLength(void) { | |
373 if (complevel != -1) { | |
374 if (offsets == 0) return false; | |
375 if (tmpdata == 0) return false; | |
376 } | |
377 return blocksize * (bps/8); | |
378 } | |
379 /* data ¤Ï BlockLength °Ê¾å¤ÎŤµ¤ò»ý¤Ä¤³¤È | |
380 ** ÊÖ¤êÃͤϺîÀ®¤·¤¿¥Ç¡¼¥¿¤ÎŤµ¡£½ªÎ»»þ¤Ï 0¡£ | |
381 ** ¥¨¥é¡¼»þ¤Ï -1 | |
382 */ | |
383 int Decode(FILE* in, char* data, int& skip_count); | |
384 void Rewind(FILE* in); | |
385 }; | |
386 | |
387 void NWAData::ReadHeader(FILE* in, int _file_size) { | |
388 char header[0x2c]; | |
389 struct stat sb; | |
390 int i; | |
391 if (offsets) delete[] offsets; | |
392 if (tmpdata) delete[] tmpdata; | |
393 offsets = 0; | |
394 tmpdata = 0; | |
395 filesize = 0; | |
396 offset_start = ftell(in); | |
397 if (offset_start == -1) offset_start = 0; | |
398 if (_file_size != -1) filesize = _file_size; | |
399 curblock = -1; | |
400 /* header Æɤ߹þ¤ß */ | |
401 if (in == 0 || feof(in) || ferror(in)) { | |
402 fprintf(stderr,"invalid stream\n"); | |
403 return; | |
404 } | |
405 fread(header, 0x2c, 1, in); | |
406 if (feof(in) || ferror(in)) { | |
407 fprintf(stderr,"invalid stream\n"); | |
408 return; | |
409 } | |
410 channels = read_little_endian_short(header+0x00); | |
411 bps = read_little_endian_short(header+0x02); | |
412 freq = read_little_endian_int(header+0x04); | |
413 complevel = read_little_endian_int(header+0x08); | |
414 dummy = read_little_endian_int(header+0x0c); | |
415 blocks = read_little_endian_int(header+0x10); | |
416 datasize = read_little_endian_int(header+0x14); | |
417 compdatasize = read_little_endian_int(header+0x18); | |
418 samplecount = read_little_endian_int(header+0x1c); | |
419 blocksize = read_little_endian_int(header+0x20); | |
420 restsize = read_little_endian_int(header+0x24); | |
421 dummy2 = read_little_endian_int(header+0x28); | |
422 if (complevel == -1) { /* ̵°µ½Ìraw¥Ç¡¼¥¿ */ | |
423 /* ŬÅö¤Ë·è¤áÂǤÁ¤¹¤ë */ | |
424 blocksize = 65536; | |
425 restsize = (datasize % (blocksize * (bps/8))) / (bps/8); | |
426 blocks = datasize / (blocksize * (bps/8)) + (restsize > 0 ? 1 : 0); | |
427 } | |
428 if (blocks <= 0 || blocks > 1000000) { | |
429 /* £±»þ´Ö¤òĶ¤¨¤ë¶Ê¤Ã¤Æ¤Î¤Ï¤Ê¤¤¤Ç¤·¤ç*/ | |
430 fprintf(stderr,"too large blocks : %d\n",blocks); | |
431 return; | |
432 } | |
433 /* regular file ¤Ê¤é filesize Æɤ߹þ¤ß */ | |
434 if (filesize == 0 && fstat(fileno(in), &sb)==0 && (sb.st_mode&S_IFMT) == S_IFREG) { | |
435 int pos = ftell(in); | |
436 fseek(in, 0, 2); | |
437 filesize = ftell(in); | |
438 fseek(in, pos, 0); | |
439 if (pos+blocks*4 >= filesize) { | |
440 fprintf(stderr,"offset block is not exist\n"); | |
441 return; | |
442 } | |
443 } | |
444 if (complevel == -1) return; | |
445 /* offset index Æɤ߹þ¤ß */ | |
446 offsets = new int[blocks]; | |
447 fread(offsets, blocks, 4, in); | |
448 for (i=0; i<blocks; i++) { | |
449 offsets[i] = read_little_endian_int((char*)(offsets+i)); | |
450 } | |
451 if (feof(in) || ferror(in)) { | |
452 fprintf(stderr,"invalid stream\n"); | |
453 delete[] offsets; | |
454 offsets = 0; | |
455 return; | |
456 } | |
457 return; | |
458 } | |
459 void NWAData::Rewind(FILE* in) { | |
460 curblock = -1; | |
461 fseek(in, 0x2c, 0); | |
462 if (offsets) fseek(in, blocks*4, 1); | |
463 } | |
464 int NWAData::CheckHeader(void) { | |
465 if (complevel != -1 && offsets == 0) return false; | |
466 /* ¥Ç¡¼¥¿¤½¤Î¤â¤Î¤Î¥Á¥§¥Ã¥¯ */ | |
467 if (channels != 1 && channels != 2) { | |
468 fprintf(stderr,"This program only supports mono / stereo data : data have %d channels.\n",channels); | |
469 return false; | |
470 } | |
471 if (bps != 8 && bps != 16) { | |
472 fprintf(stderr,"This program only supports 8 / 16bit data : data is %d bits\n",bps); | |
473 return false; | |
474 } | |
475 if (complevel == -1) { | |
476 int byps = bps/8; /* bytes per sample */ | |
477 if (datasize != samplecount*byps) { | |
478 fprintf(stderr,"invalid datasize : datasize %d != samplecount %d * samplesize %d\n",datasize,samplecount,byps); | |
479 return false; | |
480 } | |
481 if (samplecount != (blocks-1)*blocksize+restsize ) { | |
482 fprintf(stderr,"total sample count is invalid : samplecount %d != %d*%d+%d(block*blocksize+lastblocksize).\n",samplecount,blocks-1,blocksize,restsize); | |
483 return false; | |
484 } | |
485 else | |
486 return true; | |
487 } | |
488 //if (complevel < 0 || complevel > 2) { | |
489 if (complevel < 0 || complevel > 5) { | |
490 fprintf(stderr,"This program only supports -1,0,1,2 compression level : the level of data is %d\n",complevel); | |
491 return false; | |
492 } | |
493 /* À°¹çÀ¥Á¥§¥Ã¥¯ */ | |
494 if (filesize != 0 && filesize != compdatasize) { | |
495 fprintf(stderr,"file size is invalid : %d != %d\n",filesize,compdatasize); | |
496 return false; | |
497 } | |
498 if (offsets[blocks-1] >= compdatasize) { | |
499 fprintf(stderr,"the last offset overruns the file.\n"); | |
500 return false; | |
501 } | |
502 int byps = bps/8; /* bytes per sample */ | |
503 if (datasize != samplecount*byps) { | |
504 fprintf(stderr,"invalid datasize : datasize %d != samplecount %d * samplesize %d\n",datasize,samplecount,byps); | |
505 return false; | |
506 } | |
507 if (samplecount != (blocks-1)*blocksize+restsize ) { | |
508 fprintf(stderr,"total sample count is invalid : samplecount %d != %d*%d+%d(block*blocksize+lastblocksize).\n",samplecount,blocks-1,blocksize,restsize); | |
509 return false; | |
510 } | |
511 tmpdata = new char[blocksize*byps*2]; /* ¤³¤ì°Ê¾å¤ÎÂ礤µ¤Ï¤Ê¤¤¤À¤í¤¦¡¢¡¢¡¢ */ | |
512 return true; | |
513 } | |
514 | |
515 class NWAInfo_sw2 { | |
516 public: | |
517 int Channels(void) const{return 2;} | |
518 int Bps(void) const { return 16;} | |
519 int CompLevel(void) const { return 2;} | |
520 int UseRunLength(void) const { return false; } | |
521 }; | |
522 int NWAData::Decode(FILE* in, char* data, int& skip_count) { | |
523 if (complevel == -1) { /* ̵°µ½Ì»þ¤Î½èÍý */ | |
524 if (feof(in) || ferror(in)) return -1; | |
525 if (curblock == -1) { | |
526 /* ºÇ½é¤Î¥Ö¥í¥Ã¥¯¤Ê¤é¡¢wave header ½ÐÎÏ */ | |
527 memcpy(data, make_wavheader(datasize, channels, bps, freq), 0x2c); | |
528 curblock++; | |
529 fseek(in, offset_start + 0x2c, SEEK_SET); | |
530 return 0x2c; | |
531 } | |
532 if (skip_count > blocksize/channels) { | |
533 skip_count -= blocksize/channels; | |
534 fseek(in, blocksize*(bps/8), SEEK_CUR); | |
535 curblock++; | |
536 return -2; | |
537 } | |
538 if (curblock < blocks) { | |
539 int readsize = blocksize; | |
540 if (skip_count) { | |
541 fseek(in, skip_count*channels*(bps/8), SEEK_CUR); | |
542 readsize -= skip_count * channels; | |
543 skip_count = 0; | |
544 } | |
545 int err = fread(data, 1, readsize * (bps/8), in); | |
546 curblock++; | |
547 return err; | |
548 } | |
549 return -1; | |
550 } | |
551 if (offsets == 0 || tmpdata == 0) return -1; | |
552 if (blocks == curblock) return 0; | |
553 if (feof(in) || ferror(in)) return -1; | |
554 if (curblock == -1) { | |
555 /* ºÇ½é¤Î¥Ö¥í¥Ã¥¯¤Ê¤é¡¢wave header ½ÐÎÏ */ | |
556 memcpy(data, make_wavheader(datasize, channels, bps, freq), 0x2c); | |
557 curblock++; | |
558 return 0x2c; | |
559 } | |
560 /* º£²óÆɤ߹þ¤à¡¿¥Ç¥³¡¼¥É¤¹¤ë¥Ç¡¼¥¿¤ÎÂ礤µ¤òÆÀ¤ë */ | |
561 int curblocksize, curcompsize; | |
562 if (curblock != blocks-1) { | |
563 curblocksize = blocksize * (bps/8); | |
564 curcompsize = offsets[curblock+1] - offsets[curblock]; | |
565 if (curblocksize >= blocksize*(bps/8)*2) return -1; // Fatal error | |
566 } else { | |
567 curblocksize = restsize * (bps/8); | |
568 curcompsize = blocksize*(bps/8)*2; | |
569 } | |
570 if (skip_count > blocksize/channels) { | |
571 skip_count -= blocksize/channels; | |
572 fseek(in, curcompsize, SEEK_CUR); | |
573 curblock++; | |
574 return -2; | |
575 } | |
576 /* ¥Ç¡¼¥¿Æɤ߹þ¤ß */ | |
577 fread(tmpdata, 1, curcompsize, in); | |
578 /* Ÿ³« */ | |
579 if (channels == 2 && bps == 16 && complevel == 2) { | |
580 NWAInfo_sw2 info; | |
581 NWADecode(info, tmpdata, data, curcompsize, curblocksize); | |
582 } else { | |
583 NWAInfo info(channels, bps, complevel); | |
584 NWADecode(info, tmpdata, data, curcompsize, curblocksize); | |
585 } | |
586 int retsize = curblocksize; | |
587 if (skip_count) { | |
588 int skip_c = skip_count * channels * (bps/8); | |
589 retsize -= skip_c; | |
590 memmove(data, data+skip_c, skip_c); | |
591 skip_count = 0; | |
592 } | |
593 curblock++; | |
594 return retsize; | |
595 } | |
596 | |
597 #ifdef USE_MAIN | |
598 | |
599 void conv(FILE* in, FILE* out, int skip_count, int in_size = -1) { | |
600 NWAData h; | |
601 h.ReadHeader(in, in_size); | |
602 h.CheckHeader(); | |
603 int bs = h.BlockLength(); | |
604 char* d = new char[bs]; | |
605 int err; | |
606 while( (err=h.Decode(in, d, skip_count)) != 0) { | |
607 if (err == -1) break; | |
608 if (err == -2) continue; | |
609 fwrite(d, err, 1, out); | |
610 } | |
611 return; | |
612 } | |
613 int main(int argc, char** argv) { | |
614 int skip_count = 0; | |
615 | |
616 if (argc > 2 && strcmp(argv[1], "--skip") == 0) { | |
617 skip_count = atoi(argv[2]); | |
618 argc -= 2; | |
619 argv[1] = argv[3]; | |
620 argv[2] = argv[4]; | |
621 } | |
622 if (argc != 2 && argc != 3) { | |
623 fprintf(stderr,"usage : nwatowav [inputfile [outputfile]]\n"); | |
624 return -1; | |
625 } | |
626 if (strstr(argv[1], ".nwk") != 0 || strstr(argv[1], ".ovk") != 0) { | |
627 bool is_ovk; | |
628 int headblk_sz; | |
629 char* out_ext; | |
630 | |
631 char* outpath = new char[strlen(argv[1])+10]; | |
632 char buf[1024]; | |
633 memset(buf, 0, 1024); | |
634 FILE* in = fopen(argv[1], "rb"); | |
635 if (in == 0) { | |
636 fprintf(stderr,"Cannot open file : %s\n",argv[1]); | |
637 return -1; | |
638 } | |
639 if (strstr(argv[1], ".ovk") != 0) { | |
640 is_ovk = true; | |
641 headblk_sz = 16; | |
642 out_ext = "ogg"; | |
643 } else { | |
644 is_ovk = false; | |
645 headblk_sz = 12; | |
646 out_ext = "wav"; | |
647 } | |
648 fread(buf, 1, 4, in); | |
649 int index = read_little_endian_int(buf); | |
650 if (index <= 0) { | |
651 if (is_ovk) | |
652 fprintf(stderr,"Invalid Ogg-ovk file : %s : index = %d\n",argv[1],index); | |
653 else | |
654 fprintf(stderr,"Invalid Koe-nwk file : %s : index = %d\n",argv[1],index); | |
655 return -1; | |
656 } | |
657 int* tbl_off = new int[index]; | |
658 int* tbl_siz = new int[index]; | |
659 int* tbl_cnt = new int[index]; | |
660 int* tbl_origsiz = new int[index]; | |
661 int i; | |
662 for (i=0; i<index; i++) { | |
663 fread(buf, 1, headblk_sz, in); | |
664 tbl_siz[i] = read_little_endian_int(buf); | |
665 tbl_off[i] = read_little_endian_int(buf+4); | |
666 tbl_cnt[i] = read_little_endian_int(buf+8); | |
667 tbl_origsiz[i] = read_little_endian_int(buf+12); | |
668 } | |
669 fseek(in, 0, 2); | |
670 int fsize = ftell(in); | |
671 for (i=0; i<index; i++) { | |
672 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); | |
674 continue; | |
675 } | |
676 if (argc == 2) | |
677 sprintf(outpath, "%s-%d.%s", argv[1], tbl_cnt[i],out_ext); | |
678 else | |
679 sprintf(outpath, "%s-%d.%s", argv[2], tbl_cnt[i],out_ext); | |
680 FILE* out = fopen(outpath, "wb"); | |
681 if (out == 0) { | |
682 fprintf(stderr,"Cannot open output file %s\n",outpath); | |
683 continue; | |
684 } | |
685 fprintf(stderr,"Writing file %s...\n",outpath); | |
686 fseek(in, tbl_off[i], 0); | |
687 if (is_ovk) { // copy file | |
688 int sz = tbl_siz[i]; | |
689 char buf[32*1024]; | |
690 while(sz > 32*1024) { | |
691 fread(buf, 32*1024, 1, in); | |
692 fwrite(buf, 32*1024, 1, out); | |
693 sz -= 1024*32; | |
694 } | |
695 if (sz > 0) { | |
696 fread(buf, sz, 1, in); | |
697 fwrite(buf, sz, 1, out); | |
698 } | |
699 } else { // .nwk | |
700 conv(in, out, 0, tbl_siz[i]); | |
701 } | |
702 fclose(out); | |
703 } | |
704 fclose(in); | |
705 return 0; | |
706 } | |
707 FILE* in = fopen(argv[1],"rb"); | |
708 if (in == 0) { | |
709 fprintf(stderr,"Cannot open file : %s\n",argv[1]); | |
710 return -1; | |
711 } | |
712 FILE* out; | |
713 if (argc != 3 && (!isatty(fileno(stdout)))) { // wave file is written to stdout if stdout is redirected to a file | |
714 out = stdout; | |
715 } else { // make a new file or use argv[2] for output file name | |
716 char* outpath = new char[strlen(argv[1])+10]; | |
717 sprintf(outpath, "%s.wav",argv[1]); | |
718 if (argc == 3) outpath = argv[2]; | |
719 out = fopen(outpath, "wb"); | |
720 if (out == 0) { | |
721 fprintf(stderr,"Cannot open file : %s\n",outpath); | |
722 return -1; | |
723 } | |
724 } | |
725 conv(in, out, skip_count); | |
726 fclose(in); | |
727 if (out != stdout) fclose(out); | |
728 return 0; | |
729 } | |
730 #else | |
731 | |
732 #include"wavfile.h" | |
733 | |
734 void NWAFILE::Seek(int count) { | |
735 if (data == 0) data = new char[block_size]; | |
736 nwa->Rewind(stream); | |
737 int dmy = 0; | |
738 nwa->Decode(stream, data, dmy); // skip wav header | |
739 data_len = 0; | |
740 skip_count = count; | |
741 } | |
742 NWAFILE::NWAFILE(FILE* _stream) { | |
743 skip_count = 0; | |
744 data = 0; | |
745 stream = _stream; | |
746 nwa = new NWAData; | |
747 nwa->ReadHeader(stream); | |
748 if (!nwa->CheckHeader()) { | |
749 return; | |
750 } | |
751 block_size = nwa->BlockLength(); | |
752 data = new char[block_size]; | |
753 data_len = 0; | |
754 | |
755 wavinfo.SamplingRate = nwa->freq; | |
756 wavinfo.Channels = nwa->channels; | |
757 wavinfo.DataBits = nwa->bps; | |
758 | |
759 int dmy = 0; | |
760 data_len = nwa->Decode(stream, data, dmy); // skip wav header | |
761 | |
762 return; | |
763 } | |
764 NWAFILE::~NWAFILE() { | |
765 if (stream) fclose(stream); | |
766 if (data) delete[] data; | |
767 if (nwa) delete nwa; | |
768 } | |
769 int NWAFILE::Read(char* buf, int blksize, int blklen) { | |
770 if (data == 0) return -1; // end of file | |
771 | |
772 if (data_len > blksize * blklen) { | |
773 int len = blksize * blklen; | |
774 memcpy(buf, data, len); | |
775 memmove(data, data+len, data_len-len); | |
776 data_len -= len; | |
777 return blklen; | |
778 } | |
779 memcpy(buf, data, data_len); | |
780 int copied_length = data_len; | |
781 data_len = 0; | |
782 | |
783 if (stream == 0) { | |
784 delete[] data; | |
785 data = 0; | |
786 return copied_length / blksize; | |
787 } | |
788 | |
789 // read | |
790 do { | |
791 int err; | |
792 retry: | |
793 err = nwa->Decode(stream, data, skip_count); | |
794 if (err == 0 || err == -1) { // eof or error | |
795 delete[] data; | |
796 data = 0; | |
797 return copied_length / blksize; | |
798 } | |
799 if (err == -2) goto retry; // EAGAIN | |
800 data_len = err; | |
801 if (copied_length + data_len < blklen*blksize) { | |
802 memcpy(buf+copied_length, data, data_len); | |
803 copied_length += data_len; | |
804 goto retry; | |
805 } | |
806 } while(0); | |
807 | |
808 // determine return length | |
809 int datablks = (data_len+copied_length)/blksize; | |
810 if (datablks <= 0) return 0; | |
811 if (datablks > blklen) datablks = blklen; | |
812 int rest_len = datablks * blksize - copied_length; | |
813 if (rest_len) { | |
814 memcpy(buf+copied_length, data, rest_len); | |
815 memmove(data, data+rest_len, data_len-rest_len); | |
816 data_len -= rest_len; | |
817 } | |
818 return datablks; | |
819 } | |
820 | |
821 char* NWAFILE::ReadAll(FILE* in, int& total_size) { | |
822 NWAData h; | |
823 if (in == 0) return 0; | |
824 h.ReadHeader(in); | |
825 h.CheckHeader(); | |
826 int bs = h.BlockLength(); | |
827 total_size = h.datasize+0x2c; | |
828 char* d = new char[total_size + bs*2]; | |
829 int dcur = 0; | |
830 int err; | |
831 int skip = 0; | |
832 while(dcur < total_size+bs && (err=h.Decode(in, d+dcur, skip)) != 0) { | |
833 if (err == -1) break; | |
834 if (err == -2) continue; | |
835 dcur += err; | |
836 } | |
837 return d; | |
838 } | |
839 | |
840 #include"music.h" | |
841 | |
842 char* decode_koe_nwa(AvgKoeInfo info, int* data_len) { | |
843 NWAData h; | |
844 if (info.stream == 0) return 0; | |
845 fseek(info.stream, info.offset, 0); | |
846 h.ReadHeader(info.stream, info.length); | |
847 if (h.CheckHeader() == false) return 0; | |
848 int bs = h.BlockLength(); | |
849 int total = h.datasize + 0x2c; | |
850 char* d = new char[total + bs*2]; | |
851 int dcur = 0; | |
852 int err; | |
853 int skip = 0; | |
854 while(dcur < total+bs && (err=h.Decode(info.stream, d+dcur, skip)) != 0) { | |
855 if (err == -1) break; | |
856 if (err == -2) continue; | |
857 dcur += err; | |
858 } | |
859 if (data_len) { | |
860 *data_len = dcur; | |
861 if (*data_len > total) *data_len = total; | |
862 } | |
863 return d; | |
864 } | |
865 | |
866 #endif |