Mercurial > otakunoraifu
annotate music2/koedec_ogg.cc @ 74:f8751d74918b default tip
Remove “duplicate” functions as they can be remplaced by a nearly-identical existing function.
| author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
|---|---|
| date | Sat, 02 Apr 2011 19:13:54 +0200 |
| 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 |
