Imported existing code
This commit is contained in:
326
indra/llaudio/llvorbisdecode.cpp
Normal file
326
indra/llaudio/llvorbisdecode.cpp
Normal file
@@ -0,0 +1,326 @@
|
||||
/**
|
||||
* @file vorbisdecode.cpp
|
||||
* @brief Vorbis decoding routine routine for Indra.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "vorbis/codec.h"
|
||||
#include "vorbis/vorbisfile.h"
|
||||
#include "llerror.h"
|
||||
#include "llmath.h"
|
||||
#include "llvfile.h"
|
||||
|
||||
#if 0
|
||||
|
||||
size_t vfs_read(void *ptr, size_t size, size_t nmemb, void *datasource)
|
||||
{
|
||||
LLVFile *file = (LLVFile *)datasource;
|
||||
|
||||
if (size > 0 && file->read((U8*)ptr, size * nmemb)) /*Flawfinder: ignore*/
|
||||
{
|
||||
S32 read = file->getLastBytesRead();
|
||||
return read / size; /*Flawfinder: ignore*/
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int vfs_seek(void *datasource, ogg_int64_t offset, int whence)
|
||||
{
|
||||
LLVFile *file = (LLVFile *)datasource;
|
||||
|
||||
// vfs has 31-bit files
|
||||
if (offset > S32_MAX)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
S32 origin;
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
origin = 0;
|
||||
break;
|
||||
case SEEK_END:
|
||||
origin = file->getSize();
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
origin = -1;
|
||||
break;
|
||||
default:
|
||||
llerrs << "Invalid whence argument to vfs_seek" << llendl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (file->seek((S32)offset, origin))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int vfs_close (void *datasource)
|
||||
{
|
||||
LLVFile *file = (LLVFile *)datasource;
|
||||
|
||||
delete file;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long vfs_tell (void *datasource)
|
||||
{
|
||||
LLVFile *file = (LLVFile *)datasource;
|
||||
|
||||
return file->tell();
|
||||
}
|
||||
|
||||
|
||||
BOOL decode_vorbis_file(LLVFS *vfs, const LLUUID &in_uuid, char *out_fname)
|
||||
{
|
||||
ov_callbacks vfs_callbacks;
|
||||
vfs_callbacks.read_func = vfs_read;
|
||||
vfs_callbacks.seek_func = vfs_seek;
|
||||
vfs_callbacks.close_func = vfs_close;
|
||||
vfs_callbacks.tell_func = vfs_tell;
|
||||
|
||||
char pcmout[4096]; /*Flawfinder: ignore*/
|
||||
|
||||
unsigned char temp[64]; /*Flawfinder: ignore*/
|
||||
|
||||
LLVFile *in_vfile;
|
||||
|
||||
U32 data_length = 0;
|
||||
|
||||
llinfos << "Vorbis decode from vfile: " << in_uuid << llendl;
|
||||
|
||||
in_vfile = new LLVFile(vfs, in_uuid, LLAssetType::AT_SOUND);
|
||||
if (! in_vfile->getSize())
|
||||
{
|
||||
llwarning("unable to open vorbis source vfile for reading",0);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
//**********************************
|
||||
LLAPRFile outfile ;
|
||||
outfile.open(out_fname,LL_APR_WPB);
|
||||
//**********************************
|
||||
if (!outfile.getFileHandle())
|
||||
{
|
||||
llwarning("unable to open vorbis destination file for writing",0);
|
||||
return(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// write the .wav format header
|
||||
//"RIFF"
|
||||
temp[0] = 0x52;
|
||||
temp[1] = 0x49;
|
||||
temp[2] = 0x46;
|
||||
temp[3] = 0x46;
|
||||
|
||||
// length = datalen + 36 (to be filled in later)
|
||||
temp[4] = 0x00;
|
||||
temp[5] = 0x00;
|
||||
temp[6] = 0x00;
|
||||
temp[7] = 0x00;
|
||||
|
||||
//"WAVE"
|
||||
temp[8] = 0x57;
|
||||
temp[9] = 0x41;
|
||||
temp[10] = 0x56;
|
||||
temp[11] = 0x45;
|
||||
|
||||
// "fmt "
|
||||
temp[12] = 0x66;
|
||||
temp[13] = 0x6D;
|
||||
temp[14] = 0x74;
|
||||
temp[15] = 0x20;
|
||||
|
||||
// chunk size = 16
|
||||
temp[16] = 0x10;
|
||||
temp[17] = 0x00;
|
||||
temp[18] = 0x00;
|
||||
temp[19] = 0x00;
|
||||
|
||||
// format (1 = PCM)
|
||||
temp[20] = 0x01;
|
||||
temp[21] = 0x00;
|
||||
|
||||
// number of channels
|
||||
temp[22] = 0x01;
|
||||
temp[23] = 0x00;
|
||||
|
||||
// samples per second
|
||||
temp[24] = 0x44;
|
||||
temp[25] = 0xAC;
|
||||
temp[26] = 0x00;
|
||||
temp[27] = 0x00;
|
||||
|
||||
// average bytes per second
|
||||
temp[28] = 0x88;
|
||||
temp[29] = 0x58;
|
||||
temp[30] = 0x01;
|
||||
temp[31] = 0x00;
|
||||
|
||||
// bytes to output at a single time
|
||||
temp[32] = 0x02;
|
||||
temp[33] = 0x00;
|
||||
|
||||
// 16 bits per sample
|
||||
temp[34] = 0x10;
|
||||
temp[35] = 0x00;
|
||||
|
||||
// "data"
|
||||
temp[36] = 0x64;
|
||||
temp[37] = 0x61;
|
||||
temp[38] = 0x74;
|
||||
temp[39] = 0x61;
|
||||
|
||||
|
||||
// these are the length of the data chunk, to be filled in later
|
||||
temp[40] = 0x00;
|
||||
temp[41] = 0x00;
|
||||
temp[42] = 0x00;
|
||||
temp[43] = 0x00;
|
||||
|
||||
outfile.write(temp, 44);
|
||||
}
|
||||
|
||||
OggVorbis_File vf;
|
||||
int eof=0;
|
||||
int current_section;
|
||||
|
||||
int r = ov_open_callbacks(in_vfile, &vf, NULL, 0, vfs_callbacks);
|
||||
if(r < 0)
|
||||
{
|
||||
llwarns << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << in_uuid << llendl;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
{
|
||||
char **ptr=ov_comment(&vf,-1)->user_comments;
|
||||
// vorbis_info *vi=ov_info(&vf,-1);
|
||||
while(*ptr){
|
||||
fprintf(stderr,"%s\n",*ptr);
|
||||
++ptr;
|
||||
}
|
||||
// fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate);
|
||||
// fprintf(stderr,"\nDecoded length: %ld samples\n", (long)ov_pcm_total(&vf,-1));
|
||||
// fprintf(stderr,"Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor);
|
||||
}
|
||||
|
||||
while(!eof){
|
||||
long ret=ov_read(&vf,pcmout,sizeof(pcmout),0,2,1,¤t_section);
|
||||
if (ret == 0) {
|
||||
/* EOF */
|
||||
eof=1;
|
||||
// llinfos << "Vorbis EOF" << llendl;
|
||||
} else if (ret < 0) {
|
||||
/* error in the stream. Not a problem, just reporting it in
|
||||
case we (the app) cares. In this case, we don't. */
|
||||
llwarning("Error in vorbis stream",0);
|
||||
break;
|
||||
|
||||
} else {
|
||||
// llinfos << "Vorbis read " << ret << "bytes" << llendl;
|
||||
/* we don't bother dealing with sample rate changes, etc, but.
|
||||
you'll have to*/
|
||||
data_length += outfile.write(pcmout, ret);
|
||||
}
|
||||
}
|
||||
|
||||
ov_clear(&vf);
|
||||
|
||||
// write "data" chunk length
|
||||
outfile.seek(APR_SET,40);
|
||||
outfile.write(&data_length,4);
|
||||
|
||||
// write overall "RIFF" length
|
||||
data_length += 36;
|
||||
outfile.seek(APR_SET,4);
|
||||
outfile.write(&data_length,1*4);
|
||||
|
||||
// FUCK!!! Vorbis encode/decode messes up loop point transitions (pop)
|
||||
// do a cheap-and-cheesy crossfade
|
||||
|
||||
|
||||
S16 *samplep;
|
||||
S32 i;
|
||||
S32 fade_length;
|
||||
|
||||
fade_length = llmin((S32)128,(S32)(data_length-36)/8);
|
||||
|
||||
outfile.seek(APR_SET,44);
|
||||
outfile.read(pcmout,2*fade_length); //read first 16 samples
|
||||
|
||||
samplep = (S16 *)pcmout;
|
||||
|
||||
for (i = 0 ;i < fade_length; i++)
|
||||
{
|
||||
*samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length));
|
||||
}
|
||||
|
||||
outfile.seek(APR_SET,44);
|
||||
outfile.write(pcmout,2*fade_length); //write back xfaded first 16 samples
|
||||
|
||||
outfile.seek(APR_END,-fade_length*2);
|
||||
outfile.read(pcmout,2*fade_length); //read last 16 samples
|
||||
|
||||
samplep = (S16 *)pcmout;
|
||||
|
||||
for (i = fade_length-1 ; i >= 0; i--)
|
||||
{
|
||||
*samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length));
|
||||
}
|
||||
|
||||
outfile.seek(SEEK_END,-fade_length*2);
|
||||
outfile.write(pcmout,2*fade_length); //write back xfaded last 16 samples
|
||||
//*******************
|
||||
outfile.close();
|
||||
//*******************
|
||||
|
||||
if ((36 == data_length) || (!(eof)))
|
||||
{
|
||||
llwarning("BAD Vorbis DECODE!, removing .wav!",0);
|
||||
LLFile::remove(out_fname);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
// fprintf(stderr,"Done.\n");
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user