BladeMP3EncDLL.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  1. /*
  2. * Blade DLL Interface for LAME.
  3. *
  4. * Copyright (c) 1999 - 2002 A.L. Faber
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Library General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Library General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Library General Public
  17. * License along with this library; if not, write to the
  18. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. */
  21. #include <windows.h>
  22. #include <Windef.h>
  23. #include "BladeMP3EncDLL.h"
  24. #include <assert.h>
  25. #include <stdio.h>
  26. #include <lame.h>
  27. #ifdef __cplusplus
  28. extern "C" {
  29. #endif
  30. #define Min(A, B) ((A) < (B) ? (A) : (B))
  31. #define Max(A, B) ((A) > (B) ? (A) : (B))
  32. #define _RELEASEDEBUG 0
  33. // lame_enc DLL version number
  34. const BYTE MAJORVERSION = 1;
  35. const BYTE MINORVERSION = 32;
  36. // Local variables
  37. static DWORD dwSampleBufferSize=0;
  38. static HMODULE gs_hModule=NULL;
  39. static BOOL gs_bLogFile=FALSE;
  40. static lame_global_flags* gfp_save = NULL;
  41. // Local function prototypes
  42. static void dump_config( lame_global_flags* gfp );
  43. static void DebugPrintf( const char* pzFormat, ... );
  44. static void DispErr( char const* strErr );
  45. static void PresetOptions( lame_global_flags *gfp, LONG myPreset );
  46. static void DebugPrintf(const char* pzFormat, ...)
  47. {
  48. char szBuffer[1024]={'\0',};
  49. char szFileName[MAX_PATH+1]={'\0',};
  50. va_list ap;
  51. // Get the full module (DLL) file name
  52. GetModuleFileNameA( gs_hModule,
  53. szFileName,
  54. sizeof( szFileName ) );
  55. // change file name extention
  56. szFileName[ strlen(szFileName) - 3 ] = 't';
  57. szFileName[ strlen(szFileName) - 2 ] = 'x';
  58. szFileName[ strlen(szFileName) - 1 ] = 't';
  59. // start at beginning of the list
  60. va_start(ap, pzFormat);
  61. // copy it to the string buffer
  62. _vsnprintf(szBuffer, sizeof(szBuffer), pzFormat, ap);
  63. // log it to the file?
  64. if ( gs_bLogFile )
  65. {
  66. FILE* fp = NULL;
  67. // try to open the log file
  68. fp=fopen( szFileName, "a+" );
  69. // check file open result
  70. if (fp)
  71. {
  72. // write string to the file
  73. fputs(szBuffer,fp);
  74. // close the file
  75. fclose(fp);
  76. }
  77. }
  78. #if defined _DEBUG || defined _RELEASEDEBUG
  79. OutputDebugStringA( szBuffer );
  80. #endif
  81. va_end(ap);
  82. }
  83. static void PresetOptions( lame_global_flags *gfp, LONG myPreset )
  84. {
  85. switch (myPreset)
  86. {
  87. /*-1*/case LQP_NOPRESET:
  88. break;
  89. /*0*/case LQP_NORMAL_QUALITY:
  90. /* lame_set_quality( gfp, 5 );*/
  91. break;
  92. /*1*/case LQP_LOW_QUALITY:
  93. lame_set_quality( gfp, 9 );
  94. break;
  95. /*2*/case LQP_HIGH_QUALITY:
  96. lame_set_quality( gfp, 2 );
  97. break;
  98. /*3*/case LQP_VOICE_QUALITY: // --voice flag for experimental voice mode
  99. lame_set_mode( gfp, MONO );
  100. lame_set_preset( gfp, 56);
  101. break;
  102. /*4*/case LQP_R3MIX: // --R3MIX
  103. lame_set_preset( gfp, R3MIX);
  104. break;
  105. /*5*/case LQP_VERYHIGH_QUALITY:
  106. lame_set_quality( gfp, 0 );
  107. break;
  108. /*6*/case LQP_STANDARD: // --PRESET STANDARD
  109. lame_set_preset( gfp, STANDARD);
  110. break;
  111. /*7*/case LQP_FAST_STANDARD: // --PRESET FAST STANDARD
  112. lame_set_preset( gfp, STANDARD_FAST);
  113. break;
  114. /*8*/case LQP_EXTREME: // --PRESET EXTREME
  115. lame_set_preset( gfp, EXTREME);
  116. break;
  117. /*9*/case LQP_FAST_EXTREME: // --PRESET FAST EXTREME:
  118. lame_set_preset( gfp, EXTREME_FAST);
  119. break;
  120. /*10*/case LQP_INSANE: // --PRESET INSANE
  121. lame_set_preset( gfp, INSANE);
  122. break;
  123. /*11*/case LQP_ABR: // --PRESET ABR
  124. // handled in beInitStream
  125. break;
  126. /*12*/case LQP_CBR: // --PRESET CBR
  127. // handled in beInitStream
  128. break;
  129. /*13*/case LQP_MEDIUM: // --PRESET MEDIUM
  130. lame_set_preset( gfp, MEDIUM);
  131. break;
  132. /*14*/case LQP_FAST_MEDIUM: // --PRESET FAST MEDIUM
  133. lame_set_preset( gfp, MEDIUM_FAST);
  134. break;
  135. /*1000*/case LQP_PHONE:
  136. lame_set_mode( gfp, MONO );
  137. lame_set_preset( gfp, 16);
  138. break;
  139. /*2000*/case LQP_SW:
  140. lame_set_mode( gfp, MONO );
  141. lame_set_preset( gfp, 24);
  142. break;
  143. /*3000*/case LQP_AM:
  144. lame_set_mode( gfp, MONO );
  145. lame_set_preset( gfp, 40);
  146. break;
  147. /*4000*/case LQP_FM:
  148. lame_set_preset( gfp, 112);
  149. break;
  150. /*5000*/case LQP_VOICE:
  151. lame_set_mode( gfp, MONO );
  152. lame_set_preset( gfp, 56);
  153. break;
  154. /*6000*/case LQP_RADIO:
  155. lame_set_preset( gfp, 112);
  156. break;
  157. /*7000*/case LQP_TAPE:
  158. lame_set_preset( gfp, 112);
  159. break;
  160. /*8000*/case LQP_HIFI:
  161. lame_set_preset( gfp, 160);
  162. break;
  163. /*9000*/case LQP_CD:
  164. lame_set_preset( gfp, 192);
  165. break;
  166. /*10000*/case LQP_STUDIO:
  167. lame_set_preset( gfp, 256);
  168. break;
  169. }
  170. }
  171. __declspec(dllexport) BE_ERR beInitStream(PBE_CONFIG pbeConfig, PDWORD dwSamples, PDWORD dwBufferSize, PHBE_STREAM phbeStream)
  172. {
  173. int actual_bitrate;
  174. //2001-12-18
  175. BE_CONFIG lameConfig = { 0, };
  176. int nInitReturn = 0;
  177. lame_global_flags* gfp = NULL;
  178. // Init the global flags structure
  179. gfp = lame_init();
  180. *phbeStream = (HBE_STREAM)gfp;
  181. // clear out structure
  182. memset(&lameConfig,0x00,CURRENT_STRUCT_SIZE);
  183. // Check if this is a regular BLADE_ENCODER header
  184. if (pbeConfig->dwConfig!=BE_CONFIG_LAME)
  185. {
  186. int nCRC=pbeConfig->format.mp3.bCRC;
  187. int nVBR=(nCRC>>12)&0x0F;
  188. // Copy parameter from old Blade structure
  189. lameConfig.format.LHV1.dwSampleRate =pbeConfig->format.mp3.dwSampleRate;
  190. //for low bitrates, LAME will automatically downsample for better
  191. //sound quality. Forcing output samplerate = input samplerate is not a good idea
  192. //unless the user specifically requests it:
  193. //lameConfig.format.LHV1.dwReSampleRate=pbeConfig->format.mp3.dwSampleRate;
  194. lameConfig.format.LHV1.nMode =(pbeConfig->format.mp3.byMode&0x0F);
  195. lameConfig.format.LHV1.dwBitrate =pbeConfig->format.mp3.wBitrate;
  196. lameConfig.format.LHV1.bPrivate =pbeConfig->format.mp3.bPrivate;
  197. lameConfig.format.LHV1.bOriginal =pbeConfig->format.mp3.bOriginal;
  198. lameConfig.format.LHV1.bCRC =nCRC&0x01;
  199. lameConfig.format.LHV1.bCopyright =pbeConfig->format.mp3.bCopyright;
  200. // Fill out the unknowns
  201. lameConfig.format.LHV1.dwStructSize=CURRENT_STRUCT_SIZE;
  202. lameConfig.format.LHV1.dwStructVersion=CURRENT_STRUCT_VERSION;
  203. // Get VBR setting from fourth nibble
  204. if ( nVBR>0 )
  205. {
  206. lameConfig.format.LHV1.bWriteVBRHeader = TRUE;
  207. lameConfig.format.LHV1.bEnableVBR = TRUE;
  208. lameConfig.format.LHV1.nVBRQuality = nVBR-1;
  209. }
  210. // Get Quality from third nibble
  211. lameConfig.format.LHV1.nPreset=((nCRC>>8)&0x0F);
  212. }
  213. else
  214. {
  215. // Copy the parameters
  216. memcpy(&lameConfig,pbeConfig,pbeConfig->format.LHV1.dwStructSize);
  217. }
  218. // --------------- Set arguments to LAME encoder -------------------------
  219. // Set input sample frequency
  220. lame_set_in_samplerate( gfp, lameConfig.format.LHV1.dwSampleRate );
  221. // disable INFO/VBR tag by default.
  222. // if this tag is used, the calling program must call beWriteVBRTag()
  223. // after encoding. But the original DLL documentation does not
  224. // require the
  225. // app to call beWriteVBRTag() unless they have specifically
  226. // set LHV1.bWriteVBRHeader=TRUE. Thus the default setting should
  227. // be disabled.
  228. lame_set_bWriteVbrTag( gfp, 0 );
  229. //2001-12-18 Dibrom's ABR preset stuff
  230. if(lameConfig.format.LHV1.nPreset == LQP_ABR) // --ALT-PRESET ABR
  231. {
  232. actual_bitrate = lameConfig.format.LHV1.dwVbrAbr_bps / 1000;
  233. // limit range
  234. if( actual_bitrate > 320)
  235. {
  236. actual_bitrate = 320;
  237. }
  238. if( actual_bitrate < 8 )
  239. {
  240. actual_bitrate = 8;
  241. }
  242. lame_set_preset( gfp, actual_bitrate );
  243. }
  244. // end Dibrom's ABR preset 2001-12-18 ****** START OF CBR
  245. if(lameConfig.format.LHV1.nPreset == LQP_CBR) // --ALT-PRESET CBR
  246. {
  247. actual_bitrate = lameConfig.format.LHV1.dwBitrate;
  248. lame_set_preset(gfp, actual_bitrate);
  249. lame_set_VBR(gfp, vbr_off);
  250. }
  251. // end Dibrom's CBR preset 2001-12-18
  252. // The following settings only used when preset is not one of the LAME QUALITY Presets
  253. if ( (int)lameConfig.format.LHV1.nPreset < (int) LQP_STANDARD )
  254. {
  255. switch ( lameConfig.format.LHV1.nMode )
  256. {
  257. case BE_MP3_MODE_STEREO:
  258. lame_set_mode( gfp, STEREO );
  259. lame_set_num_channels( gfp, 2 );
  260. break;
  261. case BE_MP3_MODE_JSTEREO:
  262. lame_set_mode( gfp, JOINT_STEREO );
  263. //lame_set_force_ms( gfp, bForceMS ); // no check box to force this?
  264. lame_set_num_channels( gfp, 2 );
  265. break;
  266. case BE_MP3_MODE_MONO:
  267. lame_set_mode( gfp, MONO );
  268. lame_set_num_channels( gfp, 1 );
  269. break;
  270. case BE_MP3_MODE_DUALCHANNEL:
  271. lame_set_mode( gfp, DUAL_CHANNEL );
  272. lame_set_num_channels( gfp, 2 );
  273. break;
  274. default:
  275. {
  276. DebugPrintf("Invalid lameConfig.format.LHV1.nMode, value is %d\n",lameConfig.format.LHV1.nMode);
  277. return BE_ERR_INVALID_FORMAT_PARAMETERS;
  278. }
  279. }
  280. if ( lameConfig.format.LHV1.bEnableVBR )
  281. {
  282. /* set VBR quality */
  283. lame_set_VBR_q( gfp, lameConfig.format.LHV1.nVBRQuality );
  284. /* select proper VBR method */
  285. switch ( lameConfig.format.LHV1.nVbrMethod)
  286. {
  287. case VBR_METHOD_NONE:
  288. lame_set_VBR( gfp, vbr_off );
  289. break;
  290. case VBR_METHOD_DEFAULT:
  291. lame_set_VBR( gfp, vbr_default );
  292. break;
  293. case VBR_METHOD_OLD:
  294. lame_set_VBR( gfp, vbr_rh );
  295. break;
  296. case VBR_METHOD_MTRH:
  297. case VBR_METHOD_NEW:
  298. /*
  299. * the --vbr-mtrh commandline switch is obsolete.
  300. * now --vbr-mtrh is known as --vbr-new
  301. */
  302. lame_set_VBR( gfp, vbr_mtrh );
  303. break;
  304. case VBR_METHOD_ABR:
  305. lame_set_VBR( gfp, vbr_abr );
  306. break;
  307. default:
  308. /* unsupported VBR method */
  309. assert( FALSE );
  310. }
  311. }
  312. else
  313. {
  314. /* use CBR encoding method, so turn off VBR */
  315. lame_set_VBR( gfp, vbr_off );
  316. }
  317. /* Set bitrate. (CDex users always specify bitrate=Min bitrate when using VBR) */
  318. lame_set_brate( gfp, lameConfig.format.LHV1.dwBitrate );
  319. /* check if we have to use ABR, in order to backwards compatible, this
  320. * condition should still be checked indepedent of the nVbrMethod method
  321. */
  322. if (lameConfig.format.LHV1.dwVbrAbr_bps > 0 )
  323. {
  324. /* set VBR method to ABR */
  325. lame_set_VBR( gfp, vbr_abr );
  326. /* calculate to kbps, round to nearest kbps */
  327. lame_set_VBR_mean_bitrate_kbps( gfp, ( lameConfig.format.LHV1.dwVbrAbr_bps + 500 ) / 1000 );
  328. /* limit range */
  329. if( lame_get_VBR_mean_bitrate_kbps( gfp ) > 320)
  330. {
  331. lame_set_VBR_mean_bitrate_kbps( gfp, 320 );
  332. }
  333. if( lame_get_VBR_mean_bitrate_kbps( gfp ) < 8 )
  334. {
  335. lame_set_VBR_mean_bitrate_kbps( gfp, 8 );
  336. }
  337. }
  338. }
  339. // First set all the preset options
  340. if ( LQP_NOPRESET != lameConfig.format.LHV1.nPreset )
  341. {
  342. PresetOptions( gfp, lameConfig.format.LHV1.nPreset );
  343. }
  344. // Set frequency resampling rate, if specified
  345. if ( lameConfig.format.LHV1.dwReSampleRate > 0 )
  346. {
  347. lame_set_out_samplerate( gfp, lameConfig.format.LHV1.dwReSampleRate );
  348. }
  349. switch ( lameConfig.format.LHV1.nMode )
  350. {
  351. case BE_MP3_MODE_MONO:
  352. lame_set_mode( gfp, MONO );
  353. lame_set_num_channels( gfp, 1 );
  354. break;
  355. default:
  356. break;
  357. }
  358. // Use strict ISO encoding?
  359. lame_set_strict_ISO( gfp, ( lameConfig.format.LHV1.bStrictIso ) ? 1 : 0 );
  360. // Set copyright flag?
  361. if ( lameConfig.format.LHV1.bCopyright )
  362. {
  363. lame_set_copyright( gfp, 1 );
  364. }
  365. // Do we have to tag it as non original
  366. if ( !lameConfig.format.LHV1.bOriginal )
  367. {
  368. lame_set_original( gfp, 0 );
  369. }
  370. else
  371. {
  372. lame_set_original( gfp, 1 );
  373. }
  374. // Add CRC?
  375. if ( lameConfig.format.LHV1.bCRC )
  376. {
  377. lame_set_error_protection( gfp, 1 );
  378. }
  379. else
  380. {
  381. lame_set_error_protection( gfp, 0 );
  382. }
  383. // Set private bit?
  384. if ( lameConfig.format.LHV1.bPrivate )
  385. {
  386. lame_set_extension( gfp, 1 );
  387. }
  388. else
  389. {
  390. lame_set_extension( gfp, 0 );
  391. }
  392. // Set VBR min bitrate, if specified
  393. if ( lameConfig.format.LHV1.dwBitrate > 0 )
  394. {
  395. lame_set_VBR_min_bitrate_kbps( gfp, lameConfig.format.LHV1.dwBitrate );
  396. }
  397. // Set Maxbitrate, if specified
  398. if ( lameConfig.format.LHV1.dwMaxBitrate > 0 )
  399. {
  400. lame_set_VBR_max_bitrate_kbps( gfp, lameConfig.format.LHV1.dwMaxBitrate );
  401. }
  402. // Set bit resovoir option
  403. if ( lameConfig.format.LHV1.bNoRes )
  404. {
  405. lame_set_disable_reservoir( gfp,1 );
  406. }
  407. // check if the VBR tag is required
  408. if ( lameConfig.format.LHV1.bWriteVBRHeader )
  409. {
  410. lame_set_bWriteVbrTag( gfp, 1 );
  411. }
  412. else
  413. {
  414. lame_set_bWriteVbrTag( gfp, 0 );
  415. }
  416. // Override Quality setting, use HIGHBYTE = NOT LOWBYTE to be backwards compatible
  417. if ( ( lameConfig.format.LHV1.nQuality & 0xFF ) ==
  418. ((~( lameConfig.format.LHV1.nQuality >> 8 )) & 0xFF) )
  419. {
  420. lame_set_quality( gfp, lameConfig.format.LHV1.nQuality & 0xFF );
  421. }
  422. if ( 0 != ( nInitReturn = lame_init_params( gfp ) ) )
  423. {
  424. return nInitReturn;
  425. }
  426. //LAME encoding call will accept any number of samples.
  427. if ( 0 == lame_get_version( gfp ) )
  428. {
  429. // For MPEG-II, only 576 samples per frame per channel
  430. *dwSamples= 576 * lame_get_num_channels( gfp );
  431. }
  432. else
  433. {
  434. // For MPEG-I, 1152 samples per frame per channel
  435. *dwSamples= 1152 * lame_get_num_channels( gfp );
  436. }
  437. // Set the input sample buffer size, so we know what we can expect
  438. dwSampleBufferSize = *dwSamples;
  439. // Set MP3 buffer size, conservative estimate
  440. *dwBufferSize=(DWORD)( 1.25 * ( *dwSamples / lame_get_num_channels( gfp ) ) + 7200 );
  441. // For debugging purposes
  442. dump_config( gfp );
  443. // Everything went OK, thus return SUCCESSFUL
  444. return BE_ERR_SUCCESSFUL;
  445. }
  446. __declspec(dllexport) BE_ERR beFlushNoGap(HBE_STREAM hbeStream, PBYTE pOutput, PDWORD pdwOutput)
  447. {
  448. int nOutputSamples = 0;
  449. lame_global_flags* gfp = (lame_global_flags*)hbeStream;
  450. // Init the global flags structure
  451. nOutputSamples = lame_encode_flush_nogap( gfp, pOutput, LAME_MAXMP3BUFFER );
  452. if ( nOutputSamples < 0 )
  453. {
  454. *pdwOutput = 0;
  455. return BE_ERR_BUFFER_TOO_SMALL;
  456. }
  457. else
  458. {
  459. *pdwOutput = nOutputSamples;
  460. }
  461. return BE_ERR_SUCCESSFUL;
  462. }
  463. __declspec(dllexport) BE_ERR beDeinitStream(HBE_STREAM hbeStream, PBYTE pOutput, PDWORD pdwOutput)
  464. {
  465. int nOutputSamples = 0;
  466. lame_global_flags* gfp = (lame_global_flags*)hbeStream;
  467. nOutputSamples = lame_encode_flush( gfp, pOutput, 0 );
  468. if ( nOutputSamples < 0 )
  469. {
  470. *pdwOutput = 0;
  471. return BE_ERR_BUFFER_TOO_SMALL;
  472. }
  473. else
  474. {
  475. *pdwOutput = nOutputSamples;
  476. }
  477. return BE_ERR_SUCCESSFUL;
  478. }
  479. __declspec(dllexport) BE_ERR beCloseStream(HBE_STREAM hbeStream)
  480. {
  481. lame_global_flags* gfp = (lame_global_flags*)hbeStream;
  482. // lame will be close in VbrWriteTag function
  483. if ( !lame_get_bWriteVbrTag( gfp ) )
  484. {
  485. // clean up of allocated memory
  486. lame_close( gfp );
  487. gfp_save = NULL;
  488. }
  489. else
  490. {
  491. gfp_save = (lame_global_flags*)hbeStream;
  492. }
  493. // DeInit encoder
  494. return BE_ERR_SUCCESSFUL;
  495. }
  496. __declspec(dllexport) VOID beVersion(PBE_VERSION pbeVersion)
  497. {
  498. // DLL Release date
  499. char lpszDate[20] = { '\0', };
  500. char lpszTemp[5] = { '\0', };
  501. lame_version_t lv = { 0, };
  502. // Set DLL interface version
  503. pbeVersion->byDLLMajorVersion=MAJORVERSION;
  504. pbeVersion->byDLLMinorVersion=MINORVERSION;
  505. get_lame_version_numerical ( &lv );
  506. // Set Engine version number (Same as Lame version)
  507. pbeVersion->byMajorVersion = (BYTE)lv.major;
  508. pbeVersion->byMinorVersion = (BYTE)lv.minor;
  509. pbeVersion->byAlphaLevel = (BYTE)lv.alpha;
  510. pbeVersion->byBetaLevel = (BYTE)lv.beta;
  511. #ifdef MMX_choose_table
  512. pbeVersion->byMMXEnabled=1;
  513. #else
  514. pbeVersion->byMMXEnabled=0;
  515. #endif
  516. memset( pbeVersion->btReserved, 0, sizeof( pbeVersion->btReserved ) );
  517. // Get compilation date
  518. strcpy(lpszDate,__DATE__);
  519. // Get the first three character, which is the month
  520. strncpy(lpszTemp,lpszDate,3);
  521. lpszTemp[3] = '\0';
  522. pbeVersion->byMonth=1;
  523. // Set month
  524. if (strcmp(lpszTemp,"Jan")==0) pbeVersion->byMonth = 1;
  525. if (strcmp(lpszTemp,"Feb")==0) pbeVersion->byMonth = 2;
  526. if (strcmp(lpszTemp,"Mar")==0) pbeVersion->byMonth = 3;
  527. if (strcmp(lpszTemp,"Apr")==0) pbeVersion->byMonth = 4;
  528. if (strcmp(lpszTemp,"May")==0) pbeVersion->byMonth = 5;
  529. if (strcmp(lpszTemp,"Jun")==0) pbeVersion->byMonth = 6;
  530. if (strcmp(lpszTemp,"Jul")==0) pbeVersion->byMonth = 7;
  531. if (strcmp(lpszTemp,"Aug")==0) pbeVersion->byMonth = 8;
  532. if (strcmp(lpszTemp,"Sep")==0) pbeVersion->byMonth = 9;
  533. if (strcmp(lpszTemp,"Oct")==0) pbeVersion->byMonth = 10;
  534. if (strcmp(lpszTemp,"Nov")==0) pbeVersion->byMonth = 11;
  535. if (strcmp(lpszTemp,"Dec")==0) pbeVersion->byMonth = 12;
  536. // Get day of month string (char [4..5])
  537. pbeVersion->byDay = (BYTE) atoi( lpszDate + 4 );
  538. // Get year of compilation date (char [7..10])
  539. pbeVersion->wYear = (WORD) atoi( lpszDate + 7 );
  540. memset( pbeVersion->zHomepage, 0x00, BE_MAX_HOMEPAGE );
  541. strcpy( pbeVersion->zHomepage, "http://www.mp3dev.org/" );
  542. }
  543. __declspec(dllexport) BE_ERR beEncodeChunk(HBE_STREAM hbeStream, DWORD nSamples,
  544. PSHORT pSamples, PBYTE pOutput, PDWORD pdwOutput)
  545. {
  546. // Encode it
  547. int dwSamples;
  548. int nOutputSamples = 0;
  549. lame_global_flags* gfp = (lame_global_flags*)hbeStream;
  550. dwSamples = nSamples / lame_get_num_channels( gfp );
  551. // old versions of lame_enc.dll required exactly 1152 samples
  552. // and worked even if nSamples accidently set to 2304
  553. // simulate this behavoir:
  554. if ( 1 == lame_get_num_channels( gfp ) && nSamples == 2304)
  555. {
  556. dwSamples/= 2;
  557. }
  558. if ( 1 == lame_get_num_channels( gfp ) )
  559. {
  560. nOutputSamples = lame_encode_buffer(gfp,pSamples,pSamples,dwSamples,pOutput,0);
  561. }
  562. else
  563. {
  564. nOutputSamples = lame_encode_buffer_interleaved(gfp,pSamples,dwSamples,pOutput,0);
  565. }
  566. if ( nOutputSamples < 0 )
  567. {
  568. *pdwOutput=0;
  569. return BE_ERR_BUFFER_TOO_SMALL;
  570. }
  571. else
  572. {
  573. *pdwOutput = (DWORD)nOutputSamples;
  574. }
  575. return BE_ERR_SUCCESSFUL;
  576. }
  577. // accept floating point audio samples, scaled to the range of a signed 16-bit
  578. // integer (within +/- 32768), in non-interleaved channels -- DSPguru, jd
  579. __declspec(dllexport) BE_ERR beEncodeChunkFloatS16NI(HBE_STREAM hbeStream, DWORD nSamples,
  580. PFLOAT buffer_l, PFLOAT buffer_r, PBYTE pOutput, PDWORD pdwOutput)
  581. {
  582. int nOutputSamples;
  583. lame_global_flags* gfp = (lame_global_flags*)hbeStream;
  584. nOutputSamples = lame_encode_buffer_float(gfp,buffer_l,buffer_r,nSamples,pOutput,0);
  585. if ( nOutputSamples >= 0 )
  586. {
  587. *pdwOutput = (DWORD) nOutputSamples;
  588. }
  589. else
  590. {
  591. *pdwOutput=0;
  592. return BE_ERR_BUFFER_TOO_SMALL;
  593. }
  594. return BE_ERR_SUCCESSFUL;
  595. }
  596. static int
  597. maybeSyncWord(FILE* fpStream)
  598. {
  599. unsigned char mp3_frame_header[4];
  600. size_t nbytes = fread(mp3_frame_header, 1, sizeof(mp3_frame_header), fpStream);
  601. if ( nbytes != sizeof(mp3_frame_header) ) {
  602. return -1;
  603. }
  604. if ( mp3_frame_header[0] != 0xffu ) {
  605. return -1; /* doesn't look like a sync word */
  606. }
  607. if ( (mp3_frame_header[1] & 0xE0u) != 0xE0u ) {
  608. return -1; /* doesn't look like a sync word */
  609. }
  610. return 0;
  611. }
  612. static int
  613. skipId3v2(FILE * fpStream, size_t lametag_frame_size)
  614. {
  615. size_t nbytes;
  616. size_t id3v2TagSize = 0;
  617. unsigned char id3v2Header[10];
  618. /* seek to the beginning of the stream */
  619. if (fseek(fpStream, 0, SEEK_SET) != 0) {
  620. return -2; /* not seekable, abort */
  621. }
  622. /* read 10 bytes in case there's an ID3 version 2 header here */
  623. nbytes = fread(id3v2Header, 1, sizeof(id3v2Header), fpStream);
  624. if (nbytes != sizeof(id3v2Header)) {
  625. return -3; /* not readable, maybe opened Write-Only */
  626. }
  627. /* does the stream begin with the ID3 version 2 file identifier? */
  628. if (!strncmp((char *) id3v2Header, "ID3", 3)) {
  629. /* the tag size (minus the 10-byte header) is encoded into four
  630. * bytes where the most significant bit is clear in each byte
  631. */
  632. id3v2TagSize = (((id3v2Header[6] & 0x7f) << 21)
  633. | ((id3v2Header[7] & 0x7f) << 14)
  634. | ((id3v2Header[8] & 0x7f) << 7)
  635. | (id3v2Header[9] & 0x7f))
  636. + sizeof id3v2Header;
  637. }
  638. /* Seek to the beginning of the audio stream */
  639. if ( fseek(fpStream, id3v2TagSize, SEEK_SET) != 0 ) {
  640. return -2;
  641. }
  642. if ( maybeSyncWord(fpStream) != 0) {
  643. return -1;
  644. }
  645. if ( fseek(fpStream, id3v2TagSize+lametag_frame_size, SEEK_SET) != 0 ) {
  646. return -2;
  647. }
  648. if ( maybeSyncWord(fpStream) != 0) {
  649. return -1;
  650. }
  651. /* OK, it seems we found our LAME-Tag/Xing frame again */
  652. /* Seek to the beginning of the audio stream */
  653. if ( fseek(fpStream, id3v2TagSize, SEEK_SET) != 0 ) {
  654. return -2;
  655. }
  656. return 0;
  657. }
  658. static BE_ERR
  659. updateLameTagFrame(lame_global_flags* gfp, FILE* fpStream)
  660. {
  661. size_t n = lame_get_lametag_frame( gfp, 0, 0 ); /* ask for bufer size */
  662. if ( n > 0 )
  663. {
  664. unsigned char* buffer = 0;
  665. size_t m = 1;
  666. if ( 0 != skipId3v2(fpStream, n) )
  667. {
  668. DispErr( "Error updating LAME-tag frame:\n\n"
  669. "can't locate old frame\n" );
  670. return BE_ERR_INVALID_FORMAT_PARAMETERS;
  671. }
  672. buffer = (unsigned char*)malloc( n );
  673. if ( buffer == 0 )
  674. {
  675. DispErr( "Error updating LAME-tag frame:\n\n"
  676. "can't allocate frame buffer\n" );
  677. return BE_ERR_INVALID_FORMAT_PARAMETERS;
  678. }
  679. /* Put it all to disk again */
  680. n = lame_get_lametag_frame( gfp, buffer, n );
  681. if ( n > 0 )
  682. {
  683. m = fwrite( buffer, n, 1, fpStream );
  684. }
  685. free( buffer );
  686. if ( m != 1 )
  687. {
  688. DispErr( "Error updating LAME-tag frame:\n\n"
  689. "couldn't write frame into file\n" );
  690. return BE_ERR_INVALID_FORMAT_PARAMETERS;
  691. }
  692. }
  693. return BE_ERR_SUCCESSFUL;
  694. }
  695. __declspec(dllexport) BE_ERR beWriteInfoTag( HBE_STREAM hbeStream,
  696. LPCSTR lpszFileName )
  697. {
  698. FILE* fpStream = NULL;
  699. BE_ERR beResult = BE_ERR_SUCCESSFUL;
  700. lame_global_flags* gfp = (lame_global_flags*)hbeStream;
  701. if ( NULL != gfp )
  702. {
  703. // Do we have to write the VBR tag?
  704. if ( lame_get_bWriteVbrTag( gfp ) )
  705. {
  706. // Try to open the file
  707. fpStream=fopen( lpszFileName, "rb+" );
  708. // Check file open result
  709. if ( NULL == fpStream )
  710. {
  711. beResult = BE_ERR_INVALID_FORMAT_PARAMETERS;
  712. DispErr( "Error updating LAME-tag frame:\n\n"
  713. "can't open file for reading and writing\n" );
  714. }
  715. else
  716. {
  717. beResult = updateLameTagFrame( gfp, fpStream );
  718. // Close the file stream
  719. fclose( fpStream );
  720. }
  721. }
  722. // clean up of allocated memory
  723. lame_close( gfp );
  724. }
  725. else
  726. {
  727. beResult = BE_ERR_INVALID_FORMAT_PARAMETERS;
  728. }
  729. // return result
  730. return beResult;
  731. }
  732. // for backwards compatiblity
  733. __declspec(dllexport) BE_ERR beWriteVBRHeader(LPCSTR lpszFileName)
  734. {
  735. return beWriteInfoTag( (HBE_STREAM)gfp_save, lpszFileName );
  736. }
  737. BOOL APIENTRY DllMain(HANDLE hModule,
  738. DWORD ul_reason_for_call,
  739. LPVOID lpReserved)
  740. {
  741. (void) lpReserved;
  742. gs_hModule = (HMODULE) hModule;
  743. switch( ul_reason_for_call )
  744. {
  745. case DLL_PROCESS_ATTACH:
  746. // Enable debug/logging?
  747. gs_bLogFile = GetPrivateProfileIntA("Debug","WriteLogFile",gs_bLogFile,"lame_enc.ini");
  748. break;
  749. case DLL_THREAD_ATTACH:
  750. break;
  751. case DLL_THREAD_DETACH:
  752. break;
  753. case DLL_PROCESS_DETACH:
  754. break;
  755. }
  756. return TRUE;
  757. }
  758. static void dump_config( lame_global_flags* gfp )
  759. {
  760. DebugPrintf("\n\nLame_enc configuration options:\n");
  761. DebugPrintf("==========================================================\n");
  762. DebugPrintf("version =%d\n",lame_get_version( gfp ) );
  763. DebugPrintf("Layer =3\n");
  764. DebugPrintf("mode =");
  765. switch ( lame_get_mode( gfp ) )
  766. {
  767. case STEREO: DebugPrintf( "Stereo\n" ); break;
  768. case JOINT_STEREO: DebugPrintf( "Joint-Stereo\n" ); break;
  769. case DUAL_CHANNEL: DebugPrintf( "Forced Stereo\n" ); break;
  770. case MONO: DebugPrintf( "Mono\n" ); break;
  771. case NOT_SET: /* FALLTROUGH */
  772. default: DebugPrintf( "Error (unknown)\n" ); break;
  773. }
  774. DebugPrintf("Input sample rate =%.1f kHz\n", lame_get_in_samplerate( gfp ) /1000.0 );
  775. DebugPrintf("Output sample rate =%.1f kHz\n", lame_get_out_samplerate( gfp ) /1000.0 );
  776. DebugPrintf("bitrate =%d kbps\n", lame_get_brate( gfp ) );
  777. DebugPrintf("Quality Setting =%d\n", lame_get_quality( gfp ) );
  778. DebugPrintf("Low pass frequency =%d\n", lame_get_lowpassfreq( gfp ) );
  779. DebugPrintf("Low pass width =%d\n", lame_get_lowpasswidth( gfp ) );
  780. DebugPrintf("High pass frequency =%d\n", lame_get_highpassfreq( gfp ) );
  781. DebugPrintf("High pass width =%d\n", lame_get_highpasswidth( gfp ) );
  782. DebugPrintf("No short blocks =%d\n", lame_get_no_short_blocks( gfp ) );
  783. DebugPrintf("Force short blocks =%d\n", lame_get_force_short_blocks( gfp ) );
  784. DebugPrintf("de-emphasis =%d\n", lame_get_emphasis( gfp ) );
  785. DebugPrintf("private flag =%d\n", lame_get_extension( gfp ) );
  786. DebugPrintf("copyright flag =%d\n", lame_get_copyright( gfp ) );
  787. DebugPrintf("original flag =%d\n", lame_get_original( gfp ) );
  788. DebugPrintf("CRC =%s\n", lame_get_error_protection( gfp ) ? "on" : "off" );
  789. DebugPrintf("Fast mode =%s\n", ( lame_get_quality( gfp ) )? "enabled" : "disabled" );
  790. DebugPrintf("Force mid/side stereo =%s\n", ( lame_get_force_ms( gfp ) )?"enabled":"disabled" );
  791. DebugPrintf("Disable Reservoir =%d\n", lame_get_disable_reservoir( gfp ) );
  792. DebugPrintf("Allow diff-short =%d\n", lame_get_allow_diff_short( gfp ) );
  793. DebugPrintf("Interchannel masking =%f\n", lame_get_interChRatio( gfp ) );
  794. DebugPrintf("Strict ISO Encoding =%s\n", ( lame_get_strict_ISO( gfp ) ) ?"Yes":"No");
  795. DebugPrintf("Scale =%5.2f\n", lame_get_scale( gfp ) );
  796. DebugPrintf("VBR =%s, VBR_q =%d, VBR method =",
  797. ( lame_get_VBR( gfp ) !=vbr_off ) ? "enabled": "disabled",
  798. lame_get_VBR_q( gfp ) );
  799. switch ( lame_get_VBR( gfp ) )
  800. {
  801. case vbr_off: DebugPrintf( "vbr_off\n" ); break;
  802. case vbr_mt : DebugPrintf( "vbr_mt \n" ); break;
  803. case vbr_rh : DebugPrintf( "vbr_rh \n" ); break;
  804. case vbr_mtrh: DebugPrintf( "vbr_mtrh \n" ); break;
  805. case vbr_abr:
  806. DebugPrintf( "vbr_abr (average bitrate %d kbps)\n", lame_get_VBR_mean_bitrate_kbps( gfp ) );
  807. break;
  808. default:
  809. DebugPrintf("error, unknown VBR setting\n");
  810. break;
  811. }
  812. DebugPrintf("Vbr Min bitrate =%d kbps\n", lame_get_VBR_min_bitrate_kbps( gfp ) );
  813. DebugPrintf("Vbr Max bitrate =%d kbps\n", lame_get_VBR_max_bitrate_kbps( gfp ) );
  814. DebugPrintf("Write VBR Header =%s\n", ( lame_get_bWriteVbrTag( gfp ) ) ?"Yes":"No");
  815. DebugPrintf("VBR Hard min =%d\n", lame_get_VBR_hard_min( gfp ) );
  816. DebugPrintf("ATH Only =%d\n", lame_get_ATHonly( gfp ) );
  817. DebugPrintf("ATH short =%d\n", lame_get_ATHshort( gfp ) );
  818. DebugPrintf("ATH no =%d\n", lame_get_noATH( gfp ) );
  819. DebugPrintf("ATH type =%d\n", lame_get_ATHtype( gfp ) );
  820. DebugPrintf("ATH lower =%f\n", lame_get_ATHlower( gfp ) );
  821. DebugPrintf("ATH aa =%d\n", lame_get_athaa_type( gfp ) );
  822. //DebugPrintf("ATH aa loudapprox =%d\n", lame_get_athaa_loudapprox( gfp ) );
  823. DebugPrintf("ATH aa sensitivity =%f\n", lame_get_athaa_sensitivity( gfp ) );
  824. DebugPrintf("Experimental nspsytune =%d\n", lame_get_exp_nspsytune( gfp ) );
  825. DebugPrintf("Experimental X =%d\n", lame_get_experimentalX( gfp ) );
  826. DebugPrintf("Experimental Y =%d\n", lame_get_experimentalY( gfp ) );
  827. DebugPrintf("Experimental Z =%d\n", lame_get_experimentalZ( gfp ) );
  828. }
  829. static void DispErr(char const* strErr)
  830. {
  831. MessageBoxA(NULL,strErr,"LAME_ENC.DLL",MB_OK|MB_ICONHAND);
  832. }
  833. #ifdef __cplusplus
  834. }
  835. #endif