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 }