| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028 |
- /*
- * Blade DLL Interface for LAME.
- *
- * Copyright (c) 1999 - 2002 A.L. Faber
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
- #include <windows.h>
- #include <Windef.h>
- #include "BladeMP3EncDLL.h"
- #include <assert.h>
- #include <stdio.h>
- #include <lame.h>
- #ifdef __cplusplus
- extern "C" {
- #endif
- #define Min(A, B) ((A) < (B) ? (A) : (B))
- #define Max(A, B) ((A) > (B) ? (A) : (B))
- #define _RELEASEDEBUG 0
- // lame_enc DLL version number
- const BYTE MAJORVERSION = 1;
- const BYTE MINORVERSION = 32;
- // Local variables
- static DWORD dwSampleBufferSize=0;
- static HMODULE gs_hModule=NULL;
- static BOOL gs_bLogFile=FALSE;
- static lame_global_flags* gfp_save = NULL;
- // Local function prototypes
- static void dump_config( lame_global_flags* gfp );
- static void DebugPrintf( const char* pzFormat, ... );
- static void DispErr( char const* strErr );
- static void PresetOptions( lame_global_flags *gfp, LONG myPreset );
- static void DebugPrintf(const char* pzFormat, ...)
- {
- char szBuffer[1024]={'\0',};
- char szFileName[MAX_PATH+1]={'\0',};
- va_list ap;
- // Get the full module (DLL) file name
- GetModuleFileNameA( gs_hModule,
- szFileName,
- sizeof( szFileName ) );
- // change file name extention
- szFileName[ strlen(szFileName) - 3 ] = 't';
- szFileName[ strlen(szFileName) - 2 ] = 'x';
- szFileName[ strlen(szFileName) - 1 ] = 't';
- // start at beginning of the list
- va_start(ap, pzFormat);
- // copy it to the string buffer
- _vsnprintf(szBuffer, sizeof(szBuffer), pzFormat, ap);
- // log it to the file?
- if ( gs_bLogFile )
- {
- FILE* fp = NULL;
- // try to open the log file
- fp=fopen( szFileName, "a+" );
- // check file open result
- if (fp)
- {
- // write string to the file
- fputs(szBuffer,fp);
- // close the file
- fclose(fp);
- }
- }
- #if defined _DEBUG || defined _RELEASEDEBUG
- OutputDebugStringA( szBuffer );
- #endif
- va_end(ap);
- }
- static void PresetOptions( lame_global_flags *gfp, LONG myPreset )
- {
- switch (myPreset)
- {
- /*-1*/case LQP_NOPRESET:
- break;
- /*0*/case LQP_NORMAL_QUALITY:
- /* lame_set_quality( gfp, 5 );*/
- break;
- /*1*/case LQP_LOW_QUALITY:
- lame_set_quality( gfp, 9 );
- break;
- /*2*/case LQP_HIGH_QUALITY:
- lame_set_quality( gfp, 2 );
- break;
- /*3*/case LQP_VOICE_QUALITY: // --voice flag for experimental voice mode
- lame_set_mode( gfp, MONO );
- lame_set_preset( gfp, 56);
- break;
- /*4*/case LQP_R3MIX: // --R3MIX
- lame_set_preset( gfp, R3MIX);
- break;
- /*5*/case LQP_VERYHIGH_QUALITY:
- lame_set_quality( gfp, 0 );
- break;
- /*6*/case LQP_STANDARD: // --PRESET STANDARD
- lame_set_preset( gfp, STANDARD);
- break;
- /*7*/case LQP_FAST_STANDARD: // --PRESET FAST STANDARD
- lame_set_preset( gfp, STANDARD_FAST);
- break;
- /*8*/case LQP_EXTREME: // --PRESET EXTREME
- lame_set_preset( gfp, EXTREME);
- break;
- /*9*/case LQP_FAST_EXTREME: // --PRESET FAST EXTREME:
- lame_set_preset( gfp, EXTREME_FAST);
- break;
- /*10*/case LQP_INSANE: // --PRESET INSANE
- lame_set_preset( gfp, INSANE);
- break;
- /*11*/case LQP_ABR: // --PRESET ABR
- // handled in beInitStream
- break;
- /*12*/case LQP_CBR: // --PRESET CBR
- // handled in beInitStream
- break;
- /*13*/case LQP_MEDIUM: // --PRESET MEDIUM
- lame_set_preset( gfp, MEDIUM);
- break;
- /*14*/case LQP_FAST_MEDIUM: // --PRESET FAST MEDIUM
- lame_set_preset( gfp, MEDIUM_FAST);
- break;
- /*1000*/case LQP_PHONE:
- lame_set_mode( gfp, MONO );
- lame_set_preset( gfp, 16);
- break;
- /*2000*/case LQP_SW:
- lame_set_mode( gfp, MONO );
- lame_set_preset( gfp, 24);
- break;
- /*3000*/case LQP_AM:
- lame_set_mode( gfp, MONO );
- lame_set_preset( gfp, 40);
- break;
- /*4000*/case LQP_FM:
- lame_set_preset( gfp, 112);
- break;
- /*5000*/case LQP_VOICE:
- lame_set_mode( gfp, MONO );
- lame_set_preset( gfp, 56);
- break;
- /*6000*/case LQP_RADIO:
- lame_set_preset( gfp, 112);
- break;
- /*7000*/case LQP_TAPE:
- lame_set_preset( gfp, 112);
- break;
- /*8000*/case LQP_HIFI:
- lame_set_preset( gfp, 160);
- break;
- /*9000*/case LQP_CD:
- lame_set_preset( gfp, 192);
- break;
- /*10000*/case LQP_STUDIO:
- lame_set_preset( gfp, 256);
- break;
- }
- }
- __declspec(dllexport) BE_ERR beInitStream(PBE_CONFIG pbeConfig, PDWORD dwSamples, PDWORD dwBufferSize, PHBE_STREAM phbeStream)
- {
- int actual_bitrate;
- //2001-12-18
- BE_CONFIG lameConfig = { 0, };
- int nInitReturn = 0;
- lame_global_flags* gfp = NULL;
- // Init the global flags structure
- gfp = lame_init();
- *phbeStream = (HBE_STREAM)gfp;
- // clear out structure
- memset(&lameConfig,0x00,CURRENT_STRUCT_SIZE);
- // Check if this is a regular BLADE_ENCODER header
- if (pbeConfig->dwConfig!=BE_CONFIG_LAME)
- {
- int nCRC=pbeConfig->format.mp3.bCRC;
- int nVBR=(nCRC>>12)&0x0F;
- // Copy parameter from old Blade structure
- lameConfig.format.LHV1.dwSampleRate =pbeConfig->format.mp3.dwSampleRate;
- //for low bitrates, LAME will automatically downsample for better
- //sound quality. Forcing output samplerate = input samplerate is not a good idea
- //unless the user specifically requests it:
- //lameConfig.format.LHV1.dwReSampleRate=pbeConfig->format.mp3.dwSampleRate;
- lameConfig.format.LHV1.nMode =(pbeConfig->format.mp3.byMode&0x0F);
- lameConfig.format.LHV1.dwBitrate =pbeConfig->format.mp3.wBitrate;
- lameConfig.format.LHV1.bPrivate =pbeConfig->format.mp3.bPrivate;
- lameConfig.format.LHV1.bOriginal =pbeConfig->format.mp3.bOriginal;
- lameConfig.format.LHV1.bCRC =nCRC&0x01;
- lameConfig.format.LHV1.bCopyright =pbeConfig->format.mp3.bCopyright;
- // Fill out the unknowns
- lameConfig.format.LHV1.dwStructSize=CURRENT_STRUCT_SIZE;
- lameConfig.format.LHV1.dwStructVersion=CURRENT_STRUCT_VERSION;
- // Get VBR setting from fourth nibble
- if ( nVBR>0 )
- {
- lameConfig.format.LHV1.bWriteVBRHeader = TRUE;
- lameConfig.format.LHV1.bEnableVBR = TRUE;
- lameConfig.format.LHV1.nVBRQuality = nVBR-1;
- }
- // Get Quality from third nibble
- lameConfig.format.LHV1.nPreset=((nCRC>>8)&0x0F);
- }
- else
- {
- // Copy the parameters
- memcpy(&lameConfig,pbeConfig,pbeConfig->format.LHV1.dwStructSize);
- }
- // --------------- Set arguments to LAME encoder -------------------------
- // Set input sample frequency
- lame_set_in_samplerate( gfp, lameConfig.format.LHV1.dwSampleRate );
- // disable INFO/VBR tag by default.
- // if this tag is used, the calling program must call beWriteVBRTag()
- // after encoding. But the original DLL documentation does not
- // require the
- // app to call beWriteVBRTag() unless they have specifically
- // set LHV1.bWriteVBRHeader=TRUE. Thus the default setting should
- // be disabled.
- lame_set_bWriteVbrTag( gfp, 0 );
- //2001-12-18 Dibrom's ABR preset stuff
- if(lameConfig.format.LHV1.nPreset == LQP_ABR) // --ALT-PRESET ABR
- {
- actual_bitrate = lameConfig.format.LHV1.dwVbrAbr_bps / 1000;
- // limit range
- if( actual_bitrate > 320)
- {
- actual_bitrate = 320;
- }
- if( actual_bitrate < 8 )
- {
- actual_bitrate = 8;
- }
- lame_set_preset( gfp, actual_bitrate );
- }
- // end Dibrom's ABR preset 2001-12-18 ****** START OF CBR
- if(lameConfig.format.LHV1.nPreset == LQP_CBR) // --ALT-PRESET CBR
- {
- actual_bitrate = lameConfig.format.LHV1.dwBitrate;
- lame_set_preset(gfp, actual_bitrate);
- lame_set_VBR(gfp, vbr_off);
- }
- // end Dibrom's CBR preset 2001-12-18
- // The following settings only used when preset is not one of the LAME QUALITY Presets
- if ( (int)lameConfig.format.LHV1.nPreset < (int) LQP_STANDARD )
- {
- switch ( lameConfig.format.LHV1.nMode )
- {
- case BE_MP3_MODE_STEREO:
- lame_set_mode( gfp, STEREO );
- lame_set_num_channels( gfp, 2 );
- break;
- case BE_MP3_MODE_JSTEREO:
- lame_set_mode( gfp, JOINT_STEREO );
- //lame_set_force_ms( gfp, bForceMS ); // no check box to force this?
- lame_set_num_channels( gfp, 2 );
- break;
- case BE_MP3_MODE_MONO:
- lame_set_mode( gfp, MONO );
- lame_set_num_channels( gfp, 1 );
- break;
- case BE_MP3_MODE_DUALCHANNEL:
- lame_set_mode( gfp, DUAL_CHANNEL );
- lame_set_num_channels( gfp, 2 );
- break;
- default:
- {
- DebugPrintf("Invalid lameConfig.format.LHV1.nMode, value is %d\n",lameConfig.format.LHV1.nMode);
- return BE_ERR_INVALID_FORMAT_PARAMETERS;
- }
- }
- if ( lameConfig.format.LHV1.bEnableVBR )
- {
- /* set VBR quality */
- lame_set_VBR_q( gfp, lameConfig.format.LHV1.nVBRQuality );
- /* select proper VBR method */
- switch ( lameConfig.format.LHV1.nVbrMethod)
- {
- case VBR_METHOD_NONE:
- lame_set_VBR( gfp, vbr_off );
- break;
- case VBR_METHOD_DEFAULT:
- lame_set_VBR( gfp, vbr_default );
- break;
- case VBR_METHOD_OLD:
- lame_set_VBR( gfp, vbr_rh );
- break;
- case VBR_METHOD_MTRH:
- case VBR_METHOD_NEW:
- /*
- * the --vbr-mtrh commandline switch is obsolete.
- * now --vbr-mtrh is known as --vbr-new
- */
- lame_set_VBR( gfp, vbr_mtrh );
- break;
- case VBR_METHOD_ABR:
- lame_set_VBR( gfp, vbr_abr );
- break;
- default:
- /* unsupported VBR method */
- assert( FALSE );
- }
- }
- else
- {
- /* use CBR encoding method, so turn off VBR */
- lame_set_VBR( gfp, vbr_off );
- }
- /* Set bitrate. (CDex users always specify bitrate=Min bitrate when using VBR) */
- lame_set_brate( gfp, lameConfig.format.LHV1.dwBitrate );
- /* check if we have to use ABR, in order to backwards compatible, this
- * condition should still be checked indepedent of the nVbrMethod method
- */
- if (lameConfig.format.LHV1.dwVbrAbr_bps > 0 )
- {
- /* set VBR method to ABR */
- lame_set_VBR( gfp, vbr_abr );
- /* calculate to kbps, round to nearest kbps */
- lame_set_VBR_mean_bitrate_kbps( gfp, ( lameConfig.format.LHV1.dwVbrAbr_bps + 500 ) / 1000 );
- /* limit range */
- if( lame_get_VBR_mean_bitrate_kbps( gfp ) > 320)
- {
- lame_set_VBR_mean_bitrate_kbps( gfp, 320 );
- }
- if( lame_get_VBR_mean_bitrate_kbps( gfp ) < 8 )
- {
- lame_set_VBR_mean_bitrate_kbps( gfp, 8 );
- }
- }
- }
- // First set all the preset options
- if ( LQP_NOPRESET != lameConfig.format.LHV1.nPreset )
- {
- PresetOptions( gfp, lameConfig.format.LHV1.nPreset );
- }
- // Set frequency resampling rate, if specified
- if ( lameConfig.format.LHV1.dwReSampleRate > 0 )
- {
- lame_set_out_samplerate( gfp, lameConfig.format.LHV1.dwReSampleRate );
- }
- switch ( lameConfig.format.LHV1.nMode )
- {
- case BE_MP3_MODE_MONO:
- lame_set_mode( gfp, MONO );
- lame_set_num_channels( gfp, 1 );
- break;
- default:
- break;
- }
- // Use strict ISO encoding?
- lame_set_strict_ISO( gfp, ( lameConfig.format.LHV1.bStrictIso ) ? 1 : 0 );
- // Set copyright flag?
- if ( lameConfig.format.LHV1.bCopyright )
- {
- lame_set_copyright( gfp, 1 );
- }
- // Do we have to tag it as non original
- if ( !lameConfig.format.LHV1.bOriginal )
- {
- lame_set_original( gfp, 0 );
- }
- else
- {
- lame_set_original( gfp, 1 );
- }
- // Add CRC?
- if ( lameConfig.format.LHV1.bCRC )
- {
- lame_set_error_protection( gfp, 1 );
- }
- else
- {
- lame_set_error_protection( gfp, 0 );
- }
- // Set private bit?
- if ( lameConfig.format.LHV1.bPrivate )
- {
- lame_set_extension( gfp, 1 );
- }
- else
- {
- lame_set_extension( gfp, 0 );
- }
- // Set VBR min bitrate, if specified
- if ( lameConfig.format.LHV1.dwBitrate > 0 )
- {
- lame_set_VBR_min_bitrate_kbps( gfp, lameConfig.format.LHV1.dwBitrate );
- }
- // Set Maxbitrate, if specified
- if ( lameConfig.format.LHV1.dwMaxBitrate > 0 )
- {
- lame_set_VBR_max_bitrate_kbps( gfp, lameConfig.format.LHV1.dwMaxBitrate );
- }
- // Set bit resovoir option
- if ( lameConfig.format.LHV1.bNoRes )
- {
- lame_set_disable_reservoir( gfp,1 );
- }
- // check if the VBR tag is required
- if ( lameConfig.format.LHV1.bWriteVBRHeader )
- {
- lame_set_bWriteVbrTag( gfp, 1 );
- }
- else
- {
- lame_set_bWriteVbrTag( gfp, 0 );
- }
- // Override Quality setting, use HIGHBYTE = NOT LOWBYTE to be backwards compatible
- if ( ( lameConfig.format.LHV1.nQuality & 0xFF ) ==
- ((~( lameConfig.format.LHV1.nQuality >> 8 )) & 0xFF) )
- {
- lame_set_quality( gfp, lameConfig.format.LHV1.nQuality & 0xFF );
- }
- if ( 0 != ( nInitReturn = lame_init_params( gfp ) ) )
- {
- return nInitReturn;
- }
- //LAME encoding call will accept any number of samples.
- if ( 0 == lame_get_version( gfp ) )
- {
- // For MPEG-II, only 576 samples per frame per channel
- *dwSamples= 576 * lame_get_num_channels( gfp );
- }
- else
- {
- // For MPEG-I, 1152 samples per frame per channel
- *dwSamples= 1152 * lame_get_num_channels( gfp );
- }
- // Set the input sample buffer size, so we know what we can expect
- dwSampleBufferSize = *dwSamples;
- // Set MP3 buffer size, conservative estimate
- *dwBufferSize=(DWORD)( 1.25 * ( *dwSamples / lame_get_num_channels( gfp ) ) + 7200 );
- // For debugging purposes
- dump_config( gfp );
- // Everything went OK, thus return SUCCESSFUL
- return BE_ERR_SUCCESSFUL;
- }
- __declspec(dllexport) BE_ERR beFlushNoGap(HBE_STREAM hbeStream, PBYTE pOutput, PDWORD pdwOutput)
- {
- int nOutputSamples = 0;
- lame_global_flags* gfp = (lame_global_flags*)hbeStream;
- // Init the global flags structure
- nOutputSamples = lame_encode_flush_nogap( gfp, pOutput, LAME_MAXMP3BUFFER );
- if ( nOutputSamples < 0 )
- {
- *pdwOutput = 0;
- return BE_ERR_BUFFER_TOO_SMALL;
- }
- else
- {
- *pdwOutput = nOutputSamples;
- }
- return BE_ERR_SUCCESSFUL;
- }
- __declspec(dllexport) BE_ERR beDeinitStream(HBE_STREAM hbeStream, PBYTE pOutput, PDWORD pdwOutput)
- {
- int nOutputSamples = 0;
- lame_global_flags* gfp = (lame_global_flags*)hbeStream;
- nOutputSamples = lame_encode_flush( gfp, pOutput, 0 );
- if ( nOutputSamples < 0 )
- {
- *pdwOutput = 0;
- return BE_ERR_BUFFER_TOO_SMALL;
- }
- else
- {
- *pdwOutput = nOutputSamples;
- }
- return BE_ERR_SUCCESSFUL;
- }
- __declspec(dllexport) BE_ERR beCloseStream(HBE_STREAM hbeStream)
- {
- lame_global_flags* gfp = (lame_global_flags*)hbeStream;
- // lame will be close in VbrWriteTag function
- if ( !lame_get_bWriteVbrTag( gfp ) )
- {
- // clean up of allocated memory
- lame_close( gfp );
- gfp_save = NULL;
- }
- else
- {
- gfp_save = (lame_global_flags*)hbeStream;
- }
- // DeInit encoder
- return BE_ERR_SUCCESSFUL;
- }
- __declspec(dllexport) VOID beVersion(PBE_VERSION pbeVersion)
- {
- // DLL Release date
- char lpszDate[20] = { '\0', };
- char lpszTemp[5] = { '\0', };
- lame_version_t lv = { 0, };
- // Set DLL interface version
- pbeVersion->byDLLMajorVersion=MAJORVERSION;
- pbeVersion->byDLLMinorVersion=MINORVERSION;
- get_lame_version_numerical ( &lv );
- // Set Engine version number (Same as Lame version)
- pbeVersion->byMajorVersion = (BYTE)lv.major;
- pbeVersion->byMinorVersion = (BYTE)lv.minor;
- pbeVersion->byAlphaLevel = (BYTE)lv.alpha;
- pbeVersion->byBetaLevel = (BYTE)lv.beta;
- #ifdef MMX_choose_table
- pbeVersion->byMMXEnabled=1;
- #else
- pbeVersion->byMMXEnabled=0;
- #endif
- memset( pbeVersion->btReserved, 0, sizeof( pbeVersion->btReserved ) );
- // Get compilation date
- strcpy(lpszDate,__DATE__);
- // Get the first three character, which is the month
- strncpy(lpszTemp,lpszDate,3);
- lpszTemp[3] = '\0';
- pbeVersion->byMonth=1;
- // Set month
- if (strcmp(lpszTemp,"Jan")==0) pbeVersion->byMonth = 1;
- if (strcmp(lpszTemp,"Feb")==0) pbeVersion->byMonth = 2;
- if (strcmp(lpszTemp,"Mar")==0) pbeVersion->byMonth = 3;
- if (strcmp(lpszTemp,"Apr")==0) pbeVersion->byMonth = 4;
- if (strcmp(lpszTemp,"May")==0) pbeVersion->byMonth = 5;
- if (strcmp(lpszTemp,"Jun")==0) pbeVersion->byMonth = 6;
- if (strcmp(lpszTemp,"Jul")==0) pbeVersion->byMonth = 7;
- if (strcmp(lpszTemp,"Aug")==0) pbeVersion->byMonth = 8;
- if (strcmp(lpszTemp,"Sep")==0) pbeVersion->byMonth = 9;
- if (strcmp(lpszTemp,"Oct")==0) pbeVersion->byMonth = 10;
- if (strcmp(lpszTemp,"Nov")==0) pbeVersion->byMonth = 11;
- if (strcmp(lpszTemp,"Dec")==0) pbeVersion->byMonth = 12;
- // Get day of month string (char [4..5])
- pbeVersion->byDay = (BYTE) atoi( lpszDate + 4 );
- // Get year of compilation date (char [7..10])
- pbeVersion->wYear = (WORD) atoi( lpszDate + 7 );
- memset( pbeVersion->zHomepage, 0x00, BE_MAX_HOMEPAGE );
- strcpy( pbeVersion->zHomepage, "http://www.mp3dev.org/" );
- }
- __declspec(dllexport) BE_ERR beEncodeChunk(HBE_STREAM hbeStream, DWORD nSamples,
- PSHORT pSamples, PBYTE pOutput, PDWORD pdwOutput)
- {
- // Encode it
- int dwSamples;
- int nOutputSamples = 0;
- lame_global_flags* gfp = (lame_global_flags*)hbeStream;
- dwSamples = nSamples / lame_get_num_channels( gfp );
- // old versions of lame_enc.dll required exactly 1152 samples
- // and worked even if nSamples accidently set to 2304
- // simulate this behavoir:
- if ( 1 == lame_get_num_channels( gfp ) && nSamples == 2304)
- {
- dwSamples/= 2;
- }
- if ( 1 == lame_get_num_channels( gfp ) )
- {
- nOutputSamples = lame_encode_buffer(gfp,pSamples,pSamples,dwSamples,pOutput,0);
- }
- else
- {
- nOutputSamples = lame_encode_buffer_interleaved(gfp,pSamples,dwSamples,pOutput,0);
- }
- if ( nOutputSamples < 0 )
- {
- *pdwOutput=0;
- return BE_ERR_BUFFER_TOO_SMALL;
- }
- else
- {
- *pdwOutput = (DWORD)nOutputSamples;
- }
- return BE_ERR_SUCCESSFUL;
- }
- // accept floating point audio samples, scaled to the range of a signed 16-bit
- // integer (within +/- 32768), in non-interleaved channels -- DSPguru, jd
- __declspec(dllexport) BE_ERR beEncodeChunkFloatS16NI(HBE_STREAM hbeStream, DWORD nSamples,
- PFLOAT buffer_l, PFLOAT buffer_r, PBYTE pOutput, PDWORD pdwOutput)
- {
- int nOutputSamples;
- lame_global_flags* gfp = (lame_global_flags*)hbeStream;
- nOutputSamples = lame_encode_buffer_float(gfp,buffer_l,buffer_r,nSamples,pOutput,0);
- if ( nOutputSamples >= 0 )
- {
- *pdwOutput = (DWORD) nOutputSamples;
- }
- else
- {
- *pdwOutput=0;
- return BE_ERR_BUFFER_TOO_SMALL;
- }
- return BE_ERR_SUCCESSFUL;
- }
- static int
- maybeSyncWord(FILE* fpStream)
- {
- unsigned char mp3_frame_header[4];
- size_t nbytes = fread(mp3_frame_header, 1, sizeof(mp3_frame_header), fpStream);
- if ( nbytes != sizeof(mp3_frame_header) ) {
- return -1;
- }
- if ( mp3_frame_header[0] != 0xffu ) {
- return -1; /* doesn't look like a sync word */
- }
- if ( (mp3_frame_header[1] & 0xE0u) != 0xE0u ) {
- return -1; /* doesn't look like a sync word */
- }
- return 0;
- }
- static int
- skipId3v2(FILE * fpStream, size_t lametag_frame_size)
- {
- size_t nbytes;
- size_t id3v2TagSize = 0;
- unsigned char id3v2Header[10];
- /* seek to the beginning of the stream */
- if (fseek(fpStream, 0, SEEK_SET) != 0) {
- return -2; /* not seekable, abort */
- }
- /* read 10 bytes in case there's an ID3 version 2 header here */
- nbytes = fread(id3v2Header, 1, sizeof(id3v2Header), fpStream);
- if (nbytes != sizeof(id3v2Header)) {
- return -3; /* not readable, maybe opened Write-Only */
- }
- /* does the stream begin with the ID3 version 2 file identifier? */
- if (!strncmp((char *) id3v2Header, "ID3", 3)) {
- /* the tag size (minus the 10-byte header) is encoded into four
- * bytes where the most significant bit is clear in each byte
- */
- id3v2TagSize = (((id3v2Header[6] & 0x7f) << 21)
- | ((id3v2Header[7] & 0x7f) << 14)
- | ((id3v2Header[8] & 0x7f) << 7)
- | (id3v2Header[9] & 0x7f))
- + sizeof id3v2Header;
- }
- /* Seek to the beginning of the audio stream */
- if ( fseek(fpStream, id3v2TagSize, SEEK_SET) != 0 ) {
- return -2;
- }
- if ( maybeSyncWord(fpStream) != 0) {
- return -1;
- }
- if ( fseek(fpStream, id3v2TagSize+lametag_frame_size, SEEK_SET) != 0 ) {
- return -2;
- }
- if ( maybeSyncWord(fpStream) != 0) {
- return -1;
- }
- /* OK, it seems we found our LAME-Tag/Xing frame again */
- /* Seek to the beginning of the audio stream */
- if ( fseek(fpStream, id3v2TagSize, SEEK_SET) != 0 ) {
- return -2;
- }
- return 0;
- }
- static BE_ERR
- updateLameTagFrame(lame_global_flags* gfp, FILE* fpStream)
- {
- size_t n = lame_get_lametag_frame( gfp, 0, 0 ); /* ask for bufer size */
- if ( n > 0 )
- {
- unsigned char* buffer = 0;
- size_t m = 1;
- if ( 0 != skipId3v2(fpStream, n) )
- {
- DispErr( "Error updating LAME-tag frame:\n\n"
- "can't locate old frame\n" );
- return BE_ERR_INVALID_FORMAT_PARAMETERS;
- }
- buffer = (unsigned char*)malloc( n );
- if ( buffer == 0 )
- {
- DispErr( "Error updating LAME-tag frame:\n\n"
- "can't allocate frame buffer\n" );
- return BE_ERR_INVALID_FORMAT_PARAMETERS;
- }
- /* Put it all to disk again */
- n = lame_get_lametag_frame( gfp, buffer, n );
- if ( n > 0 )
- {
- m = fwrite( buffer, n, 1, fpStream );
- }
- free( buffer );
- if ( m != 1 )
- {
- DispErr( "Error updating LAME-tag frame:\n\n"
- "couldn't write frame into file\n" );
- return BE_ERR_INVALID_FORMAT_PARAMETERS;
- }
- }
- return BE_ERR_SUCCESSFUL;
- }
- __declspec(dllexport) BE_ERR beWriteInfoTag( HBE_STREAM hbeStream,
- LPCSTR lpszFileName )
- {
- FILE* fpStream = NULL;
- BE_ERR beResult = BE_ERR_SUCCESSFUL;
- lame_global_flags* gfp = (lame_global_flags*)hbeStream;
- if ( NULL != gfp )
- {
- // Do we have to write the VBR tag?
- if ( lame_get_bWriteVbrTag( gfp ) )
- {
- // Try to open the file
- fpStream=fopen( lpszFileName, "rb+" );
- // Check file open result
- if ( NULL == fpStream )
- {
- beResult = BE_ERR_INVALID_FORMAT_PARAMETERS;
- DispErr( "Error updating LAME-tag frame:\n\n"
- "can't open file for reading and writing\n" );
- }
- else
- {
- beResult = updateLameTagFrame( gfp, fpStream );
- // Close the file stream
- fclose( fpStream );
- }
- }
- // clean up of allocated memory
- lame_close( gfp );
- }
- else
- {
- beResult = BE_ERR_INVALID_FORMAT_PARAMETERS;
- }
- // return result
- return beResult;
- }
- // for backwards compatiblity
- __declspec(dllexport) BE_ERR beWriteVBRHeader(LPCSTR lpszFileName)
- {
- return beWriteInfoTag( (HBE_STREAM)gfp_save, lpszFileName );
- }
- BOOL APIENTRY DllMain(HANDLE hModule,
- DWORD ul_reason_for_call,
- LPVOID lpReserved)
- {
- (void) lpReserved;
- gs_hModule = (HMODULE) hModule;
- switch( ul_reason_for_call )
- {
- case DLL_PROCESS_ATTACH:
- // Enable debug/logging?
- gs_bLogFile = GetPrivateProfileIntA("Debug","WriteLogFile",gs_bLogFile,"lame_enc.ini");
- break;
- case DLL_THREAD_ATTACH:
- break;
- case DLL_THREAD_DETACH:
- break;
- case DLL_PROCESS_DETACH:
- break;
- }
- return TRUE;
- }
- static void dump_config( lame_global_flags* gfp )
- {
- DebugPrintf("\n\nLame_enc configuration options:\n");
- DebugPrintf("==========================================================\n");
- DebugPrintf("version =%d\n",lame_get_version( gfp ) );
- DebugPrintf("Layer =3\n");
- DebugPrintf("mode =");
- switch ( lame_get_mode( gfp ) )
- {
- case STEREO: DebugPrintf( "Stereo\n" ); break;
- case JOINT_STEREO: DebugPrintf( "Joint-Stereo\n" ); break;
- case DUAL_CHANNEL: DebugPrintf( "Forced Stereo\n" ); break;
- case MONO: DebugPrintf( "Mono\n" ); break;
- case NOT_SET: /* FALLTROUGH */
- default: DebugPrintf( "Error (unknown)\n" ); break;
- }
- DebugPrintf("Input sample rate =%.1f kHz\n", lame_get_in_samplerate( gfp ) /1000.0 );
- DebugPrintf("Output sample rate =%.1f kHz\n", lame_get_out_samplerate( gfp ) /1000.0 );
- DebugPrintf("bitrate =%d kbps\n", lame_get_brate( gfp ) );
- DebugPrintf("Quality Setting =%d\n", lame_get_quality( gfp ) );
- DebugPrintf("Low pass frequency =%d\n", lame_get_lowpassfreq( gfp ) );
- DebugPrintf("Low pass width =%d\n", lame_get_lowpasswidth( gfp ) );
- DebugPrintf("High pass frequency =%d\n", lame_get_highpassfreq( gfp ) );
- DebugPrintf("High pass width =%d\n", lame_get_highpasswidth( gfp ) );
- DebugPrintf("No short blocks =%d\n", lame_get_no_short_blocks( gfp ) );
- DebugPrintf("Force short blocks =%d\n", lame_get_force_short_blocks( gfp ) );
- DebugPrintf("de-emphasis =%d\n", lame_get_emphasis( gfp ) );
- DebugPrintf("private flag =%d\n", lame_get_extension( gfp ) );
- DebugPrintf("copyright flag =%d\n", lame_get_copyright( gfp ) );
- DebugPrintf("original flag =%d\n", lame_get_original( gfp ) );
- DebugPrintf("CRC =%s\n", lame_get_error_protection( gfp ) ? "on" : "off" );
- DebugPrintf("Fast mode =%s\n", ( lame_get_quality( gfp ) )? "enabled" : "disabled" );
- DebugPrintf("Force mid/side stereo =%s\n", ( lame_get_force_ms( gfp ) )?"enabled":"disabled" );
- DebugPrintf("Disable Reservoir =%d\n", lame_get_disable_reservoir( gfp ) );
- DebugPrintf("Allow diff-short =%d\n", lame_get_allow_diff_short( gfp ) );
- DebugPrintf("Interchannel masking =%f\n", lame_get_interChRatio( gfp ) );
- DebugPrintf("Strict ISO Encoding =%s\n", ( lame_get_strict_ISO( gfp ) ) ?"Yes":"No");
- DebugPrintf("Scale =%5.2f\n", lame_get_scale( gfp ) );
- DebugPrintf("VBR =%s, VBR_q =%d, VBR method =",
- ( lame_get_VBR( gfp ) !=vbr_off ) ? "enabled": "disabled",
- lame_get_VBR_q( gfp ) );
- switch ( lame_get_VBR( gfp ) )
- {
- case vbr_off: DebugPrintf( "vbr_off\n" ); break;
- case vbr_mt : DebugPrintf( "vbr_mt \n" ); break;
- case vbr_rh : DebugPrintf( "vbr_rh \n" ); break;
- case vbr_mtrh: DebugPrintf( "vbr_mtrh \n" ); break;
- case vbr_abr:
- DebugPrintf( "vbr_abr (average bitrate %d kbps)\n", lame_get_VBR_mean_bitrate_kbps( gfp ) );
- break;
- default:
- DebugPrintf("error, unknown VBR setting\n");
- break;
- }
- DebugPrintf("Vbr Min bitrate =%d kbps\n", lame_get_VBR_min_bitrate_kbps( gfp ) );
- DebugPrintf("Vbr Max bitrate =%d kbps\n", lame_get_VBR_max_bitrate_kbps( gfp ) );
- DebugPrintf("Write VBR Header =%s\n", ( lame_get_bWriteVbrTag( gfp ) ) ?"Yes":"No");
- DebugPrintf("VBR Hard min =%d\n", lame_get_VBR_hard_min( gfp ) );
- DebugPrintf("ATH Only =%d\n", lame_get_ATHonly( gfp ) );
- DebugPrintf("ATH short =%d\n", lame_get_ATHshort( gfp ) );
- DebugPrintf("ATH no =%d\n", lame_get_noATH( gfp ) );
- DebugPrintf("ATH type =%d\n", lame_get_ATHtype( gfp ) );
- DebugPrintf("ATH lower =%f\n", lame_get_ATHlower( gfp ) );
- DebugPrintf("ATH aa =%d\n", lame_get_athaa_type( gfp ) );
- //DebugPrintf("ATH aa loudapprox =%d\n", lame_get_athaa_loudapprox( gfp ) );
- DebugPrintf("ATH aa sensitivity =%f\n", lame_get_athaa_sensitivity( gfp ) );
- DebugPrintf("Experimental nspsytune =%d\n", lame_get_exp_nspsytune( gfp ) );
- DebugPrintf("Experimental X =%d\n", lame_get_experimentalX( gfp ) );
- DebugPrintf("Experimental Y =%d\n", lame_get_experimentalY( gfp ) );
- DebugPrintf("Experimental Z =%d\n", lame_get_experimentalZ( gfp ) );
- }
- static void DispErr(char const* strErr)
- {
- MessageBoxA(NULL,strErr,"LAME_ENC.DLL",MB_OK|MB_ICONHAND);
- }
- #ifdef __cplusplus
- }
- #endif
|