home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 24 / AACD 24.iso / AACD / Sound / LAME / WarpOS / src / Dll / BladeMP3EncDLL.c next >
Encoding:
C/C++ Source or Header  |  2001-06-12  |  18.2 KB  |  743 lines

  1. /*
  2.  *    Blade DLL Interface for LAME.
  3.  *
  4.  *    Copyright (c) 1999 - 2001 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 Lesser 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.  * Lesser General Public License for more details.
  15.  * 
  16.  * You should have received a copy of the GNU Lesser 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.  
  22. #include <windows.h>
  23. #include <Windef.h>
  24. #include "BladeMP3EncDLL.h"
  25. #include <assert.h>
  26.  
  27. // This DLL should be a wrapper around libmp3lame, and thus only need to 
  28. // include 'lame.h'.  However, the DLL provides better version information
  29. // that is currently available via libmp3lame and thus needs version.h
  30. // (is this still true as of 6/2001?).  Also, DLL has not been updated
  31. // to use the lame_set/get functions, and so still needs lame_global_flags.h
  32. // All of this is fine for the DLL (which is recompiled everytime LAME
  33. // changes, but you are writing your own wrapper to libmp3lame, dont
  34. // follow this example :-) 
  35. #include "lame.h"
  36. #include "lame_global_flags.h"
  37. #include "version.h"
  38.  
  39.  
  40. #define _RELEASEDEBUG 0
  41.  
  42. const int MAJORVERSION=1;
  43. const int MINORVERSION=22;
  44.  
  45.  
  46. // Local variables
  47. static DWORD                dwSampleBufferSize=0;
  48. static HANDLE                gs_hModule=NULL;
  49. static BOOL                    gs_bLogFile=FALSE;
  50. static lame_global_flags    gf;
  51.  
  52. // Local function prototypes
  53. static void dump_config( );
  54. static void DebugPrintf(const char* pzFormat, ...);
  55. static void DispErr(LPSTR strErr);
  56. static void PresetOptions(lame_global_flags *gfp,LONG myPreset);
  57.  
  58.  
  59. static void DebugPrintf(const char* pzFormat, ...)
  60. {
  61.     char    szBuffer[1024]={'\0',};
  62.     char    szFileName[MAX_PATH+1]={'\0',};
  63.     va_list ap;
  64.  
  65.     // Get the full module file name
  66.     GetModuleFileName(gs_hModule,szFileName,sizeof(szFileName));
  67.  
  68.     // change file name extention
  69.     szFileName[strlen(szFileName)-3]='t';
  70.     szFileName[strlen(szFileName)-2]='x';
  71.     szFileName[strlen(szFileName)-1]='t';
  72.  
  73.     // start at beginning of the list
  74.     va_start(ap, pzFormat);
  75.  
  76.     // copy it to the string buffer
  77.     _vsnprintf(szBuffer, sizeof(szBuffer), pzFormat, ap);
  78.  
  79.     // log it to the file?
  80.     if (gs_bLogFile) 
  81.     {    
  82.         FILE* fp = NULL;
  83.         
  84.         // try to open the log file
  85.         fp=fopen(szFileName, "a+");
  86.  
  87.         // check file open result
  88.         if (fp)
  89.         {
  90.             // write string to the file
  91.             fputs(szBuffer,fp);
  92.  
  93.             // close the file
  94.             fclose(fp);
  95.         }
  96.     }
  97.  
  98. #if defined _DEBUG || defined _RELEASEDEBUG
  99.     OutputDebugString(szBuffer);
  100. #endif
  101.  
  102.     va_end(ap);
  103. }
  104.  
  105.  
  106. static void PresetOptions( lame_global_flags *gfp, LONG myPreset )
  107. {
  108.     switch (myPreset)
  109.     {
  110.         case LQP_NOPRESET:
  111.         case LQP_NORMAL_QUALITY:
  112.             break;
  113.         break;
  114.         case LQP_LOW_QUALITY:
  115.             gf.quality=9;
  116.             break;
  117.         case LQP_HIGH_QUALITY:
  118.             gf.quality=2;
  119.             break;
  120.         case LQP_VOICE_QUALITY:        // --voice flag for experimental voice mode
  121.             gf.lowpassfreq=12000;
  122.             gf.VBR_max_bitrate_kbps=160;
  123.             gf.no_short_blocks=1;
  124.         break;
  125.         case LQP_R3MIX_QUALITY:
  126.             gf.VBR = vbr_rh; 
  127.             gf.VBR_q = 1;
  128.             gf.quality = 2;
  129.             gf.lowpassfreq = 19500;
  130.             gf.mode = JOINT_STEREO;
  131.             gf.ATHtype = 3 ;
  132.             gf.VBR_min_bitrate_kbps=112;
  133.         break;
  134.  
  135.  
  136.         case LQP_PHONE:
  137.             gfp->out_samplerate =  8000;
  138.             gfp->lowpassfreq = 3200;
  139.             gfp->lowpasswidth = 1000;
  140.             gfp->no_short_blocks = 1;
  141.             gfp->quality = 5;
  142.             gfp->mode = MONO; 
  143.             gfp->brate = 16; 
  144.             gfp->VBR_q = 6;
  145.             gfp->VBR_min_bitrate_kbps = 8;
  146.             gfp->VBR_max_bitrate_kbps = 56;
  147.         break;
  148.  
  149.         case LQP_SW:
  150.             gfp->out_samplerate =  11025;
  151.             gfp->lowpassfreq = 4800;
  152.             gfp->lowpasswidth = 500;
  153.             gfp->quality = 5;
  154.             gfp->mode = MONO; 
  155.             gfp->brate = 24; 
  156.             gfp->VBR_q = 5;
  157.             gfp->VBR_min_bitrate_kbps = 8;
  158.             gfp->VBR_max_bitrate_kbps = 64;
  159.         break;
  160.         case LQP_AM:
  161.             gfp->out_samplerate =  16000;
  162.             gfp->lowpassfreq = 7200;
  163.             gfp->lowpasswidth = 500;
  164.             gfp->quality = 5;
  165.             gfp->mode = MONO; 
  166.             gfp->brate = 32; 
  167.             gfp->VBR_q = 5;
  168.             gfp->VBR_min_bitrate_kbps = 16;
  169.             gfp->VBR_max_bitrate_kbps = 128;
  170.         break;
  171.         case LQP_FM:
  172.             gfp->out_samplerate = 22050; 
  173.             gfp->lowpassfreq = 9950;
  174.             gfp->lowpasswidth = 880;
  175.             gfp->quality = 5;
  176.             gfp->mode = JOINT_STEREO; 
  177.             gfp->brate = 64; 
  178.             gfp->VBR_q = 5;
  179.             gfp->VBR_min_bitrate_kbps = 24;
  180.             gfp->VBR_max_bitrate_kbps = 160;
  181.         break;
  182.         case LQP_VOICE:
  183.             gfp->out_samplerate = 32000; 
  184.             gfp->lowpassfreq = 12300;
  185.             gfp->lowpasswidth = 2000;
  186.             gfp->no_short_blocks = 1;
  187.             gfp->quality = 5;
  188.             gfp->mode = MONO; 
  189.             gfp->brate = 56; 
  190.             gfp->VBR_q = 4;
  191.             gfp->VBR_min_bitrate_kbps = 32;
  192.             gfp->VBR_max_bitrate_kbps = 128;
  193.         break;
  194.         case LQP_RADIO:
  195.             gfp->lowpassfreq = 15000;
  196.             gfp->lowpasswidth = 0;
  197.             gfp->quality = 5;
  198.             gfp->mode = JOINT_STEREO; 
  199.             gfp->brate = 112; 
  200.             gfp->VBR_q = 4;
  201.             gfp->VBR_min_bitrate_kbps = 64;
  202.             gfp->VBR_max_bitrate_kbps = 256;
  203.         break;
  204.         case LQP_TAPE:
  205.             gfp->lowpassfreq = 18500;
  206.             gfp->lowpasswidth = 2000;
  207.             gfp->quality = 5;
  208.             gfp->mode = JOINT_STEREO; 
  209.             gfp->brate = 128; 
  210.             gfp->VBR_q = 4;
  211.             gfp->VBR_min_bitrate_kbps = 96;
  212.             gfp->VBR_max_bitrate_kbps = 320;
  213.         break;
  214.         case LQP_HIFI:
  215.             gfp->lowpassfreq = 20240;
  216.             gfp->lowpasswidth = 2200;
  217.             gfp->quality = 2;
  218.             gfp->mode = JOINT_STEREO; 
  219.             gfp->brate = 160;            
  220.             gfp->VBR_q = 3;
  221.             gfp->VBR_min_bitrate_kbps = 112;
  222.             gfp->VBR_max_bitrate_kbps = 320;
  223.         break;
  224.         case LQP_CD:
  225.             gfp->lowpassfreq = -1;
  226.             gfp->highpassfreq = -1;
  227.             gfp->quality = 2;
  228.             gfp->mode = STEREO; 
  229.             gfp->brate = 192;  
  230.             gfp->VBR_q = 2;
  231.             gfp->VBR_min_bitrate_kbps = 128;
  232.             gfp->VBR_max_bitrate_kbps = 320;
  233.         break;
  234.         case LQP_STUDIO:
  235.             gfp->lowpassfreq = -1;
  236.             gfp->highpassfreq = -1;
  237.             gfp->quality = 2; 
  238.             gfp->mode = STEREO; 
  239.             gfp->brate = 256; 
  240.             gfp->VBR_q = 0;
  241.             gfp->VBR_min_bitrate_kbps = 160;
  242.             gfp->VBR_max_bitrate_kbps = 320;
  243.         break;
  244.     }
  245. }
  246.  
  247.  
  248. __declspec(dllexport) BE_ERR    beInitStream(PBE_CONFIG pbeConfig, PDWORD dwSamples, PDWORD dwBufferSize, PHBE_STREAM phbeStream)
  249. {
  250.     int            nDllArgC=0;
  251.     BE_CONFIG    lameConfig;
  252.  
  253.     // Init the global flags structure
  254.     lame_init_old(&gf);
  255.  
  256.     // clear out structure
  257.     memset(&lameConfig,0x00,CURRENT_STRUCT_SIZE);
  258.  
  259.     // Check if this is a regular BLADE_ENCODER header
  260.     if (pbeConfig->dwConfig!=BE_CONFIG_LAME)
  261.     {
  262.         int    nCRC=pbeConfig->format.mp3.bCRC;
  263.         int nVBR=(nCRC>>12)&0x0F;
  264.  
  265.         // Copy parameter from old Blade structure
  266.         lameConfig.format.LHV1.dwSampleRate    =pbeConfig->format.mp3.dwSampleRate;
  267.         //for low bitrates, LAME will automatically downsample for better
  268.         //sound quality.  Forcing output samplerate = input samplerate is not a good idea 
  269.         //unless the user specifically requests it:
  270.         //lameConfig.format.LHV1.dwReSampleRate=pbeConfig->format.mp3.dwSampleRate;
  271.         lameConfig.format.LHV1.nMode        =(pbeConfig->format.mp3.byMode&0x0F);
  272.         lameConfig.format.LHV1.dwBitrate    =pbeConfig->format.mp3.wBitrate;
  273.         lameConfig.format.LHV1.bPrivate        =pbeConfig->format.mp3.bPrivate;
  274.         lameConfig.format.LHV1.bOriginal    =pbeConfig->format.mp3.bOriginal;
  275.         lameConfig.format.LHV1.bCRC            =nCRC&0x01;
  276.         lameConfig.format.LHV1.bCopyright    =pbeConfig->format.mp3.bCopyright;
  277.     
  278.         // Fill out the unknowns
  279.         lameConfig.format.LHV1.dwStructSize=CURRENT_STRUCT_SIZE;
  280.         lameConfig.format.LHV1.dwStructVersion=CURRENT_STRUCT_VERSION;
  281.  
  282.         // Get VBR setting from fourth nibble
  283.         if (nVBR>0)
  284.         {
  285.             lameConfig.format.LHV1.bWriteVBRHeader = TRUE;
  286.             lameConfig.format.LHV1.bEnableVBR = TRUE;
  287.             lameConfig.format.LHV1.nVBRQuality = nVBR-1;
  288.         }
  289.  
  290.         // Get Quality from third nibble
  291.         lameConfig.format.LHV1.nPreset=((nCRC>>8)&0x0F);
  292.  
  293.     }
  294.     else
  295.     {
  296.         // Copy the parameters
  297.         memcpy(&lameConfig,pbeConfig,pbeConfig->format.LHV1.dwStructSize);
  298.     }
  299.  
  300.  
  301.     // Not used, always assign stream 1
  302.     *phbeStream=1;
  303.  
  304.  
  305.     // --------------- Set arguments to LAME encoder -------------------------
  306.  
  307.     // Set input sample frequency
  308.     gf.in_samplerate=lameConfig.format.LHV1.dwSampleRate;
  309.  
  310.     // The following settings only use when preset is not one of the new LAME QUALITY Presets
  311.     if ((int)lameConfig.format.LHV1.nPreset<(int)LQP_PHONE)
  312.     {
  313.           switch (lameConfig.format.LHV1.nMode)
  314.         {
  315.             case BE_MP3_MODE_STEREO:
  316.                 gf.mode=0;
  317.                 gf.num_channels=2;
  318.             break;
  319.             case BE_MP3_MODE_JSTEREO:
  320.                 gf.mode=1;
  321.                 gf.num_channels=2;
  322.             break;
  323.             case BE_MP3_MODE_MONO:
  324.                 gf.mode=3;
  325.                 gf.num_channels=1;
  326.             break;
  327.             case BE_MP3_MODE_DUALCHANNEL:
  328.                 gf.force_ms=1;
  329.                 gf.mode=1;
  330.                 gf.num_channels=2;
  331.             break;
  332.             default:
  333.             {
  334.                 DebugPrintf("Invalid lameConfig.format.LHV1.nMode, value is %d\n",lameConfig.format.LHV1.nMode);
  335.                 return BE_ERR_INVALID_FORMAT_PARAMETERS;
  336.             }
  337.         }
  338.  
  339.         if ( lameConfig.format.LHV1.bEnableVBR )
  340.         {
  341.             gf.VBR = vbr_default;
  342.  
  343.             gf.VBR_q =lameConfig.format.LHV1.nVBRQuality;
  344.  
  345.             if (lameConfig.format.LHV1.bWriteVBRHeader==TRUE)
  346.             {
  347.                 gf.bWriteVbrTag=TRUE;
  348.             }
  349.             else
  350.             {
  351.                 gf.bWriteVbrTag=FALSE;
  352.             }
  353.         }
  354.         else
  355.         {
  356.             gf.VBR = vbr_off;
  357.         }
  358.  
  359.         // Set frequency resampling rate, if specified
  360.         if (lameConfig.format.LHV1.dwReSampleRate>0)
  361.             gf.out_samplerate=lameConfig.format.LHV1.dwReSampleRate;
  362.         
  363.     
  364.         // Set bitrate.  (CDex users always specify bitrate=Min bitrate when using VBR)
  365.         gf.brate=lameConfig.format.LHV1.dwBitrate;
  366.         gf.VBR_min_bitrate_kbps=gf.brate;
  367.             
  368.         // Set Maxbitrate, if specified
  369.         if (lameConfig.format.LHV1.dwMaxBitrate>0)
  370.             gf.VBR_max_bitrate_kbps=lameConfig.format.LHV1.dwMaxBitrate;
  371.  
  372.         // Use ABR?
  373.         if (lameConfig.format.LHV1.dwVbrAbr_bps>0)
  374.         {
  375.             // set VBR to ABR
  376.             gf.VBR = vbr_abr; 
  377.  
  378.             // calculate to kbps
  379.             gf.VBR_mean_bitrate_kbps = ( lameConfig.format.LHV1.dwVbrAbr_bps + 500 ) / 1000;
  380.  
  381.             // limit range
  382.             if(gf.VBR_mean_bitrate_kbps > 320) gf.VBR_mean_bitrate_kbps = 320;
  383.             if(gf.VBR_mean_bitrate_kbps <   8) gf.VBR_mean_bitrate_kbps = 8;
  384.  
  385.         }
  386.  
  387.  
  388.         if ( lameConfig.format.LHV1.bEnableVBR )
  389.         {
  390.             switch ( lameConfig.format.LHV1.nVbrMethod)
  391.             {
  392.                 case VBR_METHOD_NONE:
  393.                     gf.VBR = vbr_off;
  394.                 break;
  395.  
  396.                 case VBR_METHOD_DEFAULT:
  397.                     gf.VBR = vbr_default;
  398.                 break;
  399.  
  400.                 case VBR_METHOD_OLD:
  401.                     gf.VBR = vbr_rh; 
  402.                 break;
  403.  
  404.                 case VBR_METHOD_NEW:
  405.                     gf.VBR = vbr_mt; 
  406.                 break;
  407.  
  408.                 case VBR_METHOD_MTRH:
  409.                     gf.VBR = vbr_mtrh; 
  410.                 break;
  411.  
  412.                 case VBR_METHOD_ABR:
  413.                     gf.VBR = vbr_abr; 
  414.                 break;
  415.                 default:
  416.                     assert( FALSE );
  417.  
  418.             }
  419.         }
  420.     }
  421.     
  422.     // Set copyright flag?
  423.     if (lameConfig.format.LHV1.bCopyright)
  424.         gf.copyright=1;
  425.  
  426.     // Do we have to tag  it as non original 
  427.     if (!lameConfig.format.LHV1.bOriginal)
  428.     {
  429.         gf.original=0;
  430.     }
  431.     else
  432.     {
  433.         gf.original=1;
  434.     }
  435.  
  436.     // Add CRC?
  437.     if (lameConfig.format.LHV1.bCRC)
  438.     {
  439.         gf.error_protection=1;
  440.     }
  441.     else
  442.     {
  443.         gf.error_protection=0;
  444.     }
  445.  
  446. //    gf.silent=1;  /* disable status ouput */
  447.  
  448.     // Set private bit?
  449.     if (lameConfig.format.LHV1.bPrivate)
  450.     {
  451.         gf.extension = 1;
  452.     }
  453.     else
  454.     {
  455.         gf.extension = 0;
  456.     }
  457.     
  458.  
  459.     // First set all the preset options
  460.     if ((int)lameConfig.format.LHV1.nPreset)
  461.         PresetOptions( &gf, lameConfig.format.LHV1.nPreset );
  462.  
  463.     if (lameConfig.format.LHV1.bNoRes)
  464.     {
  465.         gf.disable_reservoir=1;
  466.         gf.padding_type=0;
  467.     }
  468.  
  469.     lame_init_params(&gf);    
  470.  
  471.     //LAME encoding call will accept any number of samples.  
  472.     if (gf.version==0)
  473.     {
  474.         // For MPEG-II, only 576 samples per frame per channel
  475.         *dwSamples= 576 * gf.num_channels;
  476.     }
  477.     else
  478.     {
  479.         // For MPEG-I, 1152 samples per frame per channel
  480.         *dwSamples= 1152 * gf.num_channels;
  481.     }
  482.  
  483.     // Set the input sample buffer size, so we know what we can expect
  484.     dwSampleBufferSize = *dwSamples;
  485.  
  486.     // Set MP3 buffer size, conservative estimate
  487.     *dwBufferSize=(DWORD)(1.25*(*dwSamples/gf.num_channels) + 7200);
  488.  
  489.     // For debugging purposes
  490.     dump_config( );
  491.  
  492.     // Everything went OK, thus return SUCCESSFUL
  493.     return BE_ERR_SUCCESSFUL;
  494. }
  495.  
  496.  
  497. __declspec(dllexport) BE_ERR    beDeinitStream(HBE_STREAM hbeStream, PBYTE pOutput, PDWORD pdwOutput)
  498. {
  499.  
  500. //    *pdwOutput = lame_encode_finish(&gf,pOutput,0);
  501.  
  502.     *pdwOutput = lame_encode_flush( &gf, pOutput, 0 );
  503.  
  504.     if (*pdwOutput<0) {
  505.         *pdwOutput=0;
  506.         return BE_ERR_BUFFER_TOO_SMALL;
  507.     }
  508.  
  509.     
  510.  
  511.     if ( !gf.bWriteVbrTag )
  512.     {
  513.         lame_close( &gf );
  514.     }
  515.  
  516.     return BE_ERR_SUCCESSFUL;
  517. }
  518.  
  519.  
  520. __declspec(dllexport) BE_ERR    beCloseStream(HBE_STREAM hbeStream)
  521. {
  522.     // DeInit encoder
  523. //    return DeInitEncoder();
  524.     return BE_ERR_SUCCESSFUL;
  525. }
  526.  
  527.  
  528.  
  529. __declspec(dllexport) VOID        beVersion(PBE_VERSION pbeVersion)
  530. {
  531.     // DLL Release date
  532.     char lpszDate[20]    ={'\0',};
  533.     char lpszTemp[5]    ={'\0',};
  534.  
  535.  
  536.     // Set DLL interface version
  537.     pbeVersion->byDLLMajorVersion=MAJORVERSION;
  538.     pbeVersion->byDLLMinorVersion=MINORVERSION;
  539.  
  540.     // Set Engine version number (Same as Lame version)
  541.     pbeVersion->byMajorVersion=LAME_MAJOR_VERSION;
  542.     pbeVersion->byMinorVersion=LAME_MINOR_VERSION;
  543.     pbeVersion->byAlphaLevel=LAME_ALPHA_VERSION;
  544.     pbeVersion->byBetaLevel=LAME_BETA_VERSION;
  545.  
  546. #ifdef MMX_choose_table
  547.     pbeVersion->byMMXEnabled=1;
  548. #else
  549.     pbeVersion->byMMXEnabled=0;
  550. #endif
  551.  
  552.     memset(pbeVersion->btReserved,0, sizeof(pbeVersion->btReserved));
  553.  
  554.     // Get compilation date
  555.     strcpy(lpszDate,__DATE__);
  556.  
  557.     // Get the first three character, which is the month
  558.     strncpy(lpszTemp,lpszDate,3);
  559.     lpszTemp[3]='\0';
  560.     pbeVersion->byMonth=1;
  561.  
  562.     // Set month
  563.     if (strcmp(lpszTemp,"Jan")==0)    pbeVersion->byMonth=1;
  564.     if (strcmp(lpszTemp,"Feb")==0)    pbeVersion->byMonth=2;
  565.     if (strcmp(lpszTemp,"Mar")==0)    pbeVersion->byMonth=3;
  566.     if (strcmp(lpszTemp,"Apr")==0)    pbeVersion->byMonth=4;
  567.     if (strcmp(lpszTemp,"May")==0)    pbeVersion->byMonth=5;
  568.     if (strcmp(lpszTemp,"Jun")==0)    pbeVersion->byMonth=6;
  569.     if (strcmp(lpszTemp,"Jul")==0)    pbeVersion->byMonth=7;
  570.     if (strcmp(lpszTemp,"Aug")==0)    pbeVersion->byMonth=8;
  571.     if (strcmp(lpszTemp,"Sep")==0)    pbeVersion->byMonth=9;
  572.     if (strcmp(lpszTemp,"Oct")==0)    pbeVersion->byMonth=10;
  573.     if (strcmp(lpszTemp,"Nov")==0)    pbeVersion->byMonth=11;
  574.     if (strcmp(lpszTemp,"Dec")==0)    pbeVersion->byMonth=12;
  575.  
  576.     // Get day of month string (char [4..5])
  577.     pbeVersion->byDay=atoi(lpszDate+4);
  578.  
  579.     // Get year of compilation date (char [7..10])
  580.     pbeVersion->wYear=atoi(lpszDate+7);
  581.  
  582.     memset(pbeVersion->zHomepage,0x00,BE_MAX_HOMEPAGE);
  583.  
  584.     strcpy(pbeVersion->zHomepage,"http://www.mp3dev.org/");
  585. }
  586.  
  587. __declspec(dllexport) BE_ERR    beEncodeChunk(HBE_STREAM hbeStream, DWORD nSamples, 
  588.              PSHORT pSamples, PBYTE pOutput, PDWORD pdwOutput)
  589. {
  590.  
  591.     // Encode it
  592.         int dwSamples;
  593.     dwSamples=nSamples/gf.num_channels;
  594.  
  595.     // old versions of lame_enc.dll required exactly 1152 samples
  596.     // and worked even if nSamples accidently set to 2304 
  597.     // simulate this behavoir:
  598.     if (gf.num_channels==1 && nSamples == 2304)
  599.       dwSamples/=2;
  600.  
  601.  
  602.     if (gf.num_channels==1 )
  603.     {
  604.         *pdwOutput=lame_encode_buffer(&gf,pSamples,pSamples,dwSamples,pOutput,0);
  605.     }
  606.     else
  607.     {
  608.         *pdwOutput=lame_encode_buffer_interleaved(&gf,pSamples,dwSamples,pOutput,0);
  609.     }
  610.  
  611.  
  612.     if (*pdwOutput<0) {
  613.         *pdwOutput=0;
  614.         return BE_ERR_BUFFER_TOO_SMALL;
  615.     }
  616.  
  617.     return BE_ERR_SUCCESSFUL;
  618. }
  619.  
  620.  
  621. __declspec(dllexport) BE_ERR beWriteVBRHeader(LPCSTR lpszFileName)
  622. {
  623.     FILE* fpStream    =NULL;
  624.     BE_ERR beResult    =BE_ERR_SUCCESSFUL;
  625.  
  626.     // Do we have to write the VBR tag?
  627.     if ( ( gf.bWriteVbrTag ) && ( gf.VBR != vbr_off ) )
  628.     {
  629.         // Calculate relative quality of VBR stream 
  630.         // 0=best, 100=worst
  631.         int nQuality = gf.VBR_q * 100 / 9;
  632.  
  633.         // Try to open the file
  634.         fpStream=fopen( lpszFileName, "rb+" );
  635.  
  636.         // Check file open result
  637.         if ( NULL == fpStream )
  638.         {
  639.             return BE_ERR_INVALID_FORMAT_PARAMETERS;
  640.         }
  641.  
  642.         // Write Xing header again
  643.         lame_mp3_tags_fid( &gf, fpStream );
  644.  
  645.         // Close the file stream
  646.         fclose( fpStream );
  647.  
  648.     }
  649.  
  650.     if ( gf.bWriteVbrTag )
  651.     {
  652.         // clean up of allocated memory
  653.         lame_close( &gf );
  654.     }
  655.  
  656.     // return result
  657.     return beResult;
  658. }
  659.  
  660.  
  661. BOOL APIENTRY DllMain(HANDLE hModule, 
  662.                       DWORD  ul_reason_for_call, 
  663.                       LPVOID lpReserved)
  664. {
  665.     gs_hModule=hModule;
  666.  
  667.     switch( ul_reason_for_call )
  668.     {
  669.         case DLL_PROCESS_ATTACH:
  670.             // Enable debug/logging?
  671.             gs_bLogFile = GetPrivateProfileInt("Debug","WriteLogFile",gs_bLogFile,"lame_enc.ini");
  672.         break;
  673.         case DLL_THREAD_ATTACH:
  674.         break;
  675.         case DLL_THREAD_DETACH:
  676.         break;
  677.         case DLL_PROCESS_DETACH:
  678.         break;
  679.     }
  680.     return TRUE;
  681. }
  682.  
  683.  
  684. static void dump_config( )
  685. {
  686.     DebugPrintf("\n\nLame_enc configuration options:\n");
  687.     DebugPrintf("==========================================================\n");
  688.  
  689.     DebugPrintf("version                =%d\n",gf.version);
  690.     DebugPrintf("Layer                  =3\n");
  691.     DebugPrintf("mode                   =");
  692.     switch (gf.mode)
  693.     {
  694.         case 0:DebugPrintf("Stereo\n");break;
  695.         case 1:DebugPrintf("Joint-Stereo\n");break;
  696.         case 2:DebugPrintf("Dual-Channel\n");break;
  697.         case 3:DebugPrintf("Mono\n");break;
  698.         default:DebugPrintf("Error (unknown)\n");break;
  699.     }
  700.  
  701.     DebugPrintf("sampling frequency     =%.1f kHz\n",gf.in_samplerate/1000.0);
  702.     DebugPrintf("bitrate                =%d kbps\n",gf.brate);
  703.     DebugPrintf("Vbr Min bitrate        =%d kbps\n",gf.VBR_min_bitrate_kbps);
  704.     DebugPrintf("Vbr Max bitrate        =%d kbps\n",gf.VBR_max_bitrate_kbps);
  705.     DebugPrintf("Quality Setting        =%d\n",gf.quality);
  706.     DebugPrintf("Low pass frequency     =%d\n",gf.lowpassfreq);
  707.     DebugPrintf("High pass frequency    =%d\n",gf.highpassfreq);
  708.     DebugPrintf("No Short Blocks        =%s\n",(gf.no_short_blocks)?"yes":"no");
  709.     DebugPrintf("de-emphasis            =%d\n",gf.emphasis);
  710.     DebugPrintf("private flag           =%d\n",gf.extension);
  711.     DebugPrintf("copyright flag         =%d\n",gf.copyright);
  712.     DebugPrintf("original flag          =%d\n",gf.original);
  713.     DebugPrintf("CRC                    =%s\n",(gf.error_protection) ? "on" : "off");
  714.     DebugPrintf("Fast mode              =%s\n",(gf.quality==9)?"enabled":"disabled");
  715.     DebugPrintf("Force mid/side stereo  =%s\n",(gf.force_ms)?"enabled":"disabled");
  716.     DebugPrintf("Padding Type           =%d\n",gf.padding_type);
  717.     DebugPrintf("Disable Resorvoir      =%d\n",gf.disable_reservoir);
  718.     DebugPrintf("VBR                    =%s, VBR_q =%d, VBR method =",(gf.VBR!=vbr_off)?"enabled":"disabled",gf.VBR_q);
  719.  
  720.     switch (gf.VBR)
  721.     {
  722.         case vbr_off:    DebugPrintf("vbr_off\n");    break;
  723.         case vbr_mt :    DebugPrintf("vbr_mt \n");    break;
  724.         case vbr_rh :    DebugPrintf("vbr_rh \n");    break;
  725.         case vbr_mtrh:    DebugPrintf("vbr_mtrh \n");    break;
  726.         case vbr_abr: 
  727.             DebugPrintf(" vbr_abr (average bitrate %d kbps)\n",gf.VBR_mean_bitrate_kbps);
  728.         break;
  729.         default:
  730.             DebugPrintf("error, unknown VBR setting\n");
  731.         break;
  732.     }
  733.  
  734.     DebugPrintf("Write VBR Header       =%s\n",(gf.bWriteVbrTag)?"Yes":"No");
  735. }
  736.  
  737.  
  738. static void DispErr(LPSTR strErr)
  739. {
  740.     MessageBox(NULL,strErr,"",MB_OK);
  741. }
  742.  
  743.