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.1 2000/01/20 04:43:02 xiphmont Exp $
17 ********************************************************************/
22 #include "vorbis/codec.h"
24 #include "bookinternal.h"
28 extern _vi_info_map *_vorbis_map0_dup(vi_info *vi,_vi_info_mapping *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 extern void _vorbis_map0_free(_vi_info_mapping *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 extern void _vorbis_map0_pack(vorbis_info *vi,oggpack_buffer *opb,
58 vorbis_info_mapping0 *d=(vorbis_info_mapping0 *)i;
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->residuess)
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(vorbis_block *vb,vorbis_info_map *i,
146 vorbis_dsp_state *vd=vb->vd;
147 double *window=vd->window[vb->W][vb->lW][vb->nW];
148 oggpack_buffer *opb=&vb->opb;
149 vorbis_info_mapping0 *vi=i;
152 /* time domain pre-window: NONE IMPLEMENTED */
154 /* window the PCM data: takes PCM vector, vb; modifies PCM vector */
156 /* time-domain post-window: NONE IMPLEMENTED */
158 /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
160 /* perform psychoacoustics; takes PCM vector; returns transform floor
161 and resolution floor, modifies PCM vector */
163 /* perform floor encoding; takes transform floor, returns decoded floor*/
165 /* perform residue encoding with residue mapping */
169 psy_lookup *vp=&vb->vd->vp[vb->W];
170 lpc_lookup *vl=&vb->vd->vl[vb->W];
174 vb->time_envelope_bits=0;
175 vb->spectral_envelope_bits=0;
176 vb->spectral_residue_bits=0;
178 /*lpc_lookup *vbal=&vb->vd->vbal[vb->W];
179 double balance_v[vbal->m];
180 double balance_amp;*/
182 /* first things first. Make sure encode is ready*/
184 /* Encode the packet type */
185 _oggpack_write(opb,0,1);
187 /* Encode the block size */
188 _oggpack_write(opb,vb->W,1);
190 _oggpack_write(opb,vb->lW,1);
191 _oggpack_write(opb,vb->nW,1);
194 /* No envelope encoding yet */
195 _oggpack_write(opb,0,1);
197 /* time domain PCM -> MDCT domain */
198 for(i=0;i<vi->channels;i++)
199 mdct_forward(&vd->vm[vb->W],vb->pcm[i],vb->pcm[i],window);
203 /* extract the spectral envelope and residue */
204 /* just do by channel. No coupling yet */
206 for(i=0;i<vi->channels;i++){
207 static int frameno=0;
209 double *floor=alloca(n/2*sizeof(double));
210 double *curve=alloca(n/2*sizeof(double));
211 double *lpc=vb->lpc[i];
212 double *lsp=vb->lsp[i];
214 memset(floor,0,sizeof(double)*n/2);
221 sprintf(buffer,"Aspectrum%d.m",vb->sequence);
222 out=fopen(buffer,"w+");
224 fprintf(out,"%g\n",vb->pcm[i][j]);
230 _vp_mask_floor(vp,vb->pcm[i],floor);
237 sprintf(buffer,"Apremask%d.m",vb->sequence);
238 out=fopen(buffer,"w+");
240 fprintf(out,"%g\n",floor[j]);
245 /* Convert our floor to a set of lpc coefficients */
246 vb->amp[i]=sqrt(vorbis_curve_to_lpc(floor,lpc,vl));
248 /* LSP <-> LPC is orthogonal and LSP quantizes more stably */
249 vorbis_lpc_to_lsp(lpc,lsp,vl->m);
251 /* code the spectral envelope; mutates the lsp coeffs to reflect
252 what was actually encoded */
253 _vs_spectrum_encode(vb,vb->amp[i],lsp);
255 /* Generate residue from the decoded envelope, which will be
256 slightly different to the pre-encoding floor due to
257 quantization. Slow, yes, but perhaps more accurate */
259 vorbis_lsp_to_lpc(lsp,lpc,vl->m);
260 vorbis_lpc_to_curve(curve,lpc,vb->amp[i],vl);
262 /* this may do various interesting massaging too...*/
263 if(vb->amp[i])_vs_residue_train(vb,vb->pcm[i],curve,n/2);
264 _vs_residue_quantize(vb->pcm[i],curve,vi,n/2);
271 sprintf(buffer,"Alpc%d.m",vb->sequence);
272 out=fopen(buffer,"w+");
274 fprintf(out,"%g\n",lpc[j]);
277 sprintf(buffer,"Alsp%d.m",vb->sequence);
278 out=fopen(buffer,"w+");
280 fprintf(out,"%g\n",lsp[j]);
283 sprintf(buffer,"Amask%d.m",vb->sequence);
284 out=fopen(buffer,"w+");
286 fprintf(out,"%g\n",curve[j]);
289 sprintf(buffer,"Ares%d.m",vb->sequence);
290 out=fopen(buffer,"w+");
292 fprintf(out,"%g\n",vb->pcm[i][j]);
297 /* encode the residue */
298 _vs_residue_encode(vb,vb->pcm[i]);
303 /* set up the packet wrapper */
305 op->packet=opb->buffer;
306 op->bytes=_oggpack_bytes(opb);
308 op->e_o_s=vb->eofflag;
309 op->frameno=vb->frameno;
310 op->packetno=vb->sequence; /* for sake of completeness */
318 /* commented out, relocated balance stuff */
320 double *C=vb->pcm[0];
321 double *D=vb->pcm[1];
323 balance_amp=_vp_balance_compute(D,C,balance_v,vbal);
329 sprintf(buffer,"com%d.m",frameno);
330 out=fopen(buffer,"w+");
332 fprintf(out," 0. 0.\n");
333 fprintf(out,"%g %g\n",C[i],D[i]);
338 sprintf(buffer,"L%d.m",frameno);
339 out=fopen(buffer,"w+");
341 fprintf(out,"%g\n",C[i]);
344 sprintf(buffer,"R%d.m",frameno);
345 out=fopen(buffer,"w+");
347 fprintf(out,"%g\n",D[i]);
353 _vp_balance_apply(D,C,balance_v,balance_amp,vbal,1);
359 sprintf(buffer,"bal%d.m",frameno);
360 out=fopen(buffer,"w+");
362 fprintf(out," 0. 0.\n");
363 fprintf(out,"%g %g\n",C[i],D[i]);
367 sprintf(buffer,"C%d.m",frameno);
368 out=fopen(buffer,"w+");
370 fprintf(out,"%g\n",C[i]);
373 sprintf(buffer,"D%d.m",frameno);
374 out=fopen(buffer,"w+");
376 fprintf(out,"%g\n",D[i]);
384 int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){
386 vorbis_dsp_state *vd=vb->vd;
387 vorbis_info *vi=vd->vi;
388 oggpack_buffer *opb=&vb->opb;
393 /* first things first. Make sure decode is ready */
394 _oggpack_readinit(opb,op->packet,op->bytes);
396 /* Check the packet type */
397 if(_oggpack_read(opb,1)!=0){
398 /* Oops. This is not an audio data packet */
402 /* Decode the block size */
403 vb->W=_oggpack_read(opb,1);
405 vb->lW=_oggpack_read(opb,1);
406 vb->nW=_oggpack_read(opb,1);
412 window=vb->vd->window[vb->W][vb->lW][vb->nW];
414 /* other random setup */
415 vb->frameno=op->frameno;
416 vb->sequence=op->packetno-3; /* first block is third packet */
418 vb->eofflag=op->e_o_s;
419 vl=&vb->vd->vl[vb->W];
420 spectral_order=vi->floororder[vb->W];
422 /* The storage vectors are large enough; set the use markers */
423 n=vb->pcmend=vi->blocksize[vb->W];
425 /* No envelope encoding yet */
426 _oggpack_read(opb,0,1);
428 for(i=0;i<vi->channels;i++){
429 double *lpc=vb->lpc[i];
430 double *lsp=vb->lsp[i];
432 /* recover the spectral envelope */
433 if(_vs_spectrum_decode(vb,&vb->amp[i],lsp)<0)return(-1);
435 /* recover the spectral residue */
436 if(_vs_residue_decode(vb,vb->pcm[i])<0)return(-1);
444 sprintf(buffer,"Sres%d.m",vb->sequence);
445 out=fopen(buffer,"w+");
447 fprintf(out,"%g\n",vb->pcm[i][j]);
453 vorbis_lsp_to_lpc(lsp,lpc,vl->m);
455 /* apply envelope to residue */
463 vorbis_lpc_to_curve(curve,lpc,vb->amp[i],vl);
466 sprintf(buffer,"Smask%d.m",vb->sequence);
467 out=fopen(buffer,"w+");
469 fprintf(out,"%g\n",curve[j]);
472 sprintf(buffer,"Slsp%d.m",vb->sequence);
473 out=fopen(buffer,"w+");
475 fprintf(out,"%g\n",lsp[j]);
478 sprintf(buffer,"Slpc%d.m",vb->sequence);
479 out=fopen(buffer,"w+");
481 fprintf(out,"%g\n",lpc[j]);
486 vorbis_lpc_apply(vb->pcm[i],lpc,vb->amp[i],vl);
494 sprintf(buffer,"Sspectrum%d.m",vb->sequence);
495 out=fopen(buffer,"w+");
497 fprintf(out,"%g\n",vb->pcm[i][j]);
504 mdct_backward(&vb->vd->vm[vb->W],vb->pcm[i],vb->pcm[i],window);