diff options
Diffstat (limited to 'Tremolo/mapping0.c')
-rw-r--r-- | Tremolo/mapping0.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/Tremolo/mapping0.c b/Tremolo/mapping0.c new file mode 100644 index 0000000..f3e4c96 --- /dev/null +++ b/Tremolo/mapping0.c @@ -0,0 +1,241 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * + * * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + function: channel mapping 0 implementation + + ********************************************************************/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> +#include "ogg.h" +#include "os.h" +#include "ivorbiscodec.h" +#include "mdct.h" +#include "codec_internal.h" +#include "codebook.h" +#include "misc.h" + +void mapping_clear_info(vorbis_info_mapping *info){ + if(info){ + if(info->chmuxlist)_ogg_free(info->chmuxlist); + if(info->submaplist)_ogg_free(info->submaplist); + if(info->coupling)_ogg_free(info->coupling); + memset(info,0,sizeof(*info)); + } +} + +static int ilog(unsigned int v){ + int ret=0; + if(v)--v; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +/* also responsible for range checking */ +int mapping_info_unpack(vorbis_info_mapping *info,vorbis_info *vi, + oggpack_buffer *opb){ + int i; + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; + memset(info,0,sizeof(*info)); + + if(oggpack_read(opb,1)) + info->submaps=oggpack_read(opb,4)+1; + else + info->submaps=1; + + if(oggpack_read(opb,1)){ + info->coupling_steps=oggpack_read(opb,8)+1; + info->coupling= + _ogg_malloc(info->coupling_steps*sizeof(*info->coupling)); + + for(i=0;i<info->coupling_steps;i++){ + int testM=info->coupling[i].mag=(unsigned char)(oggpack_read(opb,ilog(vi->channels))); + int testA=info->coupling[i].ang=(unsigned char)(oggpack_read(opb,ilog(vi->channels))); + + if(testM<0 || + testA<0 || + testM==testA || + testM>=vi->channels || + testA>=vi->channels) goto err_out; + } + + } + + if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */ + + if(info->submaps>1){ + info->chmuxlist=_ogg_malloc(sizeof(*info->chmuxlist)*vi->channels); + for(i=0;i<vi->channels;i++){ + info->chmuxlist[i]=(unsigned char)(oggpack_read(opb,4)); + if(info->chmuxlist[i]>=info->submaps)goto err_out; + } + } + + info->submaplist=_ogg_malloc(sizeof(*info->submaplist)*info->submaps); + for(i=0;i<info->submaps;i++){ + int temp=oggpack_read(opb,8); + info->submaplist[i].floor=(char)oggpack_read(opb,8); + if(info->submaplist[i].floor>=ci->floors)goto err_out; + info->submaplist[i].residue=(char)oggpack_read(opb,8); + if(info->submaplist[i].residue>=ci->residues)goto err_out; + } + + return 0; + + err_out: + mapping_clear_info(info); + return -1; +} + +int mapping_inverse(vorbis_dsp_state *vd,vorbis_info_mapping *info){ + vorbis_info *vi=vd->vi; + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; + + int i,j; + long n=ci->blocksizes[vd->W]; + + ogg_int32_t **pcmbundle= + alloca(sizeof(*pcmbundle)*vi->channels); + int *zerobundle= + alloca(sizeof(*zerobundle)*vi->channels); + int *nonzero= + alloca(sizeof(*nonzero)*vi->channels); + ogg_int32_t **floormemo= + alloca(sizeof(*floormemo)*vi->channels); + + /* recover the spectral envelope; store it in the PCM vector for now */ + for(i=0;i<vi->channels;i++){ + int submap=0; + int floorno; + + if(info->submaps>1) + submap=info->chmuxlist[i]; + floorno=info->submaplist[submap].floor; + + if(ci->floor_type[floorno]){ + /* floor 1 */ + floormemo[i]=alloca(sizeof(*floormemo[i])* + floor1_memosize(ci->floor_param[floorno])); + floormemo[i]=floor1_inverse1(vd,ci->floor_param[floorno],floormemo[i]); + }else{ + /* floor 0 */ + floormemo[i]=alloca(sizeof(*floormemo[i])* + floor0_memosize(ci->floor_param[floorno])); + floormemo[i]=floor0_inverse1(vd,ci->floor_param[floorno],floormemo[i]); + } + + if(floormemo[i]) + nonzero[i]=1; + else + nonzero[i]=0; + memset(vd->work[i],0,sizeof(*vd->work[i])*n/2); + } + + /* channel coupling can 'dirty' the nonzero listing */ + for(i=0;i<info->coupling_steps;i++){ + if(nonzero[info->coupling[i].mag] || + nonzero[info->coupling[i].ang]){ + nonzero[info->coupling[i].mag]=1; + nonzero[info->coupling[i].ang]=1; + } + } + + /* recover the residue into our working vectors */ + for(i=0;i<info->submaps;i++){ + int ch_in_bundle=0; + for(j=0;j<vi->channels;j++){ + if(!info->chmuxlist || info->chmuxlist[j]==i){ + if(nonzero[j]) + zerobundle[ch_in_bundle]=1; + else + zerobundle[ch_in_bundle]=0; + pcmbundle[ch_in_bundle++]=vd->work[j]; + } + } + + res_inverse(vd,ci->residue_param+info->submaplist[i].residue, + pcmbundle,zerobundle,ch_in_bundle); + } + + //for(j=0;j<vi->channels;j++) + //_analysis_output("coupled",seq+j,vb->pcm[j],-8,n/2,0,0); + + /* channel coupling */ + for(i=info->coupling_steps-1;i>=0;i--){ + ogg_int32_t *pcmM=vd->work[info->coupling[i].mag]; + ogg_int32_t *pcmA=vd->work[info->coupling[i].ang]; + + for(j=0;j<n/2;j++){ + ogg_int32_t mag=pcmM[j]; + ogg_int32_t ang=pcmA[j]; + + if(mag>0) + if(ang>0){ + pcmM[j]=mag; + pcmA[j]=mag-ang; + }else{ + pcmA[j]=mag; + pcmM[j]=mag+ang; + } + else + if(ang>0){ + pcmM[j]=mag; + pcmA[j]=mag+ang; + }else{ + pcmA[j]=mag; + pcmM[j]=mag-ang; + } + } + } + + //for(j=0;j<vi->channels;j++) + //_analysis_output("residue",seq+j,vb->pcm[j],-8,n/2,0,0); + + /* compute and apply spectral envelope */ + for(i=0;i<vi->channels;i++){ + ogg_int32_t *pcm=vd->work[i]; + int submap=0; + int floorno; + + if(info->submaps>1) + submap=info->chmuxlist[i]; + floorno=info->submaplist[submap].floor; + + if(ci->floor_type[floorno]){ + /* floor 1 */ + floor1_inverse2(vd,ci->floor_param[floorno],floormemo[i],pcm); + }else{ + /* floor 0 */ + floor0_inverse2(vd,ci->floor_param[floorno],floormemo[i],pcm); + } + } + + //for(j=0;j<vi->channels;j++) + //_analysis_output("mdct",seq+j,vb->pcm[j],-24,n/2,0,1); + + /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */ + /* only MDCT right now.... */ + for(i=0;i<vi->channels;i++) + mdct_backward(n,vd->work[i]); + + //for(j=0;j<vi->channels;j++) + //_analysis_output("imdct",seq+j,vb->pcm[j],-24,n,0,0); + + /* all done! */ + return(0); +} |