It's all coming back together slowly. Incremental update.
[platform/upstream/libvorbis.git] / lib / mapping0.c
1 /********************************************************************
2  *                                                                  *
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.                            *
7  *                                                                  *
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/                                             *
11  *                                                                  *
12  ********************************************************************
13
14  function: channel mapping 0 implementation
15  last mod: $Id: mapping0.c,v 1.2 2000/01/22 13:28:23 xiphmont Exp $
16
17  ********************************************************************/
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <math.h>
22 #include "vorbis/codec.h"
23 #include "bitwise.h"
24 #include "bookinternal.h"
25 #include "registry.h"
26 #include "mapping0.h"
27
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));
32
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);
39
40   return(d);
41 }
42
43 void _vorbis_map0_free(_vi_info_map *i){
44   vorbis_info_mapping0 *d=(vorbis_info_mapping0 *)i;
45
46   if(d){
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));
51     free(d);
52   }
53 }
54
55 void _vorbis_map0_pack(vorbis_info *vi,oggpack_buffer *opb,
56                               _vi_info_map *source){
57   int i;
58   vorbis_info_mapping0 *d=(vorbis_info_mapping0 *)source;
59
60   _oggpack_write(opb,d->timesubmap,8);
61
62   /* we abbreviate the channel submappings if they all map to the same
63      floor/res/psy */
64   for(i=1;i<vi->channels;i++)if(d->floorsubmap[i]!=d->floorsubmap[i-1])break;
65   if(i==vi->channels){
66     _oggpack_write(opb,0,1);
67     _oggpack_write(opb,d->floorsubmap[0],8);
68   }else{
69     _oggpack_write(opb,1,1);
70     for(i=0;i<vi->channels;i++)
71       _oggpack_write(opb,d->floorsubmap[i],8);
72   }
73
74   for(i=1;i<vi->channels;i++)
75     if(d->residuesubmap[i]!=d->residuesubmap[i-1])break;
76   if(i==vi->channels){
77     /* no channel submapping */
78     _oggpack_write(opb,0,1);
79     _oggpack_write(opb,d->residuesubmap[0],8);
80   }else{
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);
85   }
86 }
87
88 /* also responsible for range checking */
89 extern _vi_info_map *_vorbis_map0_unpack(vorbis_info *vi,oggpack_buffer *opb){
90   int i;
91   vorbis_info_mapping0 *d=calloc(1,sizeof(vorbis_info_mapping0));
92   memset(d,0,sizeof(vorbis_info_mapping0));
93
94   d->timesubmap=_oggpack_read(opb,8);
95   if(d->timesubmap>=vi->times)goto err_out;
96
97   d->floorsubmap=malloc(sizeof(int)*vi->channels);
98   if(_oggpack_read(opb,1)){
99     /* channel submap */
100     for(i=0;i<vi->channels;i++)
101       d->floorsubmap[i]=_oggpack_read(opb,8);
102   }else{
103     int temp=_oggpack_read(opb,8);
104     for(i=0;i<vi->channels;i++)
105       d->floorsubmap[i]=temp;
106   }
107
108   d->residuesubmap=malloc(sizeof(int)*vi->channels);
109   if(_oggpack_read(opb,1)){
110     /* channel submap */
111     for(i=0;i<vi->channels;i++)
112       d->residuesubmap[i]=_oggpack_read(opb,8);
113   }else{
114     int temp=_oggpack_read(opb,8);
115     for(i=0;i<vi->channels;i++)
116       d->residuesubmap[i]=temp;
117   }
118
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)
122       goto err_out;
123   }
124
125   return d;
126
127  err_out:
128   _vorbis_map0_free(d);
129   return(NULL);
130 }
131
132 #include <stdio.h>
133 #include "os.h"
134 #include "lpc.h"
135 #include "lsp.h"
136 #include "envelope.h"
137 #include "mdct.h"
138 #include "psy.h"
139 #include "bitwise.h"
140 #include "spectrum.h"
141
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]);
148   int                   n=vb->pcmend;
149   int i,j;
150
151   /* time domain pre-window: NONE IMPLEMENTED */
152
153   /* window the PCM data: takes PCM vector, vb; modifies PCM vector */
154
155   {
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];
159       for(j=0;j<n;j++)
160         pcm[j]*=window[j];
161     }
162   }
163             
164   /* time-domain post-window: NONE IMPLEMENTED */
165
166   /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
167   /* only MDCT right now.... */
168   {
169     for(i=0;i<vi->channels;i++){
170       double *pcm=vb->pcm[i];
171       mdct_forward(vd->transform[vb->W][0],pcm,pcm);
172     }
173   }
174
175   {
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);
179
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];
186       
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);
192  
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);
196
197       /* perform residue prequantization */
198       _vp_quantize(&vd->psy[psysub],pcm,mask,decfloor,pcmaux);
199
200     }
201   }
202
203   /* perform residue encoding with residue mapping; this is multiplexed */
204   /* multiplexing works like this: The first 
205
206   vorbis_res_encode_P[vi->restypes[ressub]]
207         (vi->reslist[ressub],vd->residue[ressub],pcm,mask,decfloor);
208
209
210
211   return(0);
212 }
213
214 int _vorbis_map0_synthesis(int mode,vorbis_block *vb){
215
216
217
218   window=vb->vd->window[vb->W][vb->lW][vb->nW];
219
220   n=vb->pcmend=vi->blocksize[vb->W];
221   
222   /* No envelope encoding yet */
223   _oggpack_read(opb,0,1);
224
225   for(i=0;i<vi->channels;i++){
226     double *lpc=vb->lpc[i];
227     double *lsp=vb->lsp[i];
228     
229     /* recover the spectral envelope */
230     if(_vs_spectrum_decode(vb,&vb->amp[i],lsp)<0)return(-1);
231     
232     /* recover the spectral residue */  
233     if(_vs_residue_decode(vb,vb->pcm[i])<0)return(-1);
234
235     /* LSP->LPC */
236     vorbis_lsp_to_lpc(lsp,lpc,vl->m); 
237
238     /* apply envelope to residue */
239     
240     vorbis_lpc_apply(vb->pcm[i],lpc,vb->amp[i],vl);
241       
242
243     /* MDCT->time */
244     mdct_backward(&vb->vd->vm[vb->W],vb->pcm[i],vb->pcm[i],window);
245     
246   }
247   return(0);
248 }
249
250