Mercurial > otakunoraifu
annotate music2/koedec_ogg.cc @ 44:a85cdca1980a
* fixed itoa_ws
* now, configure fails if the requested vorbis lib is not found (so it doesn't build with the wrong lib)
* removed unused current_section in koe_ogg.cc
author | thib |
---|---|
date | Wed, 25 Mar 2009 16:00:52 +0000 |
parents | 4d7486cb20a9 |
children | 53a311ea8289 |
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 | |
28 #include<stdio.h> | |
29 #include<string.h> | |
30 #include<stdlib.h> | |
31 #include"music.h" | |
32 #include"wavfile.h" | |
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 | |
48 #include<vorbis/vorbisfile.h> | |
49 #else /* HAVE_LIBVORBISIDEC */ | |
50 #include<tremor/ivorbiscodec.h> | |
51 #include<tremor/ivorbisfile.h> | |
52 #endif | |
53 | |
54 #define INITSIZE 65536 | |
55 | |
56 static int cur_size = 0; | |
57 static char* out = 0; | |
58 static void Resize(void) { | |
59 char* new_out = (char*)realloc(out, cur_size+INITSIZE); | |
60 if (new_out == 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 }; | |
74 /* ogg stream 読み込み用の dummy callback */ | |
75 static size_t ogg_readfunc(void* ptr, size_t size, size_t nmemb, void* datasource) { | |
76 OggInfo* info = (OggInfo*)datasource; | |
77 int pt = ftell(info->stream) - info->offset; | |
78 if (pt+size*nmemb > info->length) { | |
79 nmemb = (info->length-pt) / size; | |
80 } | |
81 return fread(ptr, size, nmemb, info->stream); | |
82 } | |
83 static int ogg_seekfunc(void* datasource, ogg_int64_t new_offset, int whence) { | |
84 int pt; | |
85 OggInfo* info = (OggInfo*)datasource; | |
86 if (whence == SEEK_SET) pt = info->offset + new_offset; | |
87 else if (whence == SEEK_CUR) pt = ftell(info->stream) + new_offset; | |
88 else if (whence == SEEK_END) pt = info->offset + info->length + new_offset; | |
89 int r = fseek(info->stream, pt, 0); | |
90 return r; | |
91 } | |
92 static long ogg_tellfunc(void* datasource) { | |
93 OggInfo* info = (OggInfo*)datasource; | |
94 int pos = ftell(info->stream); | |
95 if (pos == -1) return -1; | |
96 return pos-info->offset; | |
97 } | |
98 static int ogg_closefunc(void* datasource) { | |
99 return 0; | |
100 } | |
18 | 101 |
102 static int fseek_wrap(FILE *f,ogg_int64_t off,int whence){ | |
103 if(f==NULL)return(-1); | |
104 return fseek(f,off,whence); | |
105 } | |
106 | |
107 | |
2
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
108 int ogg_get_rate(FILE *stream) |
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
109 { |
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
110 OggVorbis_File vf; |
18 | 111 ov_callbacks callback; |
112 callback.read_func = (size_t (*)(void*, size_t, size_t, void*))fread; | |
113 callback.seek_func = (int (*)(void*, ogg_int64_t, int))fseek_wrap; | |
114 callback.tell_func = (long int (*)(void*))ftell; | |
7 | 115 callback.close_func = NULL; |
116 ov_test_callbacks(stream, &vf, NULL, 0, callback); | |
117 int rate = vf.vi->rate; | |
118 ov_clear(&vf); | |
119 return rate; | |
2
422f3cb3614b
Enabled voice playing with "%04d/%04d%05d.ogg" format. Don't use a cache for this
thib
parents:
0
diff
changeset
|
120 } |
0 | 121 |
122 extern char* decode_koe_ogg(AvgKoeInfo info, int* dest_len) { | |
123 if (info.stream == 0) return 0; | |
124 // Voice ファイルを直接指定すると全ストリームを再生してしまうので | |
125 // 必要な部分だけ切り出して callback 経由で帰す | |
126 fseek(info.stream, info.offset, 0); | |
127 | |
128 ov_callbacks callback; | |
129 callback.read_func = &ogg_readfunc; | |
130 callback.seek_func = &ogg_seekfunc; | |
131 callback.close_func = &ogg_closefunc; | |
132 callback.tell_func = &ogg_tellfunc; | |
133 | |
134 OggInfo oinfo; | |
135 oinfo.stream = info.stream; | |
136 oinfo.length = info.length; | |
137 oinfo.offset = info.offset; | |
138 | |
139 OggVorbis_File vf; | |
140 int r = ov_open_callbacks((void*)&oinfo, &vf, 0, 0, callback); | |
141 if (r != 0) { | |
142 fprintf(stderr,"ogg stream err: %d\n",r); | |
143 return 0; | |
144 } | |
145 vorbis_info* vinfo = ov_info(&vf, 0); | |
146 info.rate = vinfo->rate; | |
147 int channels = vinfo->channels; | |
148 | |
149 int cur = 0x2c; | |
150 cur_size = INITSIZE; | |
151 out = (char*)malloc(cur_size); | |
152 | |
153 do { | |
154 #if HAVE_LIBVORBISFILE | |
44 | 155 r = ov_read(&vf, out+cur, cur_size-cur, 0, 2, 1, NULL); |
0 | 156 #else /* HAVE_LIBVORBISIDEC */ |
44 | 157 r = ov_read(&vf, out+cur, cur_size-cur, NULL); |
0 | 158 #endif |
159 if (r <= 0) break; | |
160 cur += r; | |
161 if (cur_size-INITSIZE/4 < cur) Resize(); | |
162 } while(1); | |
163 ov_clear(&vf); | |
164 | |
165 *dest_len = cur; // うまくコンバートできてるのかなあ…… | |
166 const char* header = MakeWavHeader(info.rate, channels, 2, cur); | |
167 memcpy(out, header, 0x2c); | |
168 | |
169 char* ret = out; | |
170 out = 0; | |
171 | |
172 return ret; | |
173 } | |
174 struct OggFILE_impl { | |
175 OggVorbis_File vf; | |
176 ov_callbacks callback; | |
177 OggInfo oinfo; | |
178 OggFILE_impl(FILE*, int); | |
179 }; | |
180 | |
181 OggFILE_impl::OggFILE_impl(FILE* stream, int length) { | |
182 callback.read_func = &ogg_readfunc; | |
183 callback.seek_func = &ogg_seekfunc; | |
184 callback.close_func = &ogg_closefunc; | |
185 callback.tell_func = &ogg_tellfunc; | |
186 oinfo.stream = stream; | |
187 oinfo.length = length; | |
188 oinfo.offset = ftell(stream); | |
189 } | |
190 | |
191 OggFILE::OggFILE(FILE* stream, int len) { | |
192 pimpl = new OggFILE_impl(stream, len); | |
193 int r = ov_open_callbacks( (void*)&(pimpl->oinfo), &(pimpl->vf), 0, 0, pimpl->callback); | |
194 if (r != 0) { | |
195 delete pimpl; | |
196 pimpl = 0; | |
197 return; | |
198 } | |
199 vorbis_info* vinfo = ov_info(&(pimpl->vf), 0); | |
200 wavinfo.SamplingRate = vinfo->rate; | |
201 wavinfo.Channels = vinfo->channels; | |
202 wavinfo.DataBits = 16; | |
203 } | |
204 OggFILE::~OggFILE() { | |
205 if (pimpl) { | |
206 ov_clear(&(pimpl->vf)); | |
207 fclose(pimpl->oinfo.stream); | |
208 delete pimpl; | |
209 } | |
210 } | |
211 int OggFILE::Read(char* buf, int blksize, int blklen) { | |
212 if (pimpl == 0) return -1; | |
213 #if HAVE_LIBVORBISFILE | |
44 | 214 int r = ov_read( &(pimpl->vf), buf, blksize*blklen, 0, 2, 1, NULL); |
0 | 215 #else /* HAVE_LIBVORBISIDEC */ |
44 | 216 int r = ov_read( &(pimpl->vf), buf, blksize*blklen, NULL); |
0 | 217 #endif |
218 if (r <= 0) { // end of file | |
219 return -1; | |
220 } | |
221 while(r < blksize*blklen) { | |
222 #if HAVE_LIBVORBISFILE | |
44 | 223 int dr = ov_read(&(pimpl->vf), buf+r, blksize*blklen-r, 0, 2, 1, NULL); |
0 | 224 #else /* HAVE_LIBVORBISIDEC */ |
44 | 225 int dr = ov_read(&(pimpl->vf), buf+r, blksize*blklen-r, NULL); |
0 | 226 #endif |
227 if (dr <= 0) break; | |
228 r += dr; | |
229 } | |
230 return r / blksize; | |
231 } | |
232 void OggFILE::Seek(int count) { | |
233 ov_pcm_seek(&(pimpl->vf), count); | |
234 return; | |
235 } | |
236 #else | |
237 extern char* decode_koe_ogg(AvgKoeInfo info, int* dest_len) { | |
238 return 0; | |
239 } | |
240 OggFILE::OggFILE(FILE* stream, int a) {pimpl = 0;} | |
241 OggFILE::~OggFILE(){} | |
242 void OggFILE::Seek(int count){} | |
243 int OggFILE::Read(char* buf, int blksize, int blklen){return -1;} | |
244 #endif |