📄 vorbis.c
字号:
vec[lx+j]=floor1_inverse_db_table[predicted]; } }*/ lx=hx; ly=hy; } } if (hx<vf->x_list[1]) { for(i=hx;i<vf->x_list[1];++i) { vec[i]=floor1_inverse_db_table[hy]; } } AV_DEBUG(" Floor decoded\n"); return 0;}// Read and decode residuestatic int vorbis_residue_decode(vorbis_context *vc, vorbis_residue *vr, uint_fast8_t ch, uint_fast8_t *do_not_decode, float *vec, uint_fast16_t vlen) { GetBitContext *gb=&vc->gb; uint_fast8_t c_p_c=vc->codebooks[vr->classbook].dimensions; uint_fast16_t n_to_read=vr->end-vr->begin; uint_fast16_t ptns_to_read=n_to_read/vr->partition_size; uint_fast8_t classifs[ptns_to_read*vc->audio_channels]; uint_fast8_t pass; uint_fast8_t ch_used; uint_fast8_t i,j,l; uint_fast16_t k; if (vr->type==2) { for(j=1;j<ch;++j) { do_not_decode[0]&=do_not_decode[j]; // FIXME - clobbering input } if (do_not_decode[0]) return 0; 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) { 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[vr->classifications])>>32; 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) { uint_fast16_t coffs; uint_fast16_t step=vr->partition_size/vc->codebooks[vqbook].dimensions; 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) * codebook.dimensions; for(l=0;l<codebook.dimensions;++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) * codebook.dimensions; for(l=0;l<codebook.dimensions;++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 && (codebook.dimensions&1)==0) { // most frequent case optimized voffs=voffset>>1; for(k=0;k<step;++k) { coffs=get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * codebook.dimensions; for(l=0;l<codebook.dimensions;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) * codebook.dimensions; for(l=0;l<codebook.dimensions;++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 { 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; } } } return 0;}// Decode the audio packet using the functions above#define BIAS 385static int vorbis_parse_audio_packet(vorbis_context *vc) { GetBitContext *gb=&vc->gb; uint_fast8_t previous_window=0,next_window=0; uint_fast8_t mode_number; uint_fast16_t blocksize; int_fast32_t i,j; uint_fast8_t no_residue[vc->audio_channels]; uint_fast8_t do_not_decode[vc->audio_channels]; vorbis_mapping *mapping; float *ch_res_ptr=vc->channel_residues; float *ch_floor_ptr=vc->channel_floors; uint_fast8_t res_chan[vc->audio_channels]; uint_fast8_t res_num=0; int_fast16_t retlen=0; uint_fast16_t saved_start=0; if (get_bits1(gb)) { 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); if (vc->modes[mode_number].blockflag) { previous_window=get_bits1(gb); next_window=get_bits1(gb); } blocksize=vc->modes[mode_number].blockflag ? vc->blocksize_1 : vc->blocksize_0; 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; for(j=0;j<blocksize/2;++j) { float temp; if (mag[j]>0.0) { if (ang[j]>0.0) { ang[j]=mag[j]-ang[j]; } else { temp=ang[j]; ang[j]=mag[j]; mag[j]+=temp; } } else { if (ang[j]>0.0) { ang[j]+=mag[j]; } else { temp=ang[j]; ang[j]=mag[j]; mag[j]-=temp; } } } }// 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; for(i=0;i<blocksize/2;++i) { ch_floor_ptr[i]*=ch_res_ptr[i]; //FPMATH } }// MDCT, overlap/add, save data for next overlapping FPMATH for(j=0;j<vc->audio_channels;++j) { uint_fast8_t step=vc->audio_channels; uint_fast16_t k; float *saved=vc->saved+j*vc->blocksize_1/2; float *ret=vc->ret; const float *lwin=vc->lwin; const float *swin=vc->swin; float *buf=vc->buf; float *buf_tmp=vc->buf_tmp; ch_floor_ptr=vc->channel_floors+j*blocksize/2; saved_start=vc->saved_start; ff_imdct_calc(vc->modes[mode_number].blockflag ? &vc->mdct1 : &vc->mdct0, buf, ch_floor_ptr, buf_tmp); if (vc->modes[mode_number].blockflag) { // -- overlap/add if (previous_window) { for(k=j, i=0;i<vc->blocksize_1/2;++i, k+=step) { ret[k]=saved[i]+buf[i]*lwin[i]+BIAS; } retlen=vc->blocksize_1/2; } else { buf += (vc->blocksize_1-vc->blocksize_0)/4; for(k=j, i=0;i<vc->blocksize_0/2;++i, k+=step) { ret[k]=saved[i]+buf[i]*swin[i]+BIAS; } buf += vc->blocksize_0/2; for(i=0;i<(vc->blocksize_1-vc->blocksize_0)/4;++i, k+=step) { ret[k]=buf[i]+BIAS; } buf=vc->buf; retlen=vc->blocksize_0/2+(vc->blocksize_1-vc->blocksize_0)/4; } // -- save if (next_window) { buf += vc->blocksize_1/2; lwin += vc->blocksize_1/2-1; for(i=0;i<vc->blocksize_1/2;++i) { saved[i]=buf[i]*lwin[-i]; } saved_start=0; } else { saved_start=(vc->blocksize_1-vc->blocksize_0)/4; buf += vc->blocksize_1/2; for(i=0;i<saved_start;++i) { saved[i]=buf[i]; } swin += vc->blocksize_0/2-1; for(i=0;i<vc->blocksize_0/2;++i) { saved[saved_start+i]=buf[saved_start+i]*swin[-i]; } } } else { // --overlap/add for(k=j, i=0;i<saved_start;++i, k+=step) { ret[k]=saved[i]+BIAS; } for(i=0;i<vc->blocksize_0/2;++i, k+=step) { ret[k]=saved[saved_start+i]+buf[i]*swin[i]+BIAS; } retlen=saved_start+vc->blocksize_0/2; // -- save buf += vc->blocksize_0/2; swin += vc->blocksize_0/2-1; for(i=0;i<vc->blocksize_0/2;++i) { saved[i]=buf[i]*swin[-i]; } saved_start=0; } } vc->saved_start=saved_start; return retlen*vc->audio_channels;}// Return the decoded audio packet through the standard apistatic int vorbis_decode_frame(AVCodecContext *avccontext, void *data, int *data_size, uint8_t *buf, int buf_size){ vorbis_context *vc = avccontext->priv_data ; GetBitContext *gb = &(vc->gb); int_fast16_t i, len; if(!buf_size){ 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; 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<len;++i) { int_fast32_t tmp= ((int32_t*)vc->ret)[i]; if(tmp & 0xf0000){// tmp= (0x43c0ffff - tmp)>>31; //ask gcc devs why this is slower if(tmp > 0x43c0ffff) tmp= 0xFFFF; else tmp= 0; } ((int16_t*)data)[i]=tmp - 0x8000; } *data_size=len*2; return buf_size ;}// Close decoderstatic 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,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -