diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llaudio/vorbisdecode.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llaudio/vorbisdecode.cpp')
-rw-r--r-- | linden/indra/llaudio/vorbisdecode.cpp | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/linden/indra/llaudio/vorbisdecode.cpp b/linden/indra/llaudio/vorbisdecode.cpp new file mode 100644 index 0000000..4308b71 --- /dev/null +++ b/linden/indra/llaudio/vorbisdecode.cpp | |||
@@ -0,0 +1,321 @@ | |||
1 | /** | ||
2 | * @file vorbisdecode.cpp | ||
3 | * @brief Vorbis decoding routine routine for Indra. | ||
4 | * | ||
5 | * Copyright (c) 2000-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "linden_common.h" | ||
29 | |||
30 | #include <stdio.h> | ||
31 | #include <stdlib.h> | ||
32 | #include <math.h> | ||
33 | |||
34 | #include "vorbis/codec.h" | ||
35 | #include "vorbis/vorbisfile.h" | ||
36 | #include "llerror.h" | ||
37 | #include "llmath.h" | ||
38 | #include "llvfile.h" | ||
39 | |||
40 | #if 0 | ||
41 | |||
42 | size_t vfs_read(void *ptr, size_t size, size_t nmemb, void *datasource) | ||
43 | { | ||
44 | LLVFile *file = (LLVFile *)datasource; | ||
45 | |||
46 | if (size > 0 && file->read((U8*)ptr, size * nmemb)) /*Flawfinder: ignore*/ | ||
47 | { | ||
48 | S32 read = file->getLastBytesRead(); | ||
49 | return read / size; /*Flawfinder: ignore*/ | ||
50 | } | ||
51 | else | ||
52 | { | ||
53 | return 0; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | int vfs_seek(void *datasource, ogg_int64_t offset, int whence) | ||
58 | { | ||
59 | LLVFile *file = (LLVFile *)datasource; | ||
60 | |||
61 | // vfs has 31-bit files | ||
62 | if (offset > S32_MAX) | ||
63 | { | ||
64 | return -1; | ||
65 | } | ||
66 | |||
67 | S32 origin; | ||
68 | switch (whence) { | ||
69 | case SEEK_SET: | ||
70 | origin = 0; | ||
71 | break; | ||
72 | case SEEK_END: | ||
73 | origin = file->getSize(); | ||
74 | break; | ||
75 | case SEEK_CUR: | ||
76 | origin = -1; | ||
77 | break; | ||
78 | default: | ||
79 | llerrs << "Invalid whence argument to vfs_seek" << llendl; | ||
80 | return -1; | ||
81 | } | ||
82 | |||
83 | if (file->seek((S32)offset, origin)) | ||
84 | { | ||
85 | return 0; | ||
86 | } | ||
87 | else | ||
88 | { | ||
89 | return -1; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | int vfs_close (void *datasource) | ||
94 | { | ||
95 | LLVFile *file = (LLVFile *)datasource; | ||
96 | |||
97 | delete file; | ||
98 | |||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | long vfs_tell (void *datasource) | ||
103 | { | ||
104 | LLVFile *file = (LLVFile *)datasource; | ||
105 | |||
106 | return file->tell(); | ||
107 | } | ||
108 | |||
109 | |||
110 | BOOL decode_vorbis_file(LLVFS *vfs, const LLUUID &in_uuid, char *out_fname) | ||
111 | { | ||
112 | ov_callbacks vfs_callbacks; | ||
113 | vfs_callbacks.read_func = vfs_read; | ||
114 | vfs_callbacks.seek_func = vfs_seek; | ||
115 | vfs_callbacks.close_func = vfs_close; | ||
116 | vfs_callbacks.tell_func = vfs_tell; | ||
117 | |||
118 | char pcmout[4096]; /*Flawfinder: ignore*/ | ||
119 | |||
120 | unsigned char temp[64]; /*Flawfinder: ignore*/ | ||
121 | |||
122 | LLVFile *in_vfile; | ||
123 | |||
124 | U32 data_length = 0; | ||
125 | |||
126 | llinfos << "Vorbis decode from vfile: " << in_uuid << llendl; | ||
127 | |||
128 | in_vfile = new LLVFile(vfs, in_uuid, LLAssetType::AT_SOUND); | ||
129 | if (! in_vfile->getSize()) | ||
130 | { | ||
131 | llwarning("unable to open vorbis source vfile for reading",0); | ||
132 | return(FALSE); | ||
133 | } | ||
134 | apr_file_t* outfp = ll_apr_file_open(out_fname,LL_APR_WPB); | ||
135 | if (!outfp) | ||
136 | { | ||
137 | llwarning("unable to open vorbis destination file for writing",0); | ||
138 | return(FALSE); | ||
139 | } | ||
140 | else | ||
141 | { | ||
142 | // write the .wav format header | ||
143 | //"RIFF" | ||
144 | temp[0] = 0x52; | ||
145 | temp[1] = 0x49; | ||
146 | temp[2] = 0x46; | ||
147 | temp[3] = 0x46; | ||
148 | |||
149 | // length = datalen + 36 (to be filled in later) | ||
150 | temp[4] = 0x00; | ||
151 | temp[5] = 0x00; | ||
152 | temp[6] = 0x00; | ||
153 | temp[7] = 0x00; | ||
154 | |||
155 | //"WAVE" | ||
156 | temp[8] = 0x57; | ||
157 | temp[9] = 0x41; | ||
158 | temp[10] = 0x56; | ||
159 | temp[11] = 0x45; | ||
160 | |||
161 | // "fmt " | ||
162 | temp[12] = 0x66; | ||
163 | temp[13] = 0x6D; | ||
164 | temp[14] = 0x74; | ||
165 | temp[15] = 0x20; | ||
166 | |||
167 | // chunk size = 16 | ||
168 | temp[16] = 0x10; | ||
169 | temp[17] = 0x00; | ||
170 | temp[18] = 0x00; | ||
171 | temp[19] = 0x00; | ||
172 | |||
173 | // format (1 = PCM) | ||
174 | temp[20] = 0x01; | ||
175 | temp[21] = 0x00; | ||
176 | |||
177 | // number of channels | ||
178 | temp[22] = 0x01; | ||
179 | temp[23] = 0x00; | ||
180 | |||
181 | // samples per second | ||
182 | temp[24] = 0x44; | ||
183 | temp[25] = 0xAC; | ||
184 | temp[26] = 0x00; | ||
185 | temp[27] = 0x00; | ||
186 | |||
187 | // average bytes per second | ||
188 | temp[28] = 0x88; | ||
189 | temp[29] = 0x58; | ||
190 | temp[30] = 0x01; | ||
191 | temp[31] = 0x00; | ||
192 | |||
193 | // bytes to output at a single time | ||
194 | temp[32] = 0x02; | ||
195 | temp[33] = 0x00; | ||
196 | |||
197 | // 16 bits per sample | ||
198 | temp[34] = 0x10; | ||
199 | temp[35] = 0x00; | ||
200 | |||
201 | // "data" | ||
202 | temp[36] = 0x64; | ||
203 | temp[37] = 0x61; | ||
204 | temp[38] = 0x74; | ||
205 | temp[39] = 0x61; | ||
206 | |||
207 | |||
208 | // these are the length of the data chunk, to be filled in later | ||
209 | temp[40] = 0x00; | ||
210 | temp[41] = 0x00; | ||
211 | temp[42] = 0x00; | ||
212 | temp[43] = 0x00; | ||
213 | |||
214 | |||
215 | ll_apr_file_write(outfp, temp, 44); | ||
216 | } | ||
217 | |||
218 | OggVorbis_File vf; | ||
219 | int eof=0; | ||
220 | int current_section; | ||
221 | |||
222 | int r = ov_open_callbacks(in_vfile, &vf, NULL, 0, vfs_callbacks); | ||
223 | if(r < 0) | ||
224 | { | ||
225 | llwarns << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << in_uuid << llendl; | ||
226 | return(FALSE); | ||
227 | } | ||
228 | |||
229 | { | ||
230 | char **ptr=ov_comment(&vf,-1)->user_comments; | ||
231 | // vorbis_info *vi=ov_info(&vf,-1); | ||
232 | while(*ptr){ | ||
233 | fprintf(stderr,"%s\n",*ptr); | ||
234 | ++ptr; | ||
235 | } | ||
236 | // fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate); | ||
237 | // fprintf(stderr,"\nDecoded length: %ld samples\n", (long)ov_pcm_total(&vf,-1)); | ||
238 | // fprintf(stderr,"Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor); | ||
239 | } | ||
240 | |||
241 | while(!eof){ | ||
242 | long ret=ov_read(&vf,pcmout,sizeof(pcmout),0,2,1,¤t_section); | ||
243 | if (ret == 0) { | ||
244 | /* EOF */ | ||
245 | eof=1; | ||
246 | // llinfos << "Vorbis EOF" << llendl; | ||
247 | } else if (ret < 0) { | ||
248 | /* error in the stream. Not a problem, just reporting it in | ||
249 | case we (the app) cares. In this case, we don't. */ | ||
250 | llwarning("Error in vorbis stream",0); | ||
251 | break; | ||
252 | |||
253 | } else { | ||
254 | // llinfos << "Vorbis read " << ret << "bytes" << llendl; | ||
255 | /* we don't bother dealing with sample rate changes, etc, but. | ||
256 | you'll have to*/ | ||
257 | data_length += ll_apr_file_write(outfp, pcmout, ret); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | ov_clear(&vf); | ||
262 | |||
263 | // write "data" chunk length | ||
264 | ll_apr_file_seek(outfp,APR_SET,40); | ||
265 | ll_apr_file_write(outfp,&data_length,4); | ||
266 | |||
267 | // write overall "RIFF" length | ||
268 | data_length += 36; | ||
269 | ll_apr_file_seek(outfp,APR_SET,4); | ||
270 | ll_apr_file_write(outfp,&data_length,1*4); | ||
271 | |||
272 | // FUCK!!! Vorbis encode/decode messes up loop point transitions (pop) | ||
273 | // do a cheap-and-cheesy crossfade | ||
274 | |||
275 | |||
276 | S16 *samplep; | ||
277 | S32 i; | ||
278 | S32 fade_length; | ||
279 | |||
280 | fade_length = llmin((S32)128,(S32)(data_length-36)/8); | ||
281 | |||
282 | ll_apr_file_seek(outfp,APR_SET,44); | ||
283 | ll_apr_file_read(outfp, pcmout,2*fade_length); //read first 16 samples | ||
284 | |||
285 | samplep = (S16 *)pcmout; | ||
286 | |||
287 | for (i = 0 ;i < fade_length; i++) | ||
288 | { | ||
289 | *samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length)); | ||
290 | } | ||
291 | |||
292 | ll_apr_file_seek(outfp,APR_SET,44); | ||
293 | ll_apr_file_write(outfp,pcmout,2*fade_length); //write back xfaded first 16 samples | ||
294 | |||
295 | ll_apr_file_seek(outfp,APR_END,-fade_length*2); | ||
296 | ll_apr_file_read(outfp, pcmout,2*fade_length); //read last 16 samples | ||
297 | |||
298 | samplep = (S16 *)pcmout; | ||
299 | |||
300 | for (i = fade_length-1 ; i >= 0; i--) | ||
301 | { | ||
302 | *samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length)); | ||
303 | } | ||
304 | |||
305 | ll_apr_file_seek(outfp,SEEK_END,-fade_length*2); | ||
306 | ll_apr_file_write(outfp,pcmout,2*fade_length); //write back xfaded last 16 samples | ||
307 | |||
308 | apr_file_close(outfp); | ||
309 | |||
310 | if ((36 == data_length) || (!(eof))) | ||
311 | { | ||
312 | llwarning("BAD Vorbis DECODE!, removing .wav!",0); | ||
313 | LLFile::remove(out_fname); | ||
314 | return (FALSE); | ||
315 | } | ||
316 | |||
317 | // fprintf(stderr,"Done.\n"); | ||
318 | |||
319 | return(TRUE); | ||
320 | } | ||
321 | #endif | ||