Commit for general psychoacoustics debugging/improvement.
[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 22 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 19991022");
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         vi->floorch=_oggpack_read(&opb,16);
116
117         return(0);
118       case 0x81:
119         if(vi->rate==0){
120           /* um... we didn;t get the initial header */
121           return(-1);
122         }
123         {
124           int vendorlen=_oggpack_read(&opb,32);
125           vi->vendor=calloc(vendorlen+1,1);
126           _v_readstring(&opb,vi->vendor,vendorlen);
127         }
128         {
129           int i;
130           vi->comments=_oggpack_read(&opb,32);
131           vi->user_comments=calloc(vi->comments+1,sizeof(char **));
132             
133           for(i=0;i<vi->comments;i++){
134             int len=_oggpack_read(&opb,32);
135             vi->user_comments[i]=calloc(len+1,1);
136             _v_readstring(&opb,vi->user_comments[i],len);
137           }       
138         }
139
140         return(0);
141       case 0x82:
142         if(vi->rate==0){
143           /* um... we didn;t get the initial header */
144           return(-1);
145         }
146
147         /* not implemented quite yet */
148
149         return(0);
150       default:
151         /* Not a valid vorbis header type */
152         return(-1);
153         break;
154       }
155     }
156   }
157   return(-1);
158 }
159
160 int vorbis_info_headerout(vorbis_info *vi,
161                           ogg_packet *op,
162                           ogg_packet *op_comm,
163                           ogg_packet *op_code){
164
165   oggpack_buffer opb;
166   /* initial header:
167
168      codec id     "vorbis"
169      header id    0x80 (byte)
170      codec ver    (4 octets, lsb first: currently 0x00)
171      pcm channels (4 octets, lsb first)
172      pcm rate     (4 octets, lsb first)
173      
174      small block  (4 octets, lsb first)
175      large block  (4 octets, lsb first)
176      floor order for small block (octet)
177      floor order for large block (octet)
178      floor octaves for small block (octet)
179      floor octaves for large block (octet)
180      floorch      (4 octets, lsb first)
181    */
182
183   _oggpack_writeinit(&opb);
184   _v_writestring(&opb,"vorbis");
185   _oggpack_write(&opb,0x80,8);
186
187   _oggpack_write(&opb,0x00,32);
188
189   _oggpack_write(&opb,vi->channels,32);
190   _oggpack_write(&opb,vi->rate,32);
191   _oggpack_write(&opb,vi->blocksize[0],32);
192   _oggpack_write(&opb,vi->blocksize[1],32);
193   _oggpack_write(&opb,vi->floororder[0],8);
194   _oggpack_write(&opb,vi->floororder[1],8);
195   _oggpack_write(&opb,vi->flooroctaves[0],8);
196   _oggpack_write(&opb,vi->flooroctaves[1],8);
197   _oggpack_write(&opb,vi->floorch,16);
198
199   /* build the packet */
200   if(vi->header)free(vi->header);
201   vi->header=malloc(_oggpack_bytes(&opb));
202   memcpy(vi->header,opb.buffer,_oggpack_bytes(&opb));
203   op->packet=vi->header;
204   op->bytes=_oggpack_bytes(&opb);
205   op->b_o_s=1;
206   op->e_o_s=0;
207   op->frameno=0;
208
209   /* comment header:
210      codec id       "vorbis"
211      header id      0x81 (byte)
212      vendor len     (4 octets, lsb first)
213      vendor and id  (n octects as above)
214      comments       (4 octets, lsb first)
215      comment 0 len  (4 octets, lsb first)
216      comment 0 len  (n octets as above)
217      ...
218      comment n-1 len  (4 octets, lsb first)
219      comment 0-1 len  (n octets as above)
220   */
221
222   _oggpack_reset(&opb);
223   _v_writestring(&opb,"vorbis");
224   _oggpack_write(&opb,0x81,8);
225
226   if(vi->vendor){
227     _oggpack_write(&opb,strlen(vi->vendor),32);
228     _v_writestring(&opb,vi->vendor);
229   }else{
230     _oggpack_write(&opb,0,32);
231   }
232   
233   _oggpack_write(&opb,vi->comments,32);
234   if(vi->comments){
235     int i;
236     for(i=0;i<vi->comments;i++){
237       if(vi->user_comments[i]){
238         _oggpack_write(&opb,strlen(vi->user_comments[i]),32);
239         _v_writestring(&opb,vi->user_comments[i]);
240       }else{
241         _oggpack_write(&opb,0,32);
242       }
243     }
244   }
245   
246   if(vi->header1)free(vi->header1);
247   vi->header1=malloc(_oggpack_bytes(&opb));
248   memcpy(vi->header1,opb.buffer,_oggpack_bytes(&opb));
249   op_comm->packet=vi->header1;
250   op_comm->bytes=_oggpack_bytes(&opb);
251   op_comm->b_o_s=0;
252   op_comm->e_o_s=0;
253   op_comm->frameno=0;
254
255   /* codebook header:
256      codec id       "vorbis"
257      header id      0x82 (byte)
258      nul so far; not encoded yet */
259
260   _oggpack_reset(&opb);
261   _v_writestring(&opb,"vorbis");
262   _oggpack_write(&opb,0x82,8);
263
264   if(vi->header2)free(vi->header2);
265   vi->header2=malloc(_oggpack_bytes(&opb));
266   memcpy(vi->header2,opb.buffer,_oggpack_bytes(&opb));
267   op_code->packet=vi->header2;
268   op_code->bytes=_oggpack_bytes(&opb);
269   op_code->b_o_s=0;
270   op_code->e_o_s=0;
271   op_code->frameno=0;
272
273   _oggpack_writeclear(&opb);
274
275   return(0);
276 }
277
278 void vorbis_info_clear(vorbis_info *vi){
279   /* clear the non-flat storage before zeroing */
280
281   /* comments */
282   if(vi->user_comments){
283     char **ptr=vi->user_comments;
284     while(*ptr){
285       free(*(ptr++));
286     }
287     free(vi->user_comments);
288   }
289
290   /* vendor string */
291   if(vi->vendor)free(vi->vendor);
292
293   /* local encoding storage */
294   if(vi->header)free(vi->header);
295   if(vi->header1)free(vi->header1);
296   if(vi->header2)free(vi->header2);
297
298   memset(vi,0,sizeof(vorbis_info));
299 }
300   
301