incremental update. Go to pure tone masking (no noise), prepare for training
[platform/upstream/libvorbis.git] / lib / info.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: maintain the info structure, info <-> header packets
15  last mod: $Id: info.c,v 1.13 2000/01/04 09:05:00 xiphmont Exp $
16
17  ********************************************************************/
18
19 /* This fills in a vorbis_info structure with settings from a few
20    pre-defined encoding modes.  Also handles choosing/blowing in the
21    codebook */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include "modes.h"
26 #include "bitwise.h"
27
28 static int ilog2(unsigned int v){
29   int ret=0;
30   while(v>1){
31     ret++;
32     v>>=1;
33   }
34   return(ret);
35 }
36   
37 void vorbis_info_init(vorbis_info *vi){
38   memset(vi,0,sizeof(vorbis_info));
39 }
40
41 /* one test mode for now; temporary of course */
42 int vorbis_info_modeset(vorbis_info *vi, int mode){
43   if(mode<0 || mode>predef_mode_max)return(-1);
44
45   /* handle the flat settings first */
46   memcpy(vi,&(predef_modes[mode]),sizeof(vorbis_info));
47   vi->user_comments=calloc(1,sizeof(char *));
48   vi->vendor=strdup("Xiphophorus libVorbis I 19991230");
49
50   return(0);
51 }
52
53 /* convenience function */
54 int vorbis_info_addcomment(vorbis_info *vi,char *comment){
55   vi->user_comments=realloc(vi->user_comments,
56                             (vi->comments+2)*sizeof(char *));
57   vi->user_comments[vi->comments]=strdup(comment);
58   vi->comments++;
59   vi->user_comments[vi->comments]=NULL;
60   return(0);
61 }
62
63 static void _v_writestring(oggpack_buffer *o,char *s){
64   while(*s){
65     _oggpack_write(o,*s++,8);
66   }
67 }
68
69 static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
70   while(bytes--){
71     *buf++=_oggpack_read(o,8);
72   }
73 }
74
75 /* The Vorbis header is in three packets; the initial small packet in
76    the first page that identifies basic parameters, a second packet
77    with bitstream comments and a third packet that holds the
78    codebook. */
79
80 int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){
81
82   oggpack_buffer opb;
83   
84   if(op){
85     _oggpack_readinit(&opb,op->packet,op->bytes);
86
87     /* Which of the three types of header is this? */
88     /* Also verify header-ness, vorbis */
89     {
90       char buffer[6];
91       memset(buffer,0,6);
92       _v_readstring(&opb,buffer,6);
93       if(memcmp(buffer,"vorbis",6)){
94         /* not a vorbis header */
95         return(-1);
96       }
97       switch(_oggpack_read(&opb,8)){
98       case 0x80:
99         if(!op->b_o_s){
100           /* Not the initial packet */
101           return(-1);
102         }
103         if(vi->rate!=0){
104           /* previously initialized info header */
105           return(-1);
106         }
107
108         if(_oggpack_read(&opb,32)!=0){
109           return(-1);
110         }
111         vi->channels=_oggpack_read(&opb,8);
112         vi->rate=_oggpack_read(&opb,32);
113
114         vi->bitrate_upper=_oggpack_read(&opb,32);
115         vi->bitrate_nominal=_oggpack_read(&opb,32);
116         vi->bitrate_lower=_oggpack_read(&opb,32);
117
118         vi->blocksize[0]=1<<_oggpack_read(&opb,4);
119         vi->blocksize[1]=1<<_oggpack_read(&opb,4);
120
121         vi->floororder[0]=_oggpack_read(&opb,8);
122         vi->floororder[1]=_oggpack_read(&opb,8);
123         vi->floormap[0]=_oggpack_read(&opb,16);
124         vi->floormap[1]=_oggpack_read(&opb,16);
125         vi->floorch=_oggpack_read(&opb,8);
126
127         if(vi->rate<1)return(-1);
128         if(vi->floorch<1 || vi->floorch>vi->channels)return(-1);
129
130         return(0);
131       case 0x81:
132         if(vi->rate==0){
133           /* um... we didn;t get the initial header */
134           return(-1);
135         }
136         {
137           int vendorlen=_oggpack_read(&opb,32);
138           vi->vendor=calloc(vendorlen+1,1);
139           _v_readstring(&opb,vi->vendor,vendorlen);
140         }
141         {
142           int i;
143           vi->comments=_oggpack_read(&opb,32);
144           vi->user_comments=calloc(vi->comments+1,sizeof(char **));
145             
146           for(i=0;i<vi->comments;i++){
147             int len=_oggpack_read(&opb,32);
148             vi->user_comments[i]=calloc(len+1,1);
149             _v_readstring(&opb,vi->user_comments[i],len);
150           }       
151         }
152
153         return(0);
154       case 0x82:
155         if(vi->rate==0){
156           /* um... we didn;t get the initial header */
157           return(-1);
158         }
159
160         /* not implemented quite yet */
161
162         return(0);
163       default:
164         /* Not a valid vorbis header type */
165         return(-1);
166         break;
167       }
168     }
169   }
170   return(-1);
171 }
172
173 int vorbis_info_headerout(vorbis_info *vi,
174                           ogg_packet *op,
175                           ogg_packet *op_comm,
176                           ogg_packet *op_code){
177
178   oggpack_buffer opb;
179   /* initial header:
180
181      codec id     "vorbis"
182      header id    0x80 (byte)
183      codec ver    (4 octets, lsb first: currently 0x00)
184      pcm channels (4 octets, lsb first)
185      pcm rate     (4 octets, lsb first)
186      
187      small block  (4 octets, lsb first)
188      large block  (4 octets, lsb first)
189      floor order for small block (octet)
190      floor order for large block (octet)
191      floor octaves for small block (octet)
192      floor octaves for large block (octet)
193      floorch      (4 octets, lsb first)
194    */
195
196   _oggpack_writeinit(&opb);
197   _v_writestring(&opb,"vorbis");
198   _oggpack_write(&opb,0x80,8);
199
200   _oggpack_write(&opb,0x00,32);
201
202   _oggpack_write(&opb,vi->channels,8);
203   _oggpack_write(&opb,vi->rate,32);
204
205   _oggpack_write(&opb,vi->bitrate_upper,32);
206   _oggpack_write(&opb,vi->bitrate_nominal,32);
207   _oggpack_write(&opb,vi->bitrate_lower,32);
208
209   _oggpack_write(&opb,ilog2(vi->blocksize[0]),4);
210   _oggpack_write(&opb,ilog2(vi->blocksize[1]),4);
211   _oggpack_write(&opb,vi->floororder[0],8);
212   _oggpack_write(&opb,vi->floororder[1],8);
213   _oggpack_write(&opb,vi->floormap[0],16);
214   _oggpack_write(&opb,vi->floormap[1],16);
215   _oggpack_write(&opb,vi->floorch,8);
216
217   /* build the packet */
218   if(vi->header)free(vi->header);
219   vi->header=malloc(_oggpack_bytes(&opb));
220   memcpy(vi->header,opb.buffer,_oggpack_bytes(&opb));
221   op->packet=vi->header;
222   op->bytes=_oggpack_bytes(&opb);
223   op->b_o_s=1;
224   op->e_o_s=0;
225   op->frameno=0;
226
227   /* comment header:
228      codec id       "vorbis"
229      header id      0x81 (byte)
230      vendor len     (4 octets, lsb first)
231      vendor and id  (n octects as above)
232      comments       (4 octets, lsb first)
233      comment 0 len  (4 octets, lsb first)
234      comment 0 len  (n octets as above)
235      ...
236      comment n-1 len  (4 octets, lsb first)
237      comment 0-1 len  (n octets as above)
238   */
239
240   _oggpack_reset(&opb);
241   _v_writestring(&opb,"vorbis");
242   _oggpack_write(&opb,0x81,8);
243
244   if(vi->vendor){
245     _oggpack_write(&opb,strlen(vi->vendor),32);
246     _v_writestring(&opb,vi->vendor);
247   }else{
248     _oggpack_write(&opb,0,32);
249   }
250   
251   _oggpack_write(&opb,vi->comments,32);
252   if(vi->comments){
253     int i;
254     for(i=0;i<vi->comments;i++){
255       if(vi->user_comments[i]){
256         _oggpack_write(&opb,strlen(vi->user_comments[i]),32);
257         _v_writestring(&opb,vi->user_comments[i]);
258       }else{
259         _oggpack_write(&opb,0,32);
260       }
261     }
262   }
263   
264   if(vi->header1)free(vi->header1);
265   vi->header1=malloc(_oggpack_bytes(&opb));
266   memcpy(vi->header1,opb.buffer,_oggpack_bytes(&opb));
267   op_comm->packet=vi->header1;
268   op_comm->bytes=_oggpack_bytes(&opb);
269   op_comm->b_o_s=0;
270   op_comm->e_o_s=0;
271   op_comm->frameno=0;
272
273   /* codebook header:
274      codec id       "vorbis"
275      header id      0x82 (byte)
276      nul so far; not encoded yet */
277
278   _oggpack_reset(&opb);
279   _v_writestring(&opb,"vorbis");
280   _oggpack_write(&opb,0x82,8);
281
282   if(vi->header2)free(vi->header2);
283   vi->header2=malloc(_oggpack_bytes(&opb));
284   memcpy(vi->header2,opb.buffer,_oggpack_bytes(&opb));
285   op_code->packet=vi->header2;
286   op_code->bytes=_oggpack_bytes(&opb);
287   op_code->b_o_s=0;
288   op_code->e_o_s=0;
289   op_code->frameno=0;
290
291   _oggpack_writeclear(&opb);
292
293   return(0);
294 }
295
296 void vorbis_info_clear(vorbis_info *vi){
297   /* clear the non-flat storage before zeroing */
298
299   /* comments */
300   if(vi->user_comments){
301     char **ptr=vi->user_comments;
302     while(*ptr){
303       free(*(ptr++));
304     }
305     free(vi->user_comments);
306   }
307
308   /* vendor string */
309   if(vi->vendor)free(vi->vendor);
310
311   /* local encoding storage */
312   if(vi->header)free(vi->header);
313   if(vi->header1)free(vi->header1);
314   if(vi->header2)free(vi->header2);
315
316   memset(vi,0,sizeof(vorbis_info));
317 }
318   
319