1 /********************************************************************
3 * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
6 * PLEASE READ THESE TERMS DISTRIBUTING. *
8 * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 *
9 * by Monty <monty@xiph.org> and The XIPHOPHORUS Company *
10 * http://www.xiph.org/ *
12 ********************************************************************
14 function: channel mapping 0 implementation
15 last mod: $Id: mapping0.c,v 1.2 2000/01/22 13:28:23 xiphmont Exp $
17 ********************************************************************/
22 #include "vorbis/codec.h"
24 #include "bookinternal.h"
28 _vi_info_map *_vorbis_map0_dup(vorbis_info *vi,_vi_info_map *source){
29 vorbis_info_mapping0 *d=malloc(sizeof(vorbis_info_mapping0));
30 vorbis_info_mapping0 *s=(vorbis_info_mapping0 *)source;
31 memcpy(d,s,sizeof(vorbis_info_mapping0));
33 d->floorsubmap=malloc(sizeof(int)*vi->channels);
34 d->residuesubmap=malloc(sizeof(int)*vi->channels);
35 d->psysubmap=malloc(sizeof(int)*vi->channels);
36 memcpy(d->floorsubmap,s->floorsubmap,sizeof(int)*vi->channels);
37 memcpy(d->residuesubmap,s->residuesubmap,sizeof(int)*vi->channels);
38 memcpy(d->psysubmap,s->psysubmap,sizeof(int)*vi->channels);
43 void _vorbis_map0_free(_vi_info_map *i){
44 vorbis_info_mapping0 *d=(vorbis_info_mapping0 *)i;
47 if(d->floorsubmap)free(d->floorsubmap);
48 if(d->residuesubmap)free(d->residuesubmap);
49 if(d->psysubmap)free(d->psysubmap);
50 memset(d,0,sizeof(vorbis_info_mapping0));
55 void _vorbis_map0_pack(vorbis_info *vi,oggpack_buffer *opb,
56 _vi_info_map *source){
58 vorbis_info_mapping0 *d=(vorbis_info_mapping0 *)source;
60 _oggpack_write(opb,d->timesubmap,8);
62 /* we abbreviate the channel submappings if they all map to the same
64 for(i=1;i<vi->channels;i++)if(d->floorsubmap[i]!=d->floorsubmap[i-1])break;
66 _oggpack_write(opb,0,1);
67 _oggpack_write(opb,d->floorsubmap[0],8);
69 _oggpack_write(opb,1,1);
70 for(i=0;i<vi->channels;i++)
71 _oggpack_write(opb,d->floorsubmap[i],8);
74 for(i=1;i<vi->channels;i++)
75 if(d->residuesubmap[i]!=d->residuesubmap[i-1])break;
77 /* no channel submapping */
78 _oggpack_write(opb,0,1);
79 _oggpack_write(opb,d->residuesubmap[0],8);
81 /* channel submapping */
82 _oggpack_write(opb,1,1);
83 for(i=0;i<vi->channels;i++)
84 _oggpack_write(opb,d->residuesubmap[i],8);
88 /* also responsible for range checking */
89 extern _vi_info_map *_vorbis_map0_unpack(vorbis_info *vi,oggpack_buffer *opb){
91 vorbis_info_mapping0 *d=calloc(1,sizeof(vorbis_info_mapping0));
92 memset(d,0,sizeof(vorbis_info_mapping0));
94 d->timesubmap=_oggpack_read(opb,8);
95 if(d->timesubmap>=vi->times)goto err_out;
97 d->floorsubmap=malloc(sizeof(int)*vi->channels);
98 if(_oggpack_read(opb,1)){
100 for(i=0;i<vi->channels;i++)
101 d->floorsubmap[i]=_oggpack_read(opb,8);
103 int temp=_oggpack_read(opb,8);
104 for(i=0;i<vi->channels;i++)
105 d->floorsubmap[i]=temp;
108 d->residuesubmap=malloc(sizeof(int)*vi->channels);
109 if(_oggpack_read(opb,1)){
111 for(i=0;i<vi->channels;i++)
112 d->residuesubmap[i]=_oggpack_read(opb,8);
114 int temp=_oggpack_read(opb,8);
115 for(i=0;i<vi->channels;i++)
116 d->residuesubmap[i]=temp;
119 for(i=0;i<vi->channels;i++){
120 if(d->floorsubmap[i]<0 || d->floorsubmap[i]>=vi->floors)goto err_out;
121 if(d->residuesubmap[i]<0 || d->residuesubmap[i]>=vi->residues)
128 _vorbis_map0_free(d);
136 #include "envelope.h"
140 #include "spectrum.h"
142 /* no time mapping implementation for now */
143 int _vorbis_map0_analysis(int mode,vorbis_block *vb){
144 vorbis_dsp_state *vd=vb->vd;
145 oggpack_buffer *opb=&vb->opb;
146 vorbis_info *vi=vd->vi;
147 vorbis_info_mapping0 *map=(vorbis_info_mapping0 *)(vi->modelist[mode]);
151 /* time domain pre-window: NONE IMPLEMENTED */
153 /* window the PCM data: takes PCM vector, vb; modifies PCM vector */
156 double *window=vd->window[vb->W][vb->lW][vb->nW][vi->windowtypes[mode]];
157 for(i=0;i<vi->channels;i++){
158 double *pcm=vb->pcm[i];
164 /* time-domain post-window: NONE IMPLEMENTED */
166 /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
167 /* only MDCT right now.... */
169 for(i=0;i<vi->channels;i++){
170 double *pcm=vb->pcm[i];
171 mdct_forward(vd->transform[vb->W][0],pcm,pcm);
176 double *decfloor=_vorbis_block_alloc(vb,n*sizeof(double)/2);
177 double *floor=_vorbis_block_alloc(vb,n*sizeof(double)/2);
178 double *mask=_vorbis_block_alloc(vb,n*sizeof(double)/2);
180 for(i=0;i<vi->channels;i++){
181 double *pcm=vb->pcm[i];
182 double *pcmaux=vb->pcm[i]+n/2;
183 int floorsub=map->floorsubmap[i];
184 int ressub=map->residuesubmap[i];
185 int psysub=map->psysubmap[i];
187 /* perform psychoacoustics; takes PCM vector;
188 returns two curves: the desired transform floor and the masking curve */
189 memset(floor,0,sizeof(double)*n/2);
190 memset(mask,0,sizeof(double)*n/2);
191 _vp_mask_floor(&vd->psy[psysub],pcm,mask,floor);
193 /* perform floor encoding; takes transform floor, returns decoded floor */
194 vorbis_floor_encode_P[vi->floortypes[floorsub]]
195 (vi->floorlist[floorsub],vd->floor[floorsub],pcm,floor,decfloor);
197 /* perform residue prequantization */
198 _vp_quantize(&vd->psy[psysub],pcm,mask,decfloor,pcmaux);
203 /* perform residue encoding with residue mapping; this is multiplexed */
204 /* multiplexing works like this: The first
206 vorbis_res_encode_P[vi->restypes[ressub]]
207 (vi->reslist[ressub],vd->residue[ressub],pcm,mask,decfloor);
214 int _vorbis_map0_synthesis(int mode,vorbis_block *vb){
218 window=vb->vd->window[vb->W][vb->lW][vb->nW];
220 n=vb->pcmend=vi->blocksize[vb->W];
222 /* No envelope encoding yet */
223 _oggpack_read(opb,0,1);
225 for(i=0;i<vi->channels;i++){
226 double *lpc=vb->lpc[i];
227 double *lsp=vb->lsp[i];
229 /* recover the spectral envelope */
230 if(_vs_spectrum_decode(vb,&vb->amp[i],lsp)<0)return(-1);
232 /* recover the spectral residue */
233 if(_vs_residue_decode(vb,vb->pcm[i])<0)return(-1);
236 vorbis_lsp_to_lpc(lsp,lpc,vl->m);
238 /* apply envelope to residue */
240 vorbis_lpc_apply(vb->pcm[i],lpc,vb->amp[i],vl);
244 mdct_backward(&vb->vd->vm[vb->W],vb->pcm[i],vb->pcm[i],window);