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 ********************************************************************/
24 #include "ivorbiscodec.h"
26 #include "codec_internal.h"
32 /* simplistic, wasteful way of doing this (unique lookup for each
33 mode/submapping); there should be a central repository for
34 identical lookups. That will require minor work, so I'm putting it
37 Why a lookup for each backend in a given mode? Because the
38 blocksize is set by the mode, and low backend lookups may require
39 parameters from other areas of the mode/mapping */
42 vorbis_info_mode
*mode
;
43 vorbis_info_mapping0
*map
;
45 vorbis_look_floor
**floor_look
;
47 vorbis_look_residue
**residue_look
;
49 vorbis_func_floor
**floor_func
;
50 vorbis_func_residue
**residue_func
;
53 long lastframe
; /* if a different mode is called, we need to
55 } vorbis_look_mapping0
;
57 static void mapping0_free_info(vorbis_info_mapping
*i
){
58 vorbis_info_mapping0
*info
=(vorbis_info_mapping0
*)i
;
60 memset(info
,0,sizeof(*info
));
65 static void mapping0_free_look(vorbis_look_mapping
*look
){
67 vorbis_look_mapping0
*l
=(vorbis_look_mapping0
*)look
;
70 for(i
=0;i
<l
->map
->submaps
;i
++){
71 l
->floor_func
[i
]->free_look(l
->floor_look
[i
]);
72 l
->residue_func
[i
]->free_look(l
->residue_look
[i
]);
75 _ogg_free(l
->floor_func
);
76 _ogg_free(l
->residue_func
);
77 _ogg_free(l
->floor_look
);
78 _ogg_free(l
->residue_look
);
79 memset(l
,0,sizeof(*l
));
84 static vorbis_look_mapping
*mapping0_look(vorbis_dsp_state
*vd
,vorbis_info_mode
*vm
,
85 vorbis_info_mapping
*m
){
87 vorbis_info
*vi
=vd
->vi
;
88 codec_setup_info
*ci
=(codec_setup_info
*)vi
->codec_setup
;
89 vorbis_look_mapping0
*look
=(vorbis_look_mapping0
*)_ogg_calloc(1,sizeof(*look
));
90 vorbis_info_mapping0
*info
=look
->map
=(vorbis_info_mapping0
*)m
;
93 look
->floor_look
=(vorbis_look_floor
**)_ogg_calloc(info
->submaps
,sizeof(*look
->floor_look
));
95 look
->residue_look
=(vorbis_look_residue
**)_ogg_calloc(info
->submaps
,sizeof(*look
->residue_look
));
97 look
->floor_func
=(vorbis_func_floor
**)_ogg_calloc(info
->submaps
,sizeof(*look
->floor_func
));
98 look
->residue_func
=(vorbis_func_residue
**)_ogg_calloc(info
->submaps
,sizeof(*look
->residue_func
));
100 for(i
=0;i
<info
->submaps
;i
++){
101 int floornum
=info
->floorsubmap
[i
];
102 int resnum
=info
->residuesubmap
[i
];
104 look
->floor_func
[i
]=_floor_P
[ci
->floor_type
[floornum
]];
105 look
->floor_look
[i
]=look
->floor_func
[i
]->
106 look(vd
,vm
,ci
->floor_param
[floornum
]);
107 look
->residue_func
[i
]=_residue_P
[ci
->residue_type
[resnum
]];
108 look
->residue_look
[i
]=look
->residue_func
[i
]->
109 look(vd
,vm
,ci
->residue_param
[resnum
]);
113 look
->ch
=vi
->channels
;
118 static int ilog(unsigned int v
){
128 /* also responsible for range checking */
129 static vorbis_info_mapping
*mapping0_unpack(vorbis_info
*vi
,oggpack_buffer
*opb
){
131 vorbis_info_mapping0
*info
=(vorbis_info_mapping0
*)_ogg_calloc(1,sizeof(*info
));
132 codec_setup_info
*ci
=(codec_setup_info
*)vi
->codec_setup
;
133 memset(info
,0,sizeof(*info
));
135 if(oggpack_read(opb
,1))
136 info
->submaps
=oggpack_read(opb
,4)+1;
140 if(oggpack_read(opb
,1)){
141 info
->coupling_steps
=oggpack_read(opb
,8)+1;
143 for(i
=0;i
<info
->coupling_steps
;i
++){
144 int testM
=info
->coupling_mag
[i
]=oggpack_read(opb
,ilog(vi
->channels
));
145 int testA
=info
->coupling_ang
[i
]=oggpack_read(opb
,ilog(vi
->channels
));
150 testM
>=vi
->channels
||
151 testA
>=vi
->channels
) goto err_out
;
156 if(oggpack_read(opb
,2)>0)goto err_out
; /* 2,3:reserved */
159 for(i
=0;i
<vi
->channels
;i
++){
160 info
->chmuxlist
[i
]=oggpack_read(opb
,4);
161 if(info
->chmuxlist
[i
]>=info
->submaps
)goto err_out
;
164 for(i
=0;i
<info
->submaps
;i
++){
165 int temp
=oggpack_read(opb
,8);
166 if(temp
>=ci
->times
)goto err_out
;
167 info
->floorsubmap
[i
]=oggpack_read(opb
,8);
168 if(info
->floorsubmap
[i
]>=ci
->floors
)goto err_out
;
169 info
->residuesubmap
[i
]=oggpack_read(opb
,8);
170 if(info
->residuesubmap
[i
]>=ci
->residues
)goto err_out
;
176 mapping0_free_info(info
);
181 static int mapping0_inverse(vorbis_block
*vb
,vorbis_look_mapping
*l
){
182 vorbis_dsp_state
*vd
=vb
->vd
;
183 vorbis_info
*vi
=vd
->vi
;
184 codec_setup_info
*ci
=(codec_setup_info
*)vi
->codec_setup
;
185 backend_lookup_state
*b
=(backend_lookup_state
*)vd
->backend_state
;
186 vorbis_look_mapping0
*look
=(vorbis_look_mapping0
*)l
;
187 vorbis_info_mapping0
*info
=look
->map
;
190 long n
=vb
->pcmend
=ci
->blocksizes
[vb
->W
];
192 ogg_int32_t
**pcmbundle
=(ogg_int32_t
**)alloca(sizeof(*pcmbundle
)*vi
->channels
);
193 int *zerobundle
=(int *)alloca(sizeof(*zerobundle
)*vi
->channels
);
195 int *nonzero
=(int *)alloca(sizeof(*nonzero
)*vi
->channels
);
196 void **floormemo
=(void **)alloca(sizeof(*floormemo
)*vi
->channels
);
198 /* time domain information decode (note that applying the
199 information would have to happen later; we'll probably add a
200 function entry to the harness for that later */
201 /* NOT IMPLEMENTED */
203 /* recover the spectral envelope; store it in the PCM vector for now */
204 for(i
=0;i
<vi
->channels
;i
++){
205 int submap
=info
->chmuxlist
[i
];
206 floormemo
[i
]=look
->floor_func
[submap
]->
207 inverse1(vb
,look
->floor_look
[submap
]);
212 memset(vb
->pcm
[i
],0,sizeof(*vb
->pcm
[i
])*n
/2);
215 /* channel coupling can 'dirty' the nonzero listing */
216 for(i
=0;i
<info
->coupling_steps
;i
++){
217 if(nonzero
[info
->coupling_mag
[i
]] ||
218 nonzero
[info
->coupling_ang
[i
]]){
219 nonzero
[info
->coupling_mag
[i
]]=1;
220 nonzero
[info
->coupling_ang
[i
]]=1;
224 /* recover the residue into our working vectors */
225 for(i
=0;i
<info
->submaps
;i
++){
227 for(j
=0;j
<vi
->channels
;j
++){
228 if(info
->chmuxlist
[j
]==i
){
230 zerobundle
[ch_in_bundle
]=1;
232 zerobundle
[ch_in_bundle
]=0;
233 pcmbundle
[ch_in_bundle
++]=vb
->pcm
[j
];
237 look
->residue_func
[i
]->inverse(vb
,look
->residue_look
[i
],
238 pcmbundle
,zerobundle
,ch_in_bundle
);
241 //for(j=0;j<vi->channels;j++)
242 //_analysis_output("coupled",seq+j,vb->pcm[j],-8,n/2,0,0);
245 /* channel coupling */
246 for(i
=info
->coupling_steps
-1;i
>=0;i
--){
247 ogg_int32_t
*pcmM
=vb
->pcm
[info
->coupling_mag
[i
]];
248 ogg_int32_t
*pcmA
=vb
->pcm
[info
->coupling_ang
[i
]];
251 ogg_int32_t mag
=pcmM
[j
];
252 ogg_int32_t ang
=pcmA
[j
];
273 //for(j=0;j<vi->channels;j++)
274 //_analysis_output("residue",seq+j,vb->pcm[j],-8,n/2,0,0);
276 /* compute and apply spectral envelope */
277 for(i
=0;i
<vi
->channels
;i
++){
278 ogg_int32_t
*pcm
=vb
->pcm
[i
];
279 int submap
=info
->chmuxlist
[i
];
280 look
->floor_func
[submap
]->
281 inverse2(vb
,look
->floor_look
[submap
],floormemo
[i
],pcm
);
284 //for(j=0;j<vi->channels;j++)
285 //_analysis_output("mdct",seq+j,vb->pcm[j],-24,n/2,0,1);
287 /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
288 /* only MDCT right now.... */
289 for(i
=0;i
<vi
->channels
;i
++){
290 ogg_int32_t
*pcm
=vb
->pcm
[i
];
291 mdct_backward(n
,pcm
,pcm
);
294 //for(j=0;j<vi->channels;j++)
295 //_analysis_output("imdct",seq+j,vb->pcm[j],-24,n,0,0);
297 /* window the data */
298 for(i
=0;i
<vi
->channels
;i
++){
299 ogg_int32_t
*pcm
=vb
->pcm
[i
];
301 _vorbis_apply_window(pcm
,b
->window
,ci
->blocksizes
,vb
->lW
,vb
->W
,vb
->nW
);
308 //for(j=0;j<vi->channels;j++)
309 //_analysis_output("window",seq+j,vb->pcm[j],-24,n,0,0);
317 vorbis_func_mapping mapping0_exportbundle
={