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