~ubuntu-dev/mplayer/ubuntu-feisty

« back to all changes in this revision

Viewing changes to tremor/block.c

  • Committer: Reinhard Tartler
  • Date: 2006-07-08 08:45:33 UTC
  • Revision ID: siretart@tauware.de-20060708084533-dbc155bde7122e78
imported mplayer_0.99+1.0pre7try2+cvs20060117

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/********************************************************************
 
2
 *                                                                  *
 
3
 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
 
4
 *                                                                  *
 
5
 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
 
6
 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
 
7
 * ALL REDISTRIBUTION RIGHTS RESERVED.                              *
 
8
 *                                                                  *
 
9
 ********************************************************************
 
10
 
 
11
 function: PCM data vector blocking, windowing and dis/reassembly
 
12
 
 
13
 ********************************************************************/
 
14
 
 
15
#include <stdio.h>
 
16
#include <stdlib.h>
 
17
#include <string.h>
 
18
#include "ogg.h"
 
19
#include "ivorbiscodec.h"
 
20
#include "codec_internal.h"
 
21
 
 
22
#include "window.h"
 
23
#include "registry.h"
 
24
#include "misc.h"
 
25
 
 
26
static int ilog(unsigned int v){
 
27
  int ret=0;
 
28
  if(v)--v;
 
29
  while(v){
 
30
    ret++;
 
31
    v>>=1;
 
32
  }
 
33
  return(ret);
 
34
}
 
35
 
 
36
/* pcm accumulator examples (not exhaustive):
 
37
 
 
38
 <-------------- lW ---------------->
 
39
                   <--------------- W ---------------->
 
40
:            .....|.....       _______________         |
 
41
:        .'''     |     '''_---      |       |\        |
 
42
:.....'''         |_____--- '''......|       | \_______|
 
43
:.................|__________________|_______|__|______|
 
44
                  |<------ Sl ------>|      > Sr <     |endW
 
45
                  |beginSl           |endSl  |  |endSr   
 
46
                  |beginW            |endlW  |beginSr
 
47
 
 
48
 
 
49
                      |< lW >|       
 
50
                   <--------------- W ---------------->
 
51
                  |   |  ..  ______________            |
 
52
                  |   | '  `/        |     ---_        |
 
53
                  |___.'___/`.       |         ---_____| 
 
54
                  |_______|__|_______|_________________|
 
55
                  |      >|Sl|<      |<------ Sr ----->|endW
 
56
                  |       |  |endSl  |beginSr          |endSr
 
57
                  |beginW |  |endlW                     
 
58
                  mult[0] |beginSl                     mult[n]
 
59
 
 
60
 <-------------- lW ----------------->
 
61
                          |<--W-->|                               
 
62
:            ..............  ___  |   |                    
 
63
:        .'''             |`/   \ |   |                       
 
64
:.....'''                 |/`....\|...|                    
 
65
:.........................|___|___|___|                  
 
66
                          |Sl |Sr |endW    
 
67
                          |   |   |endSr
 
68
                          |   |beginSr
 
69
                          |   |endSl
 
70
                          |beginSl
 
71
                          |beginW
 
72
*/
 
73
 
 
74
/* block abstraction setup *********************************************/
 
75
 
 
76
#ifndef WORD_ALIGN
 
77
#define WORD_ALIGN 8
 
78
#endif
 
79
 
 
80
int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
 
81
  memset(vb,0,sizeof(*vb));
 
82
  vb->vd=v;
 
83
  vb->localalloc=0;
 
84
  vb->localstore=NULL;
 
85
  
 
86
  return(0);
 
87
}
 
88
 
 
89
void *_vorbis_block_alloc(vorbis_block *vb,long bytes){
 
90
  bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1);
 
91
  if(bytes+vb->localtop>vb->localalloc){
 
92
    /* can't just _ogg_realloc... there are outstanding pointers */
 
93
    if(vb->localstore){
 
94
      struct alloc_chain *link=(struct alloc_chain *)_ogg_malloc(sizeof(*link));
 
95
      vb->totaluse+=vb->localtop;
 
96
      link->next=vb->reap;
 
97
      link->ptr=vb->localstore;
 
98
      vb->reap=link;
 
99
    }
 
100
    /* highly conservative */
 
101
    vb->localalloc=bytes;
 
102
    vb->localstore=_ogg_malloc(vb->localalloc);
 
103
    vb->localtop=0;
 
104
  }
 
105
  {
 
106
    void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
 
107
    vb->localtop+=bytes;
 
108
    return ret;
 
109
  }
 
110
}
 
111
 
 
112
/* reap the chain, pull the ripcord */
 
113
void _vorbis_block_ripcord(vorbis_block *vb){
 
114
  /* reap the chain */
 
115
  struct alloc_chain *reap=vb->reap;
 
116
  while(reap){
 
117
    struct alloc_chain *next=reap->next;
 
118
    _ogg_free(reap->ptr);
 
119
    memset(reap,0,sizeof(*reap));
 
120
    _ogg_free(reap);
 
121
    reap=next;
 
122
  }
 
123
  /* consolidate storage */
 
124
  if(vb->totaluse){
 
125
    vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
 
126
    vb->localalloc+=vb->totaluse;
 
127
    vb->totaluse=0;
 
128
  }
 
129
 
 
130
  /* pull the ripcord */
 
131
  vb->localtop=0;
 
132
  vb->reap=NULL;
 
133
}
 
134
 
 
135
int vorbis_block_clear(vorbis_block *vb){
 
136
  _vorbis_block_ripcord(vb);
 
137
  if(vb->localstore)_ogg_free(vb->localstore);
 
138
 
 
139
  memset(vb,0,sizeof(*vb));
 
140
  return(0);
 
141
}
 
142
 
 
143
int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
 
144
  int i;
 
145
  codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
 
146
  backend_lookup_state *b=NULL;
 
147
 
 
148
  memset(v,0,sizeof(*v));
 
149
  b=(backend_lookup_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b)));
 
150
 
 
151
  v->vi=vi;
 
152
  b->modebits=ilog(ci->modes);
 
153
 
 
154
  /* Vorbis I uses only window type 0 */
 
155
  b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2);
 
156
  b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2);
 
157
 
 
158
  /* finish the codebooks */
 
159
  if(!ci->fullbooks){
 
160
    ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
 
161
    for(i=0;i<ci->books;i++){
 
162
      vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]);
 
163
      /* decode codebooks are now standalone after init */
 
164
      vorbis_staticbook_destroy(ci->book_param[i]);
 
165
      ci->book_param[i]=NULL;
 
166
    }
 
167
  }
 
168
 
 
169
  v->pcm_storage=ci->blocksizes[1];
 
170
  v->pcm=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcm));
 
171
  v->pcmret=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcmret));
 
172
  for(i=0;i<vi->channels;i++)
 
173
    v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
 
174
 
 
175
  /* all 1 (large block) or 0 (small block) */
 
176
  /* explicitly set for the sake of clarity */
 
177
  v->lW=0; /* previous window size */
 
178
  v->W=0;  /* current window size */
 
179
 
 
180
  /* all vector indexes */
 
181
  v->centerW=ci->blocksizes[1]/2;
 
182
 
 
183
  v->pcm_current=v->centerW;
 
184
 
 
185
  /* initialize all the mapping/backend lookups */
 
186
  b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode));
 
187
  for(i=0;i<ci->modes;i++){
 
188
    int mapnum=ci->mode_param[i]->mapping;
 
189
    int maptype=ci->map_type[mapnum];
 
190
    b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i],
 
191
                                         ci->map_param[mapnum]);
 
192
  }
 
193
 
 
194
  v->pcm_returned=-1;
 
195
  v->granulepos=-1;
 
196
  v->sequence=-1;
 
197
 
 
198
  return(0);
 
199
}
 
200
 
 
201
void vorbis_dsp_clear(vorbis_dsp_state *v){
 
202
  int i;
 
203
  if(v){
 
204
    vorbis_info *vi=v->vi;
 
205
    codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL);
 
206
    backend_lookup_state *b=(backend_lookup_state *)v->backend_state;
 
207
 
 
208
    if(v->pcm){
 
209
      for(i=0;i<vi->channels;i++)
 
210
        if(v->pcm[i])_ogg_free(v->pcm[i]);
 
211
      _ogg_free(v->pcm);
 
212
      if(v->pcmret)_ogg_free(v->pcmret);
 
213
    }
 
214
 
 
215
    /* free mode lookups; these are actually vorbis_look_mapping structs */
 
216
    if(ci){
 
217
      for(i=0;i<ci->modes;i++){
 
218
        int mapnum=ci->mode_param[i]->mapping;
 
219
        int maptype=ci->map_type[mapnum];
 
220
        if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]);
 
221
      }
 
222
    }
 
223
 
 
224
    if(b){
 
225
      if(b->mode)_ogg_free(b->mode);    
 
226
      _ogg_free(b);
 
227
    }
 
228
    
 
229
    memset(v,0,sizeof(*v));
 
230
  }
 
231
}
 
232
 
 
233
/* Unlike in analysis, the window is only partially applied for each
 
234
   block.  The time domain envelope is not yet handled at the point of
 
235
   calling (as it relies on the previous block). */
 
236
 
 
237
int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
 
238
  vorbis_info *vi=v->vi;
 
239
  codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
 
240
  int i,j;
 
241
 
 
242
  if(v->pcm_current>v->pcm_returned  && v->pcm_returned!=-1)return(OV_EINVAL);
 
243
 
 
244
  v->lW=v->W;
 
245
  v->W=vb->W;
 
246
  v->nW=-1;
 
247
 
 
248
  if(v->sequence+1 != vb->sequence)v->granulepos=-1; /* out of sequence;
 
249
                                                     lose count */
 
250
 
 
251
  v->sequence=vb->sequence;
 
252
  
 
253
  {
 
254
    int n=ci->blocksizes[v->W]/2;
 
255
    int n0=ci->blocksizes[0]/2;
 
256
    int n1=ci->blocksizes[1]/2;
 
257
    
 
258
    int thisCenter;
 
259
    int prevCenter;
 
260
    
 
261
    if(v->centerW){
 
262
      thisCenter=n1;
 
263
      prevCenter=0;
 
264
    }else{
 
265
      thisCenter=0;
 
266
      prevCenter=n1;
 
267
    }
 
268
    
 
269
    /* v->pcm is now used like a two-stage double buffer.  We don't want
 
270
       to have to constantly shift *or* adjust memory usage.  Don't
 
271
       accept a new block until the old is shifted out */
 
272
    
 
273
    /* overlap/add PCM */
 
274
    
 
275
    for(j=0;j<vi->channels;j++){
 
276
      /* the overlap/add section */
 
277
      if(v->lW){
 
278
        if(v->W){
 
279
          /* large/large */
 
280
          ogg_int32_t *pcm=v->pcm[j]+prevCenter;
 
281
          ogg_int32_t *p=vb->pcm[j];
 
282
          for(i=0;i<n1;i++)
 
283
            pcm[i]+=p[i];
 
284
        }else{
 
285
          /* large/small */
 
286
          ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
 
287
          ogg_int32_t *p=vb->pcm[j];
 
288
          for(i=0;i<n0;i++)
 
289
            pcm[i]+=p[i];
 
290
        }
 
291
      }else{
 
292
        if(v->W){
 
293
          /* small/large */
 
294
          ogg_int32_t *pcm=v->pcm[j]+prevCenter;
 
295
          ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2;
 
296
          for(i=0;i<n0;i++)
 
297
            pcm[i]+=p[i];
 
298
          for(;i<n1/2+n0/2;i++)
 
299
            pcm[i]=p[i];
 
300
        }else{
 
301
          /* small/small */
 
302
          ogg_int32_t *pcm=v->pcm[j]+prevCenter;
 
303
          ogg_int32_t *p=vb->pcm[j];
 
304
          for(i=0;i<n0;i++)
 
305
            pcm[i]+=p[i];
 
306
        }
 
307
      }
 
308
      
 
309
      /* the copy section */
 
310
      {
 
311
        ogg_int32_t *pcm=v->pcm[j]+thisCenter;
 
312
        ogg_int32_t *p=vb->pcm[j]+n;
 
313
        for(i=0;i<n;i++)
 
314
          pcm[i]=p[i];
 
315
      }
 
316
    }
 
317
    
 
318
    if(v->centerW)
 
319
      v->centerW=0;
 
320
    else
 
321
      v->centerW=n1;
 
322
    
 
323
    /* deal with initial packet state; we do this using the explicit
 
324
       pcm_returned==-1 flag otherwise we're sensitive to first block
 
325
       being short or long */
 
326
 
 
327
    if(v->pcm_returned==-1){
 
328
      v->pcm_returned=thisCenter;
 
329
      v->pcm_current=thisCenter;
 
330
    }else{
 
331
      v->pcm_returned=prevCenter;
 
332
      v->pcm_current=prevCenter+
 
333
        ci->blocksizes[v->lW]/4+
 
334
        ci->blocksizes[v->W]/4;
 
335
    }
 
336
 
 
337
    /* track the frame number... This is for convenience, but also
 
338
       making sure our last packet doesn't end with added padding.  If
 
339
       the last packet is partial, the number of samples we'll have to
 
340
       return will be past the vb->granulepos.
 
341
       
 
342
       This is not foolproof!  It will be confused if we begin
 
343
       decoding at the last page after a seek or hole.  In that case,
 
344
       we don't have a starting point to judge where the last frame
 
345
       is.  For this reason, vorbisfile will always try to make sure
 
346
       it reads the last two marked pages in proper sequence */
 
347
 
 
348
    if(v->granulepos==-1)
 
349
      if(vb->granulepos==-1){
 
350
        v->granulepos=0;
 
351
      }else{
 
352
        v->granulepos=vb->granulepos;
 
353
      }
 
354
    else{
 
355
      v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
 
356
      if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
 
357
 
 
358
        if(v->granulepos>vb->granulepos){
 
359
          long extra=v->granulepos-vb->granulepos;
 
360
 
 
361
          if(vb->eofflag){
 
362
            /* partial last frame.  Strip the extra samples off */
 
363
            v->pcm_current-=extra;
 
364
          }else if(vb->sequence == 1){
 
365
            /* ^^^ argh, this can be 1 from seeking! */
 
366
 
 
367
 
 
368
            /* partial first frame.  Discard extra leading samples */
 
369
            v->pcm_returned+=extra;
 
370
            if(v->pcm_returned>v->pcm_current)
 
371
              v->pcm_returned=v->pcm_current;
 
372
            
 
373
          }
 
374
          
 
375
        }/* else{ Shouldn't happen *unless* the bitstream is out of
 
376
            spec.  Either way, believe the bitstream } */
 
377
        v->granulepos=vb->granulepos;
 
378
      }
 
379
    }
 
380
    
 
381
    /* Update, cleanup */
 
382
    
 
383
    if(vb->eofflag)v->eofflag=1;
 
384
  }
 
385
  
 
386
  return(0);
 
387
}
 
388
 
 
389
/* pcm==NULL indicates we just want the pending samples, no more */
 
390
int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm){
 
391
  vorbis_info *vi=v->vi;
 
392
  if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
 
393
    if(pcm){
 
394
      int i;
 
395
      for(i=0;i<vi->channels;i++)
 
396
        v->pcmret[i]=v->pcm[i]+v->pcm_returned;
 
397
      *pcm=v->pcmret;
 
398
    }
 
399
    return(v->pcm_current-v->pcm_returned);
 
400
  }
 
401
  return(0);
 
402
}
 
403
 
 
404
int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){
 
405
  if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL);
 
406
  v->pcm_returned+=bytes;
 
407
  return(0);
 
408
}
 
409