1 /***************************************************************************
2         \file audioencoder_lame.cpp
3         \brief Avidemux audio encoder plugin, front end for libmp3lame
4     copyright            : (C) 2006/2009 by mean
5     email                : fixounet@free.fr
6  ***************************************************************************/
7 
8 /***************************************************************************
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  ***************************************************************************/
16 
17 #include "ADM_default.h"
18 #include "DIA_factory.h"
19 #include "DIA_coreToolkit.h"
20 #include <lame/lame.h>
21 #include "audioencoder.h"
22 #include "audioencoderInternal.h"
23 #include "audioencoder_lame_param.h"
24 #include "audioencoder_lame.h"
25 #include "lame_encoder.h"
26 #include "lame_encoder_desc.cpp"
27 
28 #define LAME_DEFAULT_CONF {128, ADM_LAME_PRESET_CBR, 2, 0}
29 static lame_encoder defaultConfig = LAME_DEFAULT_CONF;
30 
31 extern "C"
32 {
33 static bool configure (CONFcouple **setup);
34 static bool setOption(CONFcouple **c, const char *paramName, uint32_t value);
35 static void getDefaultConfiguration(CONFcouple **c);
36 };
37 
38 /********************* Declare Plugin *****************************************************/
39 ADM_DECLARE_AUDIO_ENCODER_PREAMBLE(AUDMEncoder_Lame);
40 
41 static ADM_audioEncoder encoderDesc = {
42   ADM_AUDIO_ENCODER_API_VERSION,
43   create,			// Defined by macro automatically
44   destroy,			// Defined by macro automatically
45   configure,		//** put your own function here**
46   "Lame",
47   "MP3 (lame)",
48   "Lame MP3 encoder plugin Mean 2009",
49   2,                    // Max channels
50   1,0,0,                // Version
51   WAV_MP3,              // WavTag
52   200,                  // Priority
53 
54   setOption,         //** put your own function here**
55   getDefaultConfiguration,
56   NULL
57 };
58 ADM_DECLARE_AUDIO_ENCODER_CONFIG();
59 
60 /******************* / Declare plugin*******************************************************/
61 #define MYFLAGS (lame_global_flags *)lameFlags
62 /**
63     \fn AUDMEncoder_Lame Constructor
64     \brief
65 */
AUDMEncoder_Lame(AUDMAudioFilter * instream,bool globalHeader,CONFcouple * setup)66 AUDMEncoder_Lame::AUDMEncoder_Lame (AUDMAudioFilter * instream,bool globalHeader,
67     CONFcouple *setup)  :ADM_AudioEncoder    (instream,setup)
68 {
69   printf ("[Lame] Creating lame\n");
70   lameFlags = NULL;
71   wavheader.encoding = WAV_MP3;
72   _config=defaultConfig;
73   if(setup) // load config if possible
74     ADM_paramLoad(setup,lame_encoder_param,&_config);
75 };
76 
77 /**
78     \fn AUDMEncoder_Lame
79     \brief Destructor
80 */
81 
~AUDMEncoder_Lame()82 AUDMEncoder_Lame::~AUDMEncoder_Lame ()
83 {
84 
85   printf ("[Lame] Deleting lame\n");
86   if (lameFlags)
87     {
88       lame_close (MYFLAGS);
89     }
90   lameFlags = NULL;
91 };
92 
93 
94 /**
95     \fn initialize
96     \brief initialize lame encoder
97     @return 1 on success, 0 on error
98 */
99 
initialize(void)100 bool AUDMEncoder_Lame::initialize (void)
101 {
102 
103   int ret;
104   MPEG_mode_e mmode;
105   uint32_t frequence;
106 
107 
108 
109   lameFlags = lame_init ();
110   if (lameFlags == NULL)
111     return false;
112 
113   if (_incoming->getInfo ()->channels > 2)
114     {
115       printf ("[Lame]Too many channels\n");
116       return false;
117     }
118 
119   // recompute output length
120 
121 
122   ret = lame_set_in_samplerate (MYFLAGS, wavheader.frequency);
123   ret = lame_set_num_channels (MYFLAGS,  wavheader.channels);
124 
125 
126   frequence = wavheader.frequency;
127   printf ("[Lame] output frequency : %" PRIu32"\n", frequence);
128   ret = lame_set_out_samplerate (MYFLAGS, frequence);
129 
130   ret = lame_set_quality (MYFLAGS, 2);
131 
132   if (wavheader.channels == 2)
133     {
134 
135           mmode = STEREO;
136     }
137   else
138     {
139       mmode = MONO;
140       printf ("[Lame] mono audio mp3");
141     }
142 
143   ret = lame_set_brate (MYFLAGS, _config.bitrate);
144   ret = lame_set_mode (MYFLAGS, mmode);	// 0 stereo 1 jstero
145   ret = lame_set_quality (MYFLAGS, _config.quality);	// 0 stereo 1 jstero
146   ret = lame_set_disable_reservoir (MYFLAGS, _config.disableBitReservoir);
147   printf ("[Lame]Using quality of %d\n", lame_get_quality (MYFLAGS));
148   // update bitrate in header
149   wavheader.byterate = (_config.bitrate >> 3) * 1000;
150 #define BLOCK_SIZE 1152
151   // configure CBR/ABR/...
152 
153   switch (_config.preset)
154     {
155     default:
156     case ADM_LAME_PRESET_CBR:
157         ADM_info("Lame : CBR Mode\n");
158       break;
159     case ADM_LAME_PRESET_ABR:
160         ADM_info("Lame : ABR Mode\n");
161 
162       lame_set_preset (MYFLAGS, _config.bitrate);
163       wavheader.blockalign = BLOCK_SIZE;
164       break;
165     case ADM_LAME_PRESET_EXTREME:
166         ADM_info("Lame : Extreme Mode\n");
167       wavheader.blockalign = BLOCK_SIZE;
168       lame_set_preset (MYFLAGS, EXTREME);
169       break;
170 
171 
172     }
173   ret = lame_init_params (MYFLAGS);
174   if (ret == -1)
175     {
176         printf("[Lame] Init params failes %d\n",ret);
177         return false;
178     }
179 
180   lame_print_config (MYFLAGS);
181   lame_print_internals (MYFLAGS);
182   _chunk = BLOCK_SIZE * wavheader.channels;
183 
184   return true;
185 }
186 /**
187     \fn isVBR
188     @return 1 if the stream is vbr, 0 is cbr
189 
190 */
isVBR(void)191 bool AUDMEncoder_Lame::isVBR (void)
192 {
193   if (_config.preset == ADM_LAME_PRESET_CBR)
194     return false;
195   return true;
196 
197 }
198 /**
199     \fn send
200     \brief Encode a block
201 */
send(uint32_t nbSample,uint8_t * dest)202 int AUDMEncoder_Lame::send(uint32_t nbSample, uint8_t *dest)
203 {
204   int nbout;
205   dither16 (&(tmpbuffer[tmphead]), nbSample, wavheader.channels);
206   ADM_assert (tmptail >= tmphead);
207   int16_t *sample16=(int16_t *)& (tmpbuffer[tmphead]);
208   if (wavheader.channels == 1)
209     {
210       nbout =	lame_encode_buffer (MYFLAGS,
211                 sample16,
212 			    sample16, nbSample, dest,
213 			    16 * 1024);
214 
215     }
216   else
217     {
218       nbout =	lame_encode_buffer_interleaved (MYFLAGS,
219 					sample16,
220 					nbSample / 2, dest, 16 * 1024);
221     }
222     return nbout;
223 }
224 /**
225     \fn encode
226     \brief Get an encoded mp3 packet
227     @param dest [in] Where to write datas
228     @param len  [out] Length of encoded datas in bytes
229     @param samples [out] Number of samples
230     @return true on success, false on error
231 
232 */
encode(uint8_t * dest,uint32_t * len,uint32_t * samples)233 bool AUDMEncoder_Lame::encode(uint8_t *dest, uint32_t *len, uint32_t *samples)
234 {
235 
236   int32_t nbout;
237 
238   *samples = BLOCK_SIZE;	//FIXME
239   *len = 0;
240   if(AudioEncoderStopped==_state)
241         return false;
242 
243     refillBuffer (_chunk);
244     if(AudioEncoderNoInput==_state)
245     {
246         int left=tmptail-tmphead;
247         if (left < _chunk)
248         {
249             if(left)
250             {
251                 nbout=send(left,dest);
252                 tmphead=tmptail;
253                 ADM_info("[lame]Sending last packet\n");
254                 goto cont;
255             }
256               // Flush
257               _state=AudioEncoderStopped;
258               nbout=lame_encode_flush(MYFLAGS,dest,16*1024);
259               if(nbout<0)
260               {
261                     ADM_warning("Error while flushing lame\n");
262                     return false;
263               }
264 
265               *len=nbout;
266               *samples=BLOCK_SIZE;
267               ADM_info("[Lame] Flushing, last block is %d bytes\n",nbout);
268               return true;
269     }
270   }
271   nbout=send(_chunk,dest);
272   tmphead += _chunk;
273 cont:
274   if (nbout < 0)
275     {
276       printf ("[Lame] Error !!! : %" PRIi32"\n", nbout);
277       return false;
278     }
279   *len = nbout;
280   if (!*len)
281     *samples = 0;
282   else
283     *samples=BLOCK_SIZE;
284   return true;
285 }
286 /**
287       \fn configure
288       \brief Dialog to set lame settings
289       @return 1 on success, 0 on failure
290 
291 */
292 
configure(CONFcouple ** setup)293 bool configure (CONFcouple **setup)
294 {
295   int ret = 0;
296   char string[400];
297   uint32_t mmode, ppreset;
298 #define SZT(x) sizeof(x)/sizeof(diaMenuEntry )
299 #define PX(x) &(config.x)
300 
301     lame_encoder config=defaultConfig;
302     if(*setup)
303     {
304         ADM_paramLoad(*setup,lame_encoder_param,&config);
305     }
306 
307   ppreset = config.preset;
308 
309   diaMenuEntry encodingMode[] = {
310     {ADM_LAME_PRESET_CBR, QT_TRANSLATE_NOOP("lame","CBR"), NULL},
311     {ADM_LAME_PRESET_ABR, QT_TRANSLATE_NOOP("lame","ABR"), NULL},
312   };
313   diaElemMenu Mode (&ppreset, QT_TRANSLATE_NOOP("lame","Bit_rate mode:"),   SZT (encodingMode), encodingMode);
314 
315 #define BITRATE(x) {x,QT_TRANSLATE_NOOP("lame",#x)}
316   diaMenuEntry bitrateM[] = {
317     BITRATE (56),//56
318     BITRATE (64),
319     BITRATE (80),
320     BITRATE (96),
321     BITRATE (112),
322     BITRATE (128),
323     BITRATE (160),
324     BITRATE (192),
325     BITRATE (224),
326     BITRATE (256),
327     BITRATE (320)
328   };
329 
330 //***
331   diaElemMenu bitrate (&(config.bitrate), QT_TRANSLATE_NOOP("lame","_Bitrate:"), SZT (bitrateM),
332 		       bitrateM);
333   diaElemUInteger quality (PX (quality), QT_TRANSLATE_NOOP("lame","_Quality:"), 0, 9);
334   bool reservoir32=config.disableBitReservoir;
335   diaElemToggle reservoir (&reservoir32, QT_TRANSLATE_NOOP("lame","_Disable reservoir"));
336 
337   diaElem *elems[] = { &Mode, &bitrate,&quality, &reservoir };
338 
339   if (diaFactoryRun (QT_TRANSLATE_NOOP("lame","LAME Configuration"), 4, elems))
340     {
341       config.preset=(ADM_LAME_PRESET)ppreset;
342       config.disableBitReservoir=reservoir32;
343       if(*setup) delete *setup;
344       *setup=NULL;
345       ADM_paramSave(setup,lame_encoder_param,&config);
346       defaultConfig=config;
347       return 1;
348     }
349   return 0;
350 }
351 /**
352      \fn setOption
353      \brief Allow giving codec specific options as string+value
354 */
setOption(CONFcouple ** c,const char * paramName,uint32_t value)355 bool setOption(CONFcouple **c, const char *paramName, uint32_t value)
356 {
357    lame_encoder config=defaultConfig;
358     if(*c)
359     {
360         ADM_paramLoad(*c,lame_encoder_param,&config);
361     }else
362     {
363         config=defaultConfig;
364     }
365     if(!strcasecmp(paramName,"MP3DisableReservoir"))
366     {
367         config.disableBitReservoir=value;
368         ADM_paramSave(c,lame_encoder_param,&config);
369         return 1;
370     }
371     ADM_error("Not supported\n");
372     return 0;
373 }
374 
getDefaultConfiguration(CONFcouple ** c)375 void getDefaultConfiguration(CONFcouple **c)
376 {
377 	lame_encoder config = LAME_DEFAULT_CONF;
378 
379 	ADM_paramSave(c, lame_encoder_param, &config);
380 }
381 
382 // EOF
383