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