Solved

Using Lame_enc.dll In Delphi

Posted on 2004-08-28
5
6,193 Views
Last Modified: 2012-06-27
Does anyone know where I can download API info on this DLL please?

Basically, I'm after details on how to call this dll from Delphi (5) rather than calling lame.exe - which although works fine, doesn't give the calling program any data on the current encoding progress.

Thanks...

TDK_Man
0
Comment
Question by:tdk_man
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
5 Comments
 
LVL 13

Expert Comment

by:BlackTigerX
ID: 11921713
maybe a TLameCoder component would help?

http://www.inspired.sk/delphi/components/download.php?ID=29
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 11923208
Google to the resque: http://www.google.nl/search?num=100&q=Lame_enc.dll+delphi

This chinese page http://it.icxo.com/htmlnews/2004/08/05/285745.htm is partly in english and has some interesting comments. But http://lame.sourceforge.net/ could be more useful, though. You can download the full sourcecode there and all you have to do then is convert the header files to Delphi. A helluvajob but it is possible.

One warning: Using the LAME encoding engine (or other mp3 encoding technology) in your software may require a patent license in some countries.
0
 
LVL 1

Author Comment

by:tdk_man
ID: 11925580
Alex

Thanks for the Google link, but when I click on it, they all appear as visited links because I actually spent many hours on Google over two days without luck before posting on here.

If you check out the links, (and I appreciate that you personally would have had no reason to), you would find that none of them actually tell you anything. In particular, none give you a list of API calls and many are asking the same questions I am.

It's odd, but according to a few of the web sites I've visited, whoever created the dll didn't publish the API calls for it.

I've checked out the chinese site though. Very interesting, so thanks for that. Unfortunately, It looks like the dll will not encode at 128 (min 160)! If this is true, it makes it worse than what I'm using at the moment - the lame.exe program.

I have the source to the dll already, but I don't have the skills to modify and recompile it.

BlackTigerX:

Have got that file - thanks. Will check it out and report back.

TDK_Man

0
 
LVL 17

Accepted Solution

by:
Wim ten Brink earned 200 total points
ID: 11929477
Actually, if you have the source, you have an overview of the API too. ;-)
Unfortunately, since the source is written in C++ you'd have to convert it from C++ to Delphi. I don't think the people of JEDI have started on this yet so if there's no link with a Delphi version of the API, there's no other option than writing it yourself. And if you don't know C++, it would be quite difficult. (But basically, you'd have to focus on the *.H files mostly.) You don't have to recompile the source or even modify it. You just have to be able to read the source and determine which functions you need to call.

I've downloaded the latest version of the source of LAME from http://lame.sourceforge.net/ and I noticed it has a little textfile called "API" which provides a bit of information about the API. Also, it seems to me that all you need to convert to Delphi is the "Lame.h" file. I searched a bit further in the source and guess what? It's your lucky day, I hope... It has a PAS file in the \lame-3.96.1\Dll folder! They have created a Delphi unit for you already. I'll paste it here, although this is for the latest version only:

unit MP3export;

interface

uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls;

type
  //type definitions
  //typedef            unsigned long                  HBE_STREAM;
  //typedef            HBE_STREAM                        *PHBE_STREAM;
  //typedef            unsigned long                  BE_ERR;
  THBE_STREAM = LongWord;
  PHBE_STREAM = ^PHBE_STREAM;
  BE_ERR = LongWord;

const
  // encoding formats
  //#define            BE_CONFIG_MP3                  0
  //#define            BE_CONFIG_LAME                  256
  BE_CONFIG_MP3 = 0;
  BE_CONFIG_LAME = 256;

  // error codes
  //#define    BE_ERR_SUCCESSFUL                    0x00000000
  //#define    BE_ERR_INVALID_FORMAT            0x00000001
  //#define    BE_ERR_INVALID_FORMAT_PARAMETERS      0x00000002
  //#define    BE_ERR_NO_MORE_HANDLES            0x00000003
  //#define    BE_ERR_INVALID_HANDLE            0x00000004
  BE_ERR_SUCCESSFUL: LongWord = 0;
  BE_ERR_INVALID_FORMAT: LongWord = 1;
  BE_ERR_INVALID_FORMAT_PARAMETERS: LongWord = 2;
  BE_ERR_NO_MORE_HANDLES: LongWord = 3;
  BE_ERR_INVALID_HANDLE: LongWord = 4;

  // other constants

  BE_MAX_HOMEPAGE = 256;

  // format specific variables

  BE_MP3_MODE_STEREO = 0;
  BE_MP3_MODE_DUALCHANNEL = 2;
  BE_MP3_MODE_MONO = 3;

type

  TMP3 = packed record
    dwSampleRate: LongWord;
    byMode: Byte;
    wBitRate: Word;
    bPrivate: LongWord;
    bCRC: LongWord;
    bCopyright: LongWord;
    bOriginal: LongWord;
  end;

  TLHV1 = packed record
    // STRUCTURE INFORMATION
    dwStructVersion: DWORD;
    dwStructSize: DWORD;

    // BASIC ENCODER SETTINGS
    dwSampleRate: DWORD; // ALLOWED SAMPLERATE VALUES DEPENDS ON dwMPEGVersion
    dwReSampleRate: DWORD; // DOWNSAMPLERATE, 0=ENCODER DECIDES
    nMode: Integer; // BE_MP3_MODE_STEREO, BE_MP3_MODE_DUALCHANNEL, BE_MP3_MODE_MONO
    dwBitrate: DWORD; // CBR bitrate, VBR min bitrate
    dwMaxBitrate: DWORD; // CBR ignored, VBR Max bitrate
    nQuality: Integer; // Quality setting (NORMAL,HIGH,LOW,VOICE)
    dwMpegVersion: DWORD; // MPEG-1 OR MPEG-2
    dwPsyModel: DWORD; // FUTURE USE, SET TO 0
    dwEmphasis: DWORD; // FUTURE USE, SET TO 0

    // BIT STREAM SETTINGS
    bPrivate: LONGBOOL; // Set Private Bit (TRUE/FALSE)
    bCRC: LONGBOOL; // Insert CRC (TRUE/FALSE)
    bCopyright: LONGBOOL; // Set Copyright Bit (TRUE/FALSE)
    bOriginal: LONGBOOL; // Set Original Bit (TRUE/FALSE_

    // VBR STUFF
    bWriteVBRHeader: LONGBOOL; // WRITE XING VBR HEADER (TRUE/FALSE)
    bEnableVBR: LONGBOOL; // USE VBR ENCODING (TRUE/FALSE)
    nVBRQuality: Integer; // VBR QUALITY 0..9

    btReserved: array[ 0..255 ] of Byte; // FUTURE USE, SET TO 0
  end;

  TAAC = packed record
    dwSampleRate: LongWord;
    byMode: Byte;
    wBitRate: Word;
    byEncodingMethod: Byte;
  end;

  TFormat = packed record
    case byte of
      1: ( mp3: TMP3 );
      2: ( lhv1: TLHV1 );
      3: ( aac: TAAC );
  end;

  TBE_Config = packed record
    dwConfig: LongWord;
    format: TFormat;
  end;

  PBE_Config = ^TBE_Config;

  //typedef struct      {
  //      // BladeEnc DLL Version number
  //
  //      BYTE      byDLLMajorVersion;
  //      BYTE      byDLLMinorVersion;
  //
  //      // BladeEnc Engine Version Number
  //
  //      BYTE      byMajorVersion;
  //      BYTE      byMinorVersion;
  //
  //      // DLL Release date
  //
  //      BYTE      byDay;
  //      BYTE      byMonth;
  //      WORD      wYear;
  //
  //      // BladeEnc      Homepage URL
  //
  //      CHAR      zHomepage[BE_MAX_HOMEPAGE + 1];
  //
  //} BE_VERSION, *PBE_VERSION;

  TBE_Version = record
    byDLLMajorVersion: Byte;
    byDLLMinorVersion: Byte;

    byMajorVersion: Byte;
    byMinorVersion: Byte;

    byDay: Byte;
    byMonth: Byte;
    wYear: Word;

    zHomePage: array[ 0..BE_MAX_HOMEPAGE + 1 ] of Char;
  end;

  PBE_Version = ^TBE_Version;

  //__declspec(dllexport) BE_ERR      beInitStream(PBE_CONFIG pbeConfig, PDWORD dwSamples, PDWORD dwBufferSize, PHBE_STREAM phbeStream);
  //__declspec(dllexport) BE_ERR      beEncodeChunk(HBE_STREAM hbeStream, DWORD nSamples, PSHORT pSamples, PBYTE pOutput, PDWORD pdwOutput);
  //__declspec(dllexport) BE_ERR      beDeinitStream(HBE_STREAM hbeStream, PBYTE pOutput, PDWORD pdwOutput);
  //__declspec(dllexport) BE_ERR      beCloseStream(HBE_STREAM hbeStream);
  //__declspec(dllexport) VOID      beVersion(PBE_VERSION pbeVersion);

  {
  Function beInitStream(var pbeConfig: TBE_CONFIG; var dwSample: LongWord; var dwBufferSize: LongWord; var phbeStream: THBE_STREAM ): BE_Err; cdecl; external 'Bladeenc.dll';
  //Function beEncodeChunk(hbeStream: THBE_STREAM; nSamples: LongWord; pSample: PSmallInt;pOutput: PByte; var pdwOutput: LongWord): BE_Err; cdecl; external 'Bladeenc.dll';
  Function beEncodeChunk(hbeStream: THBE_STREAM; nSamples: LongWord; var pSample;var pOutput; var pdwOutput: LongWord): BE_Err; stdcall; cdecl 'Bladeenc.dll';
  Function beDeinitStream(hbeStream: THBE_STREAM; var pOutput; var pdwOutput: LongWord): BE_Err; cdecl; external 'Bladeenc.dll';
  Function beCloseStream(hbeStream: THBE_STREAM): BE_Err; cdecl; external 'Bladeenc.dll';
  Procedure beVersion(var pbeVersion: TBE_VERSION); cdecl; external 'Bladeenc.dll';
  }

function beInitStream( var pbeConfig: TBE_CONFIG; var dwSample: LongWord; var dwBufferSize: LongWord; var phbeStream: THBE_STREAM ): BE_Err; cdecl; external 'Lame_enc.dll';
//Function beEncodeChunk(hbeStream: THBE_STREAM; nSamples: LongWord; pSample: PSmallInt;pOutput: PByte; var pdwOutput: LongWord): BE_Err; cdecl; external 'Lame_enc.dll';
function beEncodeChunk( hbeStream: THBE_STREAM; nSamples: LongWord; var pSample; var pOutput; var pdwOutput: LongWord ): BE_Err; cdecl; external 'Lame_enc.dll';
function beDeinitStream( hbeStream: THBE_STREAM; var pOutput; var pdwOutput: LongWord ): BE_Err; cdecl; external 'Lame_enc.dll';
function beCloseStream( hbeStream: THBE_STREAM ): BE_Err; cdecl; external 'Lame_enc.dll';
procedure beVersion( var pbeVersion: TBE_VERSION ); cdecl; external 'Lame_enc.dll';

procedure EncodeWavToMP3( fs, fd: Integer );
implementation

uses InternetSnd, TraiteWav;

{----------------------------------------}

procedure EncodeWavToMP3( fs, fd: Integer );
var
  err: Integer;
  beConfig: TBE_Config;
  dwSamples, dwSamplesMP3: LongWord;
  hbeStream: THBE_STREAM;
  error: BE_ERR;
  pBuffer: PSmallInt;
  pMP3Buffer: PByte;
  Marque: PChar;

  done: LongWord;
  dwWrite: LongWord;
  ToRead: LongWord;
  ToWrite: LongWord;
  i: Integer;

begin
  beConfig.dwConfig := BE_CONFIG_LAME;

  {
    beConfig.Format.mp3.dwSampleRate := WavInfo.SamplesPerSec;
    beConfig.Format.mp3.byMode := BE_MP3_MODE_STEREO;
    beConfig.Format.mp3.wBitrate := strToInt(MainFrm.Mp3BitRate.Text);
    beConfig.Format.mp3.bCopyright := 0;
    beConfig.Format.mp3.bCRC := $00000000;
    beConfig.Format.mp3.bOriginal := 0;
    beConfig.Format.mp3.bPrivate := 0;
  }
  //Structure information
  beConfig.Format.lhv1.dwStructVersion := 1;
  beConfig.Format.lhv1.dwStructSize := SizeOf( beConfig );
  //Basic encoder setting
  beConfig.Format.lhv1.dwSampleRate := WavInfo.SamplesPerSec;
  beConfig.Format.lhv1.dwReSampleRate := 44100;
  beConfig.Format.lhv1.nMode := BE_MP3_MODE_STEREO;
  beConfig.Format.lhv1.dwBitrate := strToInt( MainFrm.Mp3BitRate.Text );
  beConfig.Format.lhv1.dwMaxBitrate := strToInt( MainFrm.Mp3BitRate.Text );
  beConfig.Format.lhv1.nQuality := 2;
  beConfig.Format.lhv1.dwMPegVersion := 1; //MPEG1
  beConfig.Format.lhv1.dwPsyModel := 0;
  beConfig.Format.lhv1.dwEmphasis := 0;
  //Bit Stream Settings
  beConfig.Format.lhv1.bPrivate := False;
  beConfig.Format.lhv1.bCRC := False;
  beConfig.Format.lhv1.bCopyright := True;
  beConfig.Format.lhv1.bOriginal := True;
  //VBR Stuff
  beConfig.Format.lhv1.bWriteVBRHeader := false;
  beConfig.Format.lhv1.bEnableVBR := false;
  beConfig.Format.lhv1.nVBRQuality := 0;

  i := 0;
  error := beInitStream( beConfig, dwSamples, dwSamplesMP3, hbeStream );
  if error = BE_ERR_SUCCESSFUL then begin
    pBuffer := AllocMem( dwSamples * 2 );
    pMP3Buffer := AllocMem( dwSamplesMP3 );
    try
      done := 0;

      error := FileSeek( fs, 0, 0 );
      while ( done < TotalSize ) do begin
        if ( done + dwSamples * 2 < TotalSize ) then
          ToRead := dwSamples * 2
        else begin
          ToRead := TotalSize - done;
          //FillChar(buf[0],dwSamples*2,0);
          FillChar( pbuffer^, dwSamples, 0 );
        end;

        //if FileRead(fs, buf[0], toread) = -1
        if FileRead( fs, pbuffer^, toread ) = -1 then raise Exception.Create( 'Erreur de lecture' );

        //error := beEncodeChunk(hbeStream, toRead div 2, Buf[0], TmpBuf[0], toWrite);
        error := beEncodeChunk( hbeStream, toRead div 2, pBuffer^, pMP3Buffer^, toWrite );

        if error <> BE_ERR_SUCCESSFUL then begin
          beCloseStream( hbeStream );
          raise Exception.Create( 'Echec de l''encodage' );
        end;

        //if FileWrite(fd, TmpBuf[0], toWrite) = -1
        if FileWrite( fd, pMP3Buffer^, toWrite ) = -1 then raise Exception.Create( 'Erreur d''écriture' );

        done := done + toread;
        inc( i );
        if i mod 64 = 0 then begin
          MainFrm.ProgressBar1.Position := round( 100 * done / Totalsize );
          Application.ProcessMessages;
        end;
      end;

      error := beDeInitStream( hbeStream, pMP3Buffer^, dwWrite );
      //error := beDeInitStream(hbeStream, TmpBuf[0], dwWrite);

      if error <> BE_ERR_SUCCESSFUL then begin
        beCloseStream( hbeStream );
        raise Exception.Create( 'Echec à la sortie' );
      end;

      if dwWrite <> 0 then begin
        //if FileWrite(fd, TmpBuf[0], dwWrite) = -1
        if FileWrite( fd, pMP3Buffer^, dwWrite ) = -1 then raise Exception.Create( 'Erreur à la dernière écriture' );
      end;

      beCloseStream( hbeStream );
    finally
      FreeMem( pBuffer );
      FreeMem( pMP3Buffer );
    end;
  end
  else begin

  end;
end;

end.

-------------------------------------------
Too bad the error messages are in french. ;-)
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12004540
Is your problem solved now?
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Ready to improve network connectivity? Watch this webinar to learn how SD-WANs and a one-click instant connect tool can boost provisions, deployment, and management of your cloud connection.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question