/** * Output debug information regarding the state of the Opus encoder */ void DebugEncoderInfo(OpusEncoder* Encoder) { int32 ErrCode = 0; int32 BitRate = 0; ErrCode = opus_encoder_ctl(Encoder, OPUS_GET_BITRATE(&BitRate)); int32 Vbr = 0; ErrCode = opus_encoder_ctl(Encoder, OPUS_GET_VBR(&Vbr)); int32 SampleRate = 0; ErrCode = opus_encoder_ctl(Encoder, OPUS_GET_SAMPLE_RATE(&SampleRate)); int32 Application = 0; ErrCode = opus_encoder_ctl(Encoder, OPUS_GET_APPLICATION(&Application)); int32 Complexity = 0; ErrCode = opus_encoder_ctl(Encoder, OPUS_GET_COMPLEXITY(&Complexity)); UE_LOG(LogVoiceEncode, Display, TEXT("Opus Encoder Details:\n Application: %d\n Bitrate: %d\n SampleRate: %d\n VBR: %d\n Complexity: %d"), Application, BitRate, SampleRate, Vbr, Complexity); }
void OggOpusFile::Init() { inopt.skip=0; //In our case, its 160 samples/frame. Changing rate to anything rather than 8000Hz may require significant change in the way of handle number of samples to fix the encoder frame_size=frame_size/(48000/coding_rate); /*OggOpus headers*/ /*FIXME: broke forcemono*/ header.channels=chan; header.channel_mapping= 0;//header.channels>8?255:chan>2; //=0 for wav header.input_sample_rate=rate; header.gain=inopt.gain; //=0 here st=opus_multistream_surround_encoder_create(coding_rate, chan, header.channel_mapping, &header.nb_streams, &header.nb_coupled, header.stream_map, frame_size<480/(48000/coding_rate)?OPUS_APPLICATION_RESTRICTED_LOWDELAY:OPUS_APPLICATION_AUDIO, &ret); if(ret!=OPUS_OK){ fprintf(stderr, "Error cannot create encoder: %s\n", opus_strerror(ret)); exit(1); } max_frame_bytes=(1275*3+7)*header.nb_streams; min_bytes=max_frame_bytes; m_outBuf = (unsigned char*)malloc(max_frame_bytes); if(m_outBuf==NULL){ fprintf(stderr,"Error allocating m_outBuf buffer.\n"); exit(1); } //We would set bitrate configurable as low as 6k //Or use the provided formulae to calculate a optimized bitrate if(bitrate<0){ /*Lower default rate for sampling rates [8000-44100) by a factor of (rate+16k)/(64k)*/ // bitrate=((64000*header.nb_streams+32000*header.nb_coupled)* // (IMIN(48,IMAX(8,((rate<44100?rate:48000)+1000)/1000))+16)+32)>>6; bitrate=6000; } if(bitrate>(1024000*chan)||bitrate<500){ fprintf(stderr,"Error: Bitrate %d bits/sec is insane.\nDid you mistake bits for kilobits?\n",bitrate); fprintf(stderr,"--bitrate values from 6-256 kbit/sec per channel are meaningful.\n"); exit(1); } bitrate=IMIN(chan*256000,bitrate); ret=opus_multistream_encoder_ctl(st, OPUS_SET_BITRATE(bitrate)); if(ret!=OPUS_OK){ fprintf(stderr,"Error OPUS_SET_BITRATE returned: %s\n",opus_strerror(ret)); exit(1); } ret=opus_multistream_encoder_ctl(st, OPUS_SET_VBR(!with_hard_cbr)); if(ret!=OPUS_OK){ fprintf(stderr,"Error OPUS_SET_VBR returned: %s\n",opus_strerror(ret)); exit(1); } if(!with_hard_cbr){ ret=opus_multistream_encoder_ctl(st, OPUS_SET_VBR_CONSTRAINT(with_cvbr)); if(ret!=OPUS_OK){ fprintf(stderr,"Error OPUS_SET_VBR_CONSTRAINT returned: %s\n",opus_strerror(ret)); exit(1); } } ret=opus_multistream_encoder_ctl(st, OPUS_SET_COMPLEXITY(complexity)); if(ret!=OPUS_OK){ fprintf(stderr,"Error OPUS_SET_COMPLEXITY returned: %s\n",opus_strerror(ret)); exit(1); } ret=opus_multistream_encoder_ctl(st, OPUS_SET_PACKET_LOSS_PERC(expect_loss)); if(ret!=OPUS_OK){ fprintf(stderr,"Error OPUS_SET_PACKET_LOSS_PERC returned: %s\n",opus_strerror(ret)); exit(1); } #ifdef OPUS_SET_LSB_DEPTH ret=opus_multistream_encoder_ctl(st, OPUS_SET_LSB_DEPTH(IMAX(8,IMIN(24,inopt.samplesize)))); if(ret!=OPUS_OK){ fprintf(stderr,"Warning OPUS_SET_LSB_DEPTH returned: %s\n",opus_strerror(ret)); } #endif for(i=0;i<opt_ctls;i++){ int target=opt_ctls_ctlval[i*3]; if(target==-1){ ret=opus_multistream_encoder_ctl(st,opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2]); if(ret!=OPUS_OK){ fprintf(stderr,"Error opus_multistream_encoder_ctl(st,%d,%d) returned: %s\n",opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2],opus_strerror(ret)); exit(1); } }else if(target<header.nb_streams){ OpusEncoder *oe; opus_multistream_encoder_ctl(st,OPUS_MULTISTREAM_GET_ENCODER_STATE(target,&oe)); ret=opus_encoder_ctl(oe, opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2]); if(ret!=OPUS_OK){ fprintf(stderr,"Error opus_encoder_ctl(st[%d],%d,%d) returned: %s\n",target,opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2],opus_strerror(ret)); exit(1); } }else{ fprintf(stderr,"Error --set-ctl-int target stream %d is higher than the maximum stream number %d.\n",target,header.nb_streams-1); exit(1); } } /*We do the lookahead check late so user CTLs can change it*/ ret=opus_multistream_encoder_ctl(st, OPUS_GET_LOOKAHEAD(&lookahead)); if(ret!=OPUS_OK){ fprintf(stderr,"Error OPUS_GET_LOOKAHEAD returned: %s\n",opus_strerror(ret)); exit(1); } inopt.skip+=lookahead; /*Regardless of the rate we're coding at the ogg timestamping/skip is always timed at 48000.*/ header.preskip=inopt.skip*(48000./coding_rate); /* Extra samples that need to be read to compensate for the pre-skip */ inopt.extraout=(int)header.preskip*(rate/48000.); /*Initialize Ogg stream struct*/ if(ogg_stream_init(&os, serialno)==-1){ fprintf(stderr,"Error: stream init failed\n"); exit(1); } int opus_app; fprintf(stderr,"Encoding using 1.1"); opus_multistream_encoder_ctl(st,OPUS_GET_APPLICATION(&opus_app)); if(opus_app==OPUS_APPLICATION_VOIP)fprintf(stderr," (VoIP)\n"); else if(opus_app==OPUS_APPLICATION_AUDIO)fprintf(stderr," (audio)\n"); else if(opus_app==OPUS_APPLICATION_RESTRICTED_LOWDELAY)fprintf(stderr," (low-delay)\n"); else fprintf(stderr," (unknown)\n"); fprintf(stderr,"-----------------------------------------------------\n"); fprintf(stderr," Input: %0.6gkHz %d channel%s\n", header.input_sample_rate/1000.,chan,chan<2?"":"s"); fprintf(stderr," Output: %d channel%s (",header.channels,header.channels<2?"":"s"); if(header.nb_coupled>0)fprintf(stderr,"%d coupled",header.nb_coupled*2); if(header.nb_streams-header.nb_coupled>0)fprintf(stderr, "%s%d uncoupled",header.nb_coupled>0?", ":"", header.nb_streams-header.nb_coupled); fprintf(stderr,")\n %0.2gms packets, %0.6gkbit/sec%s\n", frame_size/(coding_rate/1000.), bitrate/1000., with_hard_cbr?" CBR":with_cvbr?" CVBR":" VBR"); fprintf(stderr," Preskip: %d\n",header.preskip); }