]> icculus.org git repositories - divverent/darkplaces.git/blob - ogg.c
R_Mesh_State_Texture and GL_VertexPointer merge once again to become the reborn R_Mes...
[divverent/darkplaces.git] / ogg.c
1 /*
2         Copyright (C) 2003  Mathieu Olivier
3
4         This program is free software; you can redistribute it and/or
5         modify it under the terms of the GNU General Public License
6         as published by the Free Software Foundation; either version 2
7         of the License, or (at your option) any later version.
8
9         This program is distributed in the hope that it will be useful,
10         but WITHOUT ANY WARRANTY; without even the implied warranty of
11         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13         See the GNU General Public License for more details.
14
15         You should have received a copy of the GNU General Public License
16         along with this program; if not, write to:
17
18                 Free Software Foundation, Inc.
19                 59 Temple Place - Suite 330
20                 Boston, MA  02111-1307, USA
21
22 */
23
24
25 #include "quakedef.h"
26 #include "ogg.h"
27
28
29 extern void ResampleSfx (sfxcache_t *sc, qbyte *data, char *name);
30
31
32 /*
33 =================================================================
34
35   Minimal set of definitions from the Ogg Vorbis lib
36   (C) COPYRIGHT 1994-2001 by the XIPHOPHORUS Company
37   http://www.xiph.org/
38
39   WARNING: for a matter of simplicity, several pointer types are
40   casted to "void*", and most enumerated values are not included
41
42 =================================================================
43 */
44
45 #ifdef _MSC_VER
46 typedef __int64 ogg_int64_t;
47 #else
48 typedef long long ogg_int64_t;
49 #endif
50
51 typedef struct
52 {
53         size_t  (*read_func)    (void *ptr, size_t size, size_t nmemb, void *datasource);
54         int             (*seek_func)    (void *datasource, ogg_int64_t offset, int whence);
55         int             (*close_func)   (void *datasource);
56         long    (*tell_func)    (void *datasource);
57 } ov_callbacks;
58
59 typedef struct
60 {
61         unsigned char   *data;
62         int                             storage;
63         int                             fill;
64         int                             returned;
65         int                             unsynced;
66         int                             headerbytes;
67         int                             bodybytes;
68 } ogg_sync_state;
69
70 typedef struct
71 {
72         int             version;
73         int             channels;
74         long    rate;
75         long    bitrate_upper;
76         long    bitrate_nominal;
77         long    bitrate_lower;
78         long    bitrate_window;
79         void    *codec_setup;
80 } vorbis_info;
81
82 typedef struct
83 {
84         unsigned char   *body_data;
85         long                    body_storage;
86         long                    body_fill;
87         long                    body_returned;
88         int                             *lacing_vals;
89         ogg_int64_t             *granule_vals;
90         long                    lacing_storage;
91         long                    lacing_fill;
92         long                    lacing_packet;
93         long                    lacing_returned;
94         unsigned char   header[282];
95         int                             header_fill;
96         int                             e_o_s;
97         int                             b_o_s;
98         long                    serialno;
99         long                    pageno;
100         ogg_int64_t             packetno;
101         ogg_int64_t             granulepos;
102 } ogg_stream_state;
103
104 typedef struct
105 {
106         int                     analysisp;
107         vorbis_info     *vi;
108         float           **pcm;
109         float           **pcmret;
110         int                     pcm_storage;
111         int                     pcm_current;
112         int                     pcm_returned;
113         int                     preextrapolate;
114         int                     eofflag;
115         long            lW;
116         long            W;
117         long            nW;
118         long            centerW;
119         ogg_int64_t     granulepos;
120         ogg_int64_t     sequence;
121         ogg_int64_t     glue_bits;
122         ogg_int64_t     time_bits;
123         ogg_int64_t     floor_bits;
124         ogg_int64_t     res_bits;
125         void            *backend_state;
126 } vorbis_dsp_state;
127
128 typedef struct
129 {
130         long                    endbyte;
131         int                             endbit;
132         unsigned char   *buffer;
133         unsigned char   *ptr;
134         long                    storage;
135 } oggpack_buffer;
136
137 typedef struct
138 {
139         float                           **pcm;
140         oggpack_buffer          opb;
141         long                            lW;
142         long                            W;
143         long                            nW;
144         int                                     pcmend;
145         int                                     mode;
146         int                                     eofflag;
147         ogg_int64_t                     granulepos;
148         ogg_int64_t                     sequence;
149         vorbis_dsp_state        *vd;
150         void                            *localstore;
151         long                            localtop;
152         long                            localalloc;
153         long                            totaluse;
154         void                            *reap;  // VOIDED POINTER
155         long                            glue_bits;
156         long                            time_bits;
157         long                            floor_bits;
158         long                            res_bits;
159         void                            *internal;
160 } vorbis_block;
161
162 typedef struct
163 {
164         void                            *datasource;
165         int                                     seekable;
166         ogg_int64_t                     offset;
167         ogg_int64_t                     end;
168         ogg_sync_state          oy;
169         int                                     links;
170         ogg_int64_t                     *offsets;
171         ogg_int64_t                     *dataoffsets;
172         long                            *serialnos;
173         ogg_int64_t                     *pcmlengths;
174         vorbis_info                     *vi;
175         void                            *vc;  // VOIDED POINTER
176         ogg_int64_t                     pcm_offset;
177         int                                     ready_state;
178         long                            current_serialno;
179         int                                     current_link;
180         double                          bittrack;
181         double                          samptrack;
182         ogg_stream_state        os;
183         vorbis_dsp_state        vd;
184         vorbis_block            vb;
185         ov_callbacks            callbacks;
186 } OggVorbis_File;
187
188
189 /*
190 =================================================================
191
192   DarkPlaces definitions
193
194 =================================================================
195 */
196
197 // Functions exported from the vorbisfile library
198 static int (*qov_clear) (OggVorbis_File *vf);
199 static vorbis_info* (*qov_info) (OggVorbis_File *vf,int link);
200 static int (*qov_open_callbacks) (void *datasource, OggVorbis_File *vf,
201                                                                   char *initial, long ibytes,
202                                                                   ov_callbacks callbacks);
203 static ogg_int64_t (*qov_pcm_total) (OggVorbis_File *vf,int i);
204 static long (*qov_read) (OggVorbis_File *vf,char *buffer,int length,
205                                                  int bigendianp,int word,int sgned,int *bitstream);
206
207 static dllfunction_t oggvorbisfuncs[] =
208 {
209         {"ov_clear",                    (void **) &qov_clear},
210         {"ov_info",                             (void **) &qov_info},
211         {"ov_open_callbacks",   (void **) &qov_open_callbacks},
212         {"ov_pcm_total",                (void **) &qov_pcm_total},
213         {"ov_read",                             (void **) &qov_read},
214         {NULL, NULL}
215 };
216
217 // Handle for the Vorbisfile DLL
218 static dllhandle_t vf_dll = NULL;
219
220 typedef struct
221 {
222         qbyte *buffer;
223         ogg_int64_t ind, buffsize;
224 } ov_decode_t;
225
226
227 static size_t ovcb_read (void *ptr, size_t size, size_t nb, void *datasource)
228 {
229         ov_decode_t *ov_decode = (ov_decode_t*)datasource;
230         size_t remain, len;
231
232         remain = ov_decode->buffsize - ov_decode->ind;
233         len = size * nb;
234         if (remain < len)
235                 len = remain - remain % size;
236
237         memcpy (ptr, ov_decode->buffer + ov_decode->ind, len);
238         ov_decode->ind += len;
239
240         return len / size;
241 }
242
243 static int ovcb_seek (void *datasource, ogg_int64_t offset, int whence)
244 {
245         ov_decode_t *ov_decode = (ov_decode_t*)datasource;
246
247         switch (whence)
248         {
249                 case SEEK_SET:
250                         break;
251                 case SEEK_CUR:
252                         offset += ov_decode->ind;
253                         break;
254                 case SEEK_END:
255                         offset += ov_decode->buffsize;
256                         break;
257                 default:
258                         return -1;
259         }
260         if (offset < 0 || offset > ov_decode->buffsize)
261                 return -1;
262
263         ov_decode->ind = offset;
264         return 0;
265 }
266
267 static int ovcb_close (void *ov_decode)
268 {
269         return 0;
270 }
271
272 static long ovcb_tell (void *ov_decode)
273 {
274         return ((ov_decode_t*)ov_decode)->ind;
275 }
276
277
278 /*
279 =================================================================
280
281   DLL load & unload
282
283 =================================================================
284 */
285
286 /*
287 ====================
288 OGG_OpenLibrary
289
290 Try to load the VorbisFile DLL
291 ====================
292 */
293 qboolean OGG_OpenLibrary (void)
294 {
295         const char* dllname;
296         const dllfunction_t *func;
297
298         // Already loaded?
299         if (vf_dll)
300                 return true;
301
302 #ifdef WIN32
303         dllname = "vorbisfile.dll";
304 #else
305         dllname = "libvorbisfile.so";
306 #endif
307
308         // Initializations
309         for (func = oggvorbisfuncs; func && func->name != NULL; func++)
310                 *func->funcvariable = NULL;
311
312         // Load the DLL
313         if (! (vf_dll = Sys_LoadLibrary (dllname)))
314         {
315                 Con_DPrintf("Can't find %s. Ogg Vorbis support disabled\n", dllname);
316                 return false;
317         }
318
319         // Get the function adresses
320         for (func = oggvorbisfuncs; func && func->name != NULL; func++)
321                 if (!(*func->funcvariable = (void *) Sys_GetProcAddress (vf_dll, func->name)))
322                 {
323                         Con_Printf("missing function \"%s\" - broken Ogg Vorbis library!\n", func->name);
324                         OGG_CloseLibrary ();
325                         return false;
326                 }
327
328         Con_DPrintf("%s loaded. Ogg Vorbis support enabled\n", dllname);
329         return true;
330 }
331
332
333 /*
334 ====================
335 OGG_CloseLibrary
336
337 Unload the VorbisFile DLL
338 ====================
339 */
340 void OGG_CloseLibrary (void)
341 {
342         if (!vf_dll)
343                 return;
344
345         Sys_UnloadLibrary (vf_dll);
346         vf_dll = NULL;
347 }
348
349
350 /*
351 =================================================================
352
353         Ogg Vorbis decoding
354
355 =================================================================
356 */
357
358 /*
359 ====================
360 OGG_LoadVorbisFile
361
362 Load an Ogg Vorbis file into a sfxcache_t
363 ====================
364 */
365 sfxcache_t *OGG_LoadVorbisFile (const char *filename, sfx_t *s)
366 {
367         qbyte *data;
368         ov_decode_t ov_decode;
369         OggVorbis_File vf;
370         ov_callbacks callbacks = {ovcb_read, ovcb_seek, ovcb_close, ovcb_tell};
371         vorbis_info *vi;
372         ogg_int64_t len;
373         char *buff;
374         ogg_int64_t done;
375         int bs;
376         long ret;
377         sfxcache_t *sc;
378
379         if (!vf_dll)
380                 return NULL;
381
382         // Load the file
383         data = FS_LoadFile (filename, false);
384         if (data == NULL)
385                 return NULL;
386
387         // Open it with the VorbisFile API
388         ov_decode.buffer = data;
389         ov_decode.ind = 0;
390         ov_decode.buffsize = fs_filesize;
391         if (qov_open_callbacks (&ov_decode, &vf, NULL, 0, callbacks) < 0)
392         {
393                 Con_Printf("error while opening Ogg Vorbis file \"%s\"\n", filename);
394                 Mem_Free (data);
395                 return NULL;
396         }
397
398         // Get the stream information
399         vi = qov_info (&vf, -1);
400         if (vi->channels < 1 || vi->channels > 2)
401         {
402                 Con_Printf("%s has an unsupported number of channels (%i)\n",
403                                         s->name, vi->channels);
404                 qov_clear (&vf);
405                 Mem_Free (data);
406                 return NULL;
407         }
408
409         // Decode it
410         len = qov_pcm_total (&vf, -1) * vi->channels * 2;  // 16 bits => "* 2"
411         buff = Mem_Alloc (tempmempool, (int)len);
412         done = 0;
413         bs = 0;
414         while ((ret = qov_read (&vf, &buff[done], (int)(len - done), 0, 2, 1, &bs)) > 0)
415                 done += ret;
416
417         // Calculate resampled length
418         len = (double)done * (double)shm->speed / (double)vi->rate;
419
420         // Resample it
421         Mem_FreePool (&s->mempool);
422         s->mempool = Mem_AllocPool (s->name);
423         sc = s->sfxcache = Mem_Alloc (s->mempool, (int)len + sizeof (sfxcache_t));
424         if (sc != NULL)
425         {
426                 sc->length = (int)done / (vi->channels * 2);
427                 sc->loopstart = -1;
428                 sc->speed = vi->rate;
429                 sc->width = 2;  // We always work with 16 bits samples
430                 sc->stereo = (vi->channels == 2);
431
432                 ResampleSfx (sc, buff, s->name);
433         }
434         else
435         {
436                 Con_Printf("failed to allocate memory for sound \"%s\"\n", s->name);
437                 Mem_FreePool (&s->mempool);
438         }
439
440         qov_clear (&vf);
441         Mem_Free (buff);
442         Mem_Free (data);
443
444         return sc;
445 }