00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <inttypes.h>
00025 #include <out_vorbis.h>
00026 #ifdef HAVE_VORBIS
00027
00028 #include <jutils.h>
00029 #include <generic.h>
00030 #include <config.h>
00031
00032 OutVorbis::OutVorbis()
00033 : OutChannel("vorbis") {
00034 func("OutVorbis::OutVorbis() %p",this);
00035
00036 headersize = 0;
00037
00038 sprintf(name,"Ogg/Vorbis encoder");
00039 sprintf(version," ");
00040
00041 tipo = OGG;
00042
00043
00044
00045 pcm = (float*) malloc(INBUF);
00046 rsmpled = (float*) malloc(RSMPBUF);
00047 rsmp_state = NULL;
00048
00049 encoder_initialized = false;
00050 }
00051
00052
00053 bool OutVorbis::init() {
00054 func("OutVorbis::init() %p",this);
00055
00056
00057
00058
00059
00060
00061 if(!apply_profile()) {
00062 error("problems in setting up codec parameters");
00063
00064 return false;
00065 }
00066
00067 erbapipa->set_output_type("copy_int16_to_float");
00068
00069 initialized = true;
00070 return initialized;
00071 }
00072
00073
00074
00075 int OutVorbis::encode() {
00076 int num = 0, samples = 0;
00077 int rsmperr, res;
00078 _pbyte = (int8_t*)buffer;
00079
00080 if(headersize) {
00081 memcpy(buffer,header,headersize);
00082 encoded = headersize;
00083 shout(); dump();
00084 }
00085
00086 encoded = headersize = 0;
00087
00088 if(erbapipa->size() < out_chunk_len) {
00089
00090 return -1;
00091 }
00092
00093
00094 num = erbapipa->read(OUT_CHUNK,pcm);
00095
00096
00097
00098 if(num<OUT_CHUNK)
00099 func("OutVorbis::encode() : erbapipa->read_float_bidi reads %i samples instead of %i",
00100 num,OUT_CHUNK);
00101 if(num<1) return num;
00102
00103 rsmp_data.data_in = pcm;
00104 rsmp_data.input_frames = num;
00105 rsmp_data.data_out = rsmpled;
00106 rsmp_data.output_frames = RSMPBUF;
00107
00108
00109 rsmperr = src_process(rsmp_state,&rsmp_data);
00110 if(rsmperr) {
00111 error("error in ogg resampler: %s",src_strerror(rsmperr));
00112 if(rsmperr==6) error("resampling ratio is %.4f",rsmp_data.src_ratio);
00113 }
00114
00115 samples = rsmp_data.output_frames_gen;
00116 func("%i frames resampled in %i with ratio %.4f (num:%u OUT_CHUNK:%u)",
00117 rsmp_data.input_frames_used, samples, rsmp_data.src_ratio, num, OUT_CHUNK);
00118
00119
00120 _intbuf = vorbis_analysis_buffer(&vd,samples);
00121
00122
00123
00124
00125
00126
00127
00128
00129 prepare(rsmpled,_intbuf,samples);
00130 res = vorbis_analysis_wrote(&vd,samples);
00131 if(res) {
00132 error("OutVorbis::encode : error %i from vorbis_analysis_wrote");
00133 return 0; }
00134
00135
00136 while(vorbis_analysis_blockout(&vd,&vb)==1) {
00137
00138 res = vorbis_analysis(&vb, NULL);
00139
00140 if(res) {
00141 error("OutVorbis::encode : error %i from vorbis_analysis_wrote");
00142 return 0;
00143 }
00144
00145 res = vorbis_bitrate_addblock(&vb);
00146 if(res) {
00147 error("OutVorbis::encode : error %i from vorbis_bitrate_addblock");
00148 return 0;
00149 }
00150
00151 while(vorbis_bitrate_flushpacket(&vd, &op)) {
00152
00153 res = ogg_stream_packetin(&os,&op);
00154 if(res) {
00155 error("OutVorbis::encode : error %i from ogg_stream_packetin");
00156 return 0;
00157 }
00158
00159 while(ogg_stream_pageout(&os,&og)) {
00160 memcpy(_pbyte,og.header,og.header_len);
00161 _pbyte += og.header_len;
00162 memcpy(_pbyte,og.body,og.body_len);
00163 _pbyte += og.body_len;
00164
00165 encoded += og.header_len + og.body_len;
00166
00167
00168
00169 }
00170
00171 }
00172 }
00173 return encoded;
00174 }
00175
00176 int OutVorbis::prepare(float *buf, float **fbuf, int num) {
00177
00178
00179 int i=0;
00180 switch(channels()) {
00181 case 1:
00182 for(i=num; i>0; i--)
00183 fbuf[0][i] = buf[i];
00184 break;
00185 case 2:
00186 for(i=0; i<num; i++) {
00187 fbuf[0][i] = buf[i<<1];
00188 fbuf[1][i] = buf[(i<<1)+1];
00189 }
00190 break;
00191 default:
00192 error("error in OutVorbis::prepare");
00193 error("no more than 2 audio channels are supported");
00194 break;
00195 }
00196
00197 return i;
00198
00199
00200
00201
00202
00203
00204
00205 }
00206
00207
00208 void OutVorbis::flush() {
00209
00210 vorbis_analysis_wrote(&vd,0);
00211
00212 }
00213
00214 bool OutVorbis::apply_profile() {
00215 func("OutVorbis::apply_profile() q%.4f r%i b%i c%i",
00216 _quality,freq(),bps(),channels());
00217 bool res = true;
00218 int rsmp_err = 0;
00219
00220 if(rsmp_state) src_delete(rsmp_state);
00221
00222 rsmp_state = src_new(SRC_SINC_FASTEST, channels() ,&rsmp_err);
00223 if(!rsmp_state)
00224 error("Ogg/Vorbis can't initialize resampler: %s",src_strerror(rsmp_err));
00225 else func("ogg resampler %s initialized",src_get_name(SRC_SINC_FASTEST));
00226
00227
00228 {
00229 double ratio = (double)((float)freq() / 44100.0f);
00230 rsmp_data.src_ratio = ratio/2;
00231 }
00232 if(!src_is_valid_ratio(rsmp_data.src_ratio))
00233 error("invalid resampling ratio: %.4f", rsmp_data.src_ratio);
00234 func("resample ratio for freq %i is %.4f", freq(), rsmp_data.src_ratio);
00235
00236
00239 if(encoder_initialized) {
00240
00241 ogg_stream_clear(&os);
00242 vorbis_block_clear(&vb);
00243 vorbis_dsp_clear(&vd);
00244 vorbis_info_clear(&vi);
00245 } else encoder_initialized = true;
00246
00247 vorbis_info_init(&vi);
00248 if( vorbis_encode_init
00249 (&vi, channels(), freq(), bps()*1000, bps()*1000, bps()*1000) ) {
00250 error("vorbis_encode_init failed: invalid parameters");
00251 res = false;
00252 }
00253
00254
00255 vorbis_analysis_init(&vd,&vi);
00256 vorbis_block_init(&vd,&vb);
00257 ogg_stream_init(&os, time(NULL));
00258
00259
00260 {
00261 char tmp[128];
00262 sprintf(tmp,"%s version %s",PACKAGE,VERSION);
00263 vorbis_comment_init(&vc);
00264 vorbis_comment_add_tag(&vc,"Streamed with",tmp);
00265 }
00266
00267
00268
00269
00270
00271 vorbis_analysis_headerout
00272 (&vd,&vc,&header_main,&header_comments,&header_codebooks);
00273
00274
00275 ogg_stream_packetin(&os,&header_main);
00276 ogg_stream_packetin(&os,&header_comments);
00277 ogg_stream_packetin(&os,&header_codebooks);
00278
00279
00280 headersize = 0;
00281 _pbyte = (int8_t*)header;
00282 while(ogg_stream_flush(&os,&og)) {
00283 memcpy(_pbyte,og.header,og.header_len);
00284 _pbyte += og.header_len;
00285 memcpy(_pbyte,og.body,og.body_len);
00286 _pbyte += og.body_len;
00287 headersize += og.header_len + og.body_len;
00288 }
00289
00290 vorbis_comment_clear(&vc);
00292
00293
00294
00295 Shouter *ice = (Shouter*)icelist.begin();
00296 while(ice) {
00297 char tmp[256];
00298
00299 snprintf(tmp,256,"%u",bps()); ice->bps( tmp );
00300 snprintf(tmp,256,"%u",freq()); ice->freq( tmp );
00301 snprintf(tmp,256,"%u",channels()); ice->channels( tmp );
00302
00303
00304 ice = (Shouter*)ice->next;
00305 }
00306
00307
00308 out_chunk_len = OUT_CHUNK * sizeof(float) * 2;
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 return res;
00321 }
00322
00323 OutVorbis::~OutVorbis() {
00324 func("OutVorbis::~OutVorbis() %p",this);
00325
00326 act("closing ogg/vorbis encoder");
00327
00328 if(rsmp_state) src_delete(rsmp_state);
00329 free(pcm);
00330 free(rsmpled);
00331
00332 if(encoder_initialized) {
00333 ogg_stream_clear(&os);
00334 vorbis_block_clear(&vb);
00335 vorbis_dsp_clear(&vd);
00336 vorbis_info_clear(&vi);
00337 }
00338 }
00339
00340 #endif