1 /***************************************************************************
2     copyright            : (C) 2006 by mean
3     email                : fixounet@free.fr
4  ***************************************************************************/
5 
6 /***************************************************************************
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  ***************************************************************************/
14 
15 
16 #include "ADM_default.h"
17 #include "DIA_factory.h"
18 #include "DIA_coreToolkit.h"
19 
20 #include "audioencoder.h"
21 #include "audioencoderInternal.h"
22 #include "audioencoder_vorbis.h"
23 
24 #include "vorbis_encoder.h"
25 #include "vorbis_encoder_desc.cpp"
26 
27 #include "vorbis/vorbisenc.h"
28 #include <math.h>
29 //********************************
30 #define OPTIONS (twolame_options_struct *)_twolameOptions
31 
32 #define VD (((vorbisStruct *)_handle)->vd)
33 #define VI (((vorbisStruct *)_handle)->vi)
34 #define VB (((vorbisStruct *)_handle)->vb)
35 #define VC (((vorbisStruct *)_handle)->vc)
36 typedef struct vorbisStruct
37 {
38 	vorbis_info 	 vi ;
39 	vorbis_dsp_state vd ;
40 	vorbis_block     vb ;
41 	vorbis_comment   vc ;
42 }vorbisStruct;
43 
44 
45 typedef enum
46 {
47   ADM_VORBIS_CBR,
48   ADM_VORBIS_VBR,
49   ADM_VORBIS_QUALITY
50 
51 }ADM_VORBIS_MODE;
52 
53 #define VORBIS_DEFAULT_CONF {128, ADM_VORBIS_VBR, 9.}
54 static vorbis_encoder defaultConfig = VORBIS_DEFAULT_CONF;
55 
56 static bool configure(CONFcouple **setup);
57 static void getDefaultConfiguration(CONFcouple **c);
58 
59 /********************* Declare Plugin *****************************************************/
60 ADM_DECLARE_AUDIO_ENCODER_PREAMBLE(AUDMEncoder_Vorbis);
61 
62 static ADM_audioEncoder encoderDesc = {
63   ADM_AUDIO_ENCODER_API_VERSION,
64   create,			// Defined by macro automatically
65   destroy,			// Defined by macro automatically
66   configure,		//** put your own function here**
67   "Vorbis",
68   "Vorbis",
69   "Vorbis encoder plugin Mean 2008",
70   6,                    // Max channels
71   1,0,0,                // Version
72   WAV_OGG_VORBIS,
73   200,                  // Priority
74 
75   NULL,         //** put your own function here**
76   getDefaultConfiguration,
77   NULL
78 };
79 ADM_DECLARE_AUDIO_ENCODER_CONFIG();
80 
81 /******************* / Declare plugin*******************************************************/
82 
83 
84 //__________
85 
AUDMEncoder_Vorbis(AUDMAudioFilter * instream,bool globalHeader,CONFcouple * setup)86 AUDMEncoder_Vorbis::AUDMEncoder_Vorbis(AUDMAudioFilter * instream,bool globalHeader,CONFcouple *setup)
87 :ADM_AudioEncoder    (instream,setup)
88 {
89   printf("[Vorbis] Creating Vorbis\n");
90   _handle=NULL;
91   wavheader.encoding=WAV_OGG_VORBIS;
92   _oldpos=0;
93   _handle=(void *)new  vorbisStruct;
94   CHANNEL_TYPE *f=outputChannelMapping;
95   //http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9
96   switch(wavheader.channels)
97   {
98         case 1: f[0] = ADM_CH_MONO; break;
99         case 2: *f++=ADM_CH_FRONT_LEFT;*f++=ADM_CH_FRONT_RIGHT;break;
100         case 3:
101                 *f++=ADM_CH_FRONT_LEFT;
102                 *f++=ADM_CH_FRONT_CENTER;
103                 *f++=ADM_CH_FRONT_RIGHT;
104                 break;
105         case 6:
106         default:
107                 f[5]=ADM_CH_LFE;
108         case 5:
109                 *f++=ADM_CH_FRONT_LEFT;
110                 *f++=ADM_CH_FRONT_CENTER;
111                 *f++=ADM_CH_FRONT_RIGHT;
112                 *f++=ADM_CH_REAR_LEFT;
113                 *f++=ADM_CH_REAR_RIGHT;
114 
115                 break;
116   }
117   _config=defaultConfig;
118   if(setup) // load config if possible
119     ADM_paramLoad(setup,vorbis_encoder_param,&_config);
120 };
121 
122 /**
123 
124 */
~AUDMEncoder_Vorbis()125 AUDMEncoder_Vorbis::~AUDMEncoder_Vorbis()
126 {
127   printf("[Vorbis] Deleting Vorbis\n");
128   if(_handle)
129   {
130     vorbis_block_clear(&VB);
131     vorbis_dsp_clear(&VD);
132     vorbis_info_clear(&VI);
133     delete (vorbisStruct *)_handle;
134   }
135   _handle=NULL;
136 
137 };
138 
139 /**
140     \fn initialize
141 
142 */
initialize(void)143 bool AUDMEncoder_Vorbis::initialize(void)
144 {
145   int ret;
146 
147 
148 
149   ogg_packet header1,header2,header3;
150   int err;
151 
152 
153 
154   vorbis_info_init(&VI) ;
155 
156   switch(_config.mode)
157   {
158 
159     case ADM_VORBIS_VBR:
160                       err=vorbis_encode_init(&VI,
161                               wavheader.channels,
162                               wavheader.frequency,
163                               -1, // Max bitrate
164                               _config.bitrate*1000, //long nominal_bitrate,
165                               -1 //long min_bitrate))
166                             );
167                       break;
168     case  ADM_VORBIS_QUALITY :
169                     err=vorbis_encode_init_vbr(&VI,
170                                 wavheader.channels,
171                                 wavheader.frequency,
172                                 _config.quality/10
173                               );
174                     break;
175 
176     default:
177       ADM_assert(0);
178   }
179   if (err!=0)
180   {
181 	  delete (vorbisStruct*)_handle;
182 	  _handle = NULL;
183 
184     printf("[vorbis] init error %d\n",err);
185     return 0;
186   }
187   vorbis_analysis_init(&VD, &VI) ;
188   vorbis_block_init(&VD, &VB);
189   vorbis_comment_init(&VC);
190   vorbis_comment_add_tag(&VC, "encoder", "AVIDEMUX2") ;
191 
192   vorbis_analysis_headerout(&VD, &VC, &header1,
193                              &header2, &header3);
194 
195 
196 // Store all headers as extra data
197 // see ogg vorbis decode for details
198 // we need 3 packets
199 
200   _extraSize=header1.bytes+header2.bytes+header3.bytes+3*sizeof(uint32_t);
201   _extraData=new uint8_t[_extraSize];
202 
203   uint32_t *ex=(uint32_t *)_extraData;
204   uint8_t *d;
205   d=_extraData+sizeof(uint32_t)*3;
206   ex[0]=header1.bytes;
207   ex[1]=header2.bytes;
208   ex[2]=header3.bytes;
209   memcpy(d,header1.packet,ex[0]);
210   d+=ex[0];
211   memcpy(d,header2.packet,ex[1]);
212   d+=ex[1];
213   memcpy(d,header3.packet,ex[2]);
214   vorbis_comment_clear(&VC);
215 
216   printf("\n[Vorbis]Vorbis encoder initialized\n");
217   switch(_config.mode)
218   {
219     case ADM_VORBIS_VBR:
220       printf("[Vorbis]CBR Bitrate:%" PRIu32"\n",_config.bitrate);
221       break;
222     case ADM_VORBIS_QUALITY: //FIXME FIXME FIXME
223       printf("[Vorbis]VBR Quality:%.1f\n",_config.quality);
224     break;
225     default:
226       ADM_assert(0);
227   }
228 
229   printf("[Vorbis]Channels  :%" PRIu32"\n",wavheader.channels);
230   printf("[Vorbis]Frequency :%" PRIu32"\n",wavheader.frequency);
231   return 1;
232 }
233 
234 #define ROUNDMAX 3000
235 /**
236     \fn encode
237 
238 */
encode(uint8_t * dest,uint32_t * len,uint32_t * samples)239 bool	AUDMEncoder_Vorbis::encode(uint8_t *dest, uint32_t *len, uint32_t *samples)
240 {
241   uint32_t nbout;
242   uint32_t consumed=0;
243   float **float_samples;
244     int channels=wavheader.channels;
245   ogg_packet op ;
246 
247   *len = 0;
248   _chunk=1024*channels;
249   int count=ROUNDMAX;
250 // Check that we have packet from previous pass
251   while(count--)
252   {
253     if(!refillBuffer(_chunk ))
254     {
255       return 0;
256     }
257 
258     if(tmptail-tmphead<_chunk)
259     {
260       return 0;
261     }
262 
263 	//printf("Round %d\n",ROUNDMAX-count);
264     if(vorbis_analysis_blockout(&VD, &VB) == 1)
265     {
266       vorbis_analysis(&VB, NULL);
267       vorbis_bitrate_addblock(&VB) ;
268 	//printf("Blockout\n");
269 
270       if(vorbis_bitrate_flushpacket(&VD, &op))
271       {
272         memcpy(dest, op.packet,op.bytes);
273         *len=op.bytes;
274         *samples=op.granulepos-_oldpos;
275         _oldpos=op.granulepos;
276         //  aprintf("1st packet :sampl:%lu len :%lu sample:%lu abs:%llu\n",*samples,op.bytes,total,op.granulepos);
277         return 1;
278       }
279     }
280 
281 
282     uint32_t nbSample=(tmptail-tmphead)/channels;
283     if(nbSample>1024) nbSample=1024;
284     float_samples=vorbis_analysis_buffer(&VD, nbSample) ;
285     int index=tmphead;
286     // Put our samples in incoming buffer
287     //reorderChannels(&(tmpbuffer[tmphead]), nbSample,_incoming->getChannelMapping(),outputChannelMapping);
288     reorderToPlanar2(&(tmpbuffer[tmphead]),float_samples,nbSample,_incoming->getChannelMapping(),outputChannelMapping);
289 #if 0
290     for (int i = 0; i < nbSample; i++)
291       for (int j = 0; j < channels; j++) {
292       float_samples[j][i] = tmpbuffer[index++];
293       if (float_samples[j][i] > 1) float_samples[j][i] = 1;
294       if (float_samples[j][i] < -1) float_samples[j][i] = -1;
295       }
296 #endif
297       // Buffer full, go go go
298       vorbis_analysis_wrote(&VD, nbSample) ;
299       tmphead+=nbSample*channels;
300   }
301   return 0;
302 
303 }
304 #define SZT(x) sizeof(x)/sizeof(diaMenuEntry )
305 #define PX(x) &(config->x)
306 #define BITRATE(x) {x,QT_TRANSLATE_NOOP("vorbis",#x)}
307 /**
308       \fn configure
309       \brief Dialog to set vorbis settings
310       @return 1 on success, 0 on failure
311 
312 */
313 
configure(CONFcouple ** setup)314 bool configure(CONFcouple **setup)
315 {
316 
317     uint32_t mmode,ppreset;
318     ELEM_TYPE_FLOAT qqual;
319 
320     vorbis_encoder config=defaultConfig;
321     if(*setup)
322     {
323         ADM_paramLoad(*setup,vorbis_encoder_param,&config);
324     }
325 
326 
327     mmode=config.mode;
328     qqual=(ELEM_TYPE_FLOAT)config.quality;
329 
330     diaMenuEntry channelMode[]={
331                              {ADM_VORBIS_VBR,      QT_TRANSLATE_NOOP("vorbis","VBR"),NULL},
332                              {ADM_VORBIS_QUALITY,   QT_TRANSLATE_NOOP("vorbis","Quality based"),NULL}};
333 
334     diaElemMenu menuMode(&mmode,   QT_TRANSLATE_NOOP("vorbis","_Mode:"), SZT(channelMode),channelMode);
335 
336 
337     diaMenuEntry bitrateM[]={
338                               BITRATE(56),
339                               BITRATE(64),
340                               BITRATE(80),
341                               BITRATE(96),
342                               BITRATE(112),
343                               BITRATE(128),
344                               BITRATE(160),
345                               BITRATE(192),
346                               BITRATE(224)
347                           };
348     diaElemMenu bitrate(&(config.bitrate),   QT_TRANSLATE_NOOP("vorbis","_Bitrate:"), SZT(bitrateM),bitrateM);
349 
350     diaElemFloat quality(&qqual,QT_TRANSLATE_NOOP("vorbis","_Quality:"),-1.,10.);
351 
352 
353 
354 
355       diaElem *elems[]={&menuMode,&bitrate,&quality};
356 
357   if( diaFactoryRun(QT_TRANSLATE_NOOP("vorbis","Vorbis Configuration"),3,elems))
358   {
359     config.mode=(ADM_VORBIS_MODE)mmode;
360     config.quality=(float)qqual;
361     if(*setup) delete *setup;
362     *setup=NULL;
363     ADM_paramSave(setup,vorbis_encoder_param,&config);
364     defaultConfig=config;
365     return 1;
366   }
367   return 0;
368 }
369 
getDefaultConfiguration(CONFcouple ** c)370 void getDefaultConfiguration(CONFcouple **c)
371 {
372 	vorbis_encoder config = VORBIS_DEFAULT_CONF;
373 
374 	ADM_paramSave(c, vorbis_encoder_param, &config);
375 }
376 // EOF
377