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