annotate decoders/ogg.c @ 474:c66080364dff

Most decoders now report total sample play time, now. Technically, this breaks binary compatibility with the 1.0 branch, since it extends the Sound_Sample struct, but most (all?) programs are just passing pointers allocated by SDL_sound around, and might be okay. Source-level compatibility is not broken...yet! :) --ryan. -------- Original Message -------- Subject: SDL_sound patch: Finding total length of time of sound file. Date: Sun, 26 Jan 2003 09:31:17 -0800 (PST) Hi Ryan, I am working with Eric Wing and helping him modify SDL_sound. AS part of our efforts in improving and enhancing SDL_sound, we like to submit this patch. We modified the codecs to find the total time of a sound file. Below is the explanation of the patch. The patch is appended as an attachment to this email. * MOTIVATION: We needed the ability to get the total play time of a sample (And we noticed that we're not the only ones). Since SDL_sound blocks direct access to the specific decoders, there is no way for a user to know this information short of decoding the whole thing. Because of this, we believe this will be a useful addition, even though the accuracy may not be perfect (subject to each decoder) or the information may not always be available. * CONTRIBUTORS: Wesley Leong (modified the majority of the codecs and verified the results) Eric Wing (showed everyone how to do modify codec, modified mikmod) Wang Lam (modified a handful of codecs, researched into specs and int overflow) Ahilan Anantha (modified a few codecs and helped with integer math) * GENERAL ISSUES: We chose the value to be milliseconds as an Sint32. Milliseconds because that's what Sound_Seek takes as a parameter and -1 to allow for instances/codecs where the value could not be determined. We are not sure if this is the final convention you want, so we are willing to work with you on this. We also expect the total_time field to be set on open and never again modified by SDL_sound. Users may access it directly much like the sample buffer and buffer_size. We thought about recomputing the time on DecodeAll, but since users may seek or decode small chunks first, not all the data may be there. So this is better done by the user. This may be good information to document. Currently, all the main codecs are implemented except for QuickTime.
author Ryan C. Gordon <icculus@icculus.org>
date Sat, 08 May 2004 08:19:50 +0000
parents 30f96c853462
children 3e705c9180e5
rev   line source
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
1 /*
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
2 * SDL_sound -- An abstract sound format decoding API.
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
3 * Copyright (C) 2001 Ryan C. Gordon.
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
4 *
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
5 * This library is free software; you can redistribute it and/or
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
6 * modify it under the terms of the GNU Lesser General Public
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
7 * License as published by the Free Software Foundation; either
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
8 * version 2.1 of the License, or (at your option) any later version.
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
9 *
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
10 * This library is distributed in the hope that it will be useful,
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
13 * Lesser General Public License for more details.
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
14 *
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
15 * You should have received a copy of the GNU Lesser General Public
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
16 * License along with this library; if not, write to the Free Software
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
18 */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
19
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
20 /*
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
21 * Ogg Vorbis decoder for SDL_sound.
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
22 *
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
23 * This driver handles .OGG audio files, and depends on libvorbisfile to
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
24 * do the actual decoding work. libvorbisfile is part of libvorbis, which
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
25 * is part of the Ogg Vorbis project.
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
26 *
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
27 * Ogg Vorbis: http://www.xiph.org/ogg/vorbis/
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
28 * vorbisfile documentation: http://www.xiph.org/ogg/vorbis/doc/vorbisfile/
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
29 *
184
47cc2de2ae36 Changed reference to "LICENSE" file to "COPYING".
Ryan C. Gordon <icculus@icculus.org>
parents: 149
diff changeset
30 * Please see the file COPYING in the source's root directory.
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
31 *
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
32 * This file written by Ryan C. Gordon. (icculus@clutteredmind.org)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
33 */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
34
106
40de367eb59e Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents: 104
diff changeset
35 #if HAVE_CONFIG_H
40de367eb59e Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents: 104
diff changeset
36 # include <config.h>
40de367eb59e Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents: 104
diff changeset
37 #endif
100
6d9fdec2f708 added config.h, added --enable-debug flag, various other changes to the build system
fingolfin
parents: 63
diff changeset
38
104
103cfcb3c014 Updated to fix build system problem.
Ryan C. Gordon <icculus@icculus.org>
parents: 100
diff changeset
39 #ifdef SOUND_SUPPORTS_OGG
103cfcb3c014 Updated to fix build system problem.
Ryan C. Gordon <icculus@icculus.org>
parents: 100
diff changeset
40
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
41 #include <stdio.h>
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
42 #include <stdlib.h>
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
43 #include <string.h>
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
44 #include <math.h>
106
40de367eb59e Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents: 104
diff changeset
45
40de367eb59e Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents: 104
diff changeset
46 #include "SDL_sound.h"
40de367eb59e Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents: 104
diff changeset
47
40de367eb59e Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents: 104
diff changeset
48 #define __SDL_SOUND_INTERNAL__
40de367eb59e Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents: 104
diff changeset
49 #include "SDL_sound_internal.h"
40de367eb59e Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents: 104
diff changeset
50
443
30f96c853462 MacOS X build fixes.
Ryan C. Gordon <icculus@icculus.org>
parents: 433
diff changeset
51 #include <vorbis/codec.h>
30f96c853462 MacOS X build fixes.
Ryan C. Gordon <icculus@icculus.org>
parents: 433
diff changeset
52 #include <vorbis/vorbisfile.h>
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
53
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
54
47
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
55 static int OGG_init(void);
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
56 static void OGG_quit(void);
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
57 static int OGG_open(Sound_Sample *sample, const char *ext);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
58 static void OGG_close(Sound_Sample *sample);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
59 static Uint32 OGG_read(Sound_Sample *sample);
221
c9772a9f5271 Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents: 184
diff changeset
60 static int OGG_rewind(Sound_Sample *sample);
306
c97be6e1bd27 Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents: 231
diff changeset
61 static int OGG_seek(Sound_Sample *sample, Uint32 ms);
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
62
149
1df5c106504e Decoders can now list multiple file extensions.
Ryan C. Gordon <icculus@icculus.org>
parents: 122
diff changeset
63 static const char *extensions_ogg[] = { "OGG", NULL };
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
64 const Sound_DecoderFunctions __Sound_DecoderFunctions_OGG =
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
65 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
66 {
149
1df5c106504e Decoders can now list multiple file extensions.
Ryan C. Gordon <icculus@icculus.org>
parents: 122
diff changeset
67 extensions_ogg,
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
68 "Ogg Vorbis audio through VorbisFile",
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
69 "Ryan C. Gordon <icculus@clutteredmind.org>",
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
70 "http://www.icculus.org/SDL_sound/"
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
71 },
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
72
221
c9772a9f5271 Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents: 184
diff changeset
73 OGG_init, /* init() method */
c9772a9f5271 Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents: 184
diff changeset
74 OGG_quit, /* quit() method */
c9772a9f5271 Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents: 184
diff changeset
75 OGG_open, /* open() method */
c9772a9f5271 Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents: 184
diff changeset
76 OGG_close, /* close() method */
c9772a9f5271 Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents: 184
diff changeset
77 OGG_read, /* read() method */
306
c97be6e1bd27 Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents: 231
diff changeset
78 OGG_rewind, /* rewind() method */
c97be6e1bd27 Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents: 231
diff changeset
79 OGG_seek /* seek() method */
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
80 };
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
81
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
82
47
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
83 static int OGG_init(void)
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
84 {
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
85 return(1); /* always succeeds. */
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
86 } /* OGG_init */
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
87
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
88
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
89 static void OGG_quit(void)
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
90 {
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
91 /* it's a no-op. */
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
92 } /* OGG_quit */
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
93
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
94
ea58bc3b15d7 Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents: 24
diff changeset
95
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
96 /*
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
97 * These are callbacks from vorbisfile that let them read data from
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
98 * a RWops...
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
99 */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
100
63
9669aa13d3e0 Changes in preparation for autoconf, and the RWops wrappers changed to
Ryan C. Gordon <icculus@icculus.org>
parents: 59
diff changeset
101 static size_t RWops_ogg_read(void *ptr, size_t size, size_t nmemb, void *datasource)
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
102 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
103 return((size_t) SDL_RWread((SDL_RWops *) datasource, ptr, size, nmemb));
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
104 } /* RWops_ogg_read */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
105
122
095a066b2cd2 Portability fix.
Ryan C. Gordon <icculus@icculus.org>
parents: 106
diff changeset
106 static int RWops_ogg_seek(void *datasource, ogg_int64_t offset, int whence)
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
107 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
108 return(SDL_RWseek((SDL_RWops *) datasource, offset, whence));
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
109 } /* RWops_ogg_seek */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
110
63
9669aa13d3e0 Changes in preparation for autoconf, and the RWops wrappers changed to
Ryan C. Gordon <icculus@icculus.org>
parents: 59
diff changeset
111 static int RWops_ogg_close(void *datasource)
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
112 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
113 /* do nothing; SDL_sound will delete the RWops at a higher level. */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
114 return(0); /* this is success in fclose(), so I guess that's okay. */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
115 } /* RWops_ogg_close */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
116
63
9669aa13d3e0 Changes in preparation for autoconf, and the RWops wrappers changed to
Ryan C. Gordon <icculus@icculus.org>
parents: 59
diff changeset
117 static long RWops_ogg_tell(void *datasource)
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
118 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
119 return((long) SDL_RWtell((SDL_RWops *) datasource));
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
120 } /* RWops_ogg_tell */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
121
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
122 static const ov_callbacks RWops_ogg_callbacks =
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
123 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
124 RWops_ogg_read,
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
125 RWops_ogg_seek,
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
126 RWops_ogg_close,
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
127 RWops_ogg_tell
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
128 };
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
129
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
130
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
131 /* Return a human readable version of an VorbisFile error code... */
59
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
132 #if (defined DEBUG_CHATTER)
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
133 static const char *ogg_error(int errnum)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
134 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
135 switch(errnum)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
136 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
137 case OV_EREAD:
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
138 return("i/o error");
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
139 case OV_ENOTVORBIS:
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
140 return("not a vorbis file");
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
141 case OV_EVERSION:
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
142 return("Vorbis version mismatch");
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
143 case OV_EBADHEADER:
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
144 return("invalid Vorbis bitstream header");
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
145 case OV_EFAULT:
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
146 return("internal logic fault in Vorbis library");
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
147 } /* switch */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
148
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
149 return("unknown error");
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
150 } /* ogg_error */
59
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
151 #endif
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
152
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
153 static __inline__ void output_ogg_comments(OggVorbis_File *vf)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
154 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
155 #if (defined DEBUG_CHATTER)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
156 int i;
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
157 vorbis_comment *vc = ov_comment(vf, -1);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
158
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
159 if (vc == NULL)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
160 return;
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
161
59
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
162 SNDDBG(("OGG: vendor == [%s].\n", vc->vendor));
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
163 for (i = 0; i < vc->comments; i++)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
164 {
59
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
165 SNDDBG(("OGG: user comment [%s].\n", vc->user_comments[i]));
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
166 } /* for */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
167 #endif
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
168 } /* output_ogg_comments */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
169
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
170
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
171 static int OGG_open(Sound_Sample *sample, const char *ext)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
172 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
173 int rc;
474
c66080364dff Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents: 443
diff changeset
174 double total_time;
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
175 OggVorbis_File *vf;
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
176 vorbis_info *info;
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
177 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
178
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
179 vf = (OggVorbis_File *) malloc(sizeof (OggVorbis_File));
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
180 BAIL_IF_MACRO(vf == NULL, ERR_OUT_OF_MEMORY, 0);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
181
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
182 rc = ov_open_callbacks(internal->rw, vf, NULL, 0, RWops_ogg_callbacks);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
183 if (rc != 0)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
184 {
59
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
185 SNDDBG(("OGG: can't grok data. reason: [%s].\n", ogg_error(rc)));
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
186 free(vf);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
187 BAIL_MACRO("OGG: Not valid Ogg Vorbis data.", 0);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
188 } /* if */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
189
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
190 info = ov_info(vf, -1);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
191 if (info == NULL)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
192 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
193 ov_clear(vf);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
194 free(vf);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
195 BAIL_MACRO("OGG: failed to retrieve bitstream info", 0);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
196 } /* if */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
197
59
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
198 SNDDBG(("OGG: Accepting data stream.\n"));
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
199
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
200 output_ogg_comments(vf);
59
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
201 SNDDBG(("OGG: bitstream version == (%d).\n", info->version));
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
202 SNDDBG(("OGG: bitstream channels == (%d).\n", info->channels));
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
203 SNDDBG(("OGG: bitstream sampling rate == (%ld).\n", info->rate));
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
204 SNDDBG(("OGG: seekable == {%s}.\n", ov_seekable(vf) ? "TRUE" : "FALSE"));
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
205 SNDDBG(("OGG: number of logical bitstreams == (%ld).\n", ov_streams(vf)));
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
206 SNDDBG(("OGG: serial number == (%ld).\n", ov_serialnumber(vf, -1)));
cd91e1857b42 Changed _D macro to SNDDBG, and fixed a warning if compiling without debug
Ryan C. Gordon <icculus@icculus.org>
parents: 47
diff changeset
207 SNDDBG(("OGG: total seconds of sample == (%f).\n", ov_time_total(vf, -1)));
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
208
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
209 internal->decoder_private = vf;
327
aa7f6a110971 Added seek implementation.
Ryan C. Gordon <icculus@icculus.org>
parents: 306
diff changeset
210 sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
211 sample->actual.rate = (Uint32) info->rate;
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
212 sample->actual.channels = (Uint8) info->channels;
474
c66080364dff Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents: 443
diff changeset
213 total_time = ov_time_total(vf, -1);
c66080364dff Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents: 443
diff changeset
214 if (OV_EINVAL == total_time)
c66080364dff Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents: 443
diff changeset
215 sample->total_time = -1;
c66080364dff Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents: 443
diff changeset
216 else
c66080364dff Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents: 443
diff changeset
217 sample->total_time = (Sint32)(total_time * 1000.0 + 0.5);
c66080364dff Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents: 443
diff changeset
218
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
219
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
220 /*
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
221 * Since we might have more than one logical bitstream in the OGG file,
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
222 * and these bitstreams may be in different formats, we might be
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
223 * converting two or three times: once in vorbisfile, once again in
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
224 * SDL_sound, and perhaps a third time to get it to the sound device's
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
225 * format. That's wickedly inefficient.
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
226 *
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
227 * To combat this a little, if the user specified a desired format, we
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
228 * claim that to be the "actual" format of the collection of logical
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
229 * bitstreams. This means that VorbisFile will do a conversion as
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
230 * necessary, and SDL_sound will not. If the user didn't specify a
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
231 * desired format, then we pretend the "actual" format is something that
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
232 * OGG files are apparently commonly encoded in.
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
233 */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
234 sample->actual.format = (sample->desired.format == 0) ?
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
235 AUDIO_S16LSB : sample->desired.format;
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
236 return(1);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
237 } /* OGG_open */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
238
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
239
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
240 static void OGG_close(Sound_Sample *sample)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
241 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
242 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
243 OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private;
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
244 ov_clear(vf);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
245 free(vf);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
246 } /* OGG_close */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
247
433
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
248 /* Note: According to the Vorbis documentation:
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
249 * "ov_read() will decode at most one vorbis packet per invocation,
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
250 * so the value returned will generally be less than length."
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
251 * Due to this, for buffer sizes like 16384, SDL_Sound was always getting
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
252 * an underfilled buffer and always setting the EAGAIN flag.
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
253 * Since the SDL_Sound API implies that the entire buffer
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
254 * should be filled unless EOF, additional code has been added
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
255 * to this function to call ov_read() until the buffer is filled.
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
256 * However, there may still be some corner cases where the buffer
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
257 * cannot be entirely filled. So be aware.
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
258 */
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
259 static Uint32 OGG_read(Sound_Sample *sample)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
260 {
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
261 int rc;
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
262 int bitstream;
433
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
263 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
264 OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private;
433
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
265
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
266 rc = ov_read(vf, internal->buffer, internal->buffer_size,
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
267 ((sample->actual.format & 0x1000) ? 1 : 0), /* bigendian? */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
268 ((sample->actual.format & 0xFF) / 8), /* bytes per sample point */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
269 ((sample->actual.format & 0x8000) ? 1 : 0), /* signed data? */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
270 &bitstream);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
271
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
272 /* Make sure the read went smoothly... */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
273 if (rc == 0)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
274 sample->flags |= SOUND_SAMPLEFLAG_EOF;
433
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
275
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
276 else if (rc < 0)
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
277 sample->flags |= SOUND_SAMPLEFLAG_ERROR;
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
278
433
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
279 /* If the buffer isn't filled, keep trying to fill it
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
280 * until no more data can be grabbed */
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
281 else if ((Uint32) rc < internal->buffer_size)
433
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
282 {
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
283 /* Creating a pointer to the buffer that denotes where to start
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
284 * writing new data. */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
285 Uint8* buffer_start_point = NULL;
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
286 int total_bytes_read = rc;
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
287 int bytes_remaining = internal->buffer_size - rc;
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
288
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
289 /* Keep grabbing data until something prevents
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
290 * us from getting more. (Could be EOF,
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
291 * packets are too large to fit in remaining
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
292 * space, or an error.)
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
293 */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
294 while( (rc > 0) && (bytes_remaining > 0) )
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
295 {
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
296 /* Set buffer pointer to end of last write */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
297 /* All the messiness is to get rid of the warning for
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
298 * dereferencing a void*
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
299 */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
300 buffer_start_point = &(((Uint8*)internal->buffer)[total_bytes_read]);
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
301 rc = ov_read(vf, buffer_start_point, bytes_remaining,
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
302 ((sample->actual.format & 0x1000) ? 1 : 0), /* bigendian? */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
303 ((sample->actual.format & 0xFF) / 8), /* bytes per sample point */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
304 ((sample->actual.format & 0x8000) ? 1 : 0), /* signed data? */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
305 &bitstream);
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
306 /* Make sure rc > 0 because we don't accidently want
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
307 * to change the counters if there was an error
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
308 */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
309 if(rc > 0)
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
310 {
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
311 total_bytes_read += rc;
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
312 bytes_remaining = bytes_remaining - rc;
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
313 }
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
314 }
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
315 /* I think the minimum read size is 2, though I'm
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
316 * not sure about this. (I've hit cases where I
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
317 * couldn't read less than 4.) What I don't want to do is
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
318 * accidently claim we hit EOF when the reason rc == 0
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
319 * is because the requested amount of data was smaller
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
320 * than the minimum packet size.
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
321 * For now, I will be conservative
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
322 * and not set the EOF flag, and let the next call to
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
323 * this function figure it out.
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
324 * I think the ERROR flag is safe to set because
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
325 * it looks like OGG simply returns 0 if the
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
326 * read size is too small.
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
327 * And in most cases for sensible buffer sizes,
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
328 * this fix will fill the buffer,
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
329 * so we can set the EAGAIN flag without worrying
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
330 * that it will always be set.
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
331 */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
332 if(rc < 0)
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
333 {
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
334 sample->flags |= SOUND_SAMPLEFLAG_ERROR;
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
335 }
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
336 else if(rc == 0)
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
337 {
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
338 /* Do nothing for now until there is a better solution */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
339 /* sample->flags |= SOUND_SAMPLEFLAG_EOF; */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
340 }
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
341
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
342 /* Test for a buffer underrun. It should occur less frequently
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
343 * now, but it still may happen and not necessarily mean
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
344 * anything useful. */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
345 if ((Uint32) total_bytes_read < internal->buffer_size)
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
346 {
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
347 sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
348 }
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
349 /* change rc to the total bytes read so function
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
350 * can return the correct value.
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
351 */
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
352 rc = total_bytes_read;
f1c16afd9ebe Read until buffer is full in Sound_Decode() rather than one packet per call.
Ryan C. Gordon <icculus@icculus.org>
parents: 377
diff changeset
353 }
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
354
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
355 return((Uint32) rc);
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
356 } /* OGG_read */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
357
221
c9772a9f5271 Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents: 184
diff changeset
358
c9772a9f5271 Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents: 184
diff changeset
359 static int OGG_rewind(Sound_Sample *sample)
c9772a9f5271 Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents: 184
diff changeset
360 {
231
d3dc34315ac7 Rewind method implemented by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents: 221
diff changeset
361 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
d3dc34315ac7 Rewind method implemented by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents: 221
diff changeset
362 OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private;
d3dc34315ac7 Rewind method implemented by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents: 221
diff changeset
363
d3dc34315ac7 Rewind method implemented by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents: 221
diff changeset
364 BAIL_IF_MACRO(ov_raw_seek(vf, 0) < 0, ERR_IO_ERROR, 0);
d3dc34315ac7 Rewind method implemented by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents: 221
diff changeset
365 return(1);
221
c9772a9f5271 Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents: 184
diff changeset
366 } /* OGG_rewind */
c9772a9f5271 Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents: 184
diff changeset
367
306
c97be6e1bd27 Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents: 231
diff changeset
368
c97be6e1bd27 Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents: 231
diff changeset
369 static int OGG_seek(Sound_Sample *sample, Uint32 ms)
c97be6e1bd27 Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents: 231
diff changeset
370 {
327
aa7f6a110971 Added seek implementation.
Ryan C. Gordon <icculus@icculus.org>
parents: 306
diff changeset
371 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
aa7f6a110971 Added seek implementation.
Ryan C. Gordon <icculus@icculus.org>
parents: 306
diff changeset
372 OggVorbis_File *vf = (OggVorbis_File *) internal->decoder_private;
aa7f6a110971 Added seek implementation.
Ryan C. Gordon <icculus@icculus.org>
parents: 306
diff changeset
373 double timepos = (((double) ms) / 1000.0);
aa7f6a110971 Added seek implementation.
Ryan C. Gordon <icculus@icculus.org>
parents: 306
diff changeset
374 BAIL_IF_MACRO(ov_time_seek(vf, timepos) < 0, ERR_IO_ERROR, 0);
aa7f6a110971 Added seek implementation.
Ryan C. Gordon <icculus@icculus.org>
parents: 306
diff changeset
375 return(1);
306
c97be6e1bd27 Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents: 231
diff changeset
376 } /* OGG_seek */
c97be6e1bd27 Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents: 231
diff changeset
377
63
9669aa13d3e0 Changes in preparation for autoconf, and the RWops wrappers changed to
Ryan C. Gordon <icculus@icculus.org>
parents: 59
diff changeset
378 #endif /* SOUND_SUPPORTS_OGG */
9669aa13d3e0 Changes in preparation for autoconf, and the RWops wrappers changed to
Ryan C. Gordon <icculus@icculus.org>
parents: 59
diff changeset
379
9669aa13d3e0 Changes in preparation for autoconf, and the RWops wrappers changed to
Ryan C. Gordon <icculus@icculus.org>
parents: 59
diff changeset
380
24
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
381 /* end of ogg.c ... */
0fc0f91b1b84 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
382