root/music2/koedec_ogg.cc

Revision 65:4416cfac86ae, 6.6 KB (checked in by Thibaut Girka <thib@…>, 18 months ago)
Convert EUC-JP files to UTF8
Line 
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
34extern int is_koe_ogg(char* head);
35extern char* decode_koe_ogg(AvgKoeInfo info, int* dest_len);
36
37extern 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
56static int cur_size = 0;
57static char* out = NULL;
58static void Resize(void) {
59        char* new_out = (char*)realloc(out, cur_size+INITSIZE);
60        if (new_out == NULL) {
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
69struct OggInfo {
70        FILE* stream;
71        int length;
72        int offset;
73};
74
75/* ogg stream 読み蟌み甚の dummy callback */
76static 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}
84
85static 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;
91        int r = fseek(info->stream, pt, SEEK_SET);
92        return r;
93}
94
95static 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}
101
102static int ogg_closefunc(void* datasource) {
103        return 0;
104}
105
106static int fseek_wrap(FILE *f,ogg_int64_t off,int whence){
107        if (f == NULL) return(-1);
108        return fseek(f, off, whence);
109}
110
111extern char* decode_koe_ogg(AvgKoeInfo info, int* dest_len) {
112        if (info.stream == NULL) return NULL;
113        // Voice ファむルを盎接指定するず党ストリヌムを再生しおしたうので
114        // 必芁な郚分だけ切り出しお callback 経由で垰す
115        fseek(info.stream, info.offset, SEEK_SET);
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);
132                return NULL;
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
144                r = ov_read(&vf, out+cur, cur_size-cur, 0, 2, 1, NULL); 
145#else /* HAVE_LIBVORBISIDEC */
146                r = ov_read(&vf, out+cur, cur_size-cur, NULL); 
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
154        *dest_len = cur; // うたくコンバヌトできおるのかなあ  
155        const char* header = MakeWavHeader(info.rate, channels, 2, cur);
156        memcpy(out, header, 0x2c);
157       
158        char* ret = out;
159        out = NULL;
160
161        return ret;
162}
163
164struct OggFILE_impl {
165        OggVorbis_File vf;
166        ov_callbacks callback;
167        OggInfo oinfo;
168        OggFILE_impl(FILE*, int);
169};
170
171OggFILE_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
181OggFILE::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;
186                pimpl = NULL;
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}
194
195OggFILE::~OggFILE() {
196        if (pimpl != NULL) {
197                ov_clear(&(pimpl->vf));
198                fclose(pimpl->oinfo.stream);
199                delete pimpl;
200        }
201}
202
203int OggFILE::Read(char* buf, int blksize, int blklen) {
204        if (pimpl == NULL) return -1;
205#if HAVE_LIBVORBISFILE
206        int r = ov_read( &(pimpl->vf), buf, blksize*blklen, 0, 2, 1, NULL);
207#else /* HAVE_LIBVORBISIDEC */
208        int r = ov_read( &(pimpl->vf), buf, blksize*blklen, NULL);
209#endif
210        if (r <= 0) { // end of file
211                return -1;
212        }
213        while(r < blksize*blklen) {
214#if HAVE_LIBVORBISFILE
215                int dr = ov_read(&(pimpl->vf), buf+r, blksize*blklen-r, 0, 2, 1, NULL);
216#else /* HAVE_LIBVORBISIDEC */
217                int dr = ov_read(&(pimpl->vf), buf+r, blksize*blklen-r, NULL);
218#endif
219                if (dr <= 0) break;
220                r += dr;
221        }
222        return r / blksize;
223}
224
225void OggFILE::Seek(int count) {
226        ov_pcm_seek(&(pimpl->vf), count);
227        return;
228}
229
230#else
231extern char* decode_koe_ogg(AvgKoeInfo info, int* dest_len) {
232        return NULL;
233}
234
235OggFILE::OggFILE(FILE* stream, int a) {pimpl = NULL;}
236OggFILE::~OggFILE(){}
237void OggFILE::Seek(int count){}
238int OggFILE::Read(char* buf, int blksize, int blklen){return -1;}
239#endif
Note: See TracBrowser for help on using the browser.