xref: /plan9/sys/src/games/mp3enc/vorbis_interface.c (revision 8f5875f3e9b20916b4c52ad4336922bc8653eb7b)
1 /* $Id: vorbis_interface.c,v 1.16 2001/03/18 14:31:29 aleidinger Exp $ */
2 
3 
4 /* Compile lame with
5 
6 #! /bin/bash
7 
8 OGGVORBIS_ROOT=/home/cvs/vorbis
9 
10 export CPPFLAGS="-I${OGGVORBIS_ROOT}/ogg/include -I${OGGVORBIS_ROOT}/vorbis/lib"
11 export CONFIG_DEFS="-DUSE_FFT3DN"
12 
13 make clean
14 ../configure
15 make
16 
17 You can also do this with the "--with-vorbis" options in configure.
18 
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24 
25 /* LAME interface to libvorbis */
26 
27 #ifdef HAVE_VORBIS
28 #include <stdlib.h>
29 #include <limits.h>
30 #include <time.h>
31 #include "vorbis/codec.h"
32 #include "modes/modes.h"
33 #include "lame.h"
34 #include "util.h"
35 
36 #ifdef WITH_DMALLOC
37 #include <dmalloc.h>
38 #endif
39 
40 short int  convbuffer [4096];  /* take 8 KByte out of the data segment, not the stack */
41 int        convsize;
42 
43 ogg_sync_state    oy;  // sync and verify incoming physical bitstream
44 ogg_stream_state  os;  // take physical pages, weld into a logical stream of packets
45 ogg_page          og;  // one Ogg bitstream page. Vorbis packets are inside
46 ogg_packet        op;  // one raw packet of data for decode
47 vorbis_info       vi;  // struct that stores all the static vorbis bitstream settings
48 vorbis_comment    vc;  // struct that stores all the bitstream user comments
49 vorbis_dsp_state  vd;  // central working state for the packet->PCM decoder
50 vorbis_block      vb;  // local working space for packet->PCM decode
51 
52 
53 
lame_decode_ogg_initfile(lame_global_flags * gfp,FILE * fd,mp3data_struct * mp3data)54 int lame_decode_ogg_initfile( lame_global_flags*  gfp,
55                               FILE*               fd,
56                               mp3data_struct*     mp3data )
57 {
58 
59   lame_internal_flags *gfc = gfp->internal_flags;
60   char *buffer;
61   int  bytes;
62   int i;
63 
64 
65   /********** Decode setup ************/
66 
67   ogg_sync_init(&oy); /* Now we can read pages */
68 
69 
70   /* grab some data at the head of the stream.  We want the first page
71      (which is guaranteed to be small and only contain the Vorbis
72      stream initial header) We need the first page to get the stream
73      serialno. */
74 
75   /* submit a 4k block to libvorbis' Ogg layer */
76   buffer=ogg_sync_buffer(&oy,4096);
77   bytes=fread(buffer,1,4096,fd);
78   ogg_sync_wrote(&oy,bytes);
79 
80   /* Get the first page. */
81   if(ogg_sync_pageout(&oy,&og)!=1){
82     /* error case.  Must not be Vorbis data */
83     ERRORF( gfc, "Error initializing Ogg bitstream data.\n" );
84     return -1;
85   }
86 
87   /* Get the serial number and set up the rest of decode. */
88   /* serialno first; use it to set up a logical stream */
89   ogg_stream_init(&os,ogg_page_serialno(&og));
90 
91   /* extract the initial header from the first page and verify that the
92      Ogg bitstream is in fact Vorbis data */
93 
94   /* I handle the initial header first instead of just having the code
95      read all three Vorbis headers at once because reading the initial
96      header is an easy way to identify a Vorbis bitstream and it's
97      useful to see that functionality seperated out. */
98 
99   vorbis_info_init(&vi);
100   vorbis_comment_init(&vc);
101   if(ogg_stream_pagein(&os,&og)<0){
102     /* error; stream version mismatch perhaps */
103     ERRORF( gfc, "Error reading first page of Ogg bitstream data.\n" );
104     return -1;
105   }
106 
107   if(ogg_stream_packetout(&os,&op)!=1){
108     /* no page? must not be vorbis */
109     ERRORF( gfc, "Error reading initial header packet.\n" );
110     return -1;
111   }
112 
113   if(vorbis_synthesis_headerin(&vi,&vc,&op)<0){
114     /* error case; not a vorbis header */
115     ERRORF( gfc, "This Ogg bitstream does not contain Vorbis "
116 	    "audio data.\n");
117     return -1;
118   }
119 
120   /* At this point, we're sure we're Vorbis.  We've set up the logical
121      (Ogg) bitstream decoder.  Get the comment and codebook headers and
122      set up the Vorbis decoder */
123 
124   /* The next two packets in order are the comment and codebook headers.
125      They're likely large and may span multiple pages.  Thus we reead
126      and submit data until we get our two pacakets, watching that no
127      pages are missing.  If a page is missing, error out; losing a
128      header page is the only place where missing data is fatal. */
129 
130   i=0;
131   while(i<2){
132     while(i<2){
133       int result=ogg_sync_pageout(&oy,&og);
134       if(result==0)break; /* Need more data */
135       /* Don't complain about missing or corrupt data yet.  We'll
136 	 catch it at the packet output phase */
137       if(result==1){
138 	ogg_stream_pagein(&os,&og); /* we can ignore any errors here
139 				       as they'll also become apparent
140 				       at packetout */
141 	while(i<2){
142 	  result=ogg_stream_packetout(&os,&op);
143 	  if(result==0)break;
144 	  if(result==-1){
145 	    /* Uh oh; data at some point was corrupted or missing!
146 	       We can't tolerate that in a header.  Die. */
147 	    ERRORF( gfc, "Corrupt secondary header.  Exiting.\n" );
148 	    return -1;
149 	  }
150 	  vorbis_synthesis_headerin(&vi,&vc,&op);
151 	  i++;
152 	}
153       }
154     }
155     /* no harm in not checking before adding more */
156     buffer=ogg_sync_buffer(&oy,4096);
157     bytes=fread(buffer,1,4096,fd);
158     if(bytes==0 && i<2){
159       ERRORF( gfc, "End of file before finding all Vorbis headers!\n" );
160       return -1;
161     }
162     ogg_sync_wrote(&oy,bytes);
163   }
164 
165   /* Throw the comments plus a few lines about the bitstream we're
166      decoding */
167   {
168     /*
169     char **ptr=vc.user_comments;
170     while(*ptr){
171       MSGF( gfc, "%s\n", *ptr );
172       ++ptr;
173     }
174     MSGF( gfc, "\nBitstream is %d channel, %ldHz\n", vi.channels, vi.rate );
175     MSGF( gfc, "Encoded by: %s\n\n", vc.vendor );
176     */
177   }
178 
179 
180   /* OK, got and parsed all three headers. Initialize the Vorbis
181      packet->PCM decoder. */
182   vorbis_synthesis_init(&vd,&vi); /* central decode state */
183   vorbis_block_init(&vd,&vb);     /* local state for most of the decode
184 				     so multiple block decodes can
185 				     proceed in parallel.  We could init
186 				     multiple vorbis_block structures
187 				     for vd here */
188 
189   mp3data->stereo = vi.channels;
190   mp3data->samplerate = vi.rate;
191   mp3data->bitrate = 0; //ov_bitrate_instant(&vf);
192   mp3data->nsamp=MAX_U_32_NUM;
193 
194   return 0;
195 }
196 
197 
198 
199 /*
200   For lame_decode_fromfile:  return code
201   -1     error, or eof
202   0     ok, but need more data before outputing any samples
203   n     number of samples output.
204 */
lame_decode_ogg_fromfile(lame_global_flags * gfp,FILE * fd,short int pcm_l[],short int pcm_r[],mp3data_struct * mp3data)205 int lame_decode_ogg_fromfile( lame_global_flags*  gfp,
206                               FILE*               fd,
207                               short int           pcm_l[],
208                               short int           pcm_r[],
209                               mp3data_struct*     mp3data )
210 {
211   lame_internal_flags *gfc = gfp->internal_flags;
212   int samples,result,i,j,eof=0,eos=0,bout=0;
213   double **pcm;
214 
215   while(1){
216 
217     /*
218     **pcm is a multichannel double vector.  In stereo, for
219     example, pcm[0] is left, and pcm[1] is right.  samples is
220     the size of each channel.  Convert the float values
221     (-1.<=range<=1.) to whatever PCM format and write it out */
222     /* unpack the buffer, if it has at least 1024 samples */
223     convsize=1024;
224     samples=vorbis_synthesis_pcmout(&vd,&pcm);
225     if (samples >= convsize || eos || eof) {
226       /* read 1024 samples, or if eos, read what ever is in buffer */
227       int clipflag=0;
228       bout=(samples<convsize?samples:convsize);
229 
230       /* convert doubles to 16 bit signed ints (host order) and
231 	 interleave */
232       for(i=0;i<vi.channels;i++){
233 	double  *mono=pcm[i];
234 	for(j=0;j<bout;j++){
235 	  int val=mono[j]*32767.;
236 	  /* might as well guard against clipping */
237 	  if(val>32767){
238 	    val=32767;
239 	    clipflag=1;
240 	  }
241 	  if(val<-32768){
242 	    val=-32768;
243 	    clipflag=1;
244 	  }
245 	  if (i==0) pcm_l[j]=val;
246 	  if (i==1) pcm_r[j]=val;
247 	}
248       }
249 
250       /*
251       if(clipflag)
252 	MSGF( gfc, "Clipping in frame %ld\n", vd.sequence );
253       */
254 
255       /* tell libvorbis how many samples we actually consumed */
256       vorbis_synthesis_read(&vd,bout);
257 
258       break;
259     }
260 
261     result=ogg_sync_pageout(&oy,&og);
262 
263     if(result==0) {
264       /* need more data */
265     }else if (result==-1){ /* missing or corrupt data at this page position */
266       ERRORF( gfc, "Corrupt or missing data in bitstream; "
267 	      "continuing...\n");
268     }else{
269       /* decode this page */
270       ogg_stream_pagein(&os,&og); /* can safely ignore errors at
271 				       this point */
272       do {
273 	result=ogg_stream_packetout(&os,&op);
274 	if(result==0) {
275 	  /* need more data */
276 	} else if(result==-1){ /* missing or corrupt data at this page position */
277 	  /* no reason to complain; already complained above */
278 	}else{
279 	  /* we have a packet.  Decode it */
280 	  vorbis_synthesis(&vb,&op);
281 	  vorbis_synthesis_blockin(&vd,&vb);
282 	}
283       } while (result!=0);
284     }
285 
286     /* is this the last page? */
287     if(ogg_page_eos(&og))eos=1;
288 
289     if(!eos){
290       char *buffer;
291       int bytes;
292       buffer=ogg_sync_buffer(&oy,4096);
293       bytes=fread(buffer,1,4096,fd);
294       ogg_sync_wrote(&oy,bytes);
295       if(bytes==0)eof=1;
296     }
297   }
298 
299   mp3data->stereo = vi.channels;
300   mp3data->samplerate = vi.rate;
301   mp3data->bitrate = 0; //ov_bitrate_instant(&vf);
302   /*  mp3data->nsamp=MAX_U_32_NUM;*/
303 
304 
305   if (bout==0) {
306     /* clean up this logical bitstream; before exit we see if we're
307        followed by another [chained] */
308     ogg_stream_clear(&os);
309 
310     /* ogg_page and ogg_packet structs always point to storage in
311        libvorbis.  They're never freed or manipulated directly */
312 
313     vorbis_block_clear(&vb);
314     vorbis_dsp_clear(&vd);
315     vorbis_info_clear(&vi);  /* must be called last */
316 
317     /* OK, clean up the framer */
318     ogg_sync_clear(&oy);
319     return -1;
320   }
321   return bout;
322 }
323 
324 
325 
326 
327 
328 
329 
330 
331 
332 
333 
334 
335 
336 ogg_stream_state  os2;  // take physical pages, weld into a logical stream of packets
337 ogg_page          og2;  // one Ogg bitstream page. Vorbis packets are inside
338 ogg_packet        op2;  // one raw packet of data for decode
339 
340 vorbis_info       vi2;  // struct that stores all the static vorbis bitstream settings
341 vorbis_comment    vc2;  // struct that stores all the bitstream user comments
342 vorbis_dsp_state  vd2;  // central working state for the packet->PCM decoder
343 vorbis_block      vb2;  // local working space for packet->PCM decode
344 
345 
346 
347 
348 #define MAX_COMMENT_LENGTH 255
349 
lame_encode_ogg_init(lame_global_flags * gfp)350 int lame_encode_ogg_init(lame_global_flags *gfp)
351 {
352   lame_internal_flags *gfc=gfp->internal_flags;
353   char comment[MAX_COMMENT_LENGTH+1];
354 
355 
356   /********** Encode setup ************/
357 
358   /* choose an encoding mode */
359   /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
360   if (gfp->compression_ratio < 5.01) {
361     memcpy(&vi2,&info_E,sizeof(vi2));
362     MSGF( gfc, "Encoding with Vorbis mode info_E \n" );
363   } else if (gfp->compression_ratio < 6) {
364     memcpy(&vi2,&info_D,sizeof(vi2));
365     MSGF( gfc, "Encoding with Vorbis mode info_D \n" );
366   } else if (gfp->compression_ratio < 8) {
367     memcpy(&vi2,&info_C,sizeof(vi2));
368     MSGF( gfc, "Encoding with Vorbis mode info_C \n" );
369   } else if (gfp->compression_ratio < 10) {
370     memcpy(&vi2,&info_B,sizeof(vi2));
371     MSGF( gfc, "Encoding with Vorbis mode info_B \n" );
372   } else if (gfp->compression_ratio < 12) {
373     memcpy(&vi2,&info_A,sizeof(vi2));
374     MSGF( gfc, "Encoding with Vorbis mode info_A \n" );
375   } else {
376     memcpy(&vi2,&info_A,sizeof(vi2));
377     MSGF( gfc, "Encoding with Vorbis mode info_A \n" );
378   }
379 
380   vi2.channels = gfc->channels_out;
381   vi2.rate = gfp->out_samplerate;
382 
383 
384   /* add a comment */
385   vorbis_comment_init(&vc2);
386   vorbis_comment_add(&vc2,"Track encoded using L.A.M.E. libvorbis interface.");
387 
388   /* Add ID3-style comments to the output using (for the time being) the
389      "private data members" in the "id3tag_spec" data structure. This was
390      from a patch by Ralph Giles <giles@a3a32260.sympatico.bconnected.net> */
391 
392 #ifdef THIS_CODE_IS_NOT_BROKEN_ANYMORE
393   if(gfp->tag_spec.title) {
394     strcpy(comment,"TITLE=");
395     strncat(comment,gfp->tag_spec.title,MAX_COMMENT_LENGTH-strlen(comment));
396     vorbis_comment_add(&vc2,comment);
397   }
398   if(gfp->tag_spec.artist) {
399     strcpy(comment,"ARTIST=");
400     strncat(comment,gfp->tag_spec.artist,MAX_COMMENT_LENGTH-strlen(comment));
401     vorbis_comment_add(&vc2,comment);
402   }
403   if(gfp->tag_spec.album) {
404     strcpy(comment,"ALBUM=");
405     strncat(comment,gfp->tag_spec.album,MAX_COMMENT_LENGTH-strlen(comment));
406     vorbis_comment_add(&vc2,comment);
407   }
408   /* pretend that the ID3 fields are equivalent to the Vorbis fields */
409   if(gfp->tag_spec.year) {
410     sprintf(comment, "DATE=%d", gfp->tag_spec.year);
411     vorbis_comment_add(&vc2,comment);
412   }
413   if(gfp->tag_spec.comment) {
414     strcpy(comment,"DESCRIPTION=");
415     strncat(comment,gfp->tag_spec.comment,MAX_COMMENT_LENGTH-strlen(comment));
416     vorbis_comment_add(&vc2,comment);
417   }
418   /* TODO -- support for track and genre */
419 #endif
420 
421   /* set up the analysis state and auxiliary encoding storage */
422   vorbis_analysis_init(&vd2,&vi2);
423   vorbis_block_init(&vd2,&vb2);
424 
425   /* set up our packet->stream encoder */
426   /* pick a random serial number; that way we can more likely build
427      chained streams just by concatenation */
428   srand(time(NULL));
429   ogg_stream_init(&os2,rand());
430 
431   /* Vorbis streams begin with three headers; the initial header (with
432      most of the codec setup parameters) which is mandated by the Ogg
433      bitstream spec.  The second header holds any comment fields.  The
434      third header holds the bitstream codebook.  We merely need to
435      make the headers, then pass them to libvorbis one at a time;
436      libvorbis handles the additional Ogg bitstream constraints */
437 
438   {
439     ogg_packet header;
440     ogg_packet header_comm;
441     ogg_packet header_code;
442 
443     vorbis_analysis_headerout(&vd2,&vc2,&header,&header_comm,&header_code);
444     ogg_stream_packetin(&os2,&header); /* automatically placed in its own
445 					 page */
446     ogg_stream_packetin(&os2,&header_comm);
447     ogg_stream_packetin(&os2,&header_code);
448 
449     /* no need to write out here.  We'll get to that in the main loop */
450   }
451 
452   return 0;
453 }
454 
455 
456 
lame_encode_ogg_finish(lame_global_flags * gfp,char * mp3buf,int mp3buf_size)457 int lame_encode_ogg_finish(lame_global_flags *gfp,
458 			  char *mp3buf, int mp3buf_size)
459 {
460   int eos=0,bytes=0;
461 
462   vorbis_analysis_wrote(&vd2,0);
463 
464   while(vorbis_analysis_blockout(&vd2,&vb2)==1){
465 
466     /* analysis */
467     vorbis_analysis(&vb2,&op2);
468 
469       /* weld the packet into the bitstream */
470       ogg_stream_packetin(&os2,&op2);
471 
472       /* write out pages (if any) */
473       while(!eos){
474 	int result=ogg_stream_pageout(&os2,&og2);
475 	if(result==0)break;
476 
477 
478 	/* check if mp3buffer is big enough for the output */
479 	bytes += og2.header_len + og2.body_len;
480 	if (bytes > mp3buf_size && mp3buf_size>0)
481 	  return -5;
482 
483 	memcpy(mp3buf,og2.header,og2.header_len);
484 	memcpy(mp3buf+og2.header_len,og2.body,og2.body_len);
485 
486 	/* this could be set above, but for illustrative purposes, I do
487 	   it here (to show that vorbis does know where the stream ends) */
488 	if(ogg_page_eos(&og2))eos=1;
489 
490       }
491     }
492 
493 
494   /* clean up and exit.  vorbis_info_clear() must be called last */
495   ogg_stream_clear(&os2);
496   vorbis_block_clear(&vb2);
497   vorbis_dsp_clear(&vd2);
498 
499 
500   /* ogg_page and ogg_packet structs always point to storage in
501      libvorbis.  They're never freed or manipulated directly */
502   return bytes;
503 
504 }
505 
506 
507 
lame_encode_ogg_frame(lame_global_flags * gfp,const sample_t * inbuf_l,const sample_t * inbuf_r,unsigned char * mp3buf,size_t mp3buf_size)508 int  lame_encode_ogg_frame (
509 	lame_global_flags*  gfp,
510 	const sample_t*     inbuf_l,
511 	const sample_t*     inbuf_r,
512 	unsigned char*      mp3buf,
513 	size_t              mp3buf_size )
514 {
515     lame_internal_flags *gfc = gfp->internal_flags;
516     int  i;
517     int  eos   = 0;
518     int  bytes = 0;
519 
520     /* expose the buffer to submit data */
521     double **buffer = vorbis_analysis_buffer(&vd2,gfp->framesize);
522 
523     /* change level of input by -90 dB (no de-interleaving!) */
524     for ( i = 0; i < gfp->framesize; i++ )
525         buffer [0] [i] = (1/32768.) * inbuf_l [i];
526     if ( gfc->channels_out == 2 )
527         for ( i = 0; i < gfp->framesize; i++ )
528             buffer [1] [i] = (1/32768.) * inbuf_r [i];
529 
530   /* tell the library how much we actually submitted */
531   vorbis_analysis_wrote(&vd2,i);
532 
533   /* vorbis does some data preanalysis, then divvies up blocks for
534      more involved (potentially parallel) processing.  Get a single
535      block for encoding now */
536   while(vorbis_analysis_blockout(&vd2,&vb2)==1){
537     int result;
538     /* analysis */
539     vorbis_analysis(&vb2,&op2);
540 
541     /* weld the packet into the bitstream */
542     ogg_stream_packetin(&os2,&op2);
543 
544     /* write out pages (if any) */
545     do {
546       result=ogg_stream_pageout(&os2,&og2);
547       if (result==0) break;
548 
549       /* check if mp3buffer is big enough for the output */
550       bytes += og2.header_len + og2.body_len;
551       /*
552       DEBUGF("\n\n*********\ndecoded bytes=%i  %i \n",bytes,mp3buf_size);
553       */
554       if (bytes > mp3buf_size && mp3buf_size>0)
555 	return -6;
556 
557       memcpy(mp3buf,og2.header,og2.header_len);
558       memcpy(mp3buf+og2.header_len,og2.body,og2.body_len);
559       mp3buf += og2.header_len + og2.body_len;
560 
561       if(ogg_page_eos(&og2))eos=1;
562     } while (1);
563   }
564   (gfp -> frameNum)++;
565   return bytes;
566 }
567 
568 #endif
569 
570 /* end of vorbis_interface.c */
571 
572