📄 vorbis_dec.c
字号:
ch_used=1; } else { ch_used=ch; } AV_DEBUG(" residue type 0/1/2 decode begin, ch: %d cpc %d \n", ch, c_p_c); for(pass=0;pass<=vr->maxpass;++pass) { // FIXME OPTIMIZE? uint_fast16_t voffset; uint_fast16_t partition_count; uint_fast16_t j_times_ptns_to_read; voffset=vr->begin; for(partition_count=0;partition_count<ptns_to_read;) { // SPEC error if (!pass) { uint_fast32_t inverse_class = ff_inverse[vr->classifications]; for(j_times_ptns_to_read=0, j=0;j<ch_used;++j) { if (!do_not_decode[j]) { uint_fast32_t temp=get_vlc2(gb, vc->codebooks[vr->classbook].vlc.table, vc->codebooks[vr->classbook].nb_bits, 3); AV_DEBUG("Classword: %d \n", temp); assert(vr->classifications > 1 && temp<=65536); //needed for inverse[] for(i=0;i<c_p_c;++i) { uint_fast32_t temp2; temp2=(((uint_fast64_t)temp) * inverse_class)>>32; if (partition_count+c_p_c-1-i < ptns_to_read) { classifs[j_times_ptns_to_read+partition_count+c_p_c-1-i]=temp-temp2*vr->classifications; } temp=temp2; } } j_times_ptns_to_read+=ptns_to_read; } } for(i=0;(i<c_p_c) && (partition_count<ptns_to_read);++i) { for(j_times_ptns_to_read=0, j=0;j<ch_used;++j) { uint_fast16_t voffs; if (!do_not_decode[j]) { uint_fast8_t vqclass=classifs[j_times_ptns_to_read+partition_count]; int_fast16_t vqbook=vr->books[vqclass][pass]; if (vqbook>=0 && vc->codebooks[vqbook].codevectors) { uint_fast16_t coffs; unsigned dim= vc->codebooks[vqbook].dimensions; // not uint_fast8_t: 64bit is slower here on amd64 uint_fast16_t step= dim==1 ? vr->partition_size : FASTDIV(vr->partition_size, dim); vorbis_codebook codebook= vc->codebooks[vqbook]; if (vr->type==0) { voffs=voffset+j*vlen; for(k=0;k<step;++k) { coffs=get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * dim; for(l=0;l<dim;++l) { vec[voffs+k+l*step]+=codebook.codevectors[coffs+l]; // FPMATH } } } else if (vr->type==1) { voffs=voffset+j*vlen; for(k=0;k<step;++k) { coffs=get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * dim; for(l=0;l<dim;++l, ++voffs) { vec[voffs]+=codebook.codevectors[coffs+l]; // FPMATH AV_DEBUG(" pass %d offs: %d curr: %f change: %f cv offs.: %d \n", pass, voffs, vec[voffs], codebook.codevectors[coffs+l], coffs); } } } else if (vr->type==2 && ch==2 && (voffset&1)==0 && (dim&1)==0) { // most frequent case optimized voffs=voffset>>1; if(dim==2) { for(k=0;k<step;++k) { coffs=get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * 2; vec[voffs+k ]+=codebook.codevectors[coffs ]; // FPMATH vec[voffs+k+vlen]+=codebook.codevectors[coffs+1]; // FPMATH } } else if(dim==4) { for(k=0;k<step;++k, voffs+=2) { coffs=get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * 4; vec[voffs ]+=codebook.codevectors[coffs ]; // FPMATH vec[voffs+1 ]+=codebook.codevectors[coffs+2]; // FPMATH vec[voffs+vlen ]+=codebook.codevectors[coffs+1]; // FPMATH vec[voffs+vlen+1]+=codebook.codevectors[coffs+3]; // FPMATH } } else for(k=0;k<step;++k) { coffs=get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * dim; for(l=0;l<dim;l+=2, voffs++) { vec[voffs ]+=codebook.codevectors[coffs+l ]; // FPMATH vec[voffs+vlen]+=codebook.codevectors[coffs+l+1]; // FPMATH AV_DEBUG(" pass %d offs: %d curr: %f change: %f cv offs.: %d+%d \n", pass, voffset/ch+(voffs%ch)*vlen, vec[voffset/ch+(voffs%ch)*vlen], codebook.codevectors[coffs+l], coffs, l); } } } else if (vr->type==2) { voffs=voffset; for(k=0;k<step;++k) { coffs=get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * dim; for(l=0;l<dim;++l, ++voffs) { vec[voffs/ch+(voffs%ch)*vlen]+=codebook.codevectors[coffs+l]; // FPMATH FIXME use if and counter instead of / and % AV_DEBUG(" pass %d offs: %d curr: %f change: %f cv offs.: %d+%d \n", pass, voffset/ch+(voffs%ch)*vlen, vec[voffset/ch+(voffs%ch)*vlen], codebook.codevectors[coffs+l], coffs, l); } } } else {#ifdef __CW32__ av_free(classifs);#endif av_log(vc->avccontext, AV_LOG_ERROR, " Invalid residue type while residue decode?! \n"); return 1; } } } j_times_ptns_to_read+=ptns_to_read; } ++partition_count; voffset+=vr->partition_size; } } }#ifdef __CW32__ av_free(classifs);#endif return 0;}void vorbis_inverse_coupling(float *mag, float *ang, int blocksize){ int i; for(i=0; i<blocksize; i++) { if (mag[i]>0.0) { if (ang[i]>0.0) { ang[i]=mag[i]-ang[i]; } else { float temp=ang[i]; ang[i]=mag[i]; mag[i]+=temp; } } else { if (ang[i]>0.0) { ang[i]+=mag[i]; } else { float temp=ang[i]; ang[i]=mag[i]; mag[i]-=temp; } } }}static void copy_normalize(float *dst, float *src, int len, int exp_bias, float add_bias){ int i; if(exp_bias) { for(i=0; i<len; i++) ((uint32_t*)dst)[i] = ((uint32_t*)src)[i] + exp_bias; // dst[k]=src[i]*(1<<bias) } else { for(i=0; i<len; i++) dst[i] = src[i] + add_bias; }}// Decode the audio packet using the functions abovestatic int vorbis_parse_audio_packet(vorbis_context *vc) { GetBitContext *gb=&vc->gb; uint_fast8_t previous_window=vc->previous_window; uint_fast8_t mode_number; uint_fast8_t blockflag; uint_fast16_t blocksize; int_fast32_t i,j,dir;#ifdef __CW32__ uint_fast8_t *no_residue; uint_fast8_t *do_not_decode;#else uint_fast8_t no_residue[vc->audio_channels]; uint_fast8_t do_not_decode[vc->audio_channels];#endif vorbis_mapping *mapping; float *ch_res_ptr=vc->channel_residues; float *ch_floor_ptr=vc->channel_floors;#ifdef __CW32__ uint_fast8_t *res_chan;#else uint_fast8_t res_chan[vc->audio_channels];#endif uint_fast8_t res_num=0; int_fast16_t retlen=0; float fadd_bias = vc->add_bias;#ifdef __CW32__ no_residue = av_malloc(sizeof(uint_fast8_t)*vc->audio_channels); do_not_decode = av_malloc(sizeof(uint_fast8_t)*vc->audio_channels); res_chan = av_malloc(sizeof(uint_fast8_t)*vc->audio_channels);#endif if (get_bits1(gb)) {#ifdef __CW32__ av_free(no_residue); av_free(do_not_decode); av_free(res_chan);#endif av_log(vc->avccontext, AV_LOG_ERROR, "Not a Vorbis I audio packet.\n"); return -1; // packet type not audio } if (vc->mode_count==1) { mode_number=0; } else { mode_number=get_bits(gb, ilog(vc->mode_count-1)); } vc->mode_number=mode_number; mapping=&vc->mappings[vc->modes[mode_number].mapping]; AV_DEBUG(" Mode number: %d , mapping: %d , blocktype %d \n", mode_number, vc->modes[mode_number].mapping, vc->modes[mode_number].blockflag); blockflag=vc->modes[mode_number].blockflag; blocksize=vc->blocksize[blockflag]; if (blockflag) { skip_bits(gb, 2); // previous_window, next_window } memset(ch_res_ptr, 0, sizeof(float)*vc->audio_channels*blocksize/2); //FIXME can this be removed ? memset(ch_floor_ptr, 0, sizeof(float)*vc->audio_channels*blocksize/2); //FIXME can this be removed ?// Decode floor for(i=0;i<vc->audio_channels;++i) { vorbis_floor *floor; if (mapping->submaps>1) { floor=&vc->floors[mapping->submap_floor[mapping->mux[i]]]; } else { floor=&vc->floors[mapping->submap_floor[0]]; } no_residue[i]=floor->decode(vc, &floor->data, ch_floor_ptr); ch_floor_ptr+=blocksize/2; }// Nonzero vector propagate for(i=mapping->coupling_steps-1;i>=0;--i) { if (!(no_residue[mapping->magnitude[i]] & no_residue[mapping->angle[i]])) { no_residue[mapping->magnitude[i]]=0; no_residue[mapping->angle[i]]=0; } }// Decode residue for(i=0;i<mapping->submaps;++i) { vorbis_residue *residue; uint_fast8_t ch=0; for(j=0;j<vc->audio_channels;++j) { if ((mapping->submaps==1) || (i=mapping->mux[j])) { res_chan[j]=res_num; if (no_residue[j]) { do_not_decode[ch]=1; } else { do_not_decode[ch]=0; } ++ch; ++res_num; } } residue=&vc->residues[mapping->submap_residue[i]]; vorbis_residue_decode(vc, residue, ch, do_not_decode, ch_res_ptr, blocksize/2); ch_res_ptr+=ch*blocksize/2; }// Inverse coupling for(i=mapping->coupling_steps-1;i>=0;--i) { //warning: i has to be signed float *mag, *ang; mag=vc->channel_residues+res_chan[mapping->magnitude[i]]*blocksize/2; ang=vc->channel_residues+res_chan[mapping->angle[i]]*blocksize/2; vc->dsp.vorbis_inverse_coupling(mag, ang, blocksize/2); }// Dotproduct for(j=0, ch_floor_ptr=vc->channel_floors;j<vc->audio_channels;++j,ch_floor_ptr+=blocksize/2) { ch_res_ptr=vc->channel_residues+res_chan[j]*blocksize/2; vc->dsp.vector_fmul(ch_floor_ptr, ch_res_ptr, blocksize/2); }// MDCT, overlap/add, save data for next overlapping FPMATH retlen = (blocksize + vc->blocksize[previous_window])/4; dir = retlen <= blocksize/2; // pick an order so that ret[] can reuse residues[] without stepping on any data we need for(j=dir?0:vc->audio_channels-1; (unsigned)j<vc->audio_channels; j+=dir*2-1) { uint_fast16_t bs0=vc->blocksize[0]; uint_fast16_t bs1=vc->blocksize[1]; float *residue=vc->channel_residues+res_chan[j]*blocksize/2; float *floor=vc->channel_floors+j*blocksize/2; float *saved=vc->saved+j*bs1/4; float *ret=vc->channel_residues+j*retlen; float *buf=floor; const float *win=vc->win[blockflag&previous_window]; vc->mdct[0].fft.imdct_half(&vc->mdct[blockflag], buf, floor, residue); if(blockflag == previous_window) { vc->dsp.vector_fmul_window(ret, saved, buf, win, fadd_bias, blocksize/4); } else if(blockflag > previous_window) { vc->dsp.vector_fmul_window(ret, saved, buf, win, fadd_bias, bs0/4); copy_normalize(ret+bs0/2, buf+bs0/4, (bs1-bs0)/4, vc->exp_bias, fadd_bias); } else { copy_normalize(ret, saved, (bs1-bs0)/4, vc->exp_bias, fadd_bias); vc->dsp.vector_fmul_window(ret+(bs1-bs0)/4, saved+(bs1-bs0)/4, buf, win, fadd_bias, bs0/4); } memcpy(saved, buf+blocksize/4, blocksize/4*sizeof(float)); } vc->previous_window = blockflag;#ifdef __CW32__ av_free(no_residue); av_free(do_not_decode); av_free(res_chan);#endif return retlen;}// Return the decoded audio packet through the standard apistatic int vorbis_decode_frame(AVCodecContext *avccontext, void *data, int *data_size, const uint8_t *buf, int buf_size){ vorbis_context *vc = avccontext->priv_data ; GetBitContext *gb = &(vc->gb);#ifdef __CW32__ const float **channel_ptrs;#else const float *channel_ptrs[vc->audio_channels];#endif int i; int_fast16_t len;#ifdef __CW32__ channel_ptrs = av_malloc(sizeof(float*)*vc->audio_channels);#endif if(!buf_size){#ifdef __CW32__ av_free(channel_ptrs);#endif return 0; } AV_DEBUG("packet length %d \n", buf_size); init_get_bits(gb, buf, buf_size*8); len=vorbis_parse_audio_packet(vc); if (len<=0) { *data_size=0; return buf_size; } if (!vc->first_frame) { vc->first_frame=1; *data_size=0;#ifdef __CW32__ av_free(channel_ptrs);#endif return buf_size ; } AV_DEBUG("parsed %d bytes %d bits, returned %d samples (*ch*bits) \n", get_bits_count(gb)/8, get_bits_count(gb)%8, len); for(i=0; i<vc->audio_channels; i++) channel_ptrs[i] = vc->channel_residues+i*len; vc->dsp.float_to_int16_interleave(data, channel_ptrs, len, vc->audio_channels); *data_size=len*2*vc->audio_channels;#ifdef __CW32__ av_free(channel_ptrs);#endif return buf_size ;}// Close decoderstatic av_cold int vorbis_decode_close(AVCodecContext *avccontext) { vorbis_context *vc = avccontext->priv_data; vorbis_free(vc); return 0 ;}AVCodec vorbis_decoder = { "vorbis", CODEC_TYPE_AUDIO, CODEC_ID_VORBIS, sizeof(vorbis_context), vorbis_decode_init, NULL, vorbis_decode_close, vorbis_decode_frame,#ifdef __CW32__ 0, 0, 0, 0, 0, NULL_IF_CONFIG_SMALL("Vorbis"),#else .long_name = NULL_IF_CONFIG_SMALL("Vorbis"),#endif};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -