xref: /aosp_15_r20/external/tremolo/Tremolo/mapping0.c (revision bda690e46497e1f65c5077173b9c548e6e0cd5a1)
1*bda690e4SXin Li /************************************************************************
2*bda690e4SXin Li  * Copyright (C) 2002-2009, Xiph.org Foundation
3*bda690e4SXin Li  * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4*bda690e4SXin Li  * All rights reserved.
5*bda690e4SXin Li  *
6*bda690e4SXin Li  * Redistribution and use in source and binary forms, with or without
7*bda690e4SXin Li  * modification, are permitted provided that the following conditions
8*bda690e4SXin Li  * are met:
9*bda690e4SXin Li  *
10*bda690e4SXin Li  *     * Redistributions of source code must retain the above copyright
11*bda690e4SXin Li  * notice, this list of conditions and the following disclaimer.
12*bda690e4SXin Li  *     * Redistributions in binary form must reproduce the above
13*bda690e4SXin Li  * copyright notice, this list of conditions and the following disclaimer
14*bda690e4SXin Li  * in the documentation and/or other materials provided with the
15*bda690e4SXin Li  * distribution.
16*bda690e4SXin Li  *     * Neither the names of the Xiph.org Foundation nor Pinknoise
17*bda690e4SXin Li  * Productions Ltd nor the names of its contributors may be used to
18*bda690e4SXin Li  * endorse or promote products derived from this software without
19*bda690e4SXin Li  * specific prior written permission.
20*bda690e4SXin Li  *
21*bda690e4SXin Li  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*bda690e4SXin Li  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*bda690e4SXin Li  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24*bda690e4SXin Li  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25*bda690e4SXin Li  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26*bda690e4SXin Li  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27*bda690e4SXin Li  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28*bda690e4SXin Li  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29*bda690e4SXin Li  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30*bda690e4SXin Li  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31*bda690e4SXin Li  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*bda690e4SXin Li  ************************************************************************
33*bda690e4SXin Li 
34*bda690e4SXin Li  function: channel mapping 0 implementation
35*bda690e4SXin Li 
36*bda690e4SXin Li  ************************************************************************/
37*bda690e4SXin Li 
38*bda690e4SXin Li #include <stdlib.h>
39*bda690e4SXin Li #include <stdio.h>
40*bda690e4SXin Li #include <string.h>
41*bda690e4SXin Li #include <math.h>
42*bda690e4SXin Li #include "ogg.h"
43*bda690e4SXin Li #include "os.h"
44*bda690e4SXin Li #include "ivorbiscodec.h"
45*bda690e4SXin Li #include "mdct.h"
46*bda690e4SXin Li #include "codec_internal.h"
47*bda690e4SXin Li #include "codebook.h"
48*bda690e4SXin Li #include "misc.h"
49*bda690e4SXin Li 
mapping_clear_info(vorbis_info_mapping * info)50*bda690e4SXin Li void mapping_clear_info(vorbis_info_mapping *info){
51*bda690e4SXin Li   if(info){
52*bda690e4SXin Li     if(info->chmuxlist)_ogg_free(info->chmuxlist);
53*bda690e4SXin Li     if(info->submaplist)_ogg_free(info->submaplist);
54*bda690e4SXin Li     if(info->coupling)_ogg_free(info->coupling);
55*bda690e4SXin Li     memset(info,0,sizeof(*info));
56*bda690e4SXin Li   }
57*bda690e4SXin Li }
58*bda690e4SXin Li 
ilog(unsigned int v)59*bda690e4SXin Li static int ilog(unsigned int v){
60*bda690e4SXin Li   int ret=0;
61*bda690e4SXin Li   if(v)--v;
62*bda690e4SXin Li   while(v){
63*bda690e4SXin Li     ret++;
64*bda690e4SXin Li     v>>=1;
65*bda690e4SXin Li   }
66*bda690e4SXin Li   return(ret);
67*bda690e4SXin Li }
68*bda690e4SXin Li 
69*bda690e4SXin Li /* also responsible for range checking */
mapping_info_unpack(vorbis_info_mapping * info,vorbis_info * vi,oggpack_buffer * opb)70*bda690e4SXin Li int mapping_info_unpack(vorbis_info_mapping *info,vorbis_info *vi,
71*bda690e4SXin Li 			oggpack_buffer *opb){
72*bda690e4SXin Li   int i;
73*bda690e4SXin Li   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
74*bda690e4SXin Li   memset(info,0,sizeof(*info));
75*bda690e4SXin Li 
76*bda690e4SXin Li   if(oggpack_read(opb,1))
77*bda690e4SXin Li     info->submaps=oggpack_read(opb,4)+1;
78*bda690e4SXin Li   else
79*bda690e4SXin Li     info->submaps=1;
80*bda690e4SXin Li 
81*bda690e4SXin Li   if(oggpack_read(opb,1)){
82*bda690e4SXin Li     info->coupling_steps=oggpack_read(opb,8)+1;
83*bda690e4SXin Li     info->coupling=
84*bda690e4SXin Li       _ogg_malloc(info->coupling_steps*sizeof(*info->coupling));
85*bda690e4SXin Li 
86*bda690e4SXin Li     for(i=0;i<info->coupling_steps;i++){
87*bda690e4SXin Li       int testM=info->coupling[i].mag=(unsigned char)(oggpack_read(opb,ilog(vi->channels)));
88*bda690e4SXin Li       int testA=info->coupling[i].ang=(unsigned char)(oggpack_read(opb,ilog(vi->channels)));
89*bda690e4SXin Li 
90*bda690e4SXin Li       if(testM<0 ||
91*bda690e4SXin Li 	 testA<0 ||
92*bda690e4SXin Li 	 testM==testA ||
93*bda690e4SXin Li 	 testM>=vi->channels ||
94*bda690e4SXin Li 	 testA>=vi->channels) goto err_out;
95*bda690e4SXin Li     }
96*bda690e4SXin Li 
97*bda690e4SXin Li   }
98*bda690e4SXin Li 
99*bda690e4SXin Li   if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */
100*bda690e4SXin Li 
101*bda690e4SXin Li   if(info->submaps>1){
102*bda690e4SXin Li     info->chmuxlist=_ogg_malloc(sizeof(*info->chmuxlist)*vi->channels);
103*bda690e4SXin Li     for(i=0;i<vi->channels;i++){
104*bda690e4SXin Li       info->chmuxlist[i]=(unsigned char)(oggpack_read(opb,4));
105*bda690e4SXin Li       if(info->chmuxlist[i]>=info->submaps)goto err_out;
106*bda690e4SXin Li     }
107*bda690e4SXin Li   }
108*bda690e4SXin Li 
109*bda690e4SXin Li   info->submaplist=_ogg_malloc(sizeof(*info->submaplist)*info->submaps);
110*bda690e4SXin Li   for(i=0;i<info->submaps;i++){
111*bda690e4SXin Li     int temp=oggpack_read(opb,8);
112*bda690e4SXin Li     info->submaplist[i].floor=(char)oggpack_read(opb,8);
113*bda690e4SXin Li     if(info->submaplist[i].floor>=ci->floors)goto err_out;
114*bda690e4SXin Li     info->submaplist[i].residue=(char)oggpack_read(opb,8);
115*bda690e4SXin Li     if(info->submaplist[i].residue>=ci->residues)goto err_out;
116*bda690e4SXin Li   }
117*bda690e4SXin Li 
118*bda690e4SXin Li   return 0;
119*bda690e4SXin Li 
120*bda690e4SXin Li  err_out:
121*bda690e4SXin Li   mapping_clear_info(info);
122*bda690e4SXin Li   return -1;
123*bda690e4SXin Li }
124*bda690e4SXin Li 
mapping_inverse(vorbis_dsp_state * vd,vorbis_info_mapping * info)125*bda690e4SXin Li int mapping_inverse(vorbis_dsp_state *vd,vorbis_info_mapping *info){
126*bda690e4SXin Li   vorbis_info          *vi=vd->vi;
127*bda690e4SXin Li   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
128*bda690e4SXin Li 
129*bda690e4SXin Li   int                   i,j;
130*bda690e4SXin Li   long                  n=ci->blocksizes[vd->W];
131*bda690e4SXin Li 
132*bda690e4SXin Li   ogg_int32_t **pcmbundle=
133*bda690e4SXin Li     alloca(sizeof(*pcmbundle)*vi->channels);
134*bda690e4SXin Li   int          *zerobundle=
135*bda690e4SXin Li     alloca(sizeof(*zerobundle)*vi->channels);
136*bda690e4SXin Li   int          *nonzero=
137*bda690e4SXin Li     alloca(sizeof(*nonzero)*vi->channels);
138*bda690e4SXin Li   ogg_int32_t **floormemo=
139*bda690e4SXin Li     alloca(sizeof(*floormemo)*vi->channels);
140*bda690e4SXin Li 
141*bda690e4SXin Li   /* recover the spectral envelope; store it in the PCM vector for now */
142*bda690e4SXin Li   for(i=0;i<vi->channels;i++){
143*bda690e4SXin Li     int submap=0;
144*bda690e4SXin Li     int floorno;
145*bda690e4SXin Li 
146*bda690e4SXin Li     if(info->submaps>1)
147*bda690e4SXin Li       submap=info->chmuxlist[i];
148*bda690e4SXin Li     floorno=info->submaplist[submap].floor;
149*bda690e4SXin Li 
150*bda690e4SXin Li     if(ci->floor_type[floorno]){
151*bda690e4SXin Li       /* floor 1 */
152*bda690e4SXin Li       floormemo[i]=alloca(sizeof(*floormemo[i])*
153*bda690e4SXin Li 			  floor1_memosize(ci->floor_param[floorno]));
154*bda690e4SXin Li       floormemo[i]=floor1_inverse1(vd,ci->floor_param[floorno],floormemo[i]);
155*bda690e4SXin Li     }else{
156*bda690e4SXin Li       /* floor 0 */
157*bda690e4SXin Li       floormemo[i]=alloca(sizeof(*floormemo[i])*
158*bda690e4SXin Li 			  floor0_memosize(ci->floor_param[floorno]));
159*bda690e4SXin Li       floormemo[i]=floor0_inverse1(vd,ci->floor_param[floorno],floormemo[i]);
160*bda690e4SXin Li     }
161*bda690e4SXin Li 
162*bda690e4SXin Li     if(floormemo[i])
163*bda690e4SXin Li       nonzero[i]=1;
164*bda690e4SXin Li     else
165*bda690e4SXin Li       nonzero[i]=0;
166*bda690e4SXin Li     memset(vd->work[i],0,sizeof(*vd->work[i])*n/2);
167*bda690e4SXin Li   }
168*bda690e4SXin Li 
169*bda690e4SXin Li   /* channel coupling can 'dirty' the nonzero listing */
170*bda690e4SXin Li   for(i=0;i<info->coupling_steps;i++){
171*bda690e4SXin Li     if(nonzero[info->coupling[i].mag] ||
172*bda690e4SXin Li        nonzero[info->coupling[i].ang]){
173*bda690e4SXin Li       nonzero[info->coupling[i].mag]=1;
174*bda690e4SXin Li       nonzero[info->coupling[i].ang]=1;
175*bda690e4SXin Li     }
176*bda690e4SXin Li   }
177*bda690e4SXin Li 
178*bda690e4SXin Li   /* recover the residue into our working vectors */
179*bda690e4SXin Li   for(i=0;i<info->submaps;i++){
180*bda690e4SXin Li     int ch_in_bundle=0;
181*bda690e4SXin Li     for(j=0;j<vi->channels;j++){
182*bda690e4SXin Li       if(!info->chmuxlist || info->chmuxlist[j]==i){
183*bda690e4SXin Li 	if(nonzero[j])
184*bda690e4SXin Li 	  zerobundle[ch_in_bundle]=1;
185*bda690e4SXin Li 	else
186*bda690e4SXin Li 	  zerobundle[ch_in_bundle]=0;
187*bda690e4SXin Li 	pcmbundle[ch_in_bundle++]=vd->work[j];
188*bda690e4SXin Li       }
189*bda690e4SXin Li     }
190*bda690e4SXin Li 
191*bda690e4SXin Li     res_inverse(vd,ci->residue_param+info->submaplist[i].residue,
192*bda690e4SXin Li 		pcmbundle,zerobundle,ch_in_bundle);
193*bda690e4SXin Li   }
194*bda690e4SXin Li 
195*bda690e4SXin Li   //for(j=0;j<vi->channels;j++)
196*bda690e4SXin Li   //_analysis_output("coupled",seq+j,vb->pcm[j],-8,n/2,0,0);
197*bda690e4SXin Li 
198*bda690e4SXin Li   /* channel coupling */
199*bda690e4SXin Li   for(i=info->coupling_steps-1;i>=0;i--){
200*bda690e4SXin Li     ogg_int32_t *pcmM=vd->work[info->coupling[i].mag];
201*bda690e4SXin Li     ogg_int32_t *pcmA=vd->work[info->coupling[i].ang];
202*bda690e4SXin Li 
203*bda690e4SXin Li     for(j=0;j<n/2;j++){
204*bda690e4SXin Li       ogg_int32_t mag=pcmM[j];
205*bda690e4SXin Li       ogg_int32_t ang=pcmA[j];
206*bda690e4SXin Li 
207*bda690e4SXin Li       if(mag>0)
208*bda690e4SXin Li 	if(ang>0){
209*bda690e4SXin Li 	  pcmM[j]=mag;
210*bda690e4SXin Li 	  pcmA[j]=mag-ang;
211*bda690e4SXin Li 	}else{
212*bda690e4SXin Li 	  pcmA[j]=mag;
213*bda690e4SXin Li 	  pcmM[j]=mag+ang;
214*bda690e4SXin Li 	}
215*bda690e4SXin Li       else
216*bda690e4SXin Li 	if(ang>0){
217*bda690e4SXin Li 	  pcmM[j]=mag;
218*bda690e4SXin Li 	  pcmA[j]=mag+ang;
219*bda690e4SXin Li 	}else{
220*bda690e4SXin Li 	  pcmA[j]=mag;
221*bda690e4SXin Li 	  pcmM[j]=mag-ang;
222*bda690e4SXin Li 	}
223*bda690e4SXin Li     }
224*bda690e4SXin Li   }
225*bda690e4SXin Li 
226*bda690e4SXin Li   //for(j=0;j<vi->channels;j++)
227*bda690e4SXin Li   //_analysis_output("residue",seq+j,vb->pcm[j],-8,n/2,0,0);
228*bda690e4SXin Li 
229*bda690e4SXin Li   /* compute and apply spectral envelope */
230*bda690e4SXin Li   for(i=0;i<vi->channels;i++){
231*bda690e4SXin Li     ogg_int32_t *pcm=vd->work[i];
232*bda690e4SXin Li     int submap=0;
233*bda690e4SXin Li     int floorno;
234*bda690e4SXin Li 
235*bda690e4SXin Li     if(info->submaps>1)
236*bda690e4SXin Li       submap=info->chmuxlist[i];
237*bda690e4SXin Li     floorno=info->submaplist[submap].floor;
238*bda690e4SXin Li 
239*bda690e4SXin Li     if(ci->floor_type[floorno]){
240*bda690e4SXin Li       /* floor 1 */
241*bda690e4SXin Li       floor1_inverse2(vd,ci->floor_param[floorno],floormemo[i],pcm);
242*bda690e4SXin Li     }else{
243*bda690e4SXin Li       /* floor 0 */
244*bda690e4SXin Li       floor0_inverse2(vd,ci->floor_param[floorno],floormemo[i],pcm);
245*bda690e4SXin Li     }
246*bda690e4SXin Li   }
247*bda690e4SXin Li 
248*bda690e4SXin Li   //for(j=0;j<vi->channels;j++)
249*bda690e4SXin Li   //_analysis_output("mdct",seq+j,vb->pcm[j],-24,n/2,0,1);
250*bda690e4SXin Li 
251*bda690e4SXin Li   /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
252*bda690e4SXin Li   /* only MDCT right now.... */
253*bda690e4SXin Li   for(i=0;i<vi->channels;i++)
254*bda690e4SXin Li     mdct_backward(n,vd->work[i]);
255*bda690e4SXin Li 
256*bda690e4SXin Li   //for(j=0;j<vi->channels;j++)
257*bda690e4SXin Li   //_analysis_output("imdct",seq+j,vb->pcm[j],-24,n,0,0);
258*bda690e4SXin Li 
259*bda690e4SXin Li   /* all done! */
260*bda690e4SXin Li   return(0);
261*bda690e4SXin Li }
262