Mercurial > otakunoraifu
annotate music2/koedec_ogg.cc @ 66:d112357a0ec1
Fix a bug with savegames introduced with changeset c7bcc0ec2267.
Warning: savegames created since c7bcc0ec2267 are probably corrupted,
you may have to start the game over.
If you chose not to do so, you should replace all occurrences of 'TextWindow' by 'TextImplWindow',
and 'Text Window' by 'TextImpl Window' in your save files.
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Sat, 11 Dec 2010 18:36:20 +0100 |
parents | 4416cfac86ae |
children |
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 | |
52 | 28 #include <stdio.h> |
29 #include <string.h> | |
30 #include <stdlib.h> | |
31 #include "music.h" | |
32 #include "wavfile.h" | |
0 | 33 |
34 extern int is_koe_ogg(char* head); | |
35 extern char* decode_koe_ogg(AvgKoeInfo info, int* dest_len); | |
36 | |
37 extern int is_koe_ogg(char* head) { | |
38 #if HAVE_LIBVORBISFILE || HAVE_LIBVORBISIDEC | |
39 if (strncmp(head, "OggS", 4) == 0) return 1; | |
40 else | |
41 #endif | |
42 return 0; | |
43 } | |
44 | |
45 #if HAVE_LIBVORBISFILE || HAVE_LIBVORBISIDEC | |
46 | |
47 #if HAVE_LIBVORBISFILE | |
52 | 48 #include <vorbis/vorbisfile.h> |
0 | 49 #else /* HAVE_LIBVORBISIDEC */ |
52 | 50 #include <tremor/ivorbiscodec.h> |
51 #include <tremor/ivorbisfile.h> | |
0 | 52 #endif |
53 | |
54 #define INITSIZE 65536 | |
55 | |
56 static int cur_size = 0; | |
52 | 57 static char* out = NULL; |
0 | 58 static void Resize(void) { |
59 char* new_out = (char*)realloc(out, cur_size+INITSIZE); | |
52 | 60 if (new_out == NULL) { |
0 | 61 new_out = (char*)malloc(cur_size+INITSIZE); |
62 memcpy(new_out, out, cur_size); | |
63 free(out); | |
64 } | |
65 out = new_out; | |
66 cur_size += INITSIZE; | |
67 } | |
68 | |
69 struct OggInfo { | |
70 FILE* stream; | |
71 int length; | |
72 int offset; | |
73 }; | |
52 | 74 |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
52
diff
changeset
|
75 /* ogg stream 読み込み用の dummy callback */ |
0 | 76 static size_t ogg_readfunc(void* ptr, size_t size, size_t nmemb, void* datasource) { |
77 OggInfo* info = (OggInfo*)datasource; | |
78 int pt = ftell(info->stream) - info->offset; | |
79 if (pt+size*nmemb > info->length) { | |
80 nmemb = (info->length-pt) / size; | |
81 } | |
82 return fread(ptr, size, nmemb, info->stream); | |
83 } | |
52 | 84 |
0 | 85 static int ogg_seekfunc(void* datasource, ogg_int64_t new_offset, int whence) { |
86 int pt; | |
87 OggInfo* info = (OggInfo*)datasource; | |
88 if (whence == SEEK_SET) pt = info->offset + new_offset; | |
89 else if (whence == SEEK_CUR) pt = ftell(info->stream) + new_offset; | |
90 else if (whence == SEEK_END) pt = info->offset + info->length + new_offset; | |
52 | 91 int r = fseek(info->stream, pt, SEEK_SET); |
0 | 92 return r; |
93 } | |
52 | 94 |
0 | 95 static long ogg_tellfunc(void* datasource) { |
96 OggInfo* info = (OggInfo*)datasource; | |
97 int pos = ftell(info->stream); | |
98 if (pos == -1) return -1; | |
99 return pos-info->offset; | |
100 } | |
52 | 101 |
0 | 102 static int ogg_closefunc(void* datasource) { |
103 return 0; | |
104 } | |
18 | 105 |
106 static int fseek_wrap(FILE *f,ogg_int64_t off,int whence){ | |
52 | 107 if (f == NULL) return(-1); |
108 return fseek(f, off, whence); | |
18 | 109 } |
110 | |
0 | 111 extern char* decode_koe_ogg(AvgKoeInfo info, int* dest_len) { |
52 | 112 if (info.stream == NULL) return NULL; |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
52
diff
changeset
|
113 // Voice ファイルを直接指定すると全ストリームを再生してしまうので |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
52
diff
changeset
|
114 // 必要な部分だけ切り出して callback 経由で帰す |
52 | 115 fseek(info.stream, info.offset, SEEK_SET); |
0 | 116 |
117 ov_callbacks callback; | |
118 callback.read_func = &ogg_readfunc; | |
119 callback.seek_func = &ogg_seekfunc; | |
120 callback.close_func = &ogg_closefunc; | |
121 callback.tell_func = &ogg_tellfunc; | |
122 | |
123 OggInfo oinfo; | |
124 oinfo.stream = info.stream; | |
125 oinfo.length = info.length; | |
126 oinfo.offset = info.offset; | |
127 | |
128 OggVorbis_File vf; | |
129 int r = ov_open_callbacks((void*)&oinfo, &vf, 0, 0, callback); | |
130 if (r != 0) { | |
131 fprintf(stderr,"ogg stream err: %d\n",r); | |
52 | 132 return NULL; |
0 | 133 } |
134 vorbis_info* vinfo = ov_info(&vf, 0); | |
135 info.rate = vinfo->rate; | |
136 int channels = vinfo->channels; | |
137 | |
138 int cur = 0x2c; | |
139 cur_size = INITSIZE; | |
140 out = (char*)malloc(cur_size); | |
141 | |
142 do { | |
143 #if HAVE_LIBVORBISFILE | |
44 | 144 r = ov_read(&vf, out+cur, cur_size-cur, 0, 2, 1, NULL); |
0 | 145 #else /* HAVE_LIBVORBISIDEC */ |
44 | 146 r = ov_read(&vf, out+cur, cur_size-cur, NULL); |
0 | 147 #endif |
148 if (r <= 0) break; | |
149 cur += r; | |
150 if (cur_size-INITSIZE/4 < cur) Resize(); | |
151 } while(1); | |
152 ov_clear(&vf); | |
153 | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
52
diff
changeset
|
154 *dest_len = cur; // うまくコンバートできてるのかなあ…… |
0 | 155 const char* header = MakeWavHeader(info.rate, channels, 2, cur); |
156 memcpy(out, header, 0x2c); | |
157 | |
158 char* ret = out; | |
52 | 159 out = NULL; |
0 | 160 |
161 return ret; | |
162 } | |
52 | 163 |
0 | 164 struct OggFILE_impl { |
165 OggVorbis_File vf; | |
166 ov_callbacks callback; | |
167 OggInfo oinfo; | |
168 OggFILE_impl(FILE*, int); | |
169 }; | |
170 | |
171 OggFILE_impl::OggFILE_impl(FILE* stream, int length) { | |
172 callback.read_func = &ogg_readfunc; | |
173 callback.seek_func = &ogg_seekfunc; | |
174 callback.close_func = &ogg_closefunc; | |
175 callback.tell_func = &ogg_tellfunc; | |
176 oinfo.stream = stream; | |
177 oinfo.length = length; | |
178 oinfo.offset = ftell(stream); | |
179 } | |
180 | |
181 OggFILE::OggFILE(FILE* stream, int len) { | |
182 pimpl = new OggFILE_impl(stream, len); | |
183 int r = ov_open_callbacks( (void*)&(pimpl->oinfo), &(pimpl->vf), 0, 0, pimpl->callback); | |
184 if (r != 0) { | |
185 delete pimpl; | |
52 | 186 pimpl = NULL; |
0 | 187 return; |
188 } | |
189 vorbis_info* vinfo = ov_info(&(pimpl->vf), 0); | |
190 wavinfo.SamplingRate = vinfo->rate; | |
191 wavinfo.Channels = vinfo->channels; | |
192 wavinfo.DataBits = 16; | |
193 } | |
52 | 194 |
0 | 195 OggFILE::~OggFILE() { |
52 | 196 if (pimpl != NULL) { |
0 | 197 ov_clear(&(pimpl->vf)); |
198 fclose(pimpl->oinfo.stream); | |
199 delete pimpl; | |
200 } | |
201 } | |
52 | 202 |
0 | 203 int OggFILE::Read(char* buf, int blksize, int blklen) { |
52 | 204 if (pimpl == NULL) return -1; |
0 | 205 #if HAVE_LIBVORBISFILE |
44 | 206 int r = ov_read( &(pimpl->vf), buf, blksize*blklen, 0, 2, 1, NULL); |
0 | 207 #else /* HAVE_LIBVORBISIDEC */ |
44 | 208 int r = ov_read( &(pimpl->vf), buf, blksize*blklen, NULL); |
0 | 209 #endif |
210 if (r <= 0) { // end of file | |
211 return -1; | |
212 } | |
213 while(r < blksize*blklen) { | |
214 #if HAVE_LIBVORBISFILE | |
44 | 215 int dr = ov_read(&(pimpl->vf), buf+r, blksize*blklen-r, 0, 2, 1, NULL); |
0 | 216 #else /* HAVE_LIBVORBISIDEC */ |
44 | 217 int dr = ov_read(&(pimpl->vf), buf+r, blksize*blklen-r, NULL); |
0 | 218 #endif |
219 if (dr <= 0) break; | |
220 r += dr; | |
221 } | |
222 return r / blksize; | |
223 } | |
52 | 224 |
0 | 225 void OggFILE::Seek(int count) { |
226 ov_pcm_seek(&(pimpl->vf), count); | |
227 return; | |
228 } | |
52 | 229 |
0 | 230 #else |
231 extern char* decode_koe_ogg(AvgKoeInfo info, int* dest_len) { | |
52 | 232 return NULL; |
0 | 233 } |
52 | 234 |
235 OggFILE::OggFILE(FILE* stream, int a) {pimpl = NULL;} | |
0 | 236 OggFILE::~OggFILE(){} |
237 void OggFILE::Seek(int count){} | |
238 int OggFILE::Read(char* buf, int blksize, int blklen){return -1;} | |
239 #endif |