00001 
00032 #include "linden_common.h"
00033 
00034 #include "vorbisencode.h"
00035 #include "vorbis/vorbisenc.h"
00036 #include "llerror.h"
00037 #include "llrand.h"
00038 #include "llmath.h"
00039 #include "llapr.h"
00040 
00041 
00042 
00043 #if 0
00044 #include "VorbisFramework.h"
00045 
00046 #define vorbis_analysis                         mac_vorbis_analysis
00047 #define vorbis_analysis_headerout       mac_vorbis_analysis_headerout
00048 #define vorbis_analysis_init            mac_vorbis_analysis_init
00049 #define vorbis_encode_ctl                       mac_vorbis_encode_ctl
00050 #define vorbis_encode_setup_init        mac_vorbis_encode_setup_init
00051 #define vorbis_encode_setup_managed     mac_vorbis_encode_setup_managed
00052 
00053 #define vorbis_info_init                        mac_vorbis_info_init
00054 #define vorbis_info_clear                       mac_vorbis_info_clear
00055 #define vorbis_comment_init                     mac_vorbis_comment_init
00056 #define vorbis_comment_clear            mac_vorbis_comment_clear
00057 #define vorbis_block_init                       mac_vorbis_block_init
00058 #define vorbis_block_clear                      mac_vorbis_block_clear
00059 #define vorbis_dsp_clear                        mac_vorbis_dsp_clear
00060 #define vorbis_analysis_buffer          mac_vorbis_analysis_buffer
00061 #define vorbis_analysis_wrote           mac_vorbis_analysis_wrote
00062 #define vorbis_analysis_blockout        mac_vorbis_analysis_blockout
00063 
00064 #define ogg_stream_packetin                     mac_ogg_stream_packetin
00065 #define ogg_stream_init                         mac_ogg_stream_init
00066 #define ogg_stream_flush                        mac_ogg_stream_flush
00067 #define ogg_stream_pageout                      mac_ogg_stream_pageout
00068 #define ogg_page_eos                            mac_ogg_page_eos
00069 #define ogg_stream_clear                        mac_ogg_stream_clear
00070 
00071 #endif
00072 
00073 S32 check_for_invalid_wav_formats(const char *in_fname, char *error_msg)
00074 {
00075         U16 num_channels = 0;
00076         U32 sample_rate = 0;
00077         U32 bits_per_sample = 0;
00078         U32 physical_file_size = 0;
00079         U32 chunk_length = 0;
00080         U32 raw_data_length = 0;
00081         U32 bytes_per_sec = 0;
00082         BOOL uncompressed_pcm = FALSE;
00083 
00084         unsigned char wav_header[44];           
00085 
00086         error_msg[0] = '\0';
00087 
00088     apr_file_t* infp = ll_apr_file_open(in_fname,LL_APR_RB);
00089         if (!infp)
00090         {
00091                 strcpy(error_msg, "CannotUploadSoundFile");     
00092                 return(LLVORBISENC_SOURCE_OPEN_ERR);
00093         }
00094 
00095         ll_apr_file_read(infp, wav_header, 44);
00096         physical_file_size = ll_apr_file_seek(infp,APR_END,0);
00097 
00098         if (strncmp((char *)&(wav_header[0]),"RIFF",4))
00099         {
00100                 strcpy(error_msg, "SoundFileNotRIFF");  
00101                 apr_file_close(infp);
00102             return(LLVORBISENC_WAV_FORMAT_ERR);
00103         }
00104 
00105         if (strncmp((char *)&(wav_header[8]),"WAVE",4))
00106         {
00107                 strcpy(error_msg, "SoundFileNotRIFF");  
00108                 apr_file_close(infp);
00109             return(LLVORBISENC_WAV_FORMAT_ERR);
00110         }
00111         
00112         
00113         
00114         U32 file_pos = 12;  
00115         
00116         while ((file_pos + 8)< physical_file_size)
00117         {
00118                 ll_apr_file_seek(infp,APR_SET,file_pos);
00119                 ll_apr_file_read(infp, wav_header, 44);
00120 
00121                 chunk_length = ((U32) wav_header[7] << 24) 
00122                         + ((U32) wav_header[6] << 16) 
00123                         + ((U32) wav_header[5] << 8) 
00124                         + wav_header[4];
00125 
00126 
00127 
00128                 if (!(strncmp((char *)&(wav_header[0]),"fmt ",4)))
00129                 {
00130                         if ((wav_header[8] == 0x01) && (wav_header[9] == 0x00))
00131                         {
00132                                 uncompressed_pcm = TRUE;
00133                         }
00134                         num_channels = ((U16) wav_header[11] << 8) + wav_header[10];
00135                         sample_rate = ((U32) wav_header[15] << 24) 
00136                                 + ((U32) wav_header[14] << 16) 
00137                                 + ((U32) wav_header[13] << 8) 
00138                                 + wav_header[12];
00139                         bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22];
00140                         bytes_per_sec = ((U32) wav_header[19] << 24) 
00141                                 + ((U32) wav_header[18] << 16) 
00142                                 + ((U32) wav_header[17] << 8) 
00143                                 + wav_header[16];
00144                 }
00145                 else if (!(strncmp((char *)&(wav_header[0]),"data",4)))
00146                 {
00147                         raw_data_length = chunk_length;                 
00148                 }
00149                 file_pos += (chunk_length + 8);
00150                 chunk_length = 0;
00151         } 
00152 
00153         apr_file_close(infp);   
00154 
00155         if (!uncompressed_pcm)
00156         {       
00157                  strcpy(error_msg, "SoundFileNotPCM");          
00158                   return(LLVORBISENC_PCM_FORMAT_ERR);
00159         }
00160         
00161         if ((num_channels < 1) || (num_channels > 2))
00162         {       
00163                 strcpy(error_msg, "SoundFileInvalidChannelCount");      
00164                 return(LLVORBISENC_MULTICHANNEL_ERR);
00165         }
00166 
00167         if (sample_rate != 44100)
00168         {       
00169                 strcpy(error_msg, "SoundFileInvalidSampleRate");                
00170                 return(LLVORBISENC_UNSUPPORTED_SAMPLE_RATE);
00171         }
00172         
00173         if ((bits_per_sample != 16) && (bits_per_sample != 8))
00174         {                
00175                 strcpy(error_msg, "SoundFileInvalidWordSize");          
00176                 return(LLVORBISENC_UNSUPPORTED_WORD_SIZE);
00177         }
00178 
00179         if (!raw_data_length)
00180         {
00181                 strcpy(error_msg, "SoundFileInvalidHeader");                    
00182                 return(LLVORBISENC_CLIP_TOO_LONG);               
00183         }
00184 
00185         F32 clip_length = (F32)raw_data_length/(F32)bytes_per_sec;
00186                 
00187         if (clip_length > 10.0f)
00188         {
00189                 strcpy(error_msg, "SoundFileInvalidTooLong");                   
00190                 return(LLVORBISENC_CLIP_TOO_LONG);               
00191         }
00192 
00193     return(LLVORBISENC_NOERR);
00194 }
00195 
00196 S32 encode_vorbis_file(const char *in_fname, const char *out_fname)
00197 {
00198         return(encode_vorbis_file_at(in_fname,out_fname, 128000));
00199 }
00200 
00201 S32 encode_vorbis_file_at(const char *in_fname, const char *out_fname, S32 bitrate)
00202 {
00203 #define READ_BUFFER 1024
00204         unsigned char readbuffer[READ_BUFFER*4+44];         
00205 
00206         ogg_stream_state os; 
00207         ogg_page         og; 
00208         ogg_packet       op; 
00209         
00210         vorbis_info      vi; 
00211         vorbis_comment   vc; 
00212         
00213         vorbis_dsp_state vd; 
00214         vorbis_block     vb; 
00215         
00216         int eos=0;
00217         int result;
00218 
00219         U16 num_channels = 0;
00220         U32 sample_rate = 0;
00221         U32 bits_per_sample = 0;
00222 
00223         S32 format_error = 0;
00224         char error_msg[MAX_STRING];     
00225         if ((format_error = check_for_invalid_wav_formats(in_fname, error_msg)))
00226         {
00227                 llwarns << error_msg << ": " << in_fname << llendl;
00228                 return(format_error);
00229         }
00230 
00231 #if 1
00232         unsigned char wav_header[44];   
00233 
00234         S32 data_left = 0;
00235 
00236         apr_file_t* infp = ll_apr_file_open(in_fname,LL_APR_RB);
00237         if (!infp)
00238         {
00239                 llwarns << "Couldn't open temporary ogg file for writing: " << in_fname
00240                         << llendl;
00241                 return(LLVORBISENC_SOURCE_OPEN_ERR);
00242         }
00243         apr_file_t* outfp = ll_apr_file_open(out_fname,LL_APR_WPB);
00244         if (!outfp)
00245         {
00246                 llwarns << "Couldn't open upload sound file for reading: " << in_fname
00247                         << llendl;
00248                 apr_file_close (infp);
00249                 return(LLVORBISENC_DEST_OPEN_ERR);
00250         }
00251         
00252          
00253          U32 chunk_length = 0;
00254          U32 file_pos = 12;  
00255          
00256          while (apr_file_eof(infp) != APR_EOF)
00257          {
00258                  ll_apr_file_seek(infp,APR_SET,file_pos);
00259                  ll_apr_file_read(infp, wav_header, 44);
00260                  
00261                  chunk_length = ((U32) wav_header[7] << 24) 
00262                          + ((U32) wav_header[6] << 16) 
00263                          + ((U32) wav_header[5] << 8) 
00264                          + wav_header[4];
00265                  
00266 
00267                  
00268                  if (!(strncmp((char *)&(wav_header[0]),"fmt ",4)))
00269                  {
00270                          num_channels = ((U16) wav_header[11] << 8) + wav_header[10];
00271                          sample_rate = ((U32) wav_header[15] << 24) 
00272                                  + ((U32) wav_header[14] << 16) 
00273                                  + ((U32) wav_header[13] << 8) 
00274                                  + wav_header[12];
00275                          bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22];
00276                  }
00277                  else if (!(strncmp((char *)&(wav_header[0]),"data",4)))
00278                  {
00279                          ll_apr_file_seek(infp,APR_SET,file_pos+8);
00280                          
00281                          data_left = chunk_length;                      
00282                          break;
00283                  }
00284                  file_pos += (chunk_length + 8);
00285                  chunk_length = 0;
00286          } 
00287          
00288 
00289 
00290          
00291          
00292          
00293          
00294          vorbis_info_init(&vi);
00295 
00296          
00297 
00298 
00299 
00300 
00301 
00302 
00303          if (vorbis_encode_init(&vi,  1 ,sample_rate, -1, bitrate, -1))
00304 
00305 
00306 
00307 
00308         {
00309 
00310                 llwarns << "unable to initialize vorbis codec at bitrate " << bitrate << llendl;
00311                 return(LLVORBISENC_DEST_OPEN_ERR);
00312         }
00313          
00314          
00315          vorbis_comment_init(&vc);
00316 
00317          
00318          
00319          vorbis_analysis_init(&vd,&vi);
00320          vorbis_block_init(&vd,&vb);
00321          
00322          
00323          
00324 
00325          ogg_stream_init(&os, ll_rand());
00326          
00327          
00328 
00329 
00330 
00331 
00332 
00333          
00334          {
00335                  ogg_packet header;
00336                  ogg_packet header_comm;
00337                  ogg_packet header_code;
00338                  
00339                  vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
00340                  ogg_stream_packetin(&os,&header); 
00341 
00342                  ogg_stream_packetin(&os,&header_comm);
00343                  ogg_stream_packetin(&os,&header_code);
00344                  
00345                  
00346 
00347 
00348 
00349                  while(!eos){
00350                          int result=ogg_stream_flush(&os,&og);
00351                          if(result==0)break;
00352                          ll_apr_file_write(outfp, og.header, og.header_len);
00353                          ll_apr_file_write(outfp, og.body, og.body_len);
00354                  }
00355                  
00356          }
00357          
00358          
00359          while(!eos)
00360          {
00361                  long bytes_per_sample = bits_per_sample/8;
00362 
00363                  long bytes=(long)ll_apr_file_read(infp, readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); 
00364                  
00365                  if (bytes==0)
00366                  {
00367                          
00368 
00369 
00370 
00371 
00372                          vorbis_analysis_wrote(&vd,0);
00373 
00374                          
00375                  }
00376                  else
00377                  {
00378                          long i;
00379                          long samples;
00380                          int temp;
00381 
00382                          data_left -= bytes;
00383              
00384                          
00385                          
00386                          float **buffer=vorbis_analysis_buffer(&vd,READ_BUFFER);
00387                         
00388                          i = 0;
00389                          samples = bytes / (num_channels * bytes_per_sample);
00390 
00391                          if (num_channels == 2)
00392                          {
00393                                  if (bytes_per_sample == 2)
00394                                  {
00395                                          
00396                                          for(i=0; i<samples ;i++)
00397                                          {
00398                                                  temp =  ((signed char *)readbuffer)[i*4+1];    
00399                                                  temp += ((signed char *)readbuffer)[i*4+3];    
00400                                                  temp <<= 8;
00401                                                  temp += readbuffer[i*4];
00402                                                  temp += readbuffer[i*4+2];
00403 
00404                                                  buffer[0][i] = ((float)temp) / 65536.f;
00405                                          }
00406                                  }
00407                                  else 
00408                                  {
00409                                          
00410                                          for(i=0; i<samples ;i++)
00411                                          {
00412                                                  temp  = readbuffer[i*2+0];
00413                                                  temp += readbuffer[i*2+1];
00414                                                  temp -= 256;
00415                                                  buffer[0][i] = ((float)temp) / 256.f;
00416                                          }
00417                                  } 
00418                          }
00419                          else if (num_channels == 1)
00420                          {
00421                                  if (bytes_per_sample == 2)
00422                                  {
00423                                          for(i=0; i < samples ;i++)
00424                                          {
00425                                                  temp = ((signed char*)readbuffer)[i*2+1];
00426                                                  temp <<= 8;
00427                                                  temp += readbuffer[i*2];
00428                                                  buffer[0][i] = ((float)temp) / 32768.f;
00429                                          }
00430                                  }
00431                                  else 
00432                                  {
00433                                          for(i=0; i < samples ;i++)
00434                                          {
00435                                                  temp = readbuffer[i];
00436                                                  temp -= 128;
00437                                                  buffer[0][i] = ((float)temp) / 128.f;
00438                                          }
00439                                  }
00440                          }
00441                                 
00442                          
00443                          vorbis_analysis_wrote(&vd,i);
00444                  }
00445                          
00446                  
00447 
00448 
00449                  while(vorbis_analysis_blockout(&vd,&vb)==1)
00450                  {
00451                          
00452                          
00453                         
00454                         vorbis_analysis(&vb, NULL);
00455                         vorbis_bitrate_addblock(&vb);
00456 
00457                         while(vorbis_bitrate_flushpacket(&vd, &op)) 
00458                         {
00459                          
00460                          
00461                          ogg_stream_packetin(&os,&op);
00462                          
00463                          
00464                          while(!eos)
00465                          {
00466                                  result = ogg_stream_pageout(&os,&og);
00467 
00468                                  if(result==0)
00469                                         break;
00470 
00471                                  ll_apr_file_write(outfp, og.header, og.header_len);
00472                                  ll_apr_file_write(outfp, og.body, og.body_len);
00473                                  
00474                                  
00475 
00476                                  
00477                                  if(ogg_page_eos(&og))
00478                                         eos=1;
00479                                  
00480                          }
00481                         }
00482                  }
00483          }
00484          
00485          
00486          
00487          
00488          
00489          ogg_stream_clear(&os);
00490          vorbis_block_clear(&vb);
00491          vorbis_dsp_clear(&vd);
00492          vorbis_comment_clear(&vc);
00493          vorbis_info_clear(&vi);
00494          
00495          
00496 
00497          
00498 
00499          llinfos << "Vorbis encoding: Done." << llendl;
00500          apr_file_close(outfp);
00501          apr_file_close(infp);
00502          
00503 #endif
00504          return(LLVORBISENC_NOERR);
00505          
00506 }