gosu 0.8.0.pre3 → 0.8.0.pre4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/Gosu/Buttons.hpp +13 -11
  3. data/{linux → ext/gosu}/extconf.rb +25 -47
  4. data/{GosuImpl/RubyGosu_wrap.cxx → ext/gosu/gosu_wrap.cxx} +3 -2
  5. data/{GosuImpl/RubyGosu_wrap.h → ext/gosu/gosu_wrap.h} +0 -0
  6. data/lib/gosu.rb +6 -7
  7. data/lib/gosu/zen.rb +12 -0
  8. data/{GosuImpl → src}/Audio/ALChannelManagement.hpp +0 -0
  9. data/{GosuImpl → src}/Audio/AudioFile.hpp +0 -0
  10. data/{GosuImpl → src}/Audio/AudioOpenAL.cpp +0 -0
  11. data/{GosuImpl → src}/Audio/AudioOpenAL.mm +0 -0
  12. data/{GosuImpl → src}/Audio/AudioToolboxFile.hpp +0 -0
  13. data/{GosuImpl → src}/Audio/OggFile.hpp +0 -0
  14. data/{GosuImpl → src}/Audio/SndFile.hpp +0 -0
  15. data/{GosuImpl/Graphics → src/Bitmap}/Bitmap.cpp +2 -0
  16. data/{GosuImpl/Graphics → src/Bitmap}/BitmapApple.mm +0 -0
  17. data/{GosuImpl/Graphics → src/Bitmap}/BitmapBMP.cpp +0 -0
  18. data/{GosuImpl/Graphics → src/Bitmap}/BitmapColorKey.cpp +0 -0
  19. data/{GosuImpl/Graphics → src/Bitmap}/BitmapFreeImage.cpp +0 -0
  20. data/{GosuImpl/Graphics → src/Bitmap}/BitmapGDIplus.cpp +0 -0
  21. data/{GosuImpl/Graphics → src/Bitmap}/BitmapUtils.cpp +0 -0
  22. data/{GosuImpl → src}/DirectoriesMac.mm +0 -0
  23. data/{GosuImpl → src}/DirectoriesTouch.mm +0 -0
  24. data/{GosuImpl → src}/DirectoriesUnix.cpp +0 -0
  25. data/{GosuImpl → src}/DirectoriesWin.cpp +0 -0
  26. data/{GosuImpl → src}/FileUnix.cpp +0 -0
  27. data/{GosuImpl → src}/FileWin.cpp +0 -0
  28. data/{GosuImpl/Graphics → src}/GosuView.hpp +0 -0
  29. data/{GosuImpl/Graphics → src}/GosuView.mm +0 -0
  30. data/{GosuImpl → src}/Graphics/BlockAllocator.cpp +0 -0
  31. data/{GosuImpl → src}/Graphics/BlockAllocator.hpp +0 -0
  32. data/{GosuImpl → src}/Graphics/ClipRectStack.hpp +0 -0
  33. data/{GosuImpl → src}/Graphics/Color.cpp +0 -0
  34. data/{GosuImpl → src}/Graphics/Common.hpp +0 -0
  35. data/{GosuImpl → src}/Graphics/DrawOp.hpp +0 -0
  36. data/{GosuImpl → src}/Graphics/DrawOpQueue.hpp +0 -0
  37. data/{GosuImpl → src}/Graphics/Graphics.cpp +0 -0
  38. data/{GosuImpl → src}/Graphics/Image.cpp +0 -0
  39. data/{GosuImpl → src}/Graphics/LargeImageData.cpp +0 -0
  40. data/{GosuImpl → src}/Graphics/LargeImageData.hpp +0 -0
  41. data/{GosuImpl → src}/Graphics/Macro.hpp +0 -0
  42. data/{GosuImpl → src}/Graphics/RenderState.hpp +0 -0
  43. data/{GosuImpl → src}/Graphics/TexChunk.cpp +0 -0
  44. data/{GosuImpl → src}/Graphics/TexChunk.hpp +0 -0
  45. data/{GosuImpl → src}/Graphics/Texture.cpp +0 -0
  46. data/{GosuImpl → src}/Graphics/Texture.hpp +0 -0
  47. data/{GosuImpl → src}/Graphics/Transform.cpp +0 -0
  48. data/{GosuImpl → src}/Graphics/TransformStack.hpp +0 -0
  49. data/{GosuImpl → src}/IO.cpp +0 -0
  50. data/{GosuImpl → src}/Iconv.hpp +0 -0
  51. data/{GosuImpl → src}/Input/AccelerometerReader.hpp +0 -0
  52. data/{GosuImpl → src}/Input/AccelerometerReader.mm +0 -0
  53. data/{GosuImpl → src/Input}/Input.cpp +0 -0
  54. data/{GosuImpl → src/Input}/InputTouch.mm +0 -0
  55. data/{GosuImpl → src/Input}/TextInput.cpp +0 -0
  56. data/{GosuImpl → src/Input}/TextInputMac.mm +0 -0
  57. data/{GosuImpl → src}/Inspection.cpp +0 -0
  58. data/{GosuImpl → src}/MacUtility.hpp +0 -0
  59. data/{GosuImpl → src}/Math.cpp +0 -0
  60. data/{GosuImpl → src}/Sockets/CommSocket.cpp +0 -0
  61. data/{GosuImpl → src}/Sockets/ListenerSocket.cpp +0 -0
  62. data/{GosuImpl → src}/Sockets/MessageSocket.cpp +0 -0
  63. data/{GosuImpl → src}/Sockets/Socket.cpp +0 -0
  64. data/{GosuImpl → src}/Sockets/Socket.hpp +0 -0
  65. data/{GosuImpl/Graphics → src/Text}/Font.cpp +1 -1
  66. data/{GosuImpl/Graphics → src/Text}/FormattedString.hpp +0 -0
  67. data/{GosuImpl/Graphics → src/Text}/Text.cpp +1 -1
  68. data/{GosuImpl/Graphics/TextTouch.mm → src/Text/TextApple.mm} +0 -0
  69. data/{GosuImpl/Graphics → src/Text}/TextMac.cpp +1 -1
  70. data/{GosuImpl/Graphics → src/Text}/TextTTFWin.cpp +0 -0
  71. data/{GosuImpl/Graphics → src/Text}/TextUnix.cpp +0 -0
  72. data/{GosuImpl/Graphics → src/Text}/TextWin.cpp +0 -0
  73. data/{GosuImpl → src}/TimingApple.cpp +0 -0
  74. data/{GosuImpl → src}/TimingUnix.cpp +0 -0
  75. data/{GosuImpl → src}/TimingWin.cpp +0 -0
  76. data/{GosuImpl → src}/Utility.cpp +0 -0
  77. data/{GosuImpl → src}/UtilityApple.mm +0 -0
  78. data/{GosuImpl → src}/UtilityWin.cpp +0 -0
  79. data/{GosuImpl → src}/WinMain.cpp +0 -0
  80. data/{GosuImpl → src}/WinUtility.cpp +0 -0
  81. data/{GosuImpl → src}/Window.cpp +0 -0
  82. data/{GosuImpl → src}/WindowTouch.mm +0 -0
  83. data/{GosuImpl → src}/X11vroot.h +0 -0
  84. metadata +97 -193
  85. data/.yardopts +0 -1
  86. data/COPYING +0 -29
  87. data/GosuImpl/InputMac.mm +0 -733
  88. data/GosuImpl/InputWin.cpp +0 -483
  89. data/GosuImpl/InputX.cpp +0 -243
  90. data/GosuImpl/RubyGosu.swg +0 -821
  91. data/GosuImpl/RubyGosu_SWIG_GC_PATCH.patch +0 -126
  92. data/GosuImpl/RubyGosu_SWIG_RENAME_PATCH.patch +0 -62
  93. data/GosuImpl/TextInputWin.cpp +0 -211
  94. data/GosuImpl/TextInputX.cpp +0 -217
  95. data/GosuImpl/WindowWin.cpp +0 -534
  96. data/GosuImpl/WindowX.cpp +0 -458
  97. data/README.txt +0 -25
  98. data/dependencies/libogg/AUTHORS +0 -4
  99. data/dependencies/libogg/CHANGES +0 -70
  100. data/dependencies/libogg/COPYING +0 -28
  101. data/dependencies/libogg/include/ogg/ogg.h +0 -209
  102. data/dependencies/libogg/include/ogg/os_types.h +0 -147
  103. data/dependencies/libogg/src/bitwise.c +0 -857
  104. data/dependencies/libogg/src/framing.c +0 -2089
  105. data/dependencies/libvorbis/AUTHORS +0 -3
  106. data/dependencies/libvorbis/CHANGES +0 -126
  107. data/dependencies/libvorbis/COPYING +0 -28
  108. data/dependencies/libvorbis/include/vorbis/codec.h +0 -243
  109. data/dependencies/libvorbis/include/vorbis/vorbisenc.h +0 -436
  110. data/dependencies/libvorbis/include/vorbis/vorbisfile.h +0 -206
  111. data/dependencies/libvorbis/lib/analysis.c +0 -120
  112. data/dependencies/libvorbis/lib/backends.h +0 -144
  113. data/dependencies/libvorbis/lib/barkmel.c +0 -64
  114. data/dependencies/libvorbis/lib/bitrate.c +0 -253
  115. data/dependencies/libvorbis/lib/bitrate.h +0 -59
  116. data/dependencies/libvorbis/lib/block.c +0 -1046
  117. data/dependencies/libvorbis/lib/books/coupled/res_books_51.h +0 -12257
  118. data/dependencies/libvorbis/lib/books/coupled/res_books_stereo.h +0 -15783
  119. data/dependencies/libvorbis/lib/books/floor/floor_books.h +0 -1547
  120. data/dependencies/libvorbis/lib/books/uncoupled/res_books_uncoupled.h +0 -7758
  121. data/dependencies/libvorbis/lib/codebook.c +0 -479
  122. data/dependencies/libvorbis/lib/codebook.h +0 -119
  123. data/dependencies/libvorbis/lib/codec_internal.h +0 -167
  124. data/dependencies/libvorbis/lib/envelope.c +0 -375
  125. data/dependencies/libvorbis/lib/envelope.h +0 -80
  126. data/dependencies/libvorbis/lib/floor0.c +0 -222
  127. data/dependencies/libvorbis/lib/floor1.c +0 -1099
  128. data/dependencies/libvorbis/lib/highlevel.h +0 -58
  129. data/dependencies/libvorbis/lib/info.c +0 -664
  130. data/dependencies/libvorbis/lib/lookup.c +0 -94
  131. data/dependencies/libvorbis/lib/lookup.h +0 -32
  132. data/dependencies/libvorbis/lib/lookup_data.h +0 -192
  133. data/dependencies/libvorbis/lib/lpc.c +0 -160
  134. data/dependencies/libvorbis/lib/lpc.h +0 -29
  135. data/dependencies/libvorbis/lib/lsp.c +0 -456
  136. data/dependencies/libvorbis/lib/lsp.h +0 -28
  137. data/dependencies/libvorbis/lib/mapping0.c +0 -816
  138. data/dependencies/libvorbis/lib/masking.h +0 -785
  139. data/dependencies/libvorbis/lib/mdct.c +0 -563
  140. data/dependencies/libvorbis/lib/mdct.h +0 -71
  141. data/dependencies/libvorbis/lib/misc.h +0 -57
  142. data/dependencies/libvorbis/lib/modes/floor_all.h +0 -260
  143. data/dependencies/libvorbis/lib/modes/psych_11.h +0 -51
  144. data/dependencies/libvorbis/lib/modes/psych_16.h +0 -133
  145. data/dependencies/libvorbis/lib/modes/psych_44.h +0 -642
  146. data/dependencies/libvorbis/lib/modes/psych_8.h +0 -101
  147. data/dependencies/libvorbis/lib/modes/residue_16.h +0 -163
  148. data/dependencies/libvorbis/lib/modes/residue_44.h +0 -292
  149. data/dependencies/libvorbis/lib/modes/residue_44p51.h +0 -451
  150. data/dependencies/libvorbis/lib/modes/residue_44u.h +0 -318
  151. data/dependencies/libvorbis/lib/modes/residue_8.h +0 -109
  152. data/dependencies/libvorbis/lib/modes/setup_11.h +0 -143
  153. data/dependencies/libvorbis/lib/modes/setup_16.h +0 -153
  154. data/dependencies/libvorbis/lib/modes/setup_22.h +0 -128
  155. data/dependencies/libvorbis/lib/modes/setup_32.h +0 -132
  156. data/dependencies/libvorbis/lib/modes/setup_44.h +0 -117
  157. data/dependencies/libvorbis/lib/modes/setup_44p51.h +0 -74
  158. data/dependencies/libvorbis/lib/modes/setup_44u.h +0 -74
  159. data/dependencies/libvorbis/lib/modes/setup_8.h +0 -149
  160. data/dependencies/libvorbis/lib/modes/setup_X.h +0 -225
  161. data/dependencies/libvorbis/lib/os.h +0 -186
  162. data/dependencies/libvorbis/lib/psy.c +0 -1203
  163. data/dependencies/libvorbis/lib/psy.h +0 -154
  164. data/dependencies/libvorbis/lib/psytune.c +0 -524
  165. data/dependencies/libvorbis/lib/registry.c +0 -45
  166. data/dependencies/libvorbis/lib/registry.h +0 -32
  167. data/dependencies/libvorbis/lib/res0.c +0 -889
  168. data/dependencies/libvorbis/lib/scales.h +0 -90
  169. data/dependencies/libvorbis/lib/sharedbook.c +0 -579
  170. data/dependencies/libvorbis/lib/smallft.c +0 -1255
  171. data/dependencies/libvorbis/lib/smallft.h +0 -34
  172. data/dependencies/libvorbis/lib/synthesis.c +0 -184
  173. data/dependencies/libvorbis/lib/tone.c +0 -54
  174. data/dependencies/libvorbis/lib/vorbisenc.c +0 -1215
  175. data/dependencies/libvorbis/lib/vorbisfile.c +0 -2337
  176. data/dependencies/libvorbis/lib/window.c +0 -2135
  177. data/dependencies/libvorbis/lib/window.h +0 -26
  178. data/dependencies/ogg_vorbis.license +0 -28
  179. data/reference/gosu.rb +0 -1284
@@ -1,2337 +0,0 @@
1
- /********************************************************************
2
- * *
3
- * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5
- * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6
- * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
7
- * *
8
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
9
- * by the Xiph.Org Foundation http://www.xiph.org/ *
10
- * *
11
- ********************************************************************
12
-
13
- function: stdio-based convenience library for opening/seeking/decoding
14
- last mod: $Id: vorbisfile.c 17573 2010-10-27 14:53:59Z xiphmont $
15
-
16
- ********************************************************************/
17
-
18
- #include <stdlib.h>
19
- #include <stdio.h>
20
- #include <errno.h>
21
- #include <string.h>
22
- #include <math.h>
23
-
24
- #include "vorbis/codec.h"
25
-
26
- /* we don't need or want the static callback symbols here */
27
- #define OV_EXCLUDE_STATIC_CALLBACKS
28
- #include "vorbis/vorbisfile.h"
29
-
30
- #include "os.h"
31
- #include "misc.h"
32
-
33
- /* A 'chained bitstream' is a Vorbis bitstream that contains more than
34
- one logical bitstream arranged end to end (the only form of Ogg
35
- multiplexing allowed in a Vorbis bitstream; grouping [parallel
36
- multiplexing] is not allowed in Vorbis) */
37
-
38
- /* A Vorbis file can be played beginning to end (streamed) without
39
- worrying ahead of time about chaining (see decoder_example.c). If
40
- we have the whole file, however, and want random access
41
- (seeking/scrubbing) or desire to know the total length/time of a
42
- file, we need to account for the possibility of chaining. */
43
-
44
- /* We can handle things a number of ways; we can determine the entire
45
- bitstream structure right off the bat, or find pieces on demand.
46
- This example determines and caches structure for the entire
47
- bitstream, but builds a virtual decoder on the fly when moving
48
- between links in the chain. */
49
-
50
- /* There are also different ways to implement seeking. Enough
51
- information exists in an Ogg bitstream to seek to
52
- sample-granularity positions in the output. Or, one can seek by
53
- picking some portion of the stream roughly in the desired area if
54
- we only want coarse navigation through the stream. */
55
-
56
- /*************************************************************************
57
- * Many, many internal helpers. The intention is not to be confusing;
58
- * rampant duplication and monolithic function implementation would be
59
- * harder to understand anyway. The high level functions are last. Begin
60
- * grokking near the end of the file */
61
-
62
- /* read a little more data from the file/pipe into the ogg_sync framer
63
- */
64
- #define CHUNKSIZE 65536 /* greater-than-page-size granularity seeking */
65
- #define READSIZE 2048 /* a smaller read size is needed for low-rate streaming. */
66
-
67
- static long _get_data(OggVorbis_File *vf){
68
- errno=0;
69
- if(!(vf->callbacks.read_func))return(-1);
70
- if(vf->datasource){
71
- char *buffer=ogg_sync_buffer(&vf->oy,READSIZE);
72
- long bytes=(vf->callbacks.read_func)(buffer,1,READSIZE,vf->datasource);
73
- if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
74
- if(bytes==0 && errno)return(-1);
75
- return(bytes);
76
- }else
77
- return(0);
78
- }
79
-
80
- /* save a tiny smidge of verbosity to make the code more readable */
81
- static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
82
- if(vf->datasource){
83
- if(!(vf->callbacks.seek_func)||
84
- (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1)
85
- return OV_EREAD;
86
- vf->offset=offset;
87
- ogg_sync_reset(&vf->oy);
88
- }else{
89
- /* shouldn't happen unless someone writes a broken callback */
90
- return OV_EFAULT;
91
- }
92
- return 0;
93
- }
94
-
95
- /* The read/seek functions track absolute position within the stream */
96
-
97
- /* from the head of the stream, get the next page. boundary specifies
98
- if the function is allowed to fetch more data from the stream (and
99
- how much) or only use internally buffered data.
100
-
101
- boundary: -1) unbounded search
102
- 0) read no additional data; use cached only
103
- n) search for a new page beginning for n bytes
104
-
105
- return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
106
- n) found a page at absolute offset n */
107
-
108
- static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
109
- ogg_int64_t boundary){
110
- if(boundary>0)boundary+=vf->offset;
111
- while(1){
112
- long more;
113
-
114
- if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
115
- more=ogg_sync_pageseek(&vf->oy,og);
116
-
117
- if(more<0){
118
- /* skipped n bytes */
119
- vf->offset-=more;
120
- }else{
121
- if(more==0){
122
- /* send more paramedics */
123
- if(!boundary)return(OV_FALSE);
124
- {
125
- long ret=_get_data(vf);
126
- if(ret==0)return(OV_EOF);
127
- if(ret<0)return(OV_EREAD);
128
- }
129
- }else{
130
- /* got a page. Return the offset at the page beginning,
131
- advance the internal offset past the page end */
132
- ogg_int64_t ret=vf->offset;
133
- vf->offset+=more;
134
- return(ret);
135
-
136
- }
137
- }
138
- }
139
- }
140
-
141
- /* find the latest page beginning before the current stream cursor
142
- position. Much dirtier than the above as Ogg doesn't have any
143
- backward search linkage. no 'readp' as it will certainly have to
144
- read. */
145
- /* returns offset or OV_EREAD, OV_FAULT */
146
- static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
147
- ogg_int64_t begin=vf->offset;
148
- ogg_int64_t end=begin;
149
- ogg_int64_t ret;
150
- ogg_int64_t offset=-1;
151
-
152
- while(offset==-1){
153
- begin-=CHUNKSIZE;
154
- if(begin<0)
155
- begin=0;
156
-
157
- ret=_seek_helper(vf,begin);
158
- if(ret)return(ret);
159
-
160
- while(vf->offset<end){
161
- memset(og,0,sizeof(*og));
162
- ret=_get_next_page(vf,og,end-vf->offset);
163
- if(ret==OV_EREAD)return(OV_EREAD);
164
- if(ret<0){
165
- break;
166
- }else{
167
- offset=ret;
168
- }
169
- }
170
- }
171
-
172
- /* In a fully compliant, non-multiplexed stream, we'll still be
173
- holding the last page. In multiplexed (or noncompliant streams),
174
- we will probably have to re-read the last page we saw */
175
- if(og->header_len==0){
176
- ret=_seek_helper(vf,offset);
177
- if(ret)return(ret);
178
-
179
- ret=_get_next_page(vf,og,CHUNKSIZE);
180
- if(ret<0)
181
- /* this shouldn't be possible */
182
- return(OV_EFAULT);
183
- }
184
-
185
- return(offset);
186
- }
187
-
188
- static void _add_serialno(ogg_page *og,long **serialno_list, int *n){
189
- long s = ogg_page_serialno(og);
190
- (*n)++;
191
-
192
- if(*serialno_list){
193
- *serialno_list = _ogg_realloc(*serialno_list, sizeof(**serialno_list)*(*n));
194
- }else{
195
- *serialno_list = _ogg_malloc(sizeof(**serialno_list));
196
- }
197
-
198
- (*serialno_list)[(*n)-1] = s;
199
- }
200
-
201
- /* returns nonzero if found */
202
- static int _lookup_serialno(long s, long *serialno_list, int n){
203
- if(serialno_list){
204
- while(n--){
205
- if(*serialno_list == s) return 1;
206
- serialno_list++;
207
- }
208
- }
209
- return 0;
210
- }
211
-
212
- static int _lookup_page_serialno(ogg_page *og, long *serialno_list, int n){
213
- long s = ogg_page_serialno(og);
214
- return _lookup_serialno(s,serialno_list,n);
215
- }
216
-
217
- /* performs the same search as _get_prev_page, but prefers pages of
218
- the specified serial number. If a page of the specified serialno is
219
- spotted during the seek-back-and-read-forward, it will return the
220
- info of last page of the matching serial number instead of the very
221
- last page. If no page of the specified serialno is seen, it will
222
- return the info of last page and alter *serialno. */
223
- static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
224
- long *serial_list, int serial_n,
225
- int *serialno, ogg_int64_t *granpos){
226
- ogg_page og;
227
- ogg_int64_t begin=vf->offset;
228
- ogg_int64_t end=begin;
229
- ogg_int64_t ret;
230
-
231
- ogg_int64_t prefoffset=-1;
232
- ogg_int64_t offset=-1;
233
- ogg_int64_t ret_serialno=-1;
234
- ogg_int64_t ret_gran=-1;
235
-
236
- while(offset==-1){
237
- begin-=CHUNKSIZE;
238
- if(begin<0)
239
- begin=0;
240
-
241
- ret=_seek_helper(vf,begin);
242
- if(ret)return(ret);
243
-
244
- while(vf->offset<end){
245
- ret=_get_next_page(vf,&og,end-vf->offset);
246
- if(ret==OV_EREAD)return(OV_EREAD);
247
- if(ret<0){
248
- break;
249
- }else{
250
- ret_serialno=ogg_page_serialno(&og);
251
- ret_gran=ogg_page_granulepos(&og);
252
- offset=ret;
253
-
254
- if(ret_serialno == *serialno){
255
- prefoffset=ret;
256
- *granpos=ret_gran;
257
- }
258
-
259
- if(!_lookup_serialno(ret_serialno,serial_list,serial_n)){
260
- /* we fell off the end of the link, which means we seeked
261
- back too far and shouldn't have been looking in that link
262
- to begin with. If we found the preferred serial number,
263
- forget that we saw it. */
264
- prefoffset=-1;
265
- }
266
- }
267
- }
268
- }
269
-
270
- /* we're not interested in the page... just the serialno and granpos. */
271
- if(prefoffset>=0)return(prefoffset);
272
-
273
- *serialno = ret_serialno;
274
- *granpos = ret_gran;
275
- return(offset);
276
-
277
- }
278
-
279
- /* uses the local ogg_stream storage in vf; this is important for
280
- non-streaming input sources */
281
- static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
282
- long **serialno_list, int *serialno_n,
283
- ogg_page *og_ptr){
284
- ogg_page og;
285
- ogg_packet op;
286
- int i,ret;
287
- int allbos=0;
288
-
289
- if(!og_ptr){
290
- ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
291
- if(llret==OV_EREAD)return(OV_EREAD);
292
- if(llret<0)return(OV_ENOTVORBIS);
293
- og_ptr=&og;
294
- }
295
-
296
- vorbis_info_init(vi);
297
- vorbis_comment_init(vc);
298
- vf->ready_state=OPENED;
299
-
300
- /* extract the serialnos of all BOS pages + the first set of vorbis
301
- headers we see in the link */
302
-
303
- while(ogg_page_bos(og_ptr)){
304
- if(serialno_list){
305
- if(_lookup_page_serialno(og_ptr,*serialno_list,*serialno_n)){
306
- /* a dupe serialnumber in an initial header packet set == invalid stream */
307
- if(*serialno_list)_ogg_free(*serialno_list);
308
- *serialno_list=0;
309
- *serialno_n=0;
310
- ret=OV_EBADHEADER;
311
- goto bail_header;
312
- }
313
-
314
- _add_serialno(og_ptr,serialno_list,serialno_n);
315
- }
316
-
317
- if(vf->ready_state<STREAMSET){
318
- /* we don't have a vorbis stream in this link yet, so begin
319
- prospective stream setup. We need a stream to get packets */
320
- ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
321
- ogg_stream_pagein(&vf->os,og_ptr);
322
-
323
- if(ogg_stream_packetout(&vf->os,&op) > 0 &&
324
- vorbis_synthesis_idheader(&op)){
325
- /* vorbis header; continue setup */
326
- vf->ready_state=STREAMSET;
327
- if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
328
- ret=OV_EBADHEADER;
329
- goto bail_header;
330
- }
331
- }
332
- }
333
-
334
- /* get next page */
335
- {
336
- ogg_int64_t llret=_get_next_page(vf,og_ptr,CHUNKSIZE);
337
- if(llret==OV_EREAD){
338
- ret=OV_EREAD;
339
- goto bail_header;
340
- }
341
- if(llret<0){
342
- ret=OV_ENOTVORBIS;
343
- goto bail_header;
344
- }
345
-
346
- /* if this page also belongs to our vorbis stream, submit it and break */
347
- if(vf->ready_state==STREAMSET &&
348
- vf->os.serialno == ogg_page_serialno(og_ptr)){
349
- ogg_stream_pagein(&vf->os,og_ptr);
350
- break;
351
- }
352
- }
353
- }
354
-
355
- if(vf->ready_state!=STREAMSET){
356
- ret = OV_ENOTVORBIS;
357
- goto bail_header;
358
- }
359
-
360
- while(1){
361
-
362
- i=0;
363
- while(i<2){ /* get a page loop */
364
-
365
- while(i<2){ /* get a packet loop */
366
-
367
- int result=ogg_stream_packetout(&vf->os,&op);
368
- if(result==0)break;
369
- if(result==-1){
370
- ret=OV_EBADHEADER;
371
- goto bail_header;
372
- }
373
-
374
- if((ret=vorbis_synthesis_headerin(vi,vc,&op)))
375
- goto bail_header;
376
-
377
- i++;
378
- }
379
-
380
- while(i<2){
381
- if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
382
- ret=OV_EBADHEADER;
383
- goto bail_header;
384
- }
385
-
386
- /* if this page belongs to the correct stream, go parse it */
387
- if(vf->os.serialno == ogg_page_serialno(og_ptr)){
388
- ogg_stream_pagein(&vf->os,og_ptr);
389
- break;
390
- }
391
-
392
- /* if we never see the final vorbis headers before the link
393
- ends, abort */
394
- if(ogg_page_bos(og_ptr)){
395
- if(allbos){
396
- ret = OV_EBADHEADER;
397
- goto bail_header;
398
- }else
399
- allbos=1;
400
- }
401
-
402
- /* otherwise, keep looking */
403
- }
404
- }
405
-
406
- return 0;
407
- }
408
-
409
- bail_header:
410
- vorbis_info_clear(vi);
411
- vorbis_comment_clear(vc);
412
- vf->ready_state=OPENED;
413
-
414
- return ret;
415
- }
416
-
417
- /* Starting from current cursor position, get initial PCM offset of
418
- next page. Consumes the page in the process without decoding
419
- audio, however this is only called during stream parsing upon
420
- seekable open. */
421
- static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
422
- ogg_page og;
423
- ogg_int64_t accumulated=0;
424
- long lastblock=-1;
425
- int result;
426
- int serialno = vf->os.serialno;
427
-
428
- while(1){
429
- ogg_packet op;
430
- if(_get_next_page(vf,&og,-1)<0)
431
- break; /* should not be possible unless the file is truncated/mangled */
432
-
433
- if(ogg_page_bos(&og)) break;
434
- if(ogg_page_serialno(&og)!=serialno) continue;
435
-
436
- /* count blocksizes of all frames in the page */
437
- ogg_stream_pagein(&vf->os,&og);
438
- while((result=ogg_stream_packetout(&vf->os,&op))){
439
- if(result>0){ /* ignore holes */
440
- long thisblock=vorbis_packet_blocksize(vi,&op);
441
- if(lastblock!=-1)
442
- accumulated+=(lastblock+thisblock)>>2;
443
- lastblock=thisblock;
444
- }
445
- }
446
-
447
- if(ogg_page_granulepos(&og)!=-1){
448
- /* pcm offset of last packet on the first audio page */
449
- accumulated= ogg_page_granulepos(&og)-accumulated;
450
- break;
451
- }
452
- }
453
-
454
- /* less than zero? Either a corrupt file or a stream with samples
455
- trimmed off the beginning, a normal occurrence; in both cases set
456
- the offset to zero */
457
- if(accumulated<0)accumulated=0;
458
-
459
- return accumulated;
460
- }
461
-
462
- /* finds each bitstream link one at a time using a bisection search
463
- (has to begin by knowing the offset of the lb's initial page).
464
- Recurses for each link so it can alloc the link storage after
465
- finding them all, then unroll and fill the cache at the same time */
466
- static int _bisect_forward_serialno(OggVorbis_File *vf,
467
- ogg_int64_t begin,
468
- ogg_int64_t searched,
469
- ogg_int64_t end,
470
- ogg_int64_t endgran,
471
- int endserial,
472
- long *currentno_list,
473
- int currentnos,
474
- long m){
475
- ogg_int64_t pcmoffset;
476
- ogg_int64_t dataoffset=searched;
477
- ogg_int64_t endsearched=end;
478
- ogg_int64_t next=end;
479
- ogg_int64_t searchgran=-1;
480
- ogg_page og;
481
- ogg_int64_t ret,last;
482
- int serialno = vf->os.serialno;
483
-
484
- /* invariants:
485
- we have the headers and serialnos for the link beginning at 'begin'
486
- we have the offset and granpos of the last page in the file (potentially
487
- not a page we care about)
488
- */
489
-
490
- /* Is the last page in our list of current serialnumbers? */
491
- if(_lookup_serialno(endserial,currentno_list,currentnos)){
492
-
493
- /* last page is in the starting serialno list, so we've bisected
494
- down to (or just started with) a single link. Now we need to
495
- find the last vorbis page belonging to the first vorbis stream
496
- for this link. */
497
-
498
- while(endserial != serialno){
499
- endserial = serialno;
500
- vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&endserial,&endgran);
501
- }
502
-
503
- vf->links=m+1;
504
- if(vf->offsets)_ogg_free(vf->offsets);
505
- if(vf->serialnos)_ogg_free(vf->serialnos);
506
- if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
507
-
508
- vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
509
- vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
510
- vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
511
- vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
512
- vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
513
- vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
514
-
515
- vf->offsets[m+1]=end;
516
- vf->offsets[m]=begin;
517
- vf->pcmlengths[m*2+1]=(endgran<0?0:endgran);
518
-
519
- }else{
520
-
521
- long *next_serialno_list=NULL;
522
- int next_serialnos=0;
523
- vorbis_info vi;
524
- vorbis_comment vc;
525
-
526
- /* the below guards against garbage seperating the last and
527
- first pages of two links. */
528
- while(searched<endsearched){
529
- ogg_int64_t bisect;
530
-
531
- if(endsearched-searched<CHUNKSIZE){
532
- bisect=searched;
533
- }else{
534
- bisect=(searched+endsearched)/2;
535
- }
536
-
537
- if(bisect != vf->offset){
538
- ret=_seek_helper(vf,bisect);
539
- if(ret)return(ret);
540
- }
541
-
542
- last=_get_next_page(vf,&og,-1);
543
- if(last==OV_EREAD)return(OV_EREAD);
544
- if(last<0 || !_lookup_page_serialno(&og,currentno_list,currentnos)){
545
- endsearched=bisect;
546
- if(last>=0)next=last;
547
- }else{
548
- searched=vf->offset;
549
- }
550
- }
551
-
552
- /* Bisection point found */
553
-
554
- /* for the time being, fetch end PCM offset the simple way */
555
- {
556
- int testserial = serialno+1;
557
- vf->offset = next;
558
- while(testserial != serialno){
559
- testserial = serialno;
560
- vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&testserial,&searchgran);
561
- }
562
- }
563
-
564
- if(vf->offset!=next){
565
- ret=_seek_helper(vf,next);
566
- if(ret)return(ret);
567
- }
568
-
569
- ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL);
570
- if(ret)return(ret);
571
- serialno = vf->os.serialno;
572
- dataoffset = vf->offset;
573
-
574
- /* this will consume a page, however the next bistection always
575
- starts with a raw seek */
576
- pcmoffset = _initial_pcmoffset(vf,&vi);
577
-
578
- ret=_bisect_forward_serialno(vf,next,vf->offset,end,endgran,endserial,
579
- next_serialno_list,next_serialnos,m+1);
580
- if(ret)return(ret);
581
-
582
- if(next_serialno_list)_ogg_free(next_serialno_list);
583
-
584
- vf->offsets[m+1]=next;
585
- vf->serialnos[m+1]=serialno;
586
- vf->dataoffsets[m+1]=dataoffset;
587
-
588
- vf->vi[m+1]=vi;
589
- vf->vc[m+1]=vc;
590
-
591
- vf->pcmlengths[m*2+1]=searchgran;
592
- vf->pcmlengths[m*2+2]=pcmoffset;
593
- vf->pcmlengths[m*2+3]-=pcmoffset;
594
- if(vf->pcmlengths[m*2+3]<0)vf->pcmlengths[m*2+3]=0;
595
- }
596
- return(0);
597
- }
598
-
599
- static int _make_decode_ready(OggVorbis_File *vf){
600
- if(vf->ready_state>STREAMSET)return 0;
601
- if(vf->ready_state<STREAMSET)return OV_EFAULT;
602
- if(vf->seekable){
603
- if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link))
604
- return OV_EBADLINK;
605
- }else{
606
- if(vorbis_synthesis_init(&vf->vd,vf->vi))
607
- return OV_EBADLINK;
608
- }
609
- vorbis_block_init(&vf->vd,&vf->vb);
610
- vf->ready_state=INITSET;
611
- vf->bittrack=0.f;
612
- vf->samptrack=0.f;
613
- return 0;
614
- }
615
-
616
- static int _open_seekable2(OggVorbis_File *vf){
617
- ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1;
618
- int endserial=vf->os.serialno;
619
- int serialno=vf->os.serialno;
620
-
621
- /* we're partially open and have a first link header state in
622
- storage in vf */
623
-
624
- /* fetch initial PCM offset */
625
- ogg_int64_t pcmoffset = _initial_pcmoffset(vf,vf->vi);
626
-
627
- /* we can seek, so set out learning all about this file */
628
- if(vf->callbacks.seek_func && vf->callbacks.tell_func){
629
- (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
630
- vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
631
- }else{
632
- vf->offset=vf->end=-1;
633
- }
634
-
635
- /* If seek_func is implemented, tell_func must also be implemented */
636
- if(vf->end==-1) return(OV_EINVAL);
637
-
638
- /* Get the offset of the last page of the physical bitstream, or, if
639
- we're lucky the last vorbis page of this link as most OggVorbis
640
- files will contain a single logical bitstream */
641
- end=_get_prev_page_serial(vf,vf->serialnos+2,vf->serialnos[1],&endserial,&endgran);
642
- if(end<0)return(end);
643
-
644
- /* now determine bitstream structure recursively */
645
- if(_bisect_forward_serialno(vf,0,dataoffset,vf->offset,endgran,endserial,
646
- vf->serialnos+2,vf->serialnos[1],0)<0)return(OV_EREAD);
647
-
648
- vf->offsets[0]=0;
649
- vf->serialnos[0]=serialno;
650
- vf->dataoffsets[0]=dataoffset;
651
- vf->pcmlengths[0]=pcmoffset;
652
- vf->pcmlengths[1]-=pcmoffset;
653
- if(vf->pcmlengths[1]<0)vf->pcmlengths[1]=0;
654
-
655
- return(ov_raw_seek(vf,dataoffset));
656
- }
657
-
658
- /* clear out the current logical bitstream decoder */
659
- static void _decode_clear(OggVorbis_File *vf){
660
- vorbis_dsp_clear(&vf->vd);
661
- vorbis_block_clear(&vf->vb);
662
- vf->ready_state=OPENED;
663
- }
664
-
665
- /* fetch and process a packet. Handles the case where we're at a
666
- bitstream boundary and dumps the decoding machine. If the decoding
667
- machine is unloaded, it loads it. It also keeps pcm_offset up to
668
- date (seek and read both use this. seek uses a special hack with
669
- readp).
670
-
671
- return: <0) error, OV_HOLE (lost packet) or OV_EOF
672
- 0) need more data (only if readp==0)
673
- 1) got a packet
674
- */
675
-
676
- static int _fetch_and_process_packet(OggVorbis_File *vf,
677
- ogg_packet *op_in,
678
- int readp,
679
- int spanp){
680
- ogg_page og;
681
-
682
- /* handle one packet. Try to fetch it from current stream state */
683
- /* extract packets from page */
684
- while(1){
685
-
686
- if(vf->ready_state==STREAMSET){
687
- int ret=_make_decode_ready(vf);
688
- if(ret<0)return ret;
689
- }
690
-
691
- /* process a packet if we can. */
692
-
693
- if(vf->ready_state==INITSET){
694
- int hs=vorbis_synthesis_halfrate_p(vf->vi);
695
-
696
- while(1) {
697
- ogg_packet op;
698
- ogg_packet *op_ptr=(op_in?op_in:&op);
699
- int result=ogg_stream_packetout(&vf->os,op_ptr);
700
- ogg_int64_t granulepos;
701
-
702
- op_in=NULL;
703
- if(result==-1)return(OV_HOLE); /* hole in the data. */
704
- if(result>0){
705
- /* got a packet. process it */
706
- granulepos=op_ptr->granulepos;
707
- if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy
708
- header handling. The
709
- header packets aren't
710
- audio, so if/when we
711
- submit them,
712
- vorbis_synthesis will
713
- reject them */
714
-
715
- /* suck in the synthesis data and track bitrate */
716
- {
717
- int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
718
- /* for proper use of libvorbis within libvorbisfile,
719
- oldsamples will always be zero. */
720
- if(oldsamples)return(OV_EFAULT);
721
-
722
- vorbis_synthesis_blockin(&vf->vd,&vf->vb);
723
- vf->samptrack+=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs);
724
- vf->bittrack+=op_ptr->bytes*8;
725
- }
726
-
727
- /* update the pcm offset. */
728
- if(granulepos!=-1 && !op_ptr->e_o_s){
729
- int link=(vf->seekable?vf->current_link:0);
730
- int i,samples;
731
-
732
- /* this packet has a pcm_offset on it (the last packet
733
- completed on a page carries the offset) After processing
734
- (above), we know the pcm position of the *last* sample
735
- ready to be returned. Find the offset of the *first*
736
-
737
- As an aside, this trick is inaccurate if we begin
738
- reading anew right at the last page; the end-of-stream
739
- granulepos declares the last frame in the stream, and the
740
- last packet of the last page may be a partial frame.
741
- So, we need a previous granulepos from an in-sequence page
742
- to have a reference point. Thus the !op_ptr->e_o_s clause
743
- above */
744
-
745
- if(vf->seekable && link>0)
746
- granulepos-=vf->pcmlengths[link*2];
747
- if(granulepos<0)granulepos=0; /* actually, this
748
- shouldn't be possible
749
- here unless the stream
750
- is very broken */
751
-
752
- samples=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs);
753
-
754
- granulepos-=samples;
755
- for(i=0;i<link;i++)
756
- granulepos+=vf->pcmlengths[i*2+1];
757
- vf->pcm_offset=granulepos;
758
- }
759
- return(1);
760
- }
761
- }
762
- else
763
- break;
764
- }
765
- }
766
-
767
- if(vf->ready_state>=OPENED){
768
- ogg_int64_t ret;
769
-
770
- while(1){
771
- /* the loop is not strictly necessary, but there's no sense in
772
- doing the extra checks of the larger loop for the common
773
- case in a multiplexed bistream where the page is simply
774
- part of a different logical bitstream; keep reading until
775
- we get one with the correct serialno */
776
-
777
- if(!readp)return(0);
778
- if((ret=_get_next_page(vf,&og,-1))<0){
779
- return(OV_EOF); /* eof. leave unitialized */
780
- }
781
-
782
- /* bitrate tracking; add the header's bytes here, the body bytes
783
- are done by packet above */
784
- vf->bittrack+=og.header_len*8;
785
-
786
- if(vf->ready_state==INITSET){
787
- if(vf->current_serialno!=ogg_page_serialno(&og)){
788
-
789
- /* two possibilities:
790
- 1) our decoding just traversed a bitstream boundary
791
- 2) another stream is multiplexed into this logical section */
792
-
793
- if(ogg_page_bos(&og)){
794
- /* boundary case */
795
- if(!spanp)
796
- return(OV_EOF);
797
-
798
- _decode_clear(vf);
799
-
800
- if(!vf->seekable){
801
- vorbis_info_clear(vf->vi);
802
- vorbis_comment_clear(vf->vc);
803
- }
804
- break;
805
-
806
- }else
807
- continue; /* possibility #2 */
808
- }
809
- }
810
-
811
- break;
812
- }
813
- }
814
-
815
- /* Do we need to load a new machine before submitting the page? */
816
- /* This is different in the seekable and non-seekable cases.
817
-
818
- In the seekable case, we already have all the header
819
- information loaded and cached; we just initialize the machine
820
- with it and continue on our merry way.
821
-
822
- In the non-seekable (streaming) case, we'll only be at a
823
- boundary if we just left the previous logical bitstream and
824
- we're now nominally at the header of the next bitstream
825
- */
826
-
827
- if(vf->ready_state!=INITSET){
828
- int link;
829
-
830
- if(vf->ready_state<STREAMSET){
831
- if(vf->seekable){
832
- long serialno = ogg_page_serialno(&og);
833
-
834
- /* match the serialno to bitstream section. We use this rather than
835
- offset positions to avoid problems near logical bitstream
836
- boundaries */
837
-
838
- for(link=0;link<vf->links;link++)
839
- if(vf->serialnos[link]==serialno)break;
840
-
841
- if(link==vf->links) continue; /* not the desired Vorbis
842
- bitstream section; keep
843
- trying */
844
-
845
- vf->current_serialno=serialno;
846
- vf->current_link=link;
847
-
848
- ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
849
- vf->ready_state=STREAMSET;
850
-
851
- }else{
852
- /* we're streaming */
853
- /* fetch the three header packets, build the info struct */
854
-
855
- int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og);
856
- if(ret)return(ret);
857
- vf->current_serialno=vf->os.serialno;
858
- vf->current_link++;
859
- link=0;
860
- }
861
- }
862
- }
863
-
864
- /* the buffered page is the data we want, and we're ready for it;
865
- add it to the stream state */
866
- ogg_stream_pagein(&vf->os,&og);
867
-
868
- }
869
- }
870
-
871
- /* if, eg, 64 bit stdio is configured by default, this will build with
872
- fseek64 */
873
- static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
874
- if(f==NULL)return(-1);
875
- return fseek(f,off,whence);
876
- }
877
-
878
- static int _ov_open1(void *f,OggVorbis_File *vf,const char *initial,
879
- long ibytes, ov_callbacks callbacks){
880
- int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1);
881
- long *serialno_list=NULL;
882
- int serialno_list_size=0;
883
- int ret;
884
-
885
- memset(vf,0,sizeof(*vf));
886
- vf->datasource=f;
887
- vf->callbacks = callbacks;
888
-
889
- /* init the framing state */
890
- ogg_sync_init(&vf->oy);
891
-
892
- /* perhaps some data was previously read into a buffer for testing
893
- against other stream types. Allow initialization from this
894
- previously read data (especially as we may be reading from a
895
- non-seekable stream) */
896
- if(initial){
897
- char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
898
- memcpy(buffer,initial,ibytes);
899
- ogg_sync_wrote(&vf->oy,ibytes);
900
- }
901
-
902
- /* can we seek? Stevens suggests the seek test was portable */
903
- if(offsettest!=-1)vf->seekable=1;
904
-
905
- /* No seeking yet; Set up a 'single' (current) logical bitstream
906
- entry for partial open */
907
- vf->links=1;
908
- vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
909
- vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
910
- ogg_stream_init(&vf->os,-1); /* fill in the serialno later */
911
-
912
- /* Fetch all BOS pages, store the vorbis header and all seen serial
913
- numbers, load subsequent vorbis setup headers */
914
- if((ret=_fetch_headers(vf,vf->vi,vf->vc,&serialno_list,&serialno_list_size,NULL))<0){
915
- vf->datasource=NULL;
916
- ov_clear(vf);
917
- }else{
918
- /* serial number list for first link needs to be held somewhere
919
- for second stage of seekable stream open; this saves having to
920
- seek/reread first link's serialnumber data then. */
921
- vf->serialnos=_ogg_calloc(serialno_list_size+2,sizeof(*vf->serialnos));
922
- vf->serialnos[0]=vf->current_serialno=vf->os.serialno;
923
- vf->serialnos[1]=serialno_list_size;
924
- memcpy(vf->serialnos+2,serialno_list,serialno_list_size*sizeof(*vf->serialnos));
925
-
926
- vf->offsets=_ogg_calloc(1,sizeof(*vf->offsets));
927
- vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets));
928
- vf->offsets[0]=0;
929
- vf->dataoffsets[0]=vf->offset;
930
-
931
- vf->ready_state=PARTOPEN;
932
- }
933
- if(serialno_list)_ogg_free(serialno_list);
934
- return(ret);
935
- }
936
-
937
- static int _ov_open2(OggVorbis_File *vf){
938
- if(vf->ready_state != PARTOPEN) return OV_EINVAL;
939
- vf->ready_state=OPENED;
940
- if(vf->seekable){
941
- int ret=_open_seekable2(vf);
942
- if(ret){
943
- vf->datasource=NULL;
944
- ov_clear(vf);
945
- }
946
- return(ret);
947
- }else
948
- vf->ready_state=STREAMSET;
949
-
950
- return 0;
951
- }
952
-
953
-
954
- /* clear out the OggVorbis_File struct */
955
- int ov_clear(OggVorbis_File *vf){
956
- if(vf){
957
- vorbis_block_clear(&vf->vb);
958
- vorbis_dsp_clear(&vf->vd);
959
- ogg_stream_clear(&vf->os);
960
-
961
- if(vf->vi && vf->links){
962
- int i;
963
- for(i=0;i<vf->links;i++){
964
- vorbis_info_clear(vf->vi+i);
965
- vorbis_comment_clear(vf->vc+i);
966
- }
967
- _ogg_free(vf->vi);
968
- _ogg_free(vf->vc);
969
- }
970
- if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
971
- if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
972
- if(vf->serialnos)_ogg_free(vf->serialnos);
973
- if(vf->offsets)_ogg_free(vf->offsets);
974
- ogg_sync_clear(&vf->oy);
975
- if(vf->datasource && vf->callbacks.close_func)
976
- (vf->callbacks.close_func)(vf->datasource);
977
- memset(vf,0,sizeof(*vf));
978
- }
979
- #ifdef DEBUG_LEAKS
980
- _VDBG_dump();
981
- #endif
982
- return(0);
983
- }
984
-
985
- /* inspects the OggVorbis file and finds/documents all the logical
986
- bitstreams contained in it. Tries to be tolerant of logical
987
- bitstream sections that are truncated/woogie.
988
-
989
- return: -1) error
990
- 0) OK
991
- */
992
-
993
- int ov_open_callbacks(void *f,OggVorbis_File *vf,
994
- const char *initial,long ibytes,ov_callbacks callbacks){
995
- int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
996
- if(ret)return ret;
997
- return _ov_open2(vf);
998
- }
999
-
1000
- int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes){
1001
- ov_callbacks callbacks = {
1002
- (size_t (*)(void *, size_t, size_t, void *)) fread,
1003
- (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
1004
- (int (*)(void *)) fclose,
1005
- (long (*)(void *)) ftell
1006
- };
1007
-
1008
- return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
1009
- }
1010
-
1011
- int ov_fopen(const char *path,OggVorbis_File *vf){
1012
- int ret;
1013
- FILE *f = fopen(path,"rb");
1014
- if(!f) return -1;
1015
-
1016
- ret = ov_open(f,vf,NULL,0);
1017
- if(ret) fclose(f);
1018
- return ret;
1019
- }
1020
-
1021
-
1022
- /* cheap hack for game usage where downsampling is desirable; there's
1023
- no need for SRC as we can just do it cheaply in libvorbis. */
1024
-
1025
- int ov_halfrate(OggVorbis_File *vf,int flag){
1026
- int i;
1027
- if(vf->vi==NULL)return OV_EINVAL;
1028
- if(vf->ready_state>STREAMSET){
1029
- /* clear out stream state; dumping the decode machine is needed to
1030
- reinit the MDCT lookups. */
1031
- vorbis_dsp_clear(&vf->vd);
1032
- vorbis_block_clear(&vf->vb);
1033
- vf->ready_state=STREAMSET;
1034
- if(vf->pcm_offset>=0){
1035
- ogg_int64_t pos=vf->pcm_offset;
1036
- vf->pcm_offset=-1; /* make sure the pos is dumped if unseekable */
1037
- ov_pcm_seek(vf,pos);
1038
- }
1039
- }
1040
-
1041
- for(i=0;i<vf->links;i++){
1042
- if(vorbis_synthesis_halfrate(vf->vi+i,flag)){
1043
- if(flag) ov_halfrate(vf,0);
1044
- return OV_EINVAL;
1045
- }
1046
- }
1047
- return 0;
1048
- }
1049
-
1050
- int ov_halfrate_p(OggVorbis_File *vf){
1051
- if(vf->vi==NULL)return OV_EINVAL;
1052
- return vorbis_synthesis_halfrate_p(vf->vi);
1053
- }
1054
-
1055
- /* Only partially open the vorbis file; test for Vorbisness, and load
1056
- the headers for the first chain. Do not seek (although test for
1057
- seekability). Use ov_test_open to finish opening the file, else
1058
- ov_clear to close/free it. Same return codes as open. */
1059
-
1060
- int ov_test_callbacks(void *f,OggVorbis_File *vf,
1061
- const char *initial,long ibytes,ov_callbacks callbacks)
1062
- {
1063
- return _ov_open1(f,vf,initial,ibytes,callbacks);
1064
- }
1065
-
1066
- int ov_test(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes){
1067
- ov_callbacks callbacks = {
1068
- (size_t (*)(void *, size_t, size_t, void *)) fread,
1069
- (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
1070
- (int (*)(void *)) fclose,
1071
- (long (*)(void *)) ftell
1072
- };
1073
-
1074
- return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
1075
- }
1076
-
1077
- int ov_test_open(OggVorbis_File *vf){
1078
- if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
1079
- return _ov_open2(vf);
1080
- }
1081
-
1082
- /* How many logical bitstreams in this physical bitstream? */
1083
- long ov_streams(OggVorbis_File *vf){
1084
- return vf->links;
1085
- }
1086
-
1087
- /* Is the FILE * associated with vf seekable? */
1088
- long ov_seekable(OggVorbis_File *vf){
1089
- return vf->seekable;
1090
- }
1091
-
1092
- /* returns the bitrate for a given logical bitstream or the entire
1093
- physical bitstream. If the file is open for random access, it will
1094
- find the *actual* average bitrate. If the file is streaming, it
1095
- returns the nominal bitrate (if set) else the average of the
1096
- upper/lower bounds (if set) else -1 (unset).
1097
-
1098
- If you want the actual bitrate field settings, get them from the
1099
- vorbis_info structs */
1100
-
1101
- long ov_bitrate(OggVorbis_File *vf,int i){
1102
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1103
- if(i>=vf->links)return(OV_EINVAL);
1104
- if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
1105
- if(i<0){
1106
- ogg_int64_t bits=0;
1107
- int i;
1108
- float br;
1109
- for(i=0;i<vf->links;i++)
1110
- bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
1111
- /* This once read: return(rint(bits/ov_time_total(vf,-1)));
1112
- * gcc 3.x on x86 miscompiled this at optimisation level 2 and above,
1113
- * so this is slightly transformed to make it work.
1114
- */
1115
- br = bits/ov_time_total(vf,-1);
1116
- return(rint(br));
1117
- }else{
1118
- if(vf->seekable){
1119
- /* return the actual bitrate */
1120
- return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i)));
1121
- }else{
1122
- /* return nominal if set */
1123
- if(vf->vi[i].bitrate_nominal>0){
1124
- return vf->vi[i].bitrate_nominal;
1125
- }else{
1126
- if(vf->vi[i].bitrate_upper>0){
1127
- if(vf->vi[i].bitrate_lower>0){
1128
- return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
1129
- }else{
1130
- return vf->vi[i].bitrate_upper;
1131
- }
1132
- }
1133
- return(OV_FALSE);
1134
- }
1135
- }
1136
- }
1137
- }
1138
-
1139
- /* returns the actual bitrate since last call. returns -1 if no
1140
- additional data to offer since last call (or at beginning of stream),
1141
- EINVAL if stream is only partially open
1142
- */
1143
- long ov_bitrate_instant(OggVorbis_File *vf){
1144
- int link=(vf->seekable?vf->current_link:0);
1145
- long ret;
1146
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1147
- if(vf->samptrack==0)return(OV_FALSE);
1148
- ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
1149
- vf->bittrack=0.f;
1150
- vf->samptrack=0.f;
1151
- return(ret);
1152
- }
1153
-
1154
- /* Guess */
1155
- long ov_serialnumber(OggVorbis_File *vf,int i){
1156
- if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
1157
- if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
1158
- if(i<0){
1159
- return(vf->current_serialno);
1160
- }else{
1161
- return(vf->serialnos[i]);
1162
- }
1163
- }
1164
-
1165
- /* returns: total raw (compressed) length of content if i==-1
1166
- raw (compressed) length of that logical bitstream for i==0 to n
1167
- OV_EINVAL if the stream is not seekable (we can't know the length)
1168
- or if stream is only partially open
1169
- */
1170
- ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
1171
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1172
- if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1173
- if(i<0){
1174
- ogg_int64_t acc=0;
1175
- int i;
1176
- for(i=0;i<vf->links;i++)
1177
- acc+=ov_raw_total(vf,i);
1178
- return(acc);
1179
- }else{
1180
- return(vf->offsets[i+1]-vf->offsets[i]);
1181
- }
1182
- }
1183
-
1184
- /* returns: total PCM length (samples) of content if i==-1 PCM length
1185
- (samples) of that logical bitstream for i==0 to n
1186
- OV_EINVAL if the stream is not seekable (we can't know the
1187
- length) or only partially open
1188
- */
1189
- ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
1190
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1191
- if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1192
- if(i<0){
1193
- ogg_int64_t acc=0;
1194
- int i;
1195
- for(i=0;i<vf->links;i++)
1196
- acc+=ov_pcm_total(vf,i);
1197
- return(acc);
1198
- }else{
1199
- return(vf->pcmlengths[i*2+1]);
1200
- }
1201
- }
1202
-
1203
- /* returns: total seconds of content if i==-1
1204
- seconds in that logical bitstream for i==0 to n
1205
- OV_EINVAL if the stream is not seekable (we can't know the
1206
- length) or only partially open
1207
- */
1208
- double ov_time_total(OggVorbis_File *vf,int i){
1209
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1210
- if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1211
- if(i<0){
1212
- double acc=0;
1213
- int i;
1214
- for(i=0;i<vf->links;i++)
1215
- acc+=ov_time_total(vf,i);
1216
- return(acc);
1217
- }else{
1218
- return((double)(vf->pcmlengths[i*2+1])/vf->vi[i].rate);
1219
- }
1220
- }
1221
-
1222
- /* seek to an offset relative to the *compressed* data. This also
1223
- scans packets to update the PCM cursor. It will cross a logical
1224
- bitstream boundary, but only if it can't get any packets out of the
1225
- tail of the bitstream we seek to (so no surprises).
1226
-
1227
- returns zero on success, nonzero on failure */
1228
-
1229
- int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1230
- ogg_stream_state work_os;
1231
- int ret;
1232
-
1233
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1234
- if(!vf->seekable)
1235
- return(OV_ENOSEEK); /* don't dump machine if we can't seek */
1236
-
1237
- if(pos<0 || pos>vf->end)return(OV_EINVAL);
1238
-
1239
- /* is the seek position outside our current link [if any]? */
1240
- if(vf->ready_state>=STREAMSET){
1241
- if(pos<vf->offsets[vf->current_link] || pos>=vf->offsets[vf->current_link+1])
1242
- _decode_clear(vf); /* clear out stream state */
1243
- }
1244
-
1245
- /* don't yet clear out decoding machine (if it's initialized), in
1246
- the case we're in the same link. Restart the decode lapping, and
1247
- let _fetch_and_process_packet deal with a potential bitstream
1248
- boundary */
1249
- vf->pcm_offset=-1;
1250
- ogg_stream_reset_serialno(&vf->os,
1251
- vf->current_serialno); /* must set serialno */
1252
- vorbis_synthesis_restart(&vf->vd);
1253
-
1254
- ret=_seek_helper(vf,pos);
1255
- if(ret)goto seek_error;
1256
-
1257
- /* we need to make sure the pcm_offset is set, but we don't want to
1258
- advance the raw cursor past good packets just to get to the first
1259
- with a granulepos. That's not equivalent behavior to beginning
1260
- decoding as immediately after the seek position as possible.
1261
-
1262
- So, a hack. We use two stream states; a local scratch state and
1263
- the shared vf->os stream state. We use the local state to
1264
- scan, and the shared state as a buffer for later decode.
1265
-
1266
- Unfortuantely, on the last page we still advance to last packet
1267
- because the granulepos on the last page is not necessarily on a
1268
- packet boundary, and we need to make sure the granpos is
1269
- correct.
1270
- */
1271
-
1272
- {
1273
- ogg_page og;
1274
- ogg_packet op;
1275
- int lastblock=0;
1276
- int accblock=0;
1277
- int thisblock=0;
1278
- int lastflag=0;
1279
- int firstflag=0;
1280
- ogg_int64_t pagepos=-1;
1281
-
1282
- ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */
1283
- ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE
1284
- return from not necessarily
1285
- starting from the beginning */
1286
-
1287
- while(1){
1288
- if(vf->ready_state>=STREAMSET){
1289
- /* snarf/scan a packet if we can */
1290
- int result=ogg_stream_packetout(&work_os,&op);
1291
-
1292
- if(result>0){
1293
-
1294
- if(vf->vi[vf->current_link].codec_setup){
1295
- thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1296
- if(thisblock<0){
1297
- ogg_stream_packetout(&vf->os,NULL);
1298
- thisblock=0;
1299
- }else{
1300
-
1301
- /* We can't get a guaranteed correct pcm position out of the
1302
- last page in a stream because it might have a 'short'
1303
- granpos, which can only be detected in the presence of a
1304
- preceding page. However, if the last page is also the first
1305
- page, the granpos rules of a first page take precedence. Not
1306
- only that, but for first==last, the EOS page must be treated
1307
- as if its a normal first page for the stream to open/play. */
1308
- if(lastflag && !firstflag)
1309
- ogg_stream_packetout(&vf->os,NULL);
1310
- else
1311
- if(lastblock)accblock+=(lastblock+thisblock)>>2;
1312
- }
1313
-
1314
- if(op.granulepos!=-1){
1315
- int i,link=vf->current_link;
1316
- ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
1317
- if(granulepos<0)granulepos=0;
1318
-
1319
- for(i=0;i<link;i++)
1320
- granulepos+=vf->pcmlengths[i*2+1];
1321
- vf->pcm_offset=granulepos-accblock;
1322
- if(vf->pcm_offset<0)vf->pcm_offset=0;
1323
- break;
1324
- }
1325
- lastblock=thisblock;
1326
- continue;
1327
- }else
1328
- ogg_stream_packetout(&vf->os,NULL);
1329
- }
1330
- }
1331
-
1332
- if(!lastblock){
1333
- pagepos=_get_next_page(vf,&og,-1);
1334
- if(pagepos<0){
1335
- vf->pcm_offset=ov_pcm_total(vf,-1);
1336
- break;
1337
- }
1338
- }else{
1339
- /* huh? Bogus stream with packets but no granulepos */
1340
- vf->pcm_offset=-1;
1341
- break;
1342
- }
1343
-
1344
- /* has our decoding just traversed a bitstream boundary? */
1345
- if(vf->ready_state>=STREAMSET){
1346
- if(vf->current_serialno!=ogg_page_serialno(&og)){
1347
-
1348
- /* two possibilities:
1349
- 1) our decoding just traversed a bitstream boundary
1350
- 2) another stream is multiplexed into this logical section? */
1351
-
1352
- if(ogg_page_bos(&og)){
1353
- /* we traversed */
1354
- _decode_clear(vf); /* clear out stream state */
1355
- ogg_stream_clear(&work_os);
1356
- } /* else, do nothing; next loop will scoop another page */
1357
- }
1358
- }
1359
-
1360
- if(vf->ready_state<STREAMSET){
1361
- int link;
1362
- long serialno = ogg_page_serialno(&og);
1363
-
1364
- for(link=0;link<vf->links;link++)
1365
- if(vf->serialnos[link]==serialno)break;
1366
-
1367
- if(link==vf->links) continue; /* not the desired Vorbis
1368
- bitstream section; keep
1369
- trying */
1370
- vf->current_link=link;
1371
- vf->current_serialno=serialno;
1372
- ogg_stream_reset_serialno(&vf->os,serialno);
1373
- ogg_stream_reset_serialno(&work_os,serialno);
1374
- vf->ready_state=STREAMSET;
1375
- firstflag=(pagepos<=vf->dataoffsets[link]);
1376
- }
1377
-
1378
- ogg_stream_pagein(&vf->os,&og);
1379
- ogg_stream_pagein(&work_os,&og);
1380
- lastflag=ogg_page_eos(&og);
1381
-
1382
- }
1383
- }
1384
-
1385
- ogg_stream_clear(&work_os);
1386
- vf->bittrack=0.f;
1387
- vf->samptrack=0.f;
1388
- return(0);
1389
-
1390
- seek_error:
1391
- /* dump the machine so we're in a known state */
1392
- vf->pcm_offset=-1;
1393
- ogg_stream_clear(&work_os);
1394
- _decode_clear(vf);
1395
- return OV_EBADLINK;
1396
- }
1397
-
1398
- /* Page granularity seek (faster than sample granularity because we
1399
- don't do the last bit of decode to find a specific sample).
1400
-
1401
- Seek to the last [granule marked] page preceding the specified pos
1402
- location, such that decoding past the returned point will quickly
1403
- arrive at the requested position. */
1404
- int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1405
- int link=-1;
1406
- ogg_int64_t result=0;
1407
- ogg_int64_t total=ov_pcm_total(vf,-1);
1408
-
1409
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1410
- if(!vf->seekable)return(OV_ENOSEEK);
1411
-
1412
- if(pos<0 || pos>total)return(OV_EINVAL);
1413
-
1414
- /* which bitstream section does this pcm offset occur in? */
1415
- for(link=vf->links-1;link>=0;link--){
1416
- total-=vf->pcmlengths[link*2+1];
1417
- if(pos>=total)break;
1418
- }
1419
-
1420
- /* search within the logical bitstream for the page with the highest
1421
- pcm_pos preceding (or equal to) pos. There is a danger here;
1422
- missing pages or incorrect frame number information in the
1423
- bitstream could make our task impossible. Account for that (it
1424
- would be an error condition) */
1425
-
1426
- /* new search algorithm by HB (Nicholas Vinen) */
1427
- {
1428
- ogg_int64_t end=vf->offsets[link+1];
1429
- ogg_int64_t begin=vf->offsets[link];
1430
- ogg_int64_t begintime = vf->pcmlengths[link*2];
1431
- ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
1432
- ogg_int64_t target=pos-total+begintime;
1433
- ogg_int64_t best=begin;
1434
-
1435
- ogg_page og;
1436
- while(begin<end){
1437
- ogg_int64_t bisect;
1438
-
1439
- if(end-begin<CHUNKSIZE){
1440
- bisect=begin;
1441
- }else{
1442
- /* take a (pretty decent) guess. */
1443
- bisect=begin +
1444
- (ogg_int64_t)((double)(target-begintime)*(end-begin)/(endtime-begintime))
1445
- - CHUNKSIZE;
1446
- if(bisect<begin+CHUNKSIZE)
1447
- bisect=begin;
1448
- }
1449
-
1450
- if(bisect!=vf->offset){
1451
- result=_seek_helper(vf,bisect);
1452
- if(result) goto seek_error;
1453
- }
1454
-
1455
- while(begin<end){
1456
- result=_get_next_page(vf,&og,end-vf->offset);
1457
- if(result==OV_EREAD) goto seek_error;
1458
- if(result<0){
1459
- if(bisect<=begin+1)
1460
- end=begin; /* found it */
1461
- else{
1462
- if(bisect==0) goto seek_error;
1463
- bisect-=CHUNKSIZE;
1464
- if(bisect<=begin)bisect=begin+1;
1465
- result=_seek_helper(vf,bisect);
1466
- if(result) goto seek_error;
1467
- }
1468
- }else{
1469
- ogg_int64_t granulepos;
1470
-
1471
- if(ogg_page_serialno(&og)!=vf->serialnos[link])
1472
- continue;
1473
-
1474
- granulepos=ogg_page_granulepos(&og);
1475
- if(granulepos==-1)continue;
1476
-
1477
- if(granulepos<target){
1478
- best=result; /* raw offset of packet with granulepos */
1479
- begin=vf->offset; /* raw offset of next page */
1480
- begintime=granulepos;
1481
-
1482
- if(target-begintime>44100)break;
1483
- bisect=begin; /* *not* begin + 1 */
1484
- }else{
1485
- if(bisect<=begin+1)
1486
- end=begin; /* found it */
1487
- else{
1488
- if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
1489
- end=result;
1490
- bisect-=CHUNKSIZE; /* an endless loop otherwise. */
1491
- if(bisect<=begin)bisect=begin+1;
1492
- result=_seek_helper(vf,bisect);
1493
- if(result) goto seek_error;
1494
- }else{
1495
- end=bisect;
1496
- endtime=granulepos;
1497
- break;
1498
- }
1499
- }
1500
- }
1501
- }
1502
- }
1503
- }
1504
-
1505
- /* found our page. seek to it, update pcm offset. Easier case than
1506
- raw_seek, don't keep packets preceding granulepos. */
1507
- {
1508
- ogg_page og;
1509
- ogg_packet op;
1510
-
1511
- /* seek */
1512
- result=_seek_helper(vf,best);
1513
- vf->pcm_offset=-1;
1514
- if(result) goto seek_error;
1515
- result=_get_next_page(vf,&og,-1);
1516
- if(result<0) goto seek_error;
1517
-
1518
- if(link!=vf->current_link){
1519
- /* Different link; dump entire decode machine */
1520
- _decode_clear(vf);
1521
-
1522
- vf->current_link=link;
1523
- vf->current_serialno=vf->serialnos[link];
1524
- vf->ready_state=STREAMSET;
1525
-
1526
- }else{
1527
- vorbis_synthesis_restart(&vf->vd);
1528
- }
1529
-
1530
- ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
1531
- ogg_stream_pagein(&vf->os,&og);
1532
-
1533
- /* pull out all but last packet; the one with granulepos */
1534
- while(1){
1535
- result=ogg_stream_packetpeek(&vf->os,&op);
1536
- if(result==0){
1537
- /* !!! the packet finishing this page originated on a
1538
- preceding page. Keep fetching previous pages until we
1539
- get one with a granulepos or without the 'continued' flag
1540
- set. Then just use raw_seek for simplicity. */
1541
-
1542
- result=_seek_helper(vf,best);
1543
- if(result<0) goto seek_error;
1544
-
1545
- while(1){
1546
- result=_get_prev_page(vf,&og);
1547
- if(result<0) goto seek_error;
1548
- if(ogg_page_serialno(&og)==vf->current_serialno &&
1549
- (ogg_page_granulepos(&og)>-1 ||
1550
- !ogg_page_continued(&og))){
1551
- return ov_raw_seek(vf,result);
1552
- }
1553
- vf->offset=result;
1554
- }
1555
- }
1556
- if(result<0){
1557
- result = OV_EBADPACKET;
1558
- goto seek_error;
1559
- }
1560
- if(op.granulepos!=-1){
1561
- vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1562
- if(vf->pcm_offset<0)vf->pcm_offset=0;
1563
- vf->pcm_offset+=total;
1564
- break;
1565
- }else
1566
- result=ogg_stream_packetout(&vf->os,NULL);
1567
- }
1568
- }
1569
- }
1570
-
1571
- /* verify result */
1572
- if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1573
- result=OV_EFAULT;
1574
- goto seek_error;
1575
- }
1576
- vf->bittrack=0.f;
1577
- vf->samptrack=0.f;
1578
- return(0);
1579
-
1580
- seek_error:
1581
- /* dump machine so we're in a known state */
1582
- vf->pcm_offset=-1;
1583
- _decode_clear(vf);
1584
- return (int)result;
1585
- }
1586
-
1587
- /* seek to a sample offset relative to the decompressed pcm stream
1588
- returns zero on success, nonzero on failure */
1589
-
1590
- int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1591
- int thisblock,lastblock=0;
1592
- int ret=ov_pcm_seek_page(vf,pos);
1593
- if(ret<0)return(ret);
1594
- if((ret=_make_decode_ready(vf)))return ret;
1595
-
1596
- /* discard leading packets we don't need for the lapping of the
1597
- position we want; don't decode them */
1598
-
1599
- while(1){
1600
- ogg_packet op;
1601
- ogg_page og;
1602
-
1603
- int ret=ogg_stream_packetpeek(&vf->os,&op);
1604
- if(ret>0){
1605
- thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1606
- if(thisblock<0){
1607
- ogg_stream_packetout(&vf->os,NULL);
1608
- continue; /* non audio packet */
1609
- }
1610
- if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1611
-
1612
- if(vf->pcm_offset+((thisblock+
1613
- vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
1614
-
1615
- /* remove the packet from packet queue and track its granulepos */
1616
- ogg_stream_packetout(&vf->os,NULL);
1617
- vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with
1618
- only tracking, no
1619
- pcm_decode */
1620
- vorbis_synthesis_blockin(&vf->vd,&vf->vb);
1621
-
1622
- /* end of logical stream case is hard, especially with exact
1623
- length positioning. */
1624
-
1625
- if(op.granulepos>-1){
1626
- int i;
1627
- /* always believe the stream markers */
1628
- vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1629
- if(vf->pcm_offset<0)vf->pcm_offset=0;
1630
- for(i=0;i<vf->current_link;i++)
1631
- vf->pcm_offset+=vf->pcmlengths[i*2+1];
1632
- }
1633
-
1634
- lastblock=thisblock;
1635
-
1636
- }else{
1637
- if(ret<0 && ret!=OV_HOLE)break;
1638
-
1639
- /* suck in a new page */
1640
- if(_get_next_page(vf,&og,-1)<0)break;
1641
- if(ogg_page_bos(&og))_decode_clear(vf);
1642
-
1643
- if(vf->ready_state<STREAMSET){
1644
- long serialno=ogg_page_serialno(&og);
1645
- int link;
1646
-
1647
- for(link=0;link<vf->links;link++)
1648
- if(vf->serialnos[link]==serialno)break;
1649
- if(link==vf->links) continue;
1650
- vf->current_link=link;
1651
-
1652
- vf->ready_state=STREAMSET;
1653
- vf->current_serialno=ogg_page_serialno(&og);
1654
- ogg_stream_reset_serialno(&vf->os,serialno);
1655
- ret=_make_decode_ready(vf);
1656
- if(ret)return ret;
1657
- lastblock=0;
1658
- }
1659
-
1660
- ogg_stream_pagein(&vf->os,&og);
1661
- }
1662
- }
1663
-
1664
- vf->bittrack=0.f;
1665
- vf->samptrack=0.f;
1666
- /* discard samples until we reach the desired position. Crossing a
1667
- logical bitstream boundary with abandon is OK. */
1668
- {
1669
- /* note that halfrate could be set differently in each link, but
1670
- vorbisfile encoforces all links are set or unset */
1671
- int hs=vorbis_synthesis_halfrate_p(vf->vi);
1672
- while(vf->pcm_offset<((pos>>hs)<<hs)){
1673
- ogg_int64_t target=(pos-vf->pcm_offset)>>hs;
1674
- long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
1675
-
1676
- if(samples>target)samples=target;
1677
- vorbis_synthesis_read(&vf->vd,samples);
1678
- vf->pcm_offset+=samples<<hs;
1679
-
1680
- if(samples<target)
1681
- if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
1682
- vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1683
- }
1684
- }
1685
- return 0;
1686
- }
1687
-
1688
- /* seek to a playback time relative to the decompressed pcm stream
1689
- returns zero on success, nonzero on failure */
1690
- int ov_time_seek(OggVorbis_File *vf,double seconds){
1691
- /* translate time to PCM position and call ov_pcm_seek */
1692
-
1693
- int link=-1;
1694
- ogg_int64_t pcm_total=0;
1695
- double time_total=0.;
1696
-
1697
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1698
- if(!vf->seekable)return(OV_ENOSEEK);
1699
- if(seconds<0)return(OV_EINVAL);
1700
-
1701
- /* which bitstream section does this time offset occur in? */
1702
- for(link=0;link<vf->links;link++){
1703
- double addsec = ov_time_total(vf,link);
1704
- if(seconds<time_total+addsec)break;
1705
- time_total+=addsec;
1706
- pcm_total+=vf->pcmlengths[link*2+1];
1707
- }
1708
-
1709
- if(link==vf->links)return(OV_EINVAL);
1710
-
1711
- /* enough information to convert time offset to pcm offset */
1712
- {
1713
- ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1714
- return(ov_pcm_seek(vf,target));
1715
- }
1716
- }
1717
-
1718
- /* page-granularity version of ov_time_seek
1719
- returns zero on success, nonzero on failure */
1720
- int ov_time_seek_page(OggVorbis_File *vf,double seconds){
1721
- /* translate time to PCM position and call ov_pcm_seek */
1722
-
1723
- int link=-1;
1724
- ogg_int64_t pcm_total=0;
1725
- double time_total=0.;
1726
-
1727
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1728
- if(!vf->seekable)return(OV_ENOSEEK);
1729
- if(seconds<0)return(OV_EINVAL);
1730
-
1731
- /* which bitstream section does this time offset occur in? */
1732
- for(link=0;link<vf->links;link++){
1733
- double addsec = ov_time_total(vf,link);
1734
- if(seconds<time_total+addsec)break;
1735
- time_total+=addsec;
1736
- pcm_total+=vf->pcmlengths[link*2+1];
1737
- }
1738
-
1739
- if(link==vf->links)return(OV_EINVAL);
1740
-
1741
- /* enough information to convert time offset to pcm offset */
1742
- {
1743
- ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1744
- return(ov_pcm_seek_page(vf,target));
1745
- }
1746
- }
1747
-
1748
- /* tell the current stream offset cursor. Note that seek followed by
1749
- tell will likely not give the set offset due to caching */
1750
- ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1751
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1752
- return(vf->offset);
1753
- }
1754
-
1755
- /* return PCM offset (sample) of next PCM sample to be read */
1756
- ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1757
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1758
- return(vf->pcm_offset);
1759
- }
1760
-
1761
- /* return time offset (seconds) of next PCM sample to be read */
1762
- double ov_time_tell(OggVorbis_File *vf){
1763
- int link=0;
1764
- ogg_int64_t pcm_total=0;
1765
- double time_total=0.f;
1766
-
1767
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1768
- if(vf->seekable){
1769
- pcm_total=ov_pcm_total(vf,-1);
1770
- time_total=ov_time_total(vf,-1);
1771
-
1772
- /* which bitstream section does this time offset occur in? */
1773
- for(link=vf->links-1;link>=0;link--){
1774
- pcm_total-=vf->pcmlengths[link*2+1];
1775
- time_total-=ov_time_total(vf,link);
1776
- if(vf->pcm_offset>=pcm_total)break;
1777
- }
1778
- }
1779
-
1780
- return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1781
- }
1782
-
1783
- /* link: -1) return the vorbis_info struct for the bitstream section
1784
- currently being decoded
1785
- 0-n) to request information for a specific bitstream section
1786
-
1787
- In the case of a non-seekable bitstream, any call returns the
1788
- current bitstream. NULL in the case that the machine is not
1789
- initialized */
1790
-
1791
- vorbis_info *ov_info(OggVorbis_File *vf,int link){
1792
- if(vf->seekable){
1793
- if(link<0)
1794
- if(vf->ready_state>=STREAMSET)
1795
- return vf->vi+vf->current_link;
1796
- else
1797
- return vf->vi;
1798
- else
1799
- if(link>=vf->links)
1800
- return NULL;
1801
- else
1802
- return vf->vi+link;
1803
- }else{
1804
- return vf->vi;
1805
- }
1806
- }
1807
-
1808
- /* grr, strong typing, grr, no templates/inheritence, grr */
1809
- vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1810
- if(vf->seekable){
1811
- if(link<0)
1812
- if(vf->ready_state>=STREAMSET)
1813
- return vf->vc+vf->current_link;
1814
- else
1815
- return vf->vc;
1816
- else
1817
- if(link>=vf->links)
1818
- return NULL;
1819
- else
1820
- return vf->vc+link;
1821
- }else{
1822
- return vf->vc;
1823
- }
1824
- }
1825
-
1826
- static int host_is_big_endian() {
1827
- ogg_int32_t pattern = 0xfeedface; /* deadbeef */
1828
- unsigned char *bytewise = (unsigned char *)&pattern;
1829
- if (bytewise[0] == 0xfe) return 1;
1830
- return 0;
1831
- }
1832
-
1833
- /* up to this point, everything could more or less hide the multiple
1834
- logical bitstream nature of chaining from the toplevel application
1835
- if the toplevel application didn't particularly care. However, at
1836
- the point that we actually read audio back, the multiple-section
1837
- nature must surface: Multiple bitstream sections do not necessarily
1838
- have to have the same number of channels or sampling rate.
1839
-
1840
- ov_read returns the sequential logical bitstream number currently
1841
- being decoded along with the PCM data in order that the toplevel
1842
- application can take action on channel/sample rate changes. This
1843
- number will be incremented even for streamed (non-seekable) streams
1844
- (for seekable streams, it represents the actual logical bitstream
1845
- index within the physical bitstream. Note that the accessor
1846
- functions above are aware of this dichotomy).
1847
-
1848
- ov_read_filter is exactly the same as ov_read except that it processes
1849
- the decoded audio data through a filter before packing it into the
1850
- requested format. This gives greater accuracy than applying a filter
1851
- after the audio has been converted into integral PCM.
1852
-
1853
- input values: buffer) a buffer to hold packed PCM data for return
1854
- length) the byte length requested to be placed into buffer
1855
- bigendianp) should the data be packed LSB first (0) or
1856
- MSB first (1)
1857
- word) word size for output. currently 1 (byte) or
1858
- 2 (16 bit short)
1859
-
1860
- return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1861
- 0) EOF
1862
- n) number of bytes of PCM actually returned. The
1863
- below works on a packet-by-packet basis, so the
1864
- return length is not related to the 'length' passed
1865
- in, just guaranteed to fit.
1866
-
1867
- *section) set to the logical bitstream number */
1868
-
1869
- long ov_read_filter(OggVorbis_File *vf,char *buffer,int length,
1870
- int bigendianp,int word,int sgned,int *bitstream,
1871
- void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param){
1872
- int i,j;
1873
- int host_endian = host_is_big_endian();
1874
- int hs;
1875
-
1876
- float **pcm;
1877
- long samples;
1878
-
1879
- if(vf->ready_state<OPENED)return(OV_EINVAL);
1880
-
1881
- while(1){
1882
- if(vf->ready_state==INITSET){
1883
- samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1884
- if(samples)break;
1885
- }
1886
-
1887
- /* suck in another packet */
1888
- {
1889
- int ret=_fetch_and_process_packet(vf,NULL,1,1);
1890
- if(ret==OV_EOF)
1891
- return(0);
1892
- if(ret<=0)
1893
- return(ret);
1894
- }
1895
-
1896
- }
1897
-
1898
- if(samples>0){
1899
-
1900
- /* yay! proceed to pack data into the byte buffer */
1901
-
1902
- long channels=ov_info(vf,-1)->channels;
1903
- long bytespersample=word * channels;
1904
- vorbis_fpu_control fpu;
1905
- if(samples>length/bytespersample)samples=length/bytespersample;
1906
-
1907
- if(samples <= 0)
1908
- return OV_EINVAL;
1909
-
1910
- /* Here. */
1911
- if(filter)
1912
- filter(pcm,channels,samples,filter_param);
1913
-
1914
- /* a tight loop to pack each size */
1915
- {
1916
- int val;
1917
- if(word==1){
1918
- int off=(sgned?0:128);
1919
- vorbis_fpu_setround(&fpu);
1920
- for(j=0;j<samples;j++)
1921
- for(i=0;i<channels;i++){
1922
- val=vorbis_ftoi(pcm[i][j]*128.f);
1923
- if(val>127)val=127;
1924
- else if(val<-128)val=-128;
1925
- *buffer++=val+off;
1926
- }
1927
- vorbis_fpu_restore(fpu);
1928
- }else{
1929
- int off=(sgned?0:32768);
1930
-
1931
- if(host_endian==bigendianp){
1932
- if(sgned){
1933
-
1934
- vorbis_fpu_setround(&fpu);
1935
- for(i=0;i<channels;i++) { /* It's faster in this order */
1936
- float *src=pcm[i];
1937
- short *dest=((short *)buffer)+i;
1938
- for(j=0;j<samples;j++) {
1939
- val=vorbis_ftoi(src[j]*32768.f);
1940
- if(val>32767)val=32767;
1941
- else if(val<-32768)val=-32768;
1942
- *dest=val;
1943
- dest+=channels;
1944
- }
1945
- }
1946
- vorbis_fpu_restore(fpu);
1947
-
1948
- }else{
1949
-
1950
- vorbis_fpu_setround(&fpu);
1951
- for(i=0;i<channels;i++) {
1952
- float *src=pcm[i];
1953
- short *dest=((short *)buffer)+i;
1954
- for(j=0;j<samples;j++) {
1955
- val=vorbis_ftoi(src[j]*32768.f);
1956
- if(val>32767)val=32767;
1957
- else if(val<-32768)val=-32768;
1958
- *dest=val+off;
1959
- dest+=channels;
1960
- }
1961
- }
1962
- vorbis_fpu_restore(fpu);
1963
-
1964
- }
1965
- }else if(bigendianp){
1966
-
1967
- vorbis_fpu_setround(&fpu);
1968
- for(j=0;j<samples;j++)
1969
- for(i=0;i<channels;i++){
1970
- val=vorbis_ftoi(pcm[i][j]*32768.f);
1971
- if(val>32767)val=32767;
1972
- else if(val<-32768)val=-32768;
1973
- val+=off;
1974
- *buffer++=(val>>8);
1975
- *buffer++=(val&0xff);
1976
- }
1977
- vorbis_fpu_restore(fpu);
1978
-
1979
- }else{
1980
- int val;
1981
- vorbis_fpu_setround(&fpu);
1982
- for(j=0;j<samples;j++)
1983
- for(i=0;i<channels;i++){
1984
- val=vorbis_ftoi(pcm[i][j]*32768.f);
1985
- if(val>32767)val=32767;
1986
- else if(val<-32768)val=-32768;
1987
- val+=off;
1988
- *buffer++=(val&0xff);
1989
- *buffer++=(val>>8);
1990
- }
1991
- vorbis_fpu_restore(fpu);
1992
-
1993
- }
1994
- }
1995
- }
1996
-
1997
- vorbis_synthesis_read(&vf->vd,samples);
1998
- hs=vorbis_synthesis_halfrate_p(vf->vi);
1999
- vf->pcm_offset+=(samples<<hs);
2000
- if(bitstream)*bitstream=vf->current_link;
2001
- return(samples*bytespersample);
2002
- }else{
2003
- return(samples);
2004
- }
2005
- }
2006
-
2007
- long ov_read(OggVorbis_File *vf,char *buffer,int length,
2008
- int bigendianp,int word,int sgned,int *bitstream){
2009
- return ov_read_filter(vf, buffer, length, bigendianp, word, sgned, bitstream, NULL, NULL);
2010
- }
2011
-
2012
- /* input values: pcm_channels) a float vector per channel of output
2013
- length) the sample length being read by the app
2014
-
2015
- return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
2016
- 0) EOF
2017
- n) number of samples of PCM actually returned. The
2018
- below works on a packet-by-packet basis, so the
2019
- return length is not related to the 'length' passed
2020
- in, just guaranteed to fit.
2021
-
2022
- *section) set to the logical bitstream number */
2023
-
2024
-
2025
-
2026
- long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length,
2027
- int *bitstream){
2028
-
2029
- if(vf->ready_state<OPENED)return(OV_EINVAL);
2030
-
2031
- while(1){
2032
- if(vf->ready_state==INITSET){
2033
- float **pcm;
2034
- long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
2035
- if(samples){
2036
- int hs=vorbis_synthesis_halfrate_p(vf->vi);
2037
- if(pcm_channels)*pcm_channels=pcm;
2038
- if(samples>length)samples=length;
2039
- vorbis_synthesis_read(&vf->vd,samples);
2040
- vf->pcm_offset+=samples<<hs;
2041
- if(bitstream)*bitstream=vf->current_link;
2042
- return samples;
2043
-
2044
- }
2045
- }
2046
-
2047
- /* suck in another packet */
2048
- {
2049
- int ret=_fetch_and_process_packet(vf,NULL,1,1);
2050
- if(ret==OV_EOF)return(0);
2051
- if(ret<=0)return(ret);
2052
- }
2053
-
2054
- }
2055
- }
2056
-
2057
- extern float *vorbis_window(vorbis_dsp_state *v,int W);
2058
-
2059
- static void _ov_splice(float **pcm,float **lappcm,
2060
- int n1, int n2,
2061
- int ch1, int ch2,
2062
- float *w1, float *w2){
2063
- int i,j;
2064
- float *w=w1;
2065
- int n=n1;
2066
-
2067
- if(n1>n2){
2068
- n=n2;
2069
- w=w2;
2070
- }
2071
-
2072
- /* splice */
2073
- for(j=0;j<ch1 && j<ch2;j++){
2074
- float *s=lappcm[j];
2075
- float *d=pcm[j];
2076
-
2077
- for(i=0;i<n;i++){
2078
- float wd=w[i]*w[i];
2079
- float ws=1.-wd;
2080
- d[i]=d[i]*wd + s[i]*ws;
2081
- }
2082
- }
2083
- /* window from zero */
2084
- for(;j<ch2;j++){
2085
- float *d=pcm[j];
2086
- for(i=0;i<n;i++){
2087
- float wd=w[i]*w[i];
2088
- d[i]=d[i]*wd;
2089
- }
2090
- }
2091
-
2092
- }
2093
-
2094
- /* make sure vf is INITSET */
2095
- static int _ov_initset(OggVorbis_File *vf){
2096
- while(1){
2097
- if(vf->ready_state==INITSET)break;
2098
- /* suck in another packet */
2099
- {
2100
- int ret=_fetch_and_process_packet(vf,NULL,1,0);
2101
- if(ret<0 && ret!=OV_HOLE)return(ret);
2102
- }
2103
- }
2104
- return 0;
2105
- }
2106
-
2107
- /* make sure vf is INITSET and that we have a primed buffer; if
2108
- we're crosslapping at a stream section boundary, this also makes
2109
- sure we're sanity checking against the right stream information */
2110
- static int _ov_initprime(OggVorbis_File *vf){
2111
- vorbis_dsp_state *vd=&vf->vd;
2112
- while(1){
2113
- if(vf->ready_state==INITSET)
2114
- if(vorbis_synthesis_pcmout(vd,NULL))break;
2115
-
2116
- /* suck in another packet */
2117
- {
2118
- int ret=_fetch_and_process_packet(vf,NULL,1,0);
2119
- if(ret<0 && ret!=OV_HOLE)return(ret);
2120
- }
2121
- }
2122
- return 0;
2123
- }
2124
-
2125
- /* grab enough data for lapping from vf; this may be in the form of
2126
- unreturned, already-decoded pcm, remaining PCM we will need to
2127
- decode, or synthetic postextrapolation from last packets. */
2128
- static void _ov_getlap(OggVorbis_File *vf,vorbis_info *vi,vorbis_dsp_state *vd,
2129
- float **lappcm,int lapsize){
2130
- int lapcount=0,i;
2131
- float **pcm;
2132
-
2133
- /* try first to decode the lapping data */
2134
- while(lapcount<lapsize){
2135
- int samples=vorbis_synthesis_pcmout(vd,&pcm);
2136
- if(samples){
2137
- if(samples>lapsize-lapcount)samples=lapsize-lapcount;
2138
- for(i=0;i<vi->channels;i++)
2139
- memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
2140
- lapcount+=samples;
2141
- vorbis_synthesis_read(vd,samples);
2142
- }else{
2143
- /* suck in another packet */
2144
- int ret=_fetch_and_process_packet(vf,NULL,1,0); /* do *not* span */
2145
- if(ret==OV_EOF)break;
2146
- }
2147
- }
2148
- if(lapcount<lapsize){
2149
- /* failed to get lapping data from normal decode; pry it from the
2150
- postextrapolation buffering, or the second half of the MDCT
2151
- from the last packet */
2152
- int samples=vorbis_synthesis_lapout(&vf->vd,&pcm);
2153
- if(samples==0){
2154
- for(i=0;i<vi->channels;i++)
2155
- memset(lappcm[i]+lapcount,0,sizeof(**pcm)*lapsize-lapcount);
2156
- lapcount=lapsize;
2157
- }else{
2158
- if(samples>lapsize-lapcount)samples=lapsize-lapcount;
2159
- for(i=0;i<vi->channels;i++)
2160
- memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
2161
- lapcount+=samples;
2162
- }
2163
- }
2164
- }
2165
-
2166
- /* this sets up crosslapping of a sample by using trailing data from
2167
- sample 1 and lapping it into the windowing buffer of sample 2 */
2168
- int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){
2169
- vorbis_info *vi1,*vi2;
2170
- float **lappcm;
2171
- float **pcm;
2172
- float *w1,*w2;
2173
- int n1,n2,i,ret,hs1,hs2;
2174
-
2175
- if(vf1==vf2)return(0); /* degenerate case */
2176
- if(vf1->ready_state<OPENED)return(OV_EINVAL);
2177
- if(vf2->ready_state<OPENED)return(OV_EINVAL);
2178
-
2179
- /* the relevant overlap buffers must be pre-checked and pre-primed
2180
- before looking at settings in the event that priming would cross
2181
- a bitstream boundary. So, do it now */
2182
-
2183
- ret=_ov_initset(vf1);
2184
- if(ret)return(ret);
2185
- ret=_ov_initprime(vf2);
2186
- if(ret)return(ret);
2187
-
2188
- vi1=ov_info(vf1,-1);
2189
- vi2=ov_info(vf2,-1);
2190
- hs1=ov_halfrate_p(vf1);
2191
- hs2=ov_halfrate_p(vf2);
2192
-
2193
- lappcm=alloca(sizeof(*lappcm)*vi1->channels);
2194
- n1=vorbis_info_blocksize(vi1,0)>>(1+hs1);
2195
- n2=vorbis_info_blocksize(vi2,0)>>(1+hs2);
2196
- w1=vorbis_window(&vf1->vd,0);
2197
- w2=vorbis_window(&vf2->vd,0);
2198
-
2199
- for(i=0;i<vi1->channels;i++)
2200
- lappcm[i]=alloca(sizeof(**lappcm)*n1);
2201
-
2202
- _ov_getlap(vf1,vi1,&vf1->vd,lappcm,n1);
2203
-
2204
- /* have a lapping buffer from vf1; now to splice it into the lapping
2205
- buffer of vf2 */
2206
- /* consolidate and expose the buffer. */
2207
- vorbis_synthesis_lapout(&vf2->vd,&pcm);
2208
-
2209
- #if 0
2210
- _analysis_output_always("pcmL",0,pcm[0],n1*2,0,0,0);
2211
- _analysis_output_always("pcmR",0,pcm[1],n1*2,0,0,0);
2212
- #endif
2213
-
2214
- /* splice */
2215
- _ov_splice(pcm,lappcm,n1,n2,vi1->channels,vi2->channels,w1,w2);
2216
-
2217
- /* done */
2218
- return(0);
2219
- }
2220
-
2221
- static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos,
2222
- int (*localseek)(OggVorbis_File *,ogg_int64_t)){
2223
- vorbis_info *vi;
2224
- float **lappcm;
2225
- float **pcm;
2226
- float *w1,*w2;
2227
- int n1,n2,ch1,ch2,hs;
2228
- int i,ret;
2229
-
2230
- if(vf->ready_state<OPENED)return(OV_EINVAL);
2231
- ret=_ov_initset(vf);
2232
- if(ret)return(ret);
2233
- vi=ov_info(vf,-1);
2234
- hs=ov_halfrate_p(vf);
2235
-
2236
- ch1=vi->channels;
2237
- n1=vorbis_info_blocksize(vi,0)>>(1+hs);
2238
- w1=vorbis_window(&vf->vd,0); /* window arrays from libvorbis are
2239
- persistent; even if the decode state
2240
- from this link gets dumped, this
2241
- window array continues to exist */
2242
-
2243
- lappcm=alloca(sizeof(*lappcm)*ch1);
2244
- for(i=0;i<ch1;i++)
2245
- lappcm[i]=alloca(sizeof(**lappcm)*n1);
2246
- _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
2247
-
2248
- /* have lapping data; seek and prime the buffer */
2249
- ret=localseek(vf,pos);
2250
- if(ret)return ret;
2251
- ret=_ov_initprime(vf);
2252
- if(ret)return(ret);
2253
-
2254
- /* Guard against cross-link changes; they're perfectly legal */
2255
- vi=ov_info(vf,-1);
2256
- ch2=vi->channels;
2257
- n2=vorbis_info_blocksize(vi,0)>>(1+hs);
2258
- w2=vorbis_window(&vf->vd,0);
2259
-
2260
- /* consolidate and expose the buffer. */
2261
- vorbis_synthesis_lapout(&vf->vd,&pcm);
2262
-
2263
- /* splice */
2264
- _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
2265
-
2266
- /* done */
2267
- return(0);
2268
- }
2269
-
2270
- int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
2271
- return _ov_64_seek_lap(vf,pos,ov_raw_seek);
2272
- }
2273
-
2274
- int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
2275
- return _ov_64_seek_lap(vf,pos,ov_pcm_seek);
2276
- }
2277
-
2278
- int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos){
2279
- return _ov_64_seek_lap(vf,pos,ov_pcm_seek_page);
2280
- }
2281
-
2282
- static int _ov_d_seek_lap(OggVorbis_File *vf,double pos,
2283
- int (*localseek)(OggVorbis_File *,double)){
2284
- vorbis_info *vi;
2285
- float **lappcm;
2286
- float **pcm;
2287
- float *w1,*w2;
2288
- int n1,n2,ch1,ch2,hs;
2289
- int i,ret;
2290
-
2291
- if(vf->ready_state<OPENED)return(OV_EINVAL);
2292
- ret=_ov_initset(vf);
2293
- if(ret)return(ret);
2294
- vi=ov_info(vf,-1);
2295
- hs=ov_halfrate_p(vf);
2296
-
2297
- ch1=vi->channels;
2298
- n1=vorbis_info_blocksize(vi,0)>>(1+hs);
2299
- w1=vorbis_window(&vf->vd,0); /* window arrays from libvorbis are
2300
- persistent; even if the decode state
2301
- from this link gets dumped, this
2302
- window array continues to exist */
2303
-
2304
- lappcm=alloca(sizeof(*lappcm)*ch1);
2305
- for(i=0;i<ch1;i++)
2306
- lappcm[i]=alloca(sizeof(**lappcm)*n1);
2307
- _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
2308
-
2309
- /* have lapping data; seek and prime the buffer */
2310
- ret=localseek(vf,pos);
2311
- if(ret)return ret;
2312
- ret=_ov_initprime(vf);
2313
- if(ret)return(ret);
2314
-
2315
- /* Guard against cross-link changes; they're perfectly legal */
2316
- vi=ov_info(vf,-1);
2317
- ch2=vi->channels;
2318
- n2=vorbis_info_blocksize(vi,0)>>(1+hs);
2319
- w2=vorbis_window(&vf->vd,0);
2320
-
2321
- /* consolidate and expose the buffer. */
2322
- vorbis_synthesis_lapout(&vf->vd,&pcm);
2323
-
2324
- /* splice */
2325
- _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
2326
-
2327
- /* done */
2328
- return(0);
2329
- }
2330
-
2331
- int ov_time_seek_lap(OggVorbis_File *vf,double pos){
2332
- return _ov_d_seek_lap(vf,pos,ov_time_seek);
2333
- }
2334
-
2335
- int ov_time_seek_page_lap(OggVorbis_File *vf,double pos){
2336
- return _ov_d_seek_lap(vf,pos,ov_time_seek_page);
2337
- }