aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llaudio/vorbisdecode.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llaudio/vorbisdecode.cpp
parentREADME.txt (diff)
downloadmeta-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.cpp321
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
42size_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
57int 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
93int vfs_close (void *datasource)
94{
95 LLVFile *file = (LLVFile *)datasource;
96
97 delete file;
98
99 return 0;
100}
101
102long vfs_tell (void *datasource)
103{
104 LLVFile *file = (LLVFile *)datasource;
105
106 return file->tell();
107}
108
109
110BOOL 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,&current_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