~ubuntu-branches/ubuntu/utopic/hedgewars/utopic

« back to all changes in this revision

Viewing changes to misc/libtremor/tremor/block.c

  • Committer: Package Import Robot
  • Author(s): Gianfranco Costamagna
  • Date: 2014-01-02 12:37:23 UTC
  • mfrom: (19.1.5 sid)
  • Revision ID: package-import@ubuntu.com-20140102123723-6pdhmyj8tb5y8xbg
Tags: 0.9.20.3-1
New upstream minor release, suitable for unstable

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