vorbisdecode.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include "vorbis/codec.h"
00035 #include "vorbis/vorbisfile.h"
00036 #include "llerror.h"
00037 #include "llmath.h"
00038 #include "llvfile.h"
00039 
00040 #if 0
00041 
00042 size_t vfs_read(void *ptr, size_t size, size_t nmemb, void *datasource)
00043 {
00044         LLVFile *file = (LLVFile *)datasource;
00045 
00046         if (size > 0 && file->read((U8*)ptr, size * nmemb))     /*Flawfinder: ignore*/
00047         {
00048                 S32 read = file->getLastBytesRead();
00049                 return  read / size;    /*Flawfinder: ignore*/
00050         }
00051         else
00052         {
00053                 return 0;
00054         }
00055 }
00056 
00057 int vfs_seek(void *datasource, ogg_int64_t offset, int whence)
00058 {
00059         LLVFile *file = (LLVFile *)datasource;
00060 
00061         // vfs has 31-bit files
00062         if (offset > S32_MAX)
00063         {
00064                 return -1;
00065         }
00066 
00067         S32 origin;
00068         switch (whence) {
00069         case SEEK_SET:
00070                 origin = 0;
00071                 break;
00072         case SEEK_END:
00073                 origin = file->getSize();
00074                 break;
00075         case SEEK_CUR:
00076                 origin = -1;
00077                 break;
00078         default:
00079                 llerrs << "Invalid whence argument to vfs_seek" << llendl;
00080                 return -1;
00081         }
00082 
00083         if (file->seek((S32)offset, origin))
00084         {
00085                 return 0;
00086         }
00087         else
00088         {
00089                 return -1;
00090         }
00091 }
00092 
00093 int vfs_close (void *datasource)
00094 {
00095         LLVFile *file = (LLVFile *)datasource;
00096 
00097         delete file;
00098 
00099         return 0;
00100 }
00101 
00102 long vfs_tell (void *datasource)
00103 {
00104         LLVFile *file = (LLVFile *)datasource;
00105 
00106         return file->tell();
00107 }
00108 
00109 
00110 BOOL decode_vorbis_file(LLVFS *vfs, const LLUUID &in_uuid, char *out_fname)
00111 {
00112         ov_callbacks vfs_callbacks;
00113         vfs_callbacks.read_func = vfs_read;
00114         vfs_callbacks.seek_func = vfs_seek;
00115         vfs_callbacks.close_func = vfs_close;
00116         vfs_callbacks.tell_func = vfs_tell;
00117 
00118         char pcmout[4096]; /*Flawfinder: ignore*/
00119 
00120         unsigned char temp[64]; /*Flawfinder: ignore*/
00121 
00122         LLVFile *in_vfile;
00123 
00124         U32 data_length = 0;
00125 
00126         llinfos << "Vorbis decode from vfile: " << in_uuid << llendl;
00127 
00128         in_vfile = new LLVFile(vfs, in_uuid, LLAssetType::AT_SOUND);
00129         if (! in_vfile->getSize())
00130         {
00131                 llwarning("unable to open vorbis source vfile for reading",0);
00132                 return(FALSE);
00133         }
00134         apr_file_t* outfp = ll_apr_file_open(out_fname,LL_APR_WPB);
00135         if (!outfp)
00136         {
00137                 llwarning("unable to open vorbis destination file for writing",0);
00138                 return(FALSE);          
00139         }
00140         else
00141         {
00142                 // write the .wav format header
00143                 //"RIFF"
00144                 temp[0] = 0x52;
00145                 temp[1] = 0x49;
00146                 temp[2] = 0x46;
00147                 temp[3] = 0x46;
00148                 
00149                 // length = datalen + 36 (to be filled in later)
00150                 temp[4] = 0x00;
00151                 temp[5] = 0x00;
00152                 temp[6] = 0x00;
00153                 temp[7] = 0x00;
00154                 
00155                 //"WAVE"
00156                 temp[8] = 0x57;
00157                 temp[9] = 0x41;
00158                 temp[10] = 0x56;
00159                 temp[11] = 0x45;
00160 
00161                 // "fmt "
00162                 temp[12] = 0x66;
00163                 temp[13] = 0x6D;
00164                 temp[14] = 0x74;
00165                 temp[15] = 0x20;
00166 
00167                 // chunk size = 16
00168                 temp[16] = 0x10;
00169                 temp[17] = 0x00;
00170                 temp[18] = 0x00;
00171                 temp[19] = 0x00;
00172 
00173                 // format (1 = PCM)
00174                 temp[20] = 0x01;
00175                 temp[21] = 0x00;
00176 
00177                 // number of channels
00178                 temp[22] = 0x01;
00179                 temp[23] = 0x00;
00180 
00181                 // samples per second
00182                 temp[24] = 0x44;
00183                 temp[25] = 0xAC;
00184                 temp[26] = 0x00;
00185                 temp[27] = 0x00;
00186 
00187                 // average bytes per second
00188                 temp[28] = 0x88;
00189                 temp[29] = 0x58;
00190                 temp[30] = 0x01;
00191                 temp[31] = 0x00;
00192 
00193                 // bytes to output at a single time
00194                 temp[32] = 0x02;
00195                 temp[33] = 0x00;
00196                  
00197                 // 16 bits per sample
00198                 temp[34] = 0x10;
00199                 temp[35] = 0x00;
00200 
00201                 // "data"
00202                 temp[36] = 0x64;
00203                 temp[37] = 0x61;
00204                 temp[38] = 0x74;
00205                 temp[39] = 0x61;
00206 
00207 
00208                 // these are the length of the data chunk, to be filled in later
00209                 temp[40] = 0x00;
00210                 temp[41] = 0x00;
00211                 temp[42] = 0x00;
00212                 temp[43] = 0x00;
00213 
00214 
00215                 ll_apr_file_write(outfp, temp, 44);
00216         }
00217 
00218         OggVorbis_File vf;
00219         int eof=0;
00220         int current_section;
00221  
00222         int r = ov_open_callbacks(in_vfile, &vf, NULL, 0, vfs_callbacks);
00223         if(r < 0) 
00224         {
00225                 llwarns << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << in_uuid << llendl;
00226                 return(FALSE);
00227         }
00228 
00229         {
00230                 char **ptr=ov_comment(&vf,-1)->user_comments;
00231 //              vorbis_info *vi=ov_info(&vf,-1);
00232                 while(*ptr){
00233                         fprintf(stderr,"%s\n",*ptr);
00234                         ++ptr;
00235                 }
00236 //    fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate);
00237 //    fprintf(stderr,"\nDecoded length: %ld samples\n", (long)ov_pcm_total(&vf,-1));
00238 //    fprintf(stderr,"Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor);
00239         }
00240   
00241         while(!eof){
00242                 long ret=ov_read(&vf,pcmout,sizeof(pcmout),0,2,1,&current_section);
00243                 if (ret == 0) {
00244                         /* EOF */
00245                         eof=1;
00246 //                      llinfos << "Vorbis EOF" << llendl;
00247                 } else if (ret < 0) {
00248                         /* error in the stream.  Not a problem, just reporting it in
00249                            case we (the app) cares.  In this case, we don't. */
00250                         llwarning("Error in vorbis stream",0); 
00251                         break;
00252 
00253                 } else {
00254 //                      llinfos << "Vorbis read " << ret << "bytes" << llendl;
00255                         /* we don't bother dealing with sample rate changes, etc, but.
00256                            you'll have to*/
00257                         data_length += ll_apr_file_write(outfp, pcmout, ret);
00258                 }
00259         }
00260 
00261         ov_clear(&vf);
00262   
00263         // write "data" chunk length
00264         ll_apr_file_seek(outfp,APR_SET,40);
00265         ll_apr_file_write(outfp,&data_length,4);
00266  
00267         // write overall "RIFF" length
00268         data_length += 36;
00269         ll_apr_file_seek(outfp,APR_SET,4);
00270         ll_apr_file_write(outfp,&data_length,1*4);
00271 
00272         // FUCK!!! Vorbis encode/decode messes up loop point transitions (pop)
00273         // do a cheap-and-cheesy crossfade 
00274         
00275 
00276         S16 *samplep;
00277         S32 i;
00278         S32 fade_length;
00279 
00280         fade_length = llmin((S32)128,(S32)(data_length-36)/8);
00281         
00282         ll_apr_file_seek(outfp,APR_SET,44);
00283         ll_apr_file_read(outfp, pcmout,2*fade_length);  //read first 16 samples
00284 
00285         samplep = (S16 *)pcmout;
00286 
00287         for (i = 0 ;i < fade_length; i++)
00288         {
00289                 *samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length));          
00290         }
00291         
00292         ll_apr_file_seek(outfp,APR_SET,44);
00293         ll_apr_file_write(outfp,pcmout,2*fade_length);  //write back xfaded first 16 samples
00294 
00295         ll_apr_file_seek(outfp,APR_END,-fade_length*2); 
00296         ll_apr_file_read(outfp, pcmout,2*fade_length);  //read last 16 samples
00297 
00298         samplep = (S16 *)pcmout;
00299 
00300         for (i = fade_length-1 ; i >=  0; i--)
00301         {
00302                 *samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length));          
00303         }
00304         
00305         ll_apr_file_seek(outfp,SEEK_END,-fade_length*2); 
00306         ll_apr_file_write(outfp,pcmout,2*fade_length);  //write back xfaded last 16 samples
00307 
00308         apr_file_close(outfp);
00309 
00310         if ((36 == data_length) || (!(eof)))
00311         {
00312                 llwarning("BAD Vorbis DECODE!, removing .wav!",0); 
00313                 LLFile::remove(out_fname);
00314                 return (FALSE);
00315         }
00316     
00317 //      fprintf(stderr,"Done.\n");
00318 
00319         return(TRUE);
00320 }
00321 #endif

Generated on Fri May 16 08:31:55 2008 for SecondLife by  doxygen 1.5.5