llvorbisencode.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:15k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file vorbisencode.cpp
  3.  * @brief Vorbis encoding routine routine for Indra.
  4.  *
  5.  * $LicenseInfo:firstyear=2000&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2000-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "vorbis/vorbisenc.h"
  34. #include "llvorbisencode.h"
  35. #include "llerror.h"
  36. #include "llrand.h"
  37. #include "llmath.h"
  38. #include "llapr.h"
  39. //#if LL_DARWIN
  40. // MBW -- XXX -- Getting rid of SecondLifeVorbis for now -- no fmod means no name collisions.
  41. #if 0
  42. #include "VorbisFramework.h"
  43. #define vorbis_analysis mac_vorbis_analysis
  44. #define vorbis_analysis_headerout mac_vorbis_analysis_headerout
  45. #define vorbis_analysis_init mac_vorbis_analysis_init
  46. #define vorbis_encode_ctl mac_vorbis_encode_ctl
  47. #define vorbis_encode_setup_init mac_vorbis_encode_setup_init
  48. #define vorbis_encode_setup_managed mac_vorbis_encode_setup_managed
  49. #define vorbis_info_init mac_vorbis_info_init
  50. #define vorbis_info_clear mac_vorbis_info_clear
  51. #define vorbis_comment_init mac_vorbis_comment_init
  52. #define vorbis_comment_clear mac_vorbis_comment_clear
  53. #define vorbis_block_init mac_vorbis_block_init
  54. #define vorbis_block_clear mac_vorbis_block_clear
  55. #define vorbis_dsp_clear mac_vorbis_dsp_clear
  56. #define vorbis_analysis_buffer mac_vorbis_analysis_buffer
  57. #define vorbis_analysis_wrote mac_vorbis_analysis_wrote
  58. #define vorbis_analysis_blockout mac_vorbis_analysis_blockout
  59. #define ogg_stream_packetin mac_ogg_stream_packetin
  60. #define ogg_stream_init mac_ogg_stream_init
  61. #define ogg_stream_flush mac_ogg_stream_flush
  62. #define ogg_stream_pageout mac_ogg_stream_pageout
  63. #define ogg_page_eos mac_ogg_page_eos
  64. #define ogg_stream_clear mac_ogg_stream_clear
  65. #endif
  66. S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg)
  67. {
  68. U16 num_channels = 0;
  69. U32 sample_rate = 0;
  70. U32 bits_per_sample = 0;
  71. U32 physical_file_size = 0;
  72. U32 chunk_length = 0;
  73. U32 raw_data_length = 0;
  74. U32 bytes_per_sec = 0;
  75. BOOL uncompressed_pcm = FALSE;
  76. unsigned char wav_header[44]; /*Flawfinder: ignore*/
  77. error_msg.clear();
  78. //********************************
  79. LLAPRFile infile ;
  80.     infile.open(in_fname,LL_APR_RB);
  81. //********************************
  82. if (!infile.getFileHandle())
  83. {
  84. error_msg = "CannotUploadSoundFile";
  85. return(LLVORBISENC_SOURCE_OPEN_ERR);
  86. }
  87. infile.read(wav_header, 44);
  88. physical_file_size = infile.seek(APR_END,0);
  89. if (strncmp((char *)&(wav_header[0]),"RIFF",4))
  90. {
  91. error_msg = "SoundFileNotRIFF";
  92. return(LLVORBISENC_WAV_FORMAT_ERR);
  93. }
  94. if (strncmp((char *)&(wav_header[8]),"WAVE",4))
  95. {
  96. error_msg = "SoundFileNotRIFF";
  97. return(LLVORBISENC_WAV_FORMAT_ERR);
  98. }
  99. // parse the chunks
  100. U32 file_pos = 12;  // start at the first chunk (usually fmt but not always)
  101. while ((file_pos + 8)< physical_file_size)
  102. {
  103. infile.seek(APR_SET,file_pos);
  104. infile.read(wav_header, 44);
  105. chunk_length = ((U32) wav_header[7] << 24) 
  106. + ((U32) wav_header[6] << 16) 
  107. + ((U32) wav_header[5] << 8) 
  108. + wav_header[4];
  109. // llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl;
  110. if (!(strncmp((char *)&(wav_header[0]),"fmt ",4)))
  111. {
  112. if ((wav_header[8] == 0x01) && (wav_header[9] == 0x00))
  113. {
  114. uncompressed_pcm = TRUE;
  115. }
  116. num_channels = ((U16) wav_header[11] << 8) + wav_header[10];
  117. sample_rate = ((U32) wav_header[15] << 24) 
  118. + ((U32) wav_header[14] << 16) 
  119. + ((U32) wav_header[13] << 8) 
  120. + wav_header[12];
  121. bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22];
  122. bytes_per_sec = ((U32) wav_header[19] << 24) 
  123. + ((U32) wav_header[18] << 16) 
  124. + ((U32) wav_header[17] << 8) 
  125. + wav_header[16];
  126. }
  127. else if (!(strncmp((char *)&(wav_header[0]),"data",4)))
  128. {
  129. raw_data_length = chunk_length;
  130. }
  131. file_pos += (chunk_length + 8);
  132. chunk_length = 0;
  133. //****************
  134. infile.close();
  135. //****************
  136. if (!uncompressed_pcm)
  137. {
  138.  error_msg = "SoundFileNotPCM";
  139.   return(LLVORBISENC_PCM_FORMAT_ERR);
  140. }
  141. if ((num_channels < 1) || (num_channels > LLVORBIS_CLIP_MAX_CHANNELS))
  142. {
  143. error_msg = "SoundFileInvalidChannelCount";
  144. return(LLVORBISENC_MULTICHANNEL_ERR);
  145. }
  146. if (sample_rate != LLVORBIS_CLIP_SAMPLE_RATE)
  147. {
  148. error_msg = "SoundFileInvalidSampleRate";
  149. return(LLVORBISENC_UNSUPPORTED_SAMPLE_RATE);
  150. }
  151. if ((bits_per_sample != 16) && (bits_per_sample != 8))
  152. {  
  153. error_msg = "SoundFileInvalidWordSize";
  154. return(LLVORBISENC_UNSUPPORTED_WORD_SIZE);
  155. }
  156. if (!raw_data_length)
  157. {
  158. error_msg = "SoundFileInvalidHeader";
  159. return(LLVORBISENC_CLIP_TOO_LONG);  
  160. }
  161. F32 clip_length = (F32)raw_data_length/(F32)bytes_per_sec;
  162. if (clip_length > LLVORBIS_CLIP_MAX_TIME)
  163. {
  164. error_msg = "SoundFileInvalidTooLong";
  165. return(LLVORBISENC_CLIP_TOO_LONG);  
  166. }
  167.     return(LLVORBISENC_NOERR);
  168. }
  169. S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname)
  170. {
  171. #define READ_BUFFER 1024
  172. unsigned char readbuffer[READ_BUFFER*4+44];   /* out of the data segment, not the stack */ /*Flawfinder: ignore*/
  173. ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */
  174. ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
  175. ogg_packet       op; /* one raw packet of data for decode */
  176. vorbis_info      vi; /* struct that stores all the static vorbis bitstream settings */
  177. vorbis_comment   vc; /* struct that stores all the user comments */
  178. vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
  179. vorbis_block     vb; /* local working space for packet->PCM decode */
  180. int eos=0;
  181. int result;
  182. U16 num_channels = 0;
  183. U32 sample_rate = 0;
  184. U32 bits_per_sample = 0;
  185. S32 format_error = 0;
  186. std::string error_msg;
  187. if ((format_error = check_for_invalid_wav_formats(in_fname, error_msg)))
  188. {
  189. llwarns << error_msg << ": " << in_fname << llendl;
  190. return(format_error);
  191. }
  192. #if 1
  193. unsigned char wav_header[44]; /*Flawfinder: ignore*/
  194. S32 data_left = 0;
  195. LLAPRFile infile ;
  196. infile.open(in_fname,LL_APR_RB);
  197. if (!infile.getFileHandle())
  198. {
  199. llwarns << "Couldn't open temporary ogg file for writing: " << in_fname
  200. << llendl;
  201. return(LLVORBISENC_SOURCE_OPEN_ERR);
  202. }
  203. LLAPRFile outfile ;
  204. outfile.open(out_fname,LL_APR_WPB);
  205. if (!outfile.getFileHandle())
  206. {
  207. llwarns << "Couldn't open upload sound file for reading: " << in_fname
  208. << llendl;
  209. return(LLVORBISENC_DEST_OPEN_ERR);
  210. }
  211.  // parse the chunks
  212.  U32 chunk_length = 0;
  213.  U32 file_pos = 12;  // start at the first chunk (usually fmt but not always)
  214.  
  215.  while (infile.eof() != APR_EOF)
  216.  {
  217.  infile.seek(APR_SET,file_pos);
  218.  infile.read(wav_header, 44);
  219.  
  220.  chunk_length = ((U32) wav_header[7] << 24) 
  221.  + ((U32) wav_header[6] << 16) 
  222.  + ((U32) wav_header[5] << 8) 
  223.  + wav_header[4];
  224.  
  225. //  llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl;
  226.  
  227.  if (!(strncmp((char *)&(wav_header[0]),"fmt ",4)))
  228.  {
  229.  num_channels = ((U16) wav_header[11] << 8) + wav_header[10];
  230.  sample_rate = ((U32) wav_header[15] << 24) 
  231.  + ((U32) wav_header[14] << 16) 
  232.  + ((U32) wav_header[13] << 8) 
  233.  + wav_header[12];
  234.  bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22];
  235.  }
  236.    else if (!(strncmp((char *)&(wav_header[0]),"data",4)))
  237.  {
  238.  infile.seek(APR_SET,file_pos+8);
  239.  // leave the file pointer at the beginning of the data chunk data
  240.  data_left = chunk_length;
  241.  break;
  242.  }
  243.  file_pos += (chunk_length + 8);
  244.  chunk_length = 0;
  245.  } 
  246.  
  247.  /********** Encode setup ************/
  248.  
  249.  /* choose an encoding mode */
  250.  /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
  251.  vorbis_info_init(&vi);
  252.  // always encode to mono
  253.  // SL-52913 & SL-53779 determined this quality level to be our 'good
  254.  // enough' general-purpose quality level with a nice low bitrate.
  255.  // Equivalent to oggenc -q0.5
  256.  F32 quality = 0.05f;
  257. //  quality = (bitrate==128000 ? 0.4f : 0.1);
  258. //  if (vorbis_encode_init(&vi, /* num_channels */ 1 ,sample_rate, -1, bitrate, -1))
  259.  if (vorbis_encode_init_vbr(&vi, /* num_channels */ 1 ,sample_rate, quality))
  260. //  if (vorbis_encode_setup_managed(&vi,1,sample_rate,-1,bitrate,-1) ||
  261. // vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE_AVG,NULL) ||
  262. // vorbis_encode_setup_init(&vi))
  263. {
  264. llwarns << "unable to initialize vorbis codec at quality " << quality << llendl;
  265. // llwarns << "unable to initialize vorbis codec at bitrate " << bitrate << llendl;
  266. return(LLVORBISENC_DEST_OPEN_ERR);
  267. }
  268.  
  269.  /* add a comment */
  270.  vorbis_comment_init(&vc);
  271. //  vorbis_comment_add(&vc,"Linden");
  272.  
  273.  /* set up the analysis state and auxiliary encoding storage */
  274.  vorbis_analysis_init(&vd,&vi);
  275.  vorbis_block_init(&vd,&vb);
  276.  
  277.  /* set up our packet->stream encoder */
  278.  /* pick a random serial number; that way we can more likely build
  279. chained streams just by concatenation */
  280.  ogg_stream_init(&os, ll_rand());
  281.  
  282.  /* Vorbis streams begin with three headers; the initial header (with
  283. most of the codec setup parameters) which is mandated by the Ogg
  284. bitstream spec.  The second header holds any comment fields.  The
  285. third header holds the bitstream codebook.  We merely need to
  286. make the headers, then pass them to libvorbis one at a time;
  287. libvorbis handles the additional Ogg bitstream constraints */
  288.  
  289.  {
  290.  ogg_packet header;
  291.  ogg_packet header_comm;
  292.  ogg_packet header_code;
  293.  
  294.  vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
  295.  ogg_stream_packetin(&os,&header); /* automatically placed in its own
  296.   page */
  297.  ogg_stream_packetin(&os,&header_comm);
  298.  ogg_stream_packetin(&os,&header_code);
  299.  
  300.  /* We don't have to write out here, but doing so makes streaming 
  301.   * much easier, so we do, flushing ALL pages. This ensures the actual
  302.   * audio data will start on a new page
  303.   */
  304.  while(!eos){
  305.  int result=ogg_stream_flush(&os,&og);
  306.  if(result==0)break;
  307.  outfile.write(og.header, og.header_len);
  308.  outfile.write(og.body, og.body_len);
  309.  }
  310.  
  311.  }
  312.  
  313.  
  314.  while(!eos)
  315.  {
  316.  long bytes_per_sample = bits_per_sample/8;
  317.  long bytes=(long)infile.read(readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); /* stereo hardwired here */
  318.  
  319.  if (bytes==0)
  320.  {
  321.  /* end of file.  this can be done implicitly in the mainline,
  322. but it's easier to see here in non-clever fashion.
  323. Tell the library we're at end of stream so that it can handle
  324. the last frame and mark end of stream in the output properly */
  325.  vorbis_analysis_wrote(&vd,0);
  326. //  eos = 1;
  327.  
  328.  }
  329.  else
  330.  {
  331.  long i;
  332.  long samples;
  333.  int temp;
  334.  data_left -= bytes;
  335.              /* data to encode */
  336.  
  337.  /* expose the buffer to submit data */
  338.  float **buffer=vorbis_analysis_buffer(&vd,READ_BUFFER);
  339.  i = 0;
  340.  samples = bytes / (num_channels * bytes_per_sample);
  341.  if (num_channels == 2)
  342.  {
  343.  if (bytes_per_sample == 2)
  344.  {
  345.  /* uninterleave samples */
  346.  for(i=0; i<samples ;i++)
  347.  {
  348.    temp =  ((signed char *)readbuffer)[i*4+1]; /*Flawfinder: ignore*/
  349.  temp += ((signed char *)readbuffer)[i*4+3]; /*Flawfinder: ignore*/
  350.  temp <<= 8;
  351.  temp += readbuffer[i*4];
  352.  temp += readbuffer[i*4+2];
  353.  buffer[0][i] = ((float)temp) / 65536.f;
  354.  }
  355.  }
  356.  else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard")
  357.  {
  358.  /* uninterleave samples */
  359.  for(i=0; i<samples ;i++)
  360.  {
  361.    temp  = readbuffer[i*2+0];
  362.  temp += readbuffer[i*2+1];
  363.  temp -= 256;
  364.  buffer[0][i] = ((float)temp) / 256.f;
  365.  }
  366.  } 
  367.  }
  368.  else if (num_channels == 1)
  369.  {
  370.  if (bytes_per_sample == 2)
  371.  {
  372.  for(i=0; i < samples ;i++)
  373.  {
  374.    temp = ((signed char*)readbuffer)[i*2+1];
  375.  temp <<= 8;
  376.  temp += readbuffer[i*2];
  377.  buffer[0][i] = ((float)temp) / 32768.f;
  378.  }
  379.  }
  380.  else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard")
  381.  {
  382.  for(i=0; i < samples ;i++)
  383.  {
  384.  temp = readbuffer[i];
  385.  temp -= 128;
  386.  buffer[0][i] = ((float)temp) / 128.f;
  387.  }
  388.  }
  389.  }
  390.  /* tell the library how much we actually submitted */
  391.  vorbis_analysis_wrote(&vd,i);
  392.  }
  393.  
  394.  /* vorbis does some data preanalysis, then divvies up blocks for
  395. more involved (potentially parallel) processing.  Get a single
  396. block for encoding now */
  397.  while(vorbis_analysis_blockout(&vd,&vb)==1)
  398.  {
  399.  
  400.  /* analysis */
  401. /* Do the main analysis, creating a packet */
  402. vorbis_analysis(&vb, NULL);
  403. vorbis_bitrate_addblock(&vb);
  404. while(vorbis_bitrate_flushpacket(&vd, &op)) 
  405. {
  406.  
  407.  /* weld the packet into the bitstream */
  408.  ogg_stream_packetin(&os,&op);
  409.  
  410.  /* write out pages (if any) */
  411.  while(!eos)
  412.  {
  413.  result = ogg_stream_pageout(&os,&og);
  414.  if(result==0)
  415.   break;
  416.  outfile.write(og.header, og.header_len);
  417.  outfile.write(og.body, og.body_len);
  418.  
  419.  /* this could be set above, but for illustrative purposes, I do
  420. it here (to show that vorbis does know where the stream ends) */
  421.  
  422.  if(ogg_page_eos(&og))
  423.   eos=1;
  424.  
  425.  }
  426. }
  427.  }
  428.  }
  429.  
  430.  
  431.  
  432.  /* clean up and exit.  vorbis_info_clear() must be called last */
  433.  
  434.  ogg_stream_clear(&os);
  435.  vorbis_block_clear(&vb);
  436.  vorbis_dsp_clear(&vd);
  437.  vorbis_comment_clear(&vc);
  438.  vorbis_info_clear(&vi);
  439.  
  440.  /* ogg_page and ogg_packet structs always point to storage in
  441. libvorbis.  They're never freed or manipulated directly */
  442.  
  443. //  fprintf(stderr,"Vorbis encoding: Done.n");
  444.  llinfos << "Vorbis encoding: Done." << llendl;
  445.  
  446. #endif
  447.  return(LLVORBISENC_NOERR);
  448.  
  449. }