1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libtremor/lib/tremor_mapping0.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,328 @@ 1.4 +/******************************************************************** 1.5 + * * 1.6 + * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * 1.7 + * * 1.8 + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 1.9 + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 1.10 + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 1.11 + * * 1.12 + * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * 1.13 + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * 1.14 + * * 1.15 + ******************************************************************** 1.16 + 1.17 + function: channel mapping 0 implementation 1.18 + 1.19 + ********************************************************************/ 1.20 + 1.21 +#include <stdlib.h> 1.22 +#include <stdio.h> 1.23 +#include <string.h> 1.24 +#include <math.h> 1.25 +#include <ogg/ogg.h> 1.26 +#include "ivorbiscodec.h" 1.27 +#include "mdct.h" 1.28 +#include "codec_internal.h" 1.29 +#include "codebook.h" 1.30 +#include "window.h" 1.31 +#include "registry.h" 1.32 +#include "misc.h" 1.33 + 1.34 +/* simplistic, wasteful way of doing this (unique lookup for each 1.35 + mode/submapping); there should be a central repository for 1.36 + identical lookups. That will require minor work, so I'm putting it 1.37 + off as low priority. 1.38 + 1.39 + Why a lookup for each backend in a given mode? Because the 1.40 + blocksize is set by the mode, and low backend lookups may require 1.41 + parameters from other areas of the mode/mapping */ 1.42 + 1.43 +typedef struct { 1.44 + vorbis_info_mode *mode; 1.45 + vorbis_info_mapping0 *map; 1.46 + 1.47 + vorbis_look_floor **floor_look; 1.48 + 1.49 + vorbis_look_residue **residue_look; 1.50 + 1.51 + vorbis_func_floor **floor_func; 1.52 + vorbis_func_residue **residue_func; 1.53 + 1.54 + int ch; 1.55 + long lastframe; /* if a different mode is called, we need to 1.56 + invalidate decay */ 1.57 +} vorbis_look_mapping0; 1.58 + 1.59 +static void mapping0_free_info(vorbis_info_mapping *i){ 1.60 + vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)i; 1.61 + if(info){ 1.62 + memset(info,0,sizeof(*info)); 1.63 + _ogg_free(info); 1.64 + } 1.65 +} 1.66 + 1.67 +static void mapping0_free_look(vorbis_look_mapping *look){ 1.68 + int i; 1.69 + vorbis_look_mapping0 *l=(vorbis_look_mapping0 *)look; 1.70 + if(l){ 1.71 + 1.72 + for(i=0;i<l->map->submaps;i++){ 1.73 + l->floor_func[i]->free_look(l->floor_look[i]); 1.74 + l->residue_func[i]->free_look(l->residue_look[i]); 1.75 + } 1.76 + 1.77 + _ogg_free(l->floor_func); 1.78 + _ogg_free(l->residue_func); 1.79 + _ogg_free(l->floor_look); 1.80 + _ogg_free(l->residue_look); 1.81 + memset(l,0,sizeof(*l)); 1.82 + _ogg_free(l); 1.83 + } 1.84 +} 1.85 + 1.86 +static vorbis_look_mapping *mapping0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm, 1.87 + vorbis_info_mapping *m){ 1.88 + int i; 1.89 + vorbis_info *vi=vd->vi; 1.90 + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 1.91 + vorbis_look_mapping0 *look=(vorbis_look_mapping0 *)_ogg_calloc(1,sizeof(*look)); 1.92 + vorbis_info_mapping0 *info=look->map=(vorbis_info_mapping0 *)m; 1.93 + look->mode=vm; 1.94 + 1.95 + look->floor_look=(vorbis_look_floor **)_ogg_calloc(info->submaps,sizeof(*look->floor_look)); 1.96 + 1.97 + look->residue_look=(vorbis_look_residue **)_ogg_calloc(info->submaps,sizeof(*look->residue_look)); 1.98 + 1.99 + look->floor_func=(vorbis_func_floor **)_ogg_calloc(info->submaps,sizeof(*look->floor_func)); 1.100 + look->residue_func=(vorbis_func_residue **)_ogg_calloc(info->submaps,sizeof(*look->residue_func)); 1.101 + 1.102 + for(i=0;i<info->submaps;i++){ 1.103 + int floornum=info->floorsubmap[i]; 1.104 + int resnum=info->residuesubmap[i]; 1.105 + 1.106 + look->floor_func[i]=_floor_P[ci->floor_type[floornum]]; 1.107 + look->floor_look[i]=look->floor_func[i]-> 1.108 + look(vd,vm,ci->floor_param[floornum]); 1.109 + look->residue_func[i]=_residue_P[ci->residue_type[resnum]]; 1.110 + look->residue_look[i]=look->residue_func[i]-> 1.111 + look(vd,vm,ci->residue_param[resnum]); 1.112 + 1.113 + } 1.114 + 1.115 + look->ch=vi->channels; 1.116 + 1.117 + return(look); 1.118 +} 1.119 + 1.120 +static int ilog(unsigned int v){ 1.121 + int ret=0; 1.122 + if(v)--v; 1.123 + while(v){ 1.124 + ret++; 1.125 + v>>=1; 1.126 + } 1.127 + return(ret); 1.128 +} 1.129 + 1.130 +/* also responsible for range checking */ 1.131 +static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){ 1.132 + int i,b; 1.133 + vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)_ogg_calloc(1,sizeof(*info)); 1.134 + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 1.135 + memset(info,0,sizeof(*info)); 1.136 + 1.137 + b=oggpack_read(opb,1); 1.138 + if(b<0)goto err_out; 1.139 + if(b){ 1.140 + info->submaps=oggpack_read(opb,4)+1; 1.141 + if(info->submaps<=0)goto err_out; 1.142 + }else 1.143 + info->submaps=1; 1.144 + 1.145 + b=oggpack_read(opb,1); 1.146 + if(b<0)goto err_out; 1.147 + if(b){ 1.148 + info->coupling_steps=oggpack_read(opb,8)+1; 1.149 + if(info->coupling_steps<=0)goto err_out; 1.150 + for(i=0;i<info->coupling_steps;i++){ 1.151 + int testM=info->coupling_mag[i]=oggpack_read(opb,ilog(vi->channels)); 1.152 + int testA=info->coupling_ang[i]=oggpack_read(opb,ilog(vi->channels)); 1.153 + 1.154 + if(testM<0 || 1.155 + testA<0 || 1.156 + testM==testA || 1.157 + testM>=vi->channels || 1.158 + testA>=vi->channels) goto err_out; 1.159 + } 1.160 + 1.161 + } 1.162 + 1.163 + if(oggpack_read(opb,2)!=0)goto err_out; /* 2,3:reserved */ 1.164 + 1.165 + if(info->submaps>1){ 1.166 + for(i=0;i<vi->channels;i++){ 1.167 + info->chmuxlist[i]=oggpack_read(opb,4); 1.168 + if(info->chmuxlist[i]>=info->submaps || info->chmuxlist[i]<0)goto err_out; 1.169 + } 1.170 + } 1.171 + for(i=0;i<info->submaps;i++){ 1.172 + int temp=oggpack_read(opb,8); 1.173 + if(temp>=ci->times)goto err_out; 1.174 + info->floorsubmap[i]=oggpack_read(opb,8); 1.175 + if(info->floorsubmap[i]>=ci->floors || info->floorsubmap[i]<0)goto err_out; 1.176 + info->residuesubmap[i]=oggpack_read(opb,8); 1.177 + if(info->residuesubmap[i]>=ci->residues || info->residuesubmap[i]<0) 1.178 + goto err_out; 1.179 + } 1.180 + 1.181 + return info; 1.182 + 1.183 + err_out: 1.184 + mapping0_free_info(info); 1.185 + return(NULL); 1.186 +} 1.187 + 1.188 +static int seq=0; 1.189 +static int mapping0_inverse(vorbis_block *vb,vorbis_look_mapping *l){ 1.190 + vorbis_dsp_state *vd=vb->vd; 1.191 + vorbis_info *vi=vd->vi; 1.192 + codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; 1.193 + private_state *b=(private_state *)vd->backend_state; 1.194 + vorbis_look_mapping0 *look=(vorbis_look_mapping0 *)l; 1.195 + vorbis_info_mapping0 *info=look->map; 1.196 + 1.197 + int i,j; 1.198 + long n=vb->pcmend=ci->blocksizes[vb->W]; 1.199 + 1.200 + ogg_int32_t **pcmbundle=(ogg_int32_t **)alloca(sizeof(*pcmbundle)*vi->channels); 1.201 + int *zerobundle=(int *)alloca(sizeof(*zerobundle)*vi->channels); 1.202 + 1.203 + int *nonzero =(int *)alloca(sizeof(*nonzero)*vi->channels); 1.204 + void **floormemo=(void **)alloca(sizeof(*floormemo)*vi->channels); 1.205 + 1.206 + /* time domain information decode (note that applying the 1.207 + information would have to happen later; we'll probably add a 1.208 + function entry to the harness for that later */ 1.209 + /* NOT IMPLEMENTED */ 1.210 + 1.211 + /* recover the spectral envelope; store it in the PCM vector for now */ 1.212 + for(i=0;i<vi->channels;i++){ 1.213 + int submap=info->chmuxlist[i]; 1.214 + floormemo[i]=look->floor_func[submap]-> 1.215 + inverse1(vb,look->floor_look[submap]); 1.216 + if(floormemo[i]) 1.217 + nonzero[i]=1; 1.218 + else 1.219 + nonzero[i]=0; 1.220 + memset(vb->pcm[i],0,sizeof(*vb->pcm[i])*n/2); 1.221 + } 1.222 + 1.223 + /* channel coupling can 'dirty' the nonzero listing */ 1.224 + for(i=0;i<info->coupling_steps;i++){ 1.225 + if(nonzero[info->coupling_mag[i]] || 1.226 + nonzero[info->coupling_ang[i]]){ 1.227 + nonzero[info->coupling_mag[i]]=1; 1.228 + nonzero[info->coupling_ang[i]]=1; 1.229 + } 1.230 + } 1.231 + 1.232 + /* recover the residue into our working vectors */ 1.233 + for(i=0;i<info->submaps;i++){ 1.234 + int ch_in_bundle=0; 1.235 + for(j=0;j<vi->channels;j++){ 1.236 + if(info->chmuxlist[j]==i){ 1.237 + if(nonzero[j]) 1.238 + zerobundle[ch_in_bundle]=1; 1.239 + else 1.240 + zerobundle[ch_in_bundle]=0; 1.241 + pcmbundle[ch_in_bundle++]=vb->pcm[j]; 1.242 + } 1.243 + } 1.244 + 1.245 + look->residue_func[i]->inverse(vb,look->residue_look[i], 1.246 + pcmbundle,zerobundle,ch_in_bundle); 1.247 + } 1.248 + 1.249 + //for(j=0;j<vi->channels;j++) 1.250 + //_analysis_output("coupled",seq+j,vb->pcm[j],-8,n/2,0,0); 1.251 + 1.252 + 1.253 + /* channel coupling */ 1.254 + for(i=info->coupling_steps-1;i>=0;i--){ 1.255 + ogg_int32_t *pcmM=vb->pcm[info->coupling_mag[i]]; 1.256 + ogg_int32_t *pcmA=vb->pcm[info->coupling_ang[i]]; 1.257 + 1.258 + for(j=0;j<n/2;j++){ 1.259 + ogg_int32_t mag=pcmM[j]; 1.260 + ogg_int32_t ang=pcmA[j]; 1.261 + 1.262 + if(mag>0) 1.263 + if(ang>0){ 1.264 + pcmM[j]=mag; 1.265 + pcmA[j]=mag-ang; 1.266 + }else{ 1.267 + pcmA[j]=mag; 1.268 + pcmM[j]=mag+ang; 1.269 + } 1.270 + else 1.271 + if(ang>0){ 1.272 + pcmM[j]=mag; 1.273 + pcmA[j]=mag+ang; 1.274 + }else{ 1.275 + pcmA[j]=mag; 1.276 + pcmM[j]=mag-ang; 1.277 + } 1.278 + } 1.279 + } 1.280 + 1.281 + //for(j=0;j<vi->channels;j++) 1.282 + //_analysis_output("residue",seq+j,vb->pcm[j],-8,n/2,0,0); 1.283 + 1.284 + /* compute and apply spectral envelope */ 1.285 + for(i=0;i<vi->channels;i++){ 1.286 + ogg_int32_t *pcm=vb->pcm[i]; 1.287 + int submap=info->chmuxlist[i]; 1.288 + look->floor_func[submap]-> 1.289 + inverse2(vb,look->floor_look[submap],floormemo[i],pcm); 1.290 + } 1.291 + 1.292 + //for(j=0;j<vi->channels;j++) 1.293 + //_analysis_output("mdct",seq+j,vb->pcm[j],-24,n/2,0,1); 1.294 + 1.295 + /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */ 1.296 + /* only MDCT right now.... */ 1.297 + for(i=0;i<vi->channels;i++){ 1.298 + ogg_int32_t *pcm=vb->pcm[i]; 1.299 + mdct_backward(n,pcm,pcm); 1.300 + } 1.301 + 1.302 + //for(j=0;j<vi->channels;j++) 1.303 + //_analysis_output("imdct",seq+j,vb->pcm[j],-24,n,0,0); 1.304 + 1.305 + /* window the data */ 1.306 + for(i=0;i<vi->channels;i++){ 1.307 + ogg_int32_t *pcm=vb->pcm[i]; 1.308 + if(nonzero[i]) 1.309 + _vorbis_apply_window(pcm,b->window,ci->blocksizes,vb->lW,vb->W,vb->nW); 1.310 + else 1.311 + for(j=0;j<n;j++) 1.312 + pcm[j]=0; 1.313 + 1.314 + } 1.315 + 1.316 + //for(j=0;j<vi->channels;j++) 1.317 + //_analysis_output("window",seq+j,vb->pcm[j],-24,n,0,0); 1.318 + 1.319 + seq+=vi->channels; 1.320 + /* all done! */ 1.321 + return(0); 1.322 +} 1.323 + 1.324 +/* export hooks */ 1.325 +vorbis_func_mapping mapping0_exportbundle={ 1.326 + &mapping0_unpack, 1.327 + &mapping0_look, 1.328 + &mapping0_free_info, 1.329 + &mapping0_free_look, 1.330 + &mapping0_inverse 1.331 +};