~ubuntu-branches/ubuntu/wily/hedgewars/wily

« back to all changes in this revision

Viewing changes to misc/libtremor/info.c

  • Committer: Package Import Robot
  • Author(s): Dmitry E. Oboukhov
  • Date: 2011-09-23 10:16:55 UTC
  • mfrom: (1.2.11 upstream)
  • Revision ID: package-import@ubuntu.com-20110923101655-3977th2gc5n0a3pv
Tags: 0.9.16-1
* New upstream version.
 + Downloadable content! Simply click to install any content.
   New voices, hats, maps, themes, translations, music, scripts...
   Hedgewars is now more customisable than ever before! As time goes
   by we will be soliciting community content to feature on this page,
   so remember to check it from time to time. If you decide you want
   to go back to standard Hedgewars, just remove the Data directory
   from your Hedgewars config directory.
 + 3-D rendering! Diorama-like rendering of the game in a variety
   of 3D modes. Let us know which ones work best for you, we didn't
   really have the equipment to test them all.
 + Resizable game window.
 + New utilities! The Time Box will remove one of your hedgehogs
   from the game for a while, protecting from attack until it returns,
   somewhere else on the map. Land spray will allow you to build bridges,
   seal up holes, or just make life unpleasant for your enemies.
 + New single player: Bamboo Thicket, That Sinking Feeling, Newton and
   the Tree and multi-player: The Specialists, Space Invaders,
   Racer - scripts! And a ton more script hooks for scripters
 + New twists on old weapons. Drill strike, seduction and fire have
   been adjusted. Defective mines have been added, rope can attach to
   hogs/crates/barrels again, grenades now have variable bounce (use
   precise key + 1-5). Portal gun is now more usable in flight and
   all game actions are a lot faster.
 + New theme - Golf, dozens of new community hats and a new
   localised Default voice, Ukranian.

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-2003    *
 
10
 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
 
11
 *                                                                  *
 
12
 ********************************************************************
 
13
 
 
14
 function: maintain the info structure, info <-> header packets
 
15
 
 
16
 ********************************************************************/
 
17
 
 
18
/* general handling of the header and the vorbis_info structure (and
 
19
   substructures) */
 
20
 
 
21
#include <stdlib.h>
 
22
#include <string.h>
 
23
#include <ctype.h>
 
24
#include "ogg.h"
 
25
#include "ivorbiscodec.h"
 
26
#include "codec_internal.h"
 
27
#include "codebook.h"
 
28
#include "registry.h"
 
29
#include "window.h"
 
30
#include "misc.h"
 
31
 
 
32
/* helpers */
 
33
static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
 
34
  while(bytes--){
 
35
    *buf++=oggpack_read(o,8);
 
36
  }
 
37
}
 
38
 
 
39
void vorbis_comment_init(vorbis_comment *vc){
 
40
  memset(vc,0,sizeof(*vc));
 
41
}
 
42
 
 
43
/* This is more or less the same as strncasecmp - but that doesn't exist
 
44
 * everywhere, and this is a fairly trivial function, so we include it */
 
45
static int tagcompare(const char *s1, const char *s2, int n){
 
46
  int c=0;
 
47
  while(c < n){
 
48
    if(toupper(s1[c]) != toupper(s2[c]))
 
49
      return !0;
 
50
    c++;
 
51
  }
 
52
  return 0;
 
53
}
 
54
 
 
55
char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){
 
56
  long i;
 
57
  int found = 0;
 
58
  int taglen = strlen(tag)+1; /* +1 for the = we append */
 
59
  char *fulltag = (char *)alloca(taglen+ 1);
 
60
 
 
61
  strcpy(fulltag, tag);
 
62
  strcat(fulltag, "=");
 
63
  
 
64
  for(i=0;i<vc->comments;i++){
 
65
    if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
 
66
      if(count == found)
 
67
        /* We return a pointer to the data, not a copy */
 
68
        return vc->user_comments[i] + taglen;
 
69
      else
 
70
        found++;
 
71
    }
 
72
  }
 
73
  return NULL; /* didn't find anything */
 
74
}
 
75
 
 
76
int vorbis_comment_query_count(vorbis_comment *vc, char *tag){
 
77
  int i,count=0;
 
78
  int taglen = strlen(tag)+1; /* +1 for the = we append */
 
79
  char *fulltag = (char *)alloca(taglen+1);
 
80
  strcpy(fulltag,tag);
 
81
  strcat(fulltag, "=");
 
82
 
 
83
  for(i=0;i<vc->comments;i++){
 
84
    if(!tagcompare(vc->user_comments[i], fulltag, taglen))
 
85
      count++;
 
86
  }
 
87
 
 
88
  return count;
 
89
}
 
90
 
 
91
void vorbis_comment_clear(vorbis_comment *vc){
 
92
  if(vc){
 
93
    long i;
 
94
    for(i=0;i<vc->comments;i++)
 
95
      if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
 
96
    if(vc->user_comments)_ogg_free(vc->user_comments);
 
97
        if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
 
98
    if(vc->vendor)_ogg_free(vc->vendor);
 
99
    memset(vc,0,sizeof(*vc));
 
100
  }
 
101
}
 
102
 
 
103
/* blocksize 0 is guaranteed to be short, 1 is guarantted to be long.
 
104
   They may be equal, but short will never ge greater than long */
 
105
int vorbis_info_blocksize(vorbis_info *vi,int zo){
 
106
  codec_setup_info *ci = (codec_setup_info *)vi->codec_setup;
 
107
  return ci ? ci->blocksizes[zo] : -1;
 
108
}
 
109
 
 
110
/* used by synthesis, which has a full, alloced vi */
 
111
void vorbis_info_init(vorbis_info *vi){
 
112
  memset(vi,0,sizeof(*vi));
 
113
  vi->codec_setup=(codec_setup_info *)_ogg_calloc(1,sizeof(codec_setup_info));
 
114
}
 
115
 
 
116
void vorbis_info_clear(vorbis_info *vi){
 
117
  codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
 
118
  int i;
 
119
 
 
120
  if(ci){
 
121
 
 
122
    for(i=0;i<ci->modes;i++)
 
123
      if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
 
124
 
 
125
    for(i=0;i<ci->maps;i++) /* unpack does the range checking */
 
126
      if(ci->map_param[i])
 
127
        _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
 
128
 
 
129
    for(i=0;i<ci->floors;i++) /* unpack does the range checking */
 
130
      if(ci->floor_param[i])
 
131
        _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
 
132
    
 
133
    for(i=0;i<ci->residues;i++) /* unpack does the range checking */
 
134
      if(ci->residue_param[i])
 
135
        _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
 
136
 
 
137
    for(i=0;i<ci->books;i++){
 
138
      if(ci->book_param[i]){
 
139
        /* knows if the book was not alloced */
 
140
        vorbis_staticbook_destroy(ci->book_param[i]);
 
141
      }
 
142
      if(ci->fullbooks)
 
143
        vorbis_book_clear(ci->fullbooks+i);
 
144
    }
 
145
    if(ci->fullbooks)
 
146
        _ogg_free(ci->fullbooks);
 
147
    
 
148
    _ogg_free(ci);
 
149
  }
 
150
 
 
151
  memset(vi,0,sizeof(*vi));
 
152
}
 
153
 
 
154
/* Header packing/unpacking ********************************************/
 
155
 
 
156
static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
 
157
  codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
 
158
  if(!ci)return(OV_EFAULT);
 
159
 
 
160
  vi->version=oggpack_read(opb,32);
 
161
  if(vi->version!=0)return(OV_EVERSION);
 
162
 
 
163
  vi->channels=oggpack_read(opb,8);
 
164
  vi->rate=oggpack_read(opb,32);
 
165
 
 
166
  vi->bitrate_upper=oggpack_read(opb,32);
 
167
  vi->bitrate_nominal=oggpack_read(opb,32);
 
168
  vi->bitrate_lower=oggpack_read(opb,32);
 
169
 
 
170
  ci->blocksizes[0]=1<<oggpack_read(opb,4);
 
171
  ci->blocksizes[1]=1<<oggpack_read(opb,4);
 
172
  
 
173
  if(vi->rate<1)goto err_out;
 
174
  if(vi->channels<1)goto err_out;
 
175
  if(ci->blocksizes[0]<64)goto err_out; 
 
176
  if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
 
177
  if(ci->blocksizes[1]>8192)goto err_out;
 
178
  
 
179
  if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
 
180
 
 
181
  return(0);
 
182
 err_out:
 
183
  vorbis_info_clear(vi);
 
184
  return(OV_EBADHEADER);
 
185
}
 
186
 
 
187
static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
 
188
  int i;
 
189
  int vendorlen=oggpack_read(opb,32);
 
190
  if(vendorlen<0)goto err_out;
 
191
  vc->vendor=(char *)_ogg_calloc(vendorlen+1,1);
 
192
  _v_readstring(opb,vc->vendor,vendorlen);
 
193
  vc->comments=oggpack_read(opb,32);
 
194
  if(vc->comments<0)goto err_out;
 
195
  vc->user_comments=(char **)_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
 
196
  vc->comment_lengths=(int *)_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
 
197
            
 
198
  for(i=0;i<vc->comments;i++){
 
199
    int len=oggpack_read(opb,32);
 
200
    if(len<0)goto err_out;
 
201
        vc->comment_lengths[i]=len;
 
202
    vc->user_comments[i]=(char *)_ogg_calloc(len+1,1);
 
203
    _v_readstring(opb,vc->user_comments[i],len);
 
204
  }       
 
205
  if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
 
206
 
 
207
  return(0);
 
208
 err_out:
 
209
  vorbis_comment_clear(vc);
 
210
  return(OV_EBADHEADER);
 
211
}
 
212
 
 
213
/* all of the real encoding details are here.  The modes, books,
 
214
   everything */
 
215
static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
 
216
  codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
 
217
  int i;
 
218
  if(!ci)return(OV_EFAULT);
 
219
 
 
220
  /* codebooks */
 
221
  ci->books=oggpack_read(opb,8)+1;
 
222
  /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/
 
223
  for(i=0;i<ci->books;i++){
 
224
    ci->book_param[i]=(static_codebook *)_ogg_calloc(1,sizeof(*ci->book_param[i]));
 
225
    if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out;
 
226
  }
 
227
 
 
228
  /* time backend settings */
 
229
  ci->times=oggpack_read(opb,6)+1;
 
230
  /*ci->time_type=_ogg_malloc(ci->times*sizeof(*ci->time_type));*/
 
231
  /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/
 
232
  for(i=0;i<ci->times;i++){
 
233
    ci->time_type[i]=oggpack_read(opb,16);
 
234
    if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out;
 
235
    /* ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb);
 
236
       Vorbis I has no time backend */
 
237
    /*if(!ci->time_param[i])goto err_out;*/
 
238
  }
 
239
 
 
240
  /* floor backend settings */
 
241
  ci->floors=oggpack_read(opb,6)+1;
 
242
  /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/
 
243
  /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/
 
244
  for(i=0;i<ci->floors;i++){
 
245
    ci->floor_type[i]=oggpack_read(opb,16);
 
246
    if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
 
247
    ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
 
248
    if(!ci->floor_param[i])goto err_out;
 
249
  }
 
250
 
 
251
  /* residue backend settings */
 
252
  ci->residues=oggpack_read(opb,6)+1;
 
253
  /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/
 
254
  /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/
 
255
  for(i=0;i<ci->residues;i++){
 
256
    ci->residue_type[i]=oggpack_read(opb,16);
 
257
    if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
 
258
    ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
 
259
    if(!ci->residue_param[i])goto err_out;
 
260
  }
 
261
 
 
262
  /* map backend settings */
 
263
  ci->maps=oggpack_read(opb,6)+1;
 
264
  /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/
 
265
  /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/
 
266
  for(i=0;i<ci->maps;i++){
 
267
    ci->map_type[i]=oggpack_read(opb,16);
 
268
    if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
 
269
    ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
 
270
    if(!ci->map_param[i])goto err_out;
 
271
  }
 
272
  
 
273
  /* mode settings */
 
274
  ci->modes=oggpack_read(opb,6)+1;
 
275
  /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/
 
276
  for(i=0;i<ci->modes;i++){
 
277
    ci->mode_param[i]=(vorbis_info_mode *)_ogg_calloc(1,sizeof(*ci->mode_param[i]));
 
278
    ci->mode_param[i]->blockflag=oggpack_read(opb,1);
 
279
    ci->mode_param[i]->windowtype=oggpack_read(opb,16);
 
280
    ci->mode_param[i]->transformtype=oggpack_read(opb,16);
 
281
    ci->mode_param[i]->mapping=oggpack_read(opb,8);
 
282
 
 
283
    if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
 
284
    if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
 
285
    if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
 
286
  }
 
287
  
 
288
  if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
 
289
 
 
290
  return(0);
 
291
 err_out:
 
292
  vorbis_info_clear(vi);
 
293
  return(OV_EBADHEADER);
 
294
}
 
295
 
 
296
/* The Vorbis header is in three packets; the initial small packet in
 
297
   the first page that identifies basic parameters, a second packet
 
298
   with bitstream comments and a third packet that holds the
 
299
   codebook. */
 
300
 
 
301
int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
 
302
  oggpack_buffer opb;
 
303
  
 
304
  if(op){
 
305
    oggpack_readinit(&opb,op->packet);
 
306
 
 
307
    /* Which of the three types of header is this? */
 
308
    /* Also verify header-ness, vorbis */
 
309
    {
 
310
      char buffer[6];
 
311
      int packtype=oggpack_read(&opb,8);
 
312
      memset(buffer,0,6);
 
313
      _v_readstring(&opb,buffer,6);
 
314
      if(memcmp(buffer,"vorbis",6)){
 
315
        /* not a vorbis header */
 
316
        return(OV_ENOTVORBIS);
 
317
      }
 
318
      switch(packtype){
 
319
      case 0x01: /* least significant *bit* is read first */
 
320
        if(!op->b_o_s){
 
321
          /* Not the initial packet */
 
322
          return(OV_EBADHEADER);
 
323
        }
 
324
        if(vi->rate!=0){
 
325
          /* previously initialized info header */
 
326
          return(OV_EBADHEADER);
 
327
        }
 
328
 
 
329
        return(_vorbis_unpack_info(vi,&opb));
 
330
 
 
331
      case 0x03: /* least significant *bit* is read first */
 
332
        if(vi->rate==0){
 
333
          /* um... we didn't get the initial header */
 
334
          return(OV_EBADHEADER);
 
335
        }
 
336
 
 
337
        return(_vorbis_unpack_comment(vc,&opb));
 
338
 
 
339
      case 0x05: /* least significant *bit* is read first */
 
340
        if(vi->rate==0 || vc->vendor==NULL){
 
341
          /* um... we didn;t get the initial header or comments yet */
 
342
          return(OV_EBADHEADER);
 
343
        }
 
344
 
 
345
        return(_vorbis_unpack_books(vi,&opb));
 
346
 
 
347
      default:
 
348
        /* Not a valid vorbis header type */
 
349
        return(OV_EBADHEADER);
 
350
        break;
 
351
      }
 
352
    }
 
353
  }
 
354
  return(OV_EBADHEADER);
 
355
}
 
356