1 /********************************************************************
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
12 ********************************************************************
14 function: channel mapping 0 implementation
16 ********************************************************************/
23 #include "ivorbiscodec.h"
25 #include "codec_internal.h"
31 /* simplistic, wasteful way of doing this (unique lookup for each
32 mode/submapping); there should be a central repository for
33 identical lookups. That will require minor work, so I'm putting it
36 Why a lookup for each backend in a given mode? Because the
37 blocksize is set by the mode, and low backend lookups may require
38 parameters from other areas of the mode/mapping */
41 vorbis_info_mode
*mode
;
42 vorbis_info_mapping0
*map
;
44 vorbis_look_floor
**floor_look
;
46 vorbis_look_residue
**residue_look
;
48 vorbis_func_floor
**floor_func
;
49 vorbis_func_residue
**residue_func
;
52 long lastframe
; /* if a different mode is called, we need to
54 } vorbis_look_mapping0
;
56 static void mapping0_free_info(vorbis_info_mapping
*i
){
57 vorbis_info_mapping0
*info
=(vorbis_info_mapping0
*)i
;
59 memset(info
,0,sizeof(*info
));
64 static void mapping0_free_look(vorbis_look_mapping
*look
){
66 vorbis_look_mapping0
*l
=(vorbis_look_mapping0
*)look
;
69 for(i
=0;i
<l
->map
->submaps
;i
++){
70 l
->floor_func
[i
]->free_look(l
->floor_look
[i
]);
71 l
->residue_func
[i
]->free_look(l
->residue_look
[i
]);
74 _ogg_free(l
->floor_func
);
75 _ogg_free(l
->residue_func
);
76 _ogg_free(l
->floor_look
);
77 _ogg_free(l
->residue_look
);
78 memset(l
,0,sizeof(*l
));
83 static vorbis_look_mapping
*mapping0_look(vorbis_dsp_state
*vd
,vorbis_info_mode
*vm
,
84 vorbis_info_mapping
*m
){
86 vorbis_info
*vi
=vd
->vi
;
87 codec_setup_info
*ci
=(codec_setup_info
*)vi
->codec_setup
;
88 vorbis_look_mapping0
*look
=(vorbis_look_mapping0
*)_ogg_calloc(1,sizeof(*look
));
89 vorbis_info_mapping0
*info
=look
->map
=(vorbis_info_mapping0
*)m
;
92 look
->floor_look
=(vorbis_look_floor
**)_ogg_calloc(info
->submaps
,sizeof(*look
->floor_look
));
94 look
->residue_look
=(vorbis_look_residue
**)_ogg_calloc(info
->submaps
,sizeof(*look
->residue_look
));
96 look
->floor_func
=(vorbis_func_floor
**)_ogg_calloc(info
->submaps
,sizeof(*look
->floor_func
));
97 look
->residue_func
=(vorbis_func_residue
**)_ogg_calloc(info
->submaps
,sizeof(*look
->residue_func
));
99 for(i
=0;i
<info
->submaps
;i
++){
100 int floornum
=info
->floorsubmap
[i
];
101 int resnum
=info
->residuesubmap
[i
];
103 look
->floor_func
[i
]=_floor_P
[ci
->floor_type
[floornum
]];
104 look
->floor_look
[i
]=look
->floor_func
[i
]->
105 look(vd
,vm
,ci
->floor_param
[floornum
]);
106 look
->residue_func
[i
]=_residue_P
[ci
->residue_type
[resnum
]];
107 look
->residue_look
[i
]=look
->residue_func
[i
]->
108 look(vd
,vm
,ci
->residue_param
[resnum
]);
112 look
->ch
=vi
->channels
;
117 static int ilog(unsigned int v
){
127 /* also responsible for range checking */
128 static vorbis_info_mapping
*mapping0_unpack(vorbis_info
*vi
,oggpack_buffer
*opb
){
130 vorbis_info_mapping0
*info
=(vorbis_info_mapping0
*)_ogg_calloc(1,sizeof(*info
));
131 codec_setup_info
*ci
=(codec_setup_info
*)vi
->codec_setup
;
132 memset(info
,0,sizeof(*info
));
134 if(oggpack_read(opb
,1))
135 info
->submaps
=oggpack_read(opb
,4)+1;
139 if(oggpack_read(opb
,1)){
140 info
->coupling_steps
=oggpack_read(opb
,8)+1;
142 for(i
=0;i
<info
->coupling_steps
;i
++){
143 int testM
=info
->coupling_mag
[i
]=oggpack_read(opb
,ilog(vi
->channels
));
144 int testA
=info
->coupling_ang
[i
]=oggpack_read(opb
,ilog(vi
->channels
));
149 testM
>=vi
->channels
||
150 testA
>=vi
->channels
) goto err_out
;
155 if(oggpack_read(opb
,2)>0)goto err_out
; /* 2,3:reserved */
158 for(i
=0;i
<vi
->channels
;i
++){
159 info
->chmuxlist
[i
]=oggpack_read(opb
,4);
160 if(info
->chmuxlist
[i
]>=info
->submaps
)goto err_out
;
163 for(i
=0;i
<info
->submaps
;i
++){
164 int temp
=oggpack_read(opb
,8);
165 if(temp
>=ci
->times
)goto err_out
;
166 info
->floorsubmap
[i
]=oggpack_read(opb
,8);
167 if(info
->floorsubmap
[i
]>=ci
->floors
)goto err_out
;
168 info
->residuesubmap
[i
]=oggpack_read(opb
,8);
169 if(info
->residuesubmap
[i
]>=ci
->residues
)goto err_out
;
175 mapping0_free_info(info
);
180 static int mapping0_inverse(vorbis_block
*vb
,vorbis_look_mapping
*l
){
181 vorbis_dsp_state
*vd
=vb
->vd
;
182 vorbis_info
*vi
=vd
->vi
;
183 codec_setup_info
*ci
=(codec_setup_info
*)vi
->codec_setup
;
184 private_state
*b
=(private_state
*)vd
->backend_state
;
185 vorbis_look_mapping0
*look
=(vorbis_look_mapping0
*)l
;
186 vorbis_info_mapping0
*info
=look
->map
;
189 long n
=vb
->pcmend
=ci
->blocksizes
[vb
->W
];
191 ogg_int32_t
**pcmbundle
=(ogg_int32_t
**)alloca(sizeof(*pcmbundle
)*vi
->channels
);
192 int *zerobundle
=(int *)alloca(sizeof(*zerobundle
)*vi
->channels
);
194 int *nonzero
=(int *)alloca(sizeof(*nonzero
)*vi
->channels
);
195 void **floormemo
=(void **)alloca(sizeof(*floormemo
)*vi
->channels
);
197 /* time domain information decode (note that applying the
198 information would have to happen later; we'll probably add a
199 function entry to the harness for that later */
200 /* NOT IMPLEMENTED */
202 /* recover the spectral envelope; store it in the PCM vector for now */
203 for(i
=0;i
<vi
->channels
;i
++){
204 int submap
=info
->chmuxlist
[i
];
205 floormemo
[i
]=look
->floor_func
[submap
]->
206 inverse1(vb
,look
->floor_look
[submap
]);
211 memset(vb
->pcm
[i
],0,sizeof(*vb
->pcm
[i
])*n
/2);
214 /* channel coupling can 'dirty' the nonzero listing */
215 for(i
=0;i
<info
->coupling_steps
;i
++){
216 if(nonzero
[info
->coupling_mag
[i
]] ||
217 nonzero
[info
->coupling_ang
[i
]]){
218 nonzero
[info
->coupling_mag
[i
]]=1;
219 nonzero
[info
->coupling_ang
[i
]]=1;
223 /* recover the residue into our working vectors */
224 for(i
=0;i
<info
->submaps
;i
++){
226 for(j
=0;j
<vi
->channels
;j
++){
227 if(info
->chmuxlist
[j
]==i
){
229 zerobundle
[ch_in_bundle
]=1;
231 zerobundle
[ch_in_bundle
]=0;
232 pcmbundle
[ch_in_bundle
++]=vb
->pcm
[j
];
236 look
->residue_func
[i
]->inverse(vb
,look
->residue_look
[i
],
237 pcmbundle
,zerobundle
,ch_in_bundle
);
240 //for(j=0;j<vi->channels;j++)
241 //_analysis_output("coupled",seq+j,vb->pcm[j],-8,n/2,0,0);
244 /* channel coupling */
245 for(i
=info
->coupling_steps
-1;i
>=0;i
--){
246 ogg_int32_t
*pcmM
=vb
->pcm
[info
->coupling_mag
[i
]];
247 ogg_int32_t
*pcmA
=vb
->pcm
[info
->coupling_ang
[i
]];
250 ogg_int32_t mag
=pcmM
[j
];
251 ogg_int32_t ang
=pcmA
[j
];
272 //for(j=0;j<vi->channels;j++)
273 //_analysis_output("residue",seq+j,vb->pcm[j],-8,n/2,0,0);
275 /* compute and apply spectral envelope */
276 for(i
=0;i
<vi
->channels
;i
++){
277 ogg_int32_t
*pcm
=vb
->pcm
[i
];
278 int submap
=info
->chmuxlist
[i
];
279 look
->floor_func
[submap
]->
280 inverse2(vb
,look
->floor_look
[submap
],floormemo
[i
],pcm
);
283 //for(j=0;j<vi->channels;j++)
284 //_analysis_output("mdct",seq+j,vb->pcm[j],-24,n/2,0,1);
286 /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
287 /* only MDCT right now.... */
288 for(i
=0;i
<vi
->channels
;i
++){
289 ogg_int32_t
*pcm
=vb
->pcm
[i
];
290 mdct_backward(n
,pcm
,pcm
);
293 //for(j=0;j<vi->channels;j++)
294 //_analysis_output("imdct",seq+j,vb->pcm[j],-24,n,0,0);
296 /* window the data */
297 for(i
=0;i
<vi
->channels
;i
++){
298 ogg_int32_t
*pcm
=vb
->pcm
[i
];
300 _vorbis_apply_window(pcm
,b
->window
,ci
->blocksizes
,vb
->lW
,vb
->W
,vb
->nW
);
307 //for(j=0;j<vi->channels;j++)
308 //_analysis_output("window",seq+j,vb->pcm[j],-24,n,0,0);
316 vorbis_func_mapping mapping0_exportbundle
={