zgrywanie strumienia z formatem AAC jako Mp3

0

Cześć [browar]
Od pewnego czasu mam bardzo duży problem ze zgraniem strumienia radia internetowego nadawanego w formacie AAC plus jako pliku mp3
Przyznam się że toczę boje od pół roku :-D
Doszedłem do punktu w którym udało mi się zgrywać strumienie na dysk, ale w postaci takiej jakiej są nadawane - czyli AAC plus lub MP3 (w zależności jaki format nadaje radio)
Jeśli ktoś sie tym bawił to wie o co chodzi - zrobiłem to w procedurze:

PROCEDURE StatusProc(buffer:Pointer; len,user:DWORD);stdcall;

umieściłem tam instrukcje FileStream i zapisuję dane ze zmiennej "buffer" na dysk w postaci pliku.
I jak powyżej pisałem te dane zapisywane są jak lecą - bez zadnej obróbki, zmiany formatu , dekodowania itp. Bo własnie tu utknąłem :/
Przestudiowałem całą rodzimą witrynę Bassa un4seen i nic :( oraz przez ostatnie pół roku szukam szukam i szukam... i nic.
Są podpowiedzi ale mętne i dotyczące użycia dosowego programiku Lame.exe
ale nie o to chodzi bym Lame zamieniał juz zapisany plik na inny format - ale abym mógł go w trakcie nadawania przez stację formatować na mp3 w locie. Czyli dane napływające do zmiennej buffer które są dopisywane do pliku, przed samym zapisaniem jakoś przekodować na dane formatu mp3.
Proszę o pomoc w tym temacie. Chociaż o popowiedź jaki dodatkowy moduł lub bibliotekę użyć ?
Ogólnie sciągałem rózne rippery radiowe i podglądałem działanie. 90% działa jak mój - czyli zapisuje pliki w oryginalnych nadawanych formatach. Ale jest jeden programik o nazwie Screamer.
Zawiera w sobie pliki bass.dll bass_acc.dll (te i ja wykorzystuje) i lame_enc.dll
Domyślam się że autor wykorzystał właśnie lame_enc.dll do przeformatowania danych w strumieniu na dane o formacie mp3.
Mam dodatkowy moduł obsługujący tą bibliotekę - lame.pas
Zerkam w niego i jakoś nie mogę wyczaić którą procedure użyć bym osiągnął swój cel.
Proszę o pomoc i jakieś wskazówki.

0

Oki dzięki, sciągnąłem, przejrzałem i stwierdziłem że nie zabardzo mi się to przyda :(
Ja zrobiłem programik do odtwarzania radia internetowego w oparciu o biblioteki Bass.
Więc musiałbym zrezygnować z tej idei i na nowo rozpocząć program w oparciu o to co poleciłeś, czyli wykorzystując inne komponenty z tego pakietu który jest w Twoim linku.
Wspomnę że ukończyłem program w 90% - zgrywa mi strumienie ale w oryginalnych formatach, czyli AAC, OGG, WMA, MP3 - zgrywam je w specjalnej procedurze gdzie dane z bufora w którym są zawarte dane napływające w trakcie nadawania audycji i zapisywane do pliku.
W moim pytaniu chodziło mi o to jak te dane przerobić na jeden format MP3 i w takim formacie zapisywać zgrywane audycje na dysk.
Podglądałem program Screamer. Nie zawiera żadnych komponentów do odtwarzania radia tylko korzysta z biblioteki Bass.dll Bass_aac.dll Basswma.dll i lame_enc.dll
Ja też korzystam z tych bibliotek, jedynie nie wiem jak wykorzystana jest biblioteka lame_enc.dll ?
Podejrzewam że właśnie jakąś funkcją z tej biblioteki, w podobnej procedurze co moja - autor zamienia napływające dane do bufora na dane które po zapisaniu nadają format pliku mp3.
I właśnie o to pytam - jak sformatować dane zawarte w buforze ?
Wiem że odpada sposób zapisywania pliku np jako wav a po zapisaniu przekonwertowanie na mp3.
Ponieważ już w trakcie zapisywania pliku (leci np jakaś zapisywana muza) kreowany jest plik mp3 i do niego dopisywane dane ze strumienia. Czyli autor formatuje je w "locie" inaczej .. dane zawarte w buforze przed zapisywaniem formatuje na mp3.
W necie jest minimum na ten temat, a jak juz jest to pomoc dla programistów w C+ . Śledzę i te kawałki kodu w C+ ale niewiele one dotyczą przeformatowania strumienia.
A o przeformatowanie mi chodzi.

0

A tak na szybko: tworzysz dwa strumienie BASS, jeden odbiera dane (callback DOWNLOADPROC), dopisujesz je do własnego bufora, drugi strumień z flagą BASS_STREAM_DECODE (zerknij na BassEnc) zajmuje się kodowaniem - z niego odczytasz zakodowany strumień. Jak opróżnisz bufor zanim zapełnisz go nowymi danymi robisz pause i encoder czeka. Jak plik osiągnie żądaną wielkość, dopisuję mu tagi i tworzysz następny. Przynajmniej tak spróbowałbym to zorganizować.

Jacek

0

Ale co za problem, jezeli strumien masz juz zdekodowany nie zrzucac go do pliku na dysk tylko do lame?

Użycie lame.exe jest prostsze bo mozesz uzyc BassEnc. Ale rownie dobrze mozesz strumien wrzucac do lame enc.dll uzywajac funkcji importowanej z biblioteki.

Po necie krazy przyklad uzycia lameenc.dll do kodowania pliku WAV na mp3, łatwo to przerobisz - zamiast pobierac dane z pliku WAV pobierasz je z twojego zdekodowanego strumienia.

Lame jest proste, z ogg mialbys wiecej problemow

0

Dziękuje Wam obu za podpowiedzi [browar] i ten pomysł i ten pomysł jest dobry.
Właśnie mam procedurę w której wspomniał kolega JacekH i w niej dokonuje zapisu strumienia na dysk (DOWNLOADPROC) i domyślam się że właśnie w tej procedurze jak pisał drugi kolega Otello
jest dodatkowo zawarta funkcja kodująca dane z bufora jako dane mp3. i te dane zapisywane w trakcie słuchania radia.. jako plik mp3.
Pisałem wcześniej że opieram się na działaniu programu Screamer. I tam własnie zastosowana jest biblioteka lame_enc.dll. Nic poza tym, żaden programik zewnętrzny typu lame.exe. Muzyczka leci z radia i jednocześnie się zgrywa jako mp3. Niezależnie czy to radio nadaje w AAC, AAC plus, OGG, WMA itd. Tak jak tu podpowiadasz Otello, na pewno do zakodowania strumienia w "locie" jako mp3, użył ten gość jakiejś funkcji z lame_enc.dll.
Tylko niezbyt wiem jak do tego podejść ? Nie mam żadnej pomocy co do wiedzy na temat użycia zawartych w niej funkcji. Samych wersji plików pas do obsługi tej bliblioteki jest full.
Poniżej podam dwa przykłady - są tak różne że w głowie mam zamęt.

  1. unit do obsługi
unit Lame_enc;
{Delphi conversion for Lame_enc.dll 3.8x
 Lame is freeware MP3 encoder
 Full source (in C++) available from http://www.sulaco.org/mp3}

interface

uses Windows;

const
     BE_CONFIG_MP3  = 0;
     BE_CONFIG_LAME = 256;

type
    THBESTREAM = ULONG;
    PHBESTREAM = ^THBESTREAM;
    TBEERR     = ULONG;
    PSHORT      = ^SHORT;
    PBYTE       = ^Byte;
const

    BE_ERR_SUCCESSFUL                = $00000000;
    BE_ERR_INVALID_FORMAT	     = $00000001;    BE_ERR_INVALID_FORMAT_PARAMETERS = $00000002;    BE_ERR_NO_MORE_HANDLES	     = $00000003;    BE_ERR_INVALID_HANDLE	     = $00000004;    BE_ERR_BUFFER_TOO_SMALL	     = $00000005;

    BE_MAX_HOMEPAGE = 256;

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

    MPEG1 = 1;
    MPEG2 = 0;



type

  MPEG_QUALITY = (NORMAL_QUALITY, LOW_QUALITY, HIGH_QUALITY, VOICE_QUALITY);

  PLHV1 = ^TLHV1;
  TLHV1 = packed record
    dwStructVersion : DWORD;
    dwStructSize    : DWORD;    dwSampleRate    : DWORD;    dwReSampleRate  : DWORD;    nMode	    : INTEGER;    dwBitrate       : DWORD;    dwMaxBitrate    : DWORD;    nQuality        : DWORD; {MPEG_QUALITY ;}    dwMpegVersion   : DWORD;    dwPsyModel      : DWORD;    dwEmphasis      : DWORD;    bPrivate	    : BOOL;    bCRC	    : BOOL;    bCopyright	    : BOOL;    bOriginal       : BOOL;    bWriteVBRHeader : BOOL;    bEnableVBR	    : BOOL;    nVBRQuality     : integer;    btReserved      : array [1..255] of byte;end;

  PLameMP3 = ^TLameMP3;
  TLameMP3 = packed record
    dwSampleRate : DWORD;
    // 48000, 44100 and 32000 allowed
    byMode       : Byte;
    // BE_MP3_MODE_STEREO, BE_MP3_MODE_DUALCHANNEL, BE_MP3_MODE_MONO
    wBitrate     : Word;
    // 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256 and 320 allowed
    bPrivate,
    bCRC,
    bCopyright,
    bOriginal    : BOOLean;
  end;

  PAAC = ^TAAC;
  TAAC = packed record
    dwSampleRate : DWORD;
    byMode : Byte;
    wBitrate : Word;
    byEncodingMethod : Byte;
  end;


  PFormat = ^TFormat;
  TFormat = packed record
    case dwConfig : DWord of
      BE_CONFIG_MP3 : (MP3 : TLameMP3);
      BE_CONFIG_LAME : (LHV1 : TLHV1);
  end;

  PBECONFIG = ^TBECONFIG;
  TBECONFIG = packed record
    Format : TFormat;
  end;

  PBEVersion = ^TBEVersion;
  TBEVersion = packed record
    // BladeEnc DLL Version number
    byDLLMajorVersion,
    byDLLMinorVersion,
    // BladeEnc Engine Version Number
    byMajorVersion,
    byMinorVersion,
    // DLL Release date
    byDay,
    byMonth : Byte;
    wYear : Word;
    zHomepage : Array[0..BE_MAX_HOMEPAGE] of char;
  end;

  function beInitStream(var pbeConfig : TBEConfig; var dwSamples : DWORD; var dwBufferSize : DWORD; var phbeStream : THBESTREAM) : TBeErr; cdecl; external 'LAME_ENC.DLL';
  (*
    pbeConfig    = Type of mp3
    dwSamples    = Maximum number of samples to encode
    dwBufferSize = Maximum mp3 buffer size
    hbeStream    = BladeEnc-stream
  *)
  function beEncodeChunk(hbeStream : THBEStream; nSamples : DWORD; pSamples : PShort;  pOutput : PByte; var pdwOutput : DWORD) : TBeErr; cdecl; external 'LAME_ENC.DLL';
  (*
    hbeStream    =
    nSamples     = Number of samples to encode
    pSamples	 = Pointer to buffer with Samples to encode
    pOutput	 = Pointer to buffer to recieve encoded samples
    pdwOutput	 = number of samples encoded
  *)
  function beDeinitStream(hbeStream : THBEStream;  pOutput : PByte; var pdwOutput : DWORD) : TBeErr; cdecl; external 'LAME_ENC.DLL';
  (*
    hbeStream    =
    pOutput	 = Pointer to buffer holding encoded samples
    pdwOutput	 = Number of samples to write
  *)
  function beCloseStream(hbeStream : THBEStream) : TBeErr; cdecl; external 'LAME_ENC.DLL';
  procedure beVersion(var pbeVersion : TBEVersion); cdecl; external 'LAME_ENC.DLL';

implementation

end.
  1. unit do obsługi
(*
  Delphi/Kylix header for LAME encoder.
  Translated from lame.h C/C++ header
  by Andrei Borovsky, [email protected]
  The original C/C++ header and library
  Copyright (c) 1999 Mark Taylor                

  Note by A.B.: Some fragments of the original header file are skipped.
  See the comments below.
*)                           

// $Id: lame.pas,v 1.1 2005/10/19 09:43:03 artee Exp $

unit LameEnc;

interface

uses
{$IFDEF WIN32}
  Windows;
{$ENDIF}

{$IFDEF LINUX}
  Libc;
{$ENDIF}

const

{$IFDEF LINUX}
    LAME_PATH = '/usr/lib/libmp3lame.so';
{$ENDIF}

{$IFDEF WIN32}
    LAME_PATH = 'lame_enc.dll';
{$ENDIF}

type

  vbr_mode = (
    vbr_off = 0,
    vbr_mt,                    // obsolete, same as vbr_mtrh
    vbr_rh,
    vbr_abr,
    vbr_mtrh,
    vbr_max_indicator,        // Don't use this! It's used for sanity checks.
    vbr_default = vbr_rh      // change this to change the default VBR mode of LAME
  );

// MPEG modes

  MPEG_mode = (
    STEREO = 0,
    JOINT_STEREO,
    DUAL_CHANNEL,             // LAME doesn't supports this!
    MONO,
    NOT_SET,
    MAX_INDICATOR            // Don't use this! It's used for sanity checks.
  );

  Padding_type = (
    PAD_NO = 0,
    PAD_ALL,
    PAD_ADJUST,
    PAD_MAX_INDICATOR      // Don't use this! It's used for sanity checks.
  );

  preset_mode = (
    (* values from 8 to 320 should be reserved for abr bitrates
      for abr I'd suggest to directly use the targeted bitrate as a value *)
    ABR_8 = 8,
    ABR_320 = 320,
    R3MIX = 1000,
    STANDARD = 1001,
    EXTREME = 1002,
    INSANE = 1003,
    STANDARD_FAST = 1004,
    EXTREME_FAST = 1005
  );

  asm_optimizations = (
    MMX = 1,
    AMD_3DNOW = 2,
    SSE = 3
  );

(* Note by A.B.:
   The following type is a placeholder for * lame_global_flags.
   We treat this type as integer since it is interpreted as such by some
   functions and the underlying structure is opaque anyway.
*)

  PLame_global_flags = Integer;

  PLame_t = Pointer;

  // function pointers

  (***********************************************************************
  *
  *  The LAME API
  *  These functions should be called, in this order, for each
  *  MP3 file to be encoded
  *
  ***********************************************************************)

 (*
 * REQUIRED:
 * initialize the encoder.  sets default for all encoder paramters,
 * returns -1 if some malloc()'s failed
 * otherwise returns 0
 *)

 lame_init_t = function : PLame_global_flags; cdecl;

 (*
 * OPTIONAL:
 * set as needed to override defaults
 *)

(********************************************************************
 *  input stream description
 ***********************************************************************)
// number of samples.  default = 2^32-1

  lame_set_num_samples_t = function(handle : PLame_global_flags; ul : LongWord)
  : Integer; cdecl;
  lame_get_num_samples_t = function(handle : PLame_global_flags) : LongWord; cdecl;

  // input sample rate in Hz.  default = 44100hz
  lame_set_in_samplerate_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_in_samplerate_t = function(handle : PLame_global_flags) : Integer; cdecl;

  // number of channels in input stream. default=2
  lame_set_num_channels_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_num_channels_t = function(handle : PLame_global_flags) : Integer; cdecl;

  (* scale the input by this amount before encoding.  default=0 (disabled)
   (not used by decoding routines) *)
  lame_set_scale_t = function(handle : PLame_global_flags; d : Single)
  : Integer; cdecl;
  lame_get_scale_t = function(handle : PLame_global_flags) : Single; cdecl;

  (* scale the channel 0 (left) input by this amount before encoding.
   default=0 (disabled)
  (not used by decoding routines) *)
  lame_set_scale_left_t = function(handle : PLame_global_flags; d : Single)
  : Integer; cdecl;
  lame_get_scale_left_t = function(handle : PLame_global_flags) : Single; cdecl;

(* scale the channel 1 (right) input by this amount before encoding.
   default=0 (disabled)
 (not used by decoding routines) *)

  lame_set_scale_right_t = function(handle : PLame_global_flags; d : Single)
  : Integer; cdecl;
  lame_get_scale_right_t = function(handle : PLame_global_flags) : Single; cdecl;

  (* output sample rate in Hz.  default = 0, which means LAME picks best value
     based on the amount of compression.  MPEG only allows:
   MPEG1    32, 44.1,   48khz
   MPEG2    16, 22.05,  24
   MPEG2.5   8, 11.025, 12
  (not used by decoding routines) *)

  lame_set_out_samplerate_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_out_samplerate_t = function(handle : PLame_global_flags) : Integer; cdecl;

 (********************************************************************
 *  general control parameters
 ***********************************************************************)
// 1=cause LAME to collect data for an MP3 frame analyzer. default=0
  lame_set_analysis_t  = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_analysis_t = function(handle : PLame_global_flags) : Integer; cdecl;

(* 1 = write a Xing VBR header frame.
 default = 1 for VBR/ABR modes, 0 for CBR mode
 this variable must have been added by a Hungarian notation Windows programmer :-) *)
 lame_set_bWriteVbrTag_t  = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_bWriteVbrTag_t = function(handle : PLame_global_flags) : Integer; cdecl;

  // 1=decode only.  use lame/mpglib to convert mp3/ogg to wav.  default=0
  lame_set_decode_only_t  = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_decode_only_t = function(handle : PLame_global_flags) : Integer; cdecl;

  // 1=encode a Vorbis .ogg file.  default=0
  lame_set_ogg_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_ogg_t = function(handle : PLame_global_flags) : Integer; cdecl;

(* internal algorithm selection.  True quality is determined by the bitrate
 but this variable will effect quality by selecting expensive or cheap algorithms.
 quality=0..9.  0=best (very slow).  9=worst.
 recommended:  2     near-best quality, not too slow
               5     good quality, fast
               7     ok quality, really fast *)
  lame_set_quality_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_quality_t = function(handle : PLame_global_flags) : Integer; cdecl;

(* mode = 0,1,2,3 = stereo, jstereo, dual channel (not supported), mono
 default: lame picks based on compression ration and input channels *)
  lame_set_mode_t = function(handle : PLame_global_flags; MPEGMode : Integer)
  : Integer; cdecl;
  lame_get_mode_t = function(handle : PLame_global_flags) : Integer; cdecl;

(* mode_automs.  Use a M/S mode with a switching threshold based on
 compression ratio
 default = 0 (disabled) *)
  lame_set_mode_automs_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_mode_automs_t = function(handle : PLame_global_flags) : Integer; cdecl;

(* force_ms.  Force M/S for all frames.  For testing only.
 default = 0 (disabled) *)
  lame_set_force_ms_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_force_ms_t = function(handle : PLame_global_flags) : Integer; cdecl;

// use free_format?  default = 0 (disabled)
  lame_set_free_format_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_free_format_t = function(handle : PLame_global_flags) : Integer; cdecl;

// Note by A.B.: Attention! Skipping optional debug/error messages functions.

// set one of brate compression ratio.  default is compression ratio of 11.
  lame_set_brate_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_brate_t = function(handle : PLame_global_flags) : Integer; cdecl;
  lame_set_compression_ratio_t = function(handle : PLame_global_flags; d : Single)
  : Integer; cdecl;
  lame_get_compression_ratio_t = function(handle : PLame_global_flags) : Single; cdecl;

  lame_set_preset_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_set_asm_optimizations_t = function(handle : PLame_global_flags; i1, i2 : Integer)
  : Integer; cdecl;

 (********************************************************************
 *  frame params
 ***********************************************************************)
// mark as copyright.  default=0
  lame_set_copyright_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_copyright_t = function(handle : PLame_global_flags) : Integer; cdecl;

// mark as original.  default=1
  lame_set_original_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_original_t = function(handle : PLame_global_flags) : Integer; cdecl;

// error_protection.  Use 2 bytes from each frame for CRC checksum. default=0
  lame_set_error_protection_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_error_protection_t = function(handle : PLame_global_flags) : Integer; cdecl;

// padding_type.  0=pad no frames  1=pad all frames 2=adjust padding(default)
  lame_set_padding_type_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_padding_type_t = function(handle : PLame_global_flags) : Integer; cdecl;

// MP3 'private extension' bit  Meaningless.  default=0
  lame_set_extension_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_extension_t = function(handle : PLame_global_flags) : Integer; cdecl;

// enforce strict ISO compliance.  default=0
  lame_set_strict_ISO_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_strict_ISO_t = function(handle : PLame_global_flags) : Integer; cdecl;

  (********************************************************************
   * VBR control
   ***********************************************************************)

// Types of VBR.  default = vbr_off = CBR
   lame_set_VBR_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_VBR_t = function(handle : PLame_global_flags) : Integer; cdecl;

// VBR quality level.  0=highest  9=lowest
  lame_set_VBR_q_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_VBR_q_t = function(handle : PLame_global_flags) : Integer; cdecl;

// Ignored except for VBR=vbr_abr (ABR mode)
  lame_set_VBR_mean_bitrate_kbps_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_VBR_mean_bitrate_kbps_t = function(handle : PLame_global_flags) : Integer; cdecl;

  lame_set_VBR_min_bitrate_kbps_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_VBR_min_bitrate_kbps_t = function(handle : PLame_global_flags) : Integer; cdecl;

  lame_set_VBR_max_bitrate_kbps_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_VBR_max_bitrate_kbps_t = function(handle : PLame_global_flags) : Integer; cdecl;

(* 1=stricetly enforce VBR_min_bitrate.  Normally it will be violated for
 analog silence *)
  lame_set_VBR_hard_min_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_VBR_hard_min_t = function(handle : PLame_global_flags) : Integer; cdecl;

 (********************************************************************
 * Filtering control
 ***********************************************************************)
 // freq in Hz to apply lowpass. Default = 0 = lame chooses.  -1 = disabled
  lame_set_lowpassfreq_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_lowpassfreq_t = function(handle : PLame_global_flags) : Integer; cdecl;
// width of transition band, in Hz.  Default = one polyphase filter band
  lame_set_lowpasswidth_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_lowpasswidth_t = function(handle : PLame_global_flags) : Integer; cdecl;

// freq in Hz to apply highpass. Default = 0 = lame chooses.  -1 = disabled
  lame_set_highpassfreq_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_highpassfreq_t = function(handle : PLame_global_flags) : Integer; cdecl;
// width of transition band, in Hz.  Default = one polyphase filter band
  lame_set_highpasswidth_t = function(handle : PLame_global_flags; i : Integer)
  : Integer; cdecl;
  lame_get_highpasswidth_t = function(handle : PLame_global_flags) : Integer; cdecl;

// Note by A.B.: Attention! Skipping psycho acoustics and other special functions

(************************************************************************
* internal variables, cannot be set...                                 *
* provided because they may be of use to calling application           *
************************************************************************)
// version  0=MPEG-2  1=MPEG-1  (2=MPEG-2.5)
  lame_get_version_t = function(handle : PLame_global_flags) : Integer; cdecl;

// encoder delay
  lame_get_encoder_delay_t = function(handle : PLame_global_flags) : Integer; cdecl;

(* padding appended to the input to make sure decoder can fully decode
   all input.  Note that this value can only be calculated during the
   call to lame_encoder_flush().  Before lame_encoder_flush() has
   been called, the value of encoder_padding = 0. *)
  lame_get_encoder_padding_t = function(handle : PLame_global_flags) : Integer; cdecl;

// size of MPEG frame
  lame_get_framesize_t = function(handle : PLame_global_flags) : Integer; cdecl;

// number of PCM samples buffered, but not yet encoded to mp3 data.
  lame_get_mf_samples_to_encode_t = function(handle : PLame_global_flags) : Integer; cdecl;

(* size (bytes) of mp3 data buffered, but not yet encoded.
 this is the number of bytes which would be output by a call to
 lame_encode_flush_nogap.  NOTE: lame_encode_flush() will return
 more bytes than this because it will encode the reamining buffered
 PCM samples before flushing the mp3 buffers. *)
  lame_get_size_mp3buffer_t = function(handle : PLame_global_flags) : Integer; cdecl;

// number of frames encoded so far
  lame_get_frameNum_t = function(handle : PLame_global_flags) : Integer; cdecl;

(* lame's estimate of the total number of frames to be encoded
 only valid if calling program set num_samples *)
  lame_get_totalframes_t = function(handle : PLame_global_flags) : Integer; cdecl;

(*
 * REQUIRED:
 * sets more internal configuration based on data provided above.
 * returns -1 if something failed.
 *)

  lame_init_params_t = function(handle : PLame_global_flags) : Integer; cdecl;

(*
 * OPTIONAL:
 * get the version number, in a string. of the form:
 * "3.63 (beta)" or just "3.63".
 *)
  get_lame_version_t = function : PChar; cdecl;
  get_lame_short_version_t = function : PChar; cdecl;
  get_lame_very_short_version_t = function : PChar; cdecl;
  get_psy_version_t = function : PChar; cdecl;
  get_lame_url_t = function : PChar; cdecl;

(*
 * OPTIONAL:
 * get the version numbers in numerical form.
 *)

  lame_version_t = record
    // generic LAME version
    major : Integer;
    minor : Integer;
    alpha : Integer;               // 0 if not an alpha version
    beta : Integer;                // 0 if not a beta version

    // version of the psy model
    psy_major : Integer;
    psy_minor : Integer;
    psy_alpha : Integer;           // 0 if not an alpha version
    psy_beta : Integer;            // 0 if not a beta version

    // compile time features
    features : PChar;              // Don't make assumptions about the contents!
  end;

  get_lame_version_numerical_t = procedure(lnv : lame_version_t); cdecl;

// Note by A.B.: Attention! Skipping optional functions printing internal lame configuration

(*
 * input pcm data, output (maybe) mp3 frames.
 * This routine handles all buffering, resampling and filtering for you.
 *
 * return code     number of bytes output in mp3buf. Can be 0
 *                 -1:  mp3buf was too small
 *                 -2:  malloc() problem
 *                 -3:  lame_init_params() not called
 *                 -4:  psycho acoustic problems
 *                 -5:  ogg cleanup encoding error
 *                 -6:  ogg frame encoding error
 *
 * The required mp3buf_size can be computed from num_samples,
 * samplerate and encoding rate, but here is a worst case estimate:
 *
 * mp3buf_size in bytes = 1.25*num_samples + 7200
 *
 * I think a tighter bound could be:  (mt, March 2000)
 * MPEG1:
 *    num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512
 * MPEG2:
 *    num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256
 *
 * but test first if you use that!
 *
 * set mp3buf_size = 0 and LAME will not check if mp3buf_size is
 * large enough.
 *
 * NOTE:
 * if gfp->num_channels=2, but gfp->mode = 3 (mono), the L & R channels
 * will be averaged into the L channel before encoding only the L channel
 * This will overwrite the data in buffer_l[] and buffer_r[].
 *
*)

  lame_encode_buffer_t = function(handle : PLame_global_flags;  // global context handle
                                  buffer_l : PShortInt;         // PCM data for left channel
                                  buffer_r : PShortInt;         // PCM data for right channel
                                  nsamples : Integer;           // number of samples per channel
                                  mp3buf : PByte;               // pointer to encoded MP3 stream
                                  mp3buf_size : Integer         // number of valid octets in this stream
                                 ) : Integer; cdecl;

(*
 * as above, but input has L & R channel data interleaved.
 * NOTE:
 * num_samples = number of samples in the L (or R)
 * channel, not the total number of samples in pcm[]
 *)
 lame_encode_buffer_interleaved_t = function(handle : PLame_global_flags;       // global context handle
                                             pcm : PShortInt;                   (* PCM data for left and right
                                                                                   channel, interleaved *)
                                             num_samples : Integer;             (* number of samples per channel,
                                                                                   _not_ number of samples in pcm[] *)
                                             mp3buf : PByte;                    // pointer to encoded MP3 stream
                                             mp3buf_size : Integer              // number of valid octets in this stream
                                            ) : Integer; cdecl;

(* as lame_encode_buffer, but for 'float's.
 * !! NOTE: !! data must still be scaled to be in the same range as
 * short int, +/- 32768
 *)
  lame_encode_buffer_float_t = function(handle : PLame_global_flags;       // global context handle
                             buffer_l : PSingle;                // PCM data for left channel
                             buffer_r : PSingle;                // PCM data for right channel
                             nsamples : Integer;                // number of samples per channel
                             mp3buf : PByte;                    // pointer to encoded MP3 stream
                             mp3buf_size : Integer              // number of valid octets in this stream
                            ) : Integer; cdecl;

// Note by A.B.: Attention! Skipping several variants of encoding functions

(*
 * REQUIRED:
 * lame_encode_flush will flush the intenal PCM buffers, padding with
 * 0's to make sure the final frame is complete, and then flush
 * the internal MP3 buffers, and thus may return a
 * final few mp3 frames.  'mp3buf' should be at least 7200 bytes long
 * to hold all possible emitted data.
 *
 * will also write id3v1 tags (if any) into the bitstream
 *
 * return code = number of bytes output to mp3buf. Can be 0
 *)
  lame_encode_flush_t = function(handle : PLame_global_flags;       // global context handle
                      mp3buf : PByte;                     // pointer to encoded MP3 stream
                      size : Integer                     // number of valid octets in this stream
                     ) : Integer; cdecl;

(*
 * OPTIONAL:
 * lame_encode_flush_nogap will flush the internal mp3 buffers and pad
 * the last frame with ancillary data so it is a complete mp3 frame.
 *
 * 'mp3buf' should be at least 7200 bytes long
 * to hold all possible emitted data.
 *
 * After a call to this routine, the outputed mp3 data is complete, but
 * you may continue to encode new PCM samples and write future mp3 data
 * to a different file.  The two mp3 files will play back with no gaps
 * if they are concatenated together.
 *
 * This routine will NOT write id3v1 tags into the bitstream.
 *
 * return code = number of bytes output to mp3buf. Can be 0
 *)
  lame_encode_flush_nogap_t = function(handle : PLame_global_flags;       // global context handle
                      mp3buf : PByte;                     // pointer to encoded MP3 stream
                      size : Integer                     // number of valid octets in this stream
                     ) : Integer; cdecl;

(*
 * OPTIONAL:
 * Normally, this is called by lame_init_params().  It writes id3v2 and
 * Xing headers into the front of the bitstream, and sets frame counters
 * and bitrate histogram data to 0.  You can also call this after
 * lame_encode_flush_nogap().
 *)
  lame_init_bitstream_t = function(handle : PLame_global_flags) : Integer; cdecl;

// Note by A.B.: Attention! Skipping several optional functions.

(*
 * REQUIRED:
 * final call to free all remaining buffers
 *)
  lame_close_t = function(handle : PLame_global_flags) : Integer; cdecl;

(*********************************************************************
 *
 * decoding
 *
 * a simple interface to mpglib, part of mpg123, is also included if
 * libmp3lame is compiled with HAVE_MPGLIB
 *
 *********************************************************************)

  PMP3data_struct = ^mp3data_struct;

  mp3data_struct = record
    header_parsed : Integer;            (* 1 if header was parsed and following
                                           data was computed *)
    stereo : Integer;                   // number of channels
    samplerate : Integer;               // sample rate
    bitrate : Integer;                  // bitrate
    mode : Integer;                     // mp3 frame type
    mode_ext : Integer;                 // mp3 frame type
    framesize : Integer;                // number of samples per mp3 frame

    // this data is only computed if mpglib detects a Xing VBR header
    nsamp : LongWord;                   // number of samples in mp3 file.
    totalframes : Integer;              // total number of frames in mp3 file

    // this data is not currently computed by the mpglib routines
    framenum : Integer;                 // frames decoded counter                         */
  end;


// required call to initialize decoder
  lame_decode_init_t = function : Integer; cdecl;

(*********************************************************************
 * input 1 mp3 frame, output (maybe) pcm data.
 * lame_decode() return code:
 *   -1: error
 *    0: need more data
 *  n>0: size of pcm output
 *********************************************************************)
  lame_decode_t = function(mp3buf : PByte; len : Integer; pcm_l, pcm_r : PShortInt)
  : Integer; cdecl;

// same as lame_decode, and also returns mp3 header data
  lame_decode_headers_t = function(mp3buf : PByte; len : Integer; pcm_l, pcm_r : PShortInt;
  mp3data : PMP3data_struct) : Integer; cdecl;

// same as lame_decode, but returns at most one frame
  lame_decode1_t = function(mp3buf : PByte; len : Integer; pcm_l, pcm_r : PShortInt)
  : Integer; cdecl;

// same as lame_decode1, but returns at most one frame and mp3 header data
  lame_decode1_headers_t = function(mp3buf : PByte; len : Integer; pcm_l, pcm_r : PShortInt;
  mp3data : PMP3data_struct) : Integer; cdecl;

(*********************************************************************
 *
 * id3tag stuff
 *
 *********************************************************************)

(*
 * The original header file is
 * id3tag.h -- Interface to write ID3 version 1 and 2 tags.
 * Copyright (C) 2000 Don Melton.
 *)

  id3tag_genre_list_cbf = procedure(Number : Integer; Genre : PChar; CustomData : Pointer); cdecl;

  // utility to obtain alphabetically sorted list of genre names with numbers */
  id3tag_genre_list_t = procedure(handler : id3tag_genre_list_cbf; CustomData : Pointer); cdecl;

  id3tag_init_t = procedure(handle : PLame_global_flags); cdecl;

  // force addition of version 2 tag */
  id3tag_add_v2_t = procedure(handle : PLame_global_flags); cdecl;

  // add only a version 1 tag
  id3tag_v1_only_t = procedure(handle : PLame_global_flags); cdecl;

  // add only a version 2 tag
  id3tag_v2_only_t = procedure(handle : PLame_global_flags); cdecl;

  // pad version 1 tag with spaces instead of nulls
  id3tag_space_v1_t = procedure(handle : PLame_global_flags); cdecl;

  // pad version 2 tag with extra 128 bytes
  id3tag_pad_v2_t = procedure(handle : PLame_global_flags); cdecl;

  id3tag_set_title_t = procedure(handle : PLame_global_flags; title : PChar); cdecl;
  id3tag_set_artist_t = procedure(handle : PLame_global_flags; artist : PChar); cdecl;
  id3tag_set_album_t = procedure(handle : PLame_global_flags; album : PChar); cdecl;
  id3tag_set_year_t = procedure(handle : PLame_global_flags; year : PChar); cdecl;
  id3tag_set_comment_t = procedure(handle : PLame_global_flags; comment : PChar); cdecl;
  id3tag_set_track_t = procedure(handle : PLame_global_flags; track : PChar); cdecl;

  // return non-zero result if genre name or number is invalid
  id3tag_set_genre_t = function(handle : PLame_global_flags; genre : PChar) : Integer; cdecl;

const
  LAME_MAXMP3BUFFER = 16384;

var
  LameLoaded : Boolean = False;

  lame_init : lame_init_t;
  lame_set_num_samples : lame_set_num_samples_t;
  lame_get_num_samples : lame_get_num_samples_t;
  lame_set_in_samplerate : lame_set_in_samplerate_t;
  lame_get_in_samplerate : lame_get_in_samplerate_t;
  lame_set_num_channels : lame_set_num_channels_t;
  lame_get_num_channels : lame_get_num_channels_t;
  lame_set_scale : lame_set_scale_t;
  lame_get_scale : lame_get_scale_t;
  lame_set_scale_left : lame_set_scale_left_t;
  lame_get_scale_left : lame_get_scale_left_t;
  lame_set_scale_right : lame_set_scale_right_t;
  lame_get_scale_right : lame_get_scale_right_t;
  lame_set_out_samplerate : lame_set_out_samplerate_t;
  lame_get_out_samplerate : lame_get_out_samplerate_t;
  lame_set_analysis : lame_set_analysis_t;
  lame_get_analysis : lame_get_analysis_t;
  lame_set_bWriteVbrTag : lame_set_bWriteVbrTag_t;
  lame_get_bWriteVbrTag  : lame_get_bWriteVbrTag_t;
  lame_set_decode_only : lame_set_decode_only_t;
  lame_get_decode_only : lame_get_decode_only_t;
  lame_set_ogg : lame_set_ogg_t;
  lame_get_ogg : lame_get_ogg_t;
  lame_set_quality : lame_set_quality_t;
  lame_get_quality : lame_get_quality_t;
  lame_set_mode : lame_set_mode_t;
  lame_get_mode : lame_get_mode_t;
  lame_set_mode_automs : lame_set_mode_automs_t;
  lame_get_mode_automs : lame_get_mode_automs_t;
  lame_set_force_ms : lame_set_force_ms_t;
  lame_get_force_ms : lame_get_force_ms_t;
  lame_set_free_format : lame_set_free_format_t;
  lame_get_free_format : lame_get_free_format_t;
  lame_set_brate : lame_set_brate_t;
  lame_get_brate : lame_get_brate_t;
  lame_set_compression_ratio : lame_set_compression_ratio_t;
  lame_get_compression_ratio : lame_get_compression_ratio_t;
  lame_set_preset : lame_set_preset_t;
  lame_set_asm_optimizations : lame_set_asm_optimizations_t;
  lame_set_copyright : lame_set_copyright_t;
  lame_get_copyright : lame_get_copyright_t;
  lame_set_original : lame_set_original_t;
  lame_get_original : lame_get_original_t;
  lame_set_error_protection : lame_set_error_protection_t;
  lame_get_error_protection : lame_get_error_protection_t;
  lame_set_padding_type : lame_set_padding_type_t;
  lame_get_padding_type : lame_get_padding_type_t;
  lame_set_extension : lame_set_extension_t;
  lame_get_extension : lame_get_extension_t;
  lame_set_strict_ISO : lame_set_strict_ISO_t;
  lame_get_strict_ISO : lame_get_strict_ISO_t;
  lame_set_VBR : lame_set_VBR_t;
  lame_get_VBR : lame_get_VBR_t;
  lame_set_VBR_q : lame_set_VBR_q_t;
  lame_get_VBR_q : lame_get_VBR_q_t;
  lame_set_VBR_mean_bitrate_kbps : lame_set_VBR_mean_bitrate_kbps_t;
  lame_get_VBR_mean_bitrate_kbps : lame_get_VBR_mean_bitrate_kbps_t;
  lame_set_VBR_min_bitrate_kbps : lame_set_VBR_min_bitrate_kbps_t;
  lame_get_VBR_min_bitrate_kbps : lame_get_VBR_min_bitrate_kbps_t;
  lame_set_VBR_max_bitrate_kbps : lame_set_VBR_max_bitrate_kbps_t;
  lame_get_VBR_max_bitrate_kbps : lame_get_VBR_max_bitrate_kbps_t;
  lame_set_VBR_hard_min : lame_set_VBR_hard_min_t;
  lame_get_VBR_hard_min : lame_get_VBR_hard_min_t;
  lame_set_lowpassfreq : lame_set_lowpassfreq_t;
  lame_get_lowpassfreq : lame_get_lowpassfreq_t;
  lame_set_lowpasswidth : lame_set_lowpasswidth_t;
  lame_get_lowpasswidth : lame_get_lowpasswidth_t;
  lame_set_highpassfreq : lame_set_highpassfreq_t;
  lame_get_highpassfreq : lame_get_highpassfreq_t;
  lame_set_highpasswidth : lame_set_highpasswidth_t;
  lame_get_highpasswidth : lame_get_highpasswidth_t;
  lame_get_version : lame_get_version_t;
  lame_get_encoder_delay : lame_get_encoder_delay_t;
  lame_get_encoder_padding : lame_get_encoder_padding_t;
  lame_get_framesize : lame_get_framesize_t;
  lame_get_mf_samples_to_encode : lame_get_mf_samples_to_encode_t;
  lame_get_size_mp3buffer : lame_get_size_mp3buffer_t;
  lame_get_frameNum : lame_get_frameNum_t;
  lame_get_totalframes : lame_get_totalframes_t;
  lame_init_params : lame_init_params_t;
  get_lame_version : get_lame_version_t;
  get_lame_short_version : get_lame_short_version_t;
  get_lame_very_short_version : get_lame_very_short_version_t;
  get_psy_version : get_psy_version_t;
  get_lame_url : get_lame_url_t;
  get_lame_version_numerical : get_lame_version_numerical_t;
  lame_encode_buffer : lame_encode_buffer_t;
  lame_encode_buffer_interleaved : lame_encode_buffer_interleaved_t;
  lame_encode_buffer_float : lame_encode_buffer_float_t;
  lame_encode_flush : lame_encode_flush_t;
  lame_encode_flush_nogap : lame_encode_flush_nogap_t;
  lame_init_bitstream : lame_init_bitstream_t;
  lame_close : lame_close_t;
  lame_decode_init : lame_decode_init_t;
  lame_decode : lame_decode_t;
  lame_decode_headers : lame_decode_headers_t;
  lame_decode1 : lame_decode1_t;
  lame_decode1_headers : lame_decode1_headers_t;
  id3tag_genre_list : id3tag_genre_list_t;
  id3tag_init : id3tag_init_t;
  id3tag_add_v2 : id3tag_add_v2_t;
  id3tag_v1_only : id3tag_v1_only_t;
  id3tag_v2_only : id3tag_v2_only_t;
  id3tag_space_v1 : id3tag_space_v1_t;
  id3tag_pad_v2 : id3tag_pad_v2_t;
  id3tag_set_title : id3tag_set_title_t;
  id3tag_set_artist : id3tag_set_artist_t;
  id3tag_set_album : id3tag_set_album_t;
  id3tag_set_year : id3tag_set_year_t;
  id3tag_set_comment : id3tag_set_comment_t;
  id3tag_set_track : id3tag_set_track_t;
  id3tag_set_genre : id3tag_set_genre_t;

procedure LoadLAME;
procedure UnloadLAME;

implementation

var

{$IFDEF LINUX}
  Libhandle : Pointer;
{$ENDIF}

{$IFDEF WIN32}
  Libhandle : HMODULE;
{$ENDIF}

procedure LoadLAME;
begin
  if LAMELoaded then Exit;
{$IFDEF LINUX}
  Libhandle := dlopen(LAME_PATH, RTLD_NOW or RTLD_GLOBAL);
  if Libhandle <> nil then
  begin
    LAMELoaded := True;

    lame_init := dlsym(Libhandle, 'lame_init');
    lame_set_num_samples := dlsym(Libhandle, 'lame_set_num_samples');
    lame_get_num_samples := dlsym(Libhandle, 'lame_get_num_samples');
    lame_set_in_samplerate := dlsym(Libhandle, 'lame_set_in_samplerate');
    lame_get_in_samplerate := dlsym(Libhandle, 'lame_get_in_samplerate');
    lame_set_num_channels := dlsym(Libhandle, 'lame_set_num_channels');
    lame_get_num_channels := dlsym(Libhandle, 'lame_get_num_channels');
    lame_set_scale := dlsym(Libhandle, 'lame_set_scale');
    lame_get_scale := dlsym(Libhandle, 'lame_get_scale');
    lame_set_scale_left := dlsym(Libhandle, 'lame_set_scale_left');
    lame_get_scale_left := dlsym(Libhandle, 'lame_get_scale_left');
    lame_set_scale_right := dlsym(Libhandle, 'lame_set_scale_right');
    lame_get_scale_right := dlsym(Libhandle, 'lame_get_scale_right');
    lame_set_out_samplerate := dlsym(Libhandle, 'lame_set_out_samplerate');
    lame_get_out_samplerate := dlsym(Libhandle, 'lame_get_out_samplerate');
    lame_set_analysis := dlsym(Libhandle, 'lame_set_analysis');
    lame_get_analysis := dlsym(Libhandle, 'lame_get_analysis');
    lame_set_bWriteVbrTag := dlsym(Libhandle, 'lame_set_bWriteVbrTag');
    lame_get_bWriteVbrTag    := dlsym(Libhandle, 'lame_get_bWriteVbrTag');
    lame_set_decode_only := dlsym(Libhandle, 'lame_set_decode_only');
    lame_get_decode_only := dlsym(Libhandle, 'lame_get_decode_only');
    lame_set_ogg := dlsym(Libhandle, 'lame_set_ogg');
    lame_get_ogg := dlsym(Libhandle, 'lame_get_ogg');
    lame_set_quality := dlsym(Libhandle, 'lame_set_quality');
    lame_get_quality := dlsym(Libhandle, 'lame_get_quality');
    lame_set_mode := dlsym(Libhandle, 'lame_set_mode');
    lame_get_mode := dlsym(Libhandle, 'lame_get_mode');
    lame_set_mode_automs := dlsym(Libhandle, 'lame_set_mode_automs');
    lame_get_mode_automs := dlsym(Libhandle, 'lame_get_mode_automs');
    lame_set_force_ms := dlsym(Libhandle, 'lame_set_force_ms');
    lame_get_force_ms := dlsym(Libhandle, 'lame_get_force_ms');
    lame_set_free_format := dlsym(Libhandle, 'lame_set_free_format');
    lame_get_free_format := dlsym(Libhandle, 'lame_get_free_format');
    lame_set_brate := dlsym(Libhandle, 'lame_set_brate');
    lame_get_brate := dlsym(Libhandle, 'lame_get_brate');
    lame_set_compression_ratio := dlsym(Libhandle, 'lame_set_compression_ratio');
    lame_get_compression_ratio := dlsym(Libhandle, 'lame_get_compression_ratio');
    lame_set_preset := dlsym(Libhandle, 'lame_set_preset');
    lame_set_asm_optimizations := dlsym(Libhandle, 'lame_set_asm_optimizations');
    lame_set_copyright := dlsym(Libhandle, 'lame_set_copyright');
    lame_get_copyright := dlsym(Libhandle, 'lame_get_copyright');
    lame_set_original := dlsym(Libhandle, 'lame_set_original');
    lame_get_original := dlsym(Libhandle, 'lame_get_original');
    lame_set_error_protection := dlsym(Libhandle, 'lame_set_error_protection');
    lame_get_error_protection := dlsym(Libhandle, 'lame_get_error_protection');
    lame_set_padding_type := dlsym(Libhandle, 'lame_set_padding_type');
    lame_get_padding_type := dlsym(Libhandle, 'lame_get_padding_type');
    lame_set_extension := dlsym(Libhandle, 'lame_set_extension');
    lame_get_extension := dlsym(Libhandle, 'lame_get_extension');
    lame_set_strict_ISO := dlsym(Libhandle, 'lame_set_strict_ISO');
    lame_get_strict_ISO := dlsym(Libhandle, 'lame_get_strict_ISO');
    lame_set_VBR := dlsym(Libhandle, 'lame_set_VBR');
    lame_get_VBR := dlsym(Libhandle, 'lame_get_VBR');
    lame_set_VBR_q := dlsym(Libhandle, 'lame_set_VBR_q');
    lame_get_VBR_q := dlsym(Libhandle, 'lame_get_VBR_q');
    lame_set_VBR_mean_bitrate_kbps := dlsym(Libhandle, 'lame_set_VBR_mean_bitrate_kbps');
    lame_get_VBR_mean_bitrate_kbps := dlsym(Libhandle, 'lame_get_VBR_mean_bitrate_kbps');
    lame_set_VBR_min_bitrate_kbps := dlsym(Libhandle, 'lame_set_VBR_min_bitrate_kbps');
    lame_get_VBR_min_bitrate_kbps := dlsym(Libhandle, 'lame_get_VBR_min_bitrate_kbps');
    lame_set_VBR_max_bitrate_kbps := dlsym(Libhandle, 'lame_set_VBR_max_bitrate_kbps');
    lame_get_VBR_max_bitrate_kbps := dlsym(Libhandle, 'lame_get_VBR_max_bitrate_kbps');
    lame_set_VBR_hard_min := dlsym(Libhandle, 'lame_set_VBR_hard_min');
    lame_get_VBR_hard_min := dlsym(Libhandle, 'lame_get_VBR_hard_min');
    lame_set_lowpassfreq := dlsym(Libhandle, 'lame_set_lowpassfreq');
    lame_get_lowpassfreq := dlsym(Libhandle, 'lame_get_lowpassfreq');
    lame_set_lowpasswidth := dlsym(Libhandle, 'lame_set_lowpasswidth');
    lame_get_lowpasswidth := dlsym(Libhandle, 'lame_get_lowpasswidth');
    lame_set_highpassfreq := dlsym(Libhandle, 'lame_set_highpassfreq');
    lame_get_highpassfreq := dlsym(Libhandle, 'lame_get_highpassfreq');
    lame_set_highpasswidth := dlsym(Libhandle, 'lame_set_highpasswidth');
    lame_get_highpasswidth := dlsym(Libhandle, 'lame_get_highpasswidth');
    lame_get_version := dlsym(Libhandle, 'lame_get_version');
    lame_get_encoder_delay := dlsym(Libhandle, 'lame_get_encoder_delay');
    lame_get_encoder_padding := dlsym(Libhandle, 'lame_get_encoder_padding');
    lame_get_framesize := dlsym(Libhandle, 'lame_get_framesize');
    lame_get_mf_samples_to_encode := dlsym(Libhandle, 'lame_get_mf_samples_to_encode');
    lame_get_size_mp3buffer := dlsym(Libhandle, 'lame_get_size_mp3buffer');
    lame_get_frameNum := dlsym(Libhandle, 'lame_get_frameNum');
    lame_get_totalframes := dlsym(Libhandle, 'lame_get_totalframes');
    lame_init_params := dlsym(Libhandle, 'lame_init_params');
    get_lame_version := dlsym(Libhandle, 'get_lame_version');
    get_lame_short_version := dlsym(Libhandle, 'get_lame_short_version');
    get_lame_very_short_version := dlsym(Libhandle, 'get_lame_very_short_version');
    get_psy_version := dlsym(Libhandle, 'get_psy_version');
    get_lame_url := dlsym(Libhandle, 'get_lame_url');
    get_lame_version_numerical := dlsym(Libhandle, 'get_lame_version_numerical');
    lame_encode_buffer := dlsym(Libhandle, 'lame_encode_buffer');
    lame_encode_buffer_interleaved := dlsym(Libhandle, 'lame_encode_buffer_interleaved');
    lame_encode_buffer_float := dlsym(Libhandle, 'lame_encode_buffer_float');
    lame_encode_flush := dlsym(Libhandle, 'lame_encode_flush');
    lame_encode_flush_nogap := dlsym(Libhandle, 'lame_encode_flush_nogap');
    lame_init_bitstream := dlsym(Libhandle, 'lame_init_bitstream');
    lame_close := dlsym(Libhandle, 'lame_close');
    lame_decode_init := dlsym(Libhandle, 'lame_decode_init');
    lame_decode := dlsym(Libhandle, 'lame_decode');
    lame_decode_headers := dlsym(Libhandle, 'lame_decode_headers');
    lame_decode1 := dlsym(Libhandle, 'lame_decode1');
    lame_decode1_headers := dlsym(Libhandle, 'lame_decode1_headers');
    id3tag_genre_list := dlsym(Libhandle, 'id3tag_genre_list');
    id3tag_init := dlsym(Libhandle, 'id3tag_init');
    id3tag_add_v2 := dlsym(Libhandle, 'id3tag_add_v2');
    id3tag_v1_only := dlsym(Libhandle, 'id3tag_v1_only');
    id3tag_v2_only := dlsym(Libhandle, 'id3tag_v2_only');
    id3tag_space_v1 := dlsym(Libhandle, 'id3tag_space_v1');
    id3tag_pad_v2 := dlsym(Libhandle, 'id3tag_pad_v2');
    id3tag_set_title := dlsym(Libhandle, 'id3tag_set_title');
    id3tag_set_artist := dlsym(Libhandle, 'id3tag_set_artist');
    id3tag_set_album := dlsym(Libhandle, 'id3tag_set_album');
    id3tag_set_year := dlsym(Libhandle, 'id3tag_set_year');
    id3tag_set_comment := dlsym(Libhandle, 'id3tag_set_comment');
    id3tag_set_track := dlsym(Libhandle, 'id3tag_set_track');
    id3tag_set_genre := dlsym(Libhandle, 'id3tag_set_genre');
  end;
{$ENDIF}

{$IFDEF WIN32}
  Libhandle := LoadLibraryEx(LAME_PATH, 0, 0);
  if Libhandle <> 0 then
  begin
    LAMELoaded := True;

    lame_init := GetProcAddress(Libhandle, 'lame_init');
    lame_set_num_samples := GetProcAddress(Libhandle, 'lame_set_num_samples');
    lame_get_num_samples := GetProcAddress(Libhandle, 'lame_get_num_samples');
    lame_set_in_samplerate := GetProcAddress(Libhandle, 'lame_set_in_samplerate');
    lame_get_in_samplerate := GetProcAddress(Libhandle, 'lame_get_in_samplerate');
    lame_set_num_channels := GetProcAddress(Libhandle, 'lame_set_num_channels');
    lame_get_num_channels := GetProcAddress(Libhandle, 'lame_get_num_channels');
    lame_set_scale := GetProcAddress(Libhandle, 'lame_set_scale');
    lame_get_scale := GetProcAddress(Libhandle, 'lame_get_scale');
    lame_set_scale_left := GetProcAddress(Libhandle, 'lame_set_scale_left');
    lame_get_scale_left := GetProcAddress(Libhandle, 'lame_get_scale_left');
    lame_set_scale_right := GetProcAddress(Libhandle, 'lame_set_scale_right');
    lame_get_scale_right := GetProcAddress(Libhandle, 'lame_get_scale_right');
    lame_set_out_samplerate := GetProcAddress(Libhandle, 'lame_set_out_samplerate');
    lame_get_out_samplerate := GetProcAddress(Libhandle, 'lame_get_out_samplerate');
    lame_set_analysis := GetProcAddress(Libhandle, 'lame_set_analysis');
    lame_get_analysis := GetProcAddress(Libhandle, 'lame_get_analysis');
    lame_set_bWriteVbrTag := GetProcAddress(Libhandle, 'lame_set_bWriteVbrTag');
    lame_get_bWriteVbrTag    := GetProcAddress(Libhandle, 'lame_get_bWriteVbrTag');
    lame_set_decode_only := GetProcAddress(Libhandle, 'lame_set_decode_only');
    lame_get_decode_only := GetProcAddress(Libhandle, 'lame_get_decode_only');
    lame_set_ogg := GetProcAddress(Libhandle, 'lame_set_ogg');
    lame_get_ogg := GetProcAddress(Libhandle, 'lame_get_ogg');
    lame_set_quality := GetProcAddress(Libhandle, 'lame_set_quality');
    lame_get_quality := GetProcAddress(Libhandle, 'lame_get_quality');
    lame_set_mode := GetProcAddress(Libhandle, 'lame_set_mode');
    lame_get_mode := GetProcAddress(Libhandle, 'lame_get_mode');
    lame_set_mode_automs := GetProcAddress(Libhandle, 'lame_set_mode_automs');
    lame_get_mode_automs := GetProcAddress(Libhandle, 'lame_get_mode_automs');
    lame_set_force_ms := GetProcAddress(Libhandle, 'lame_set_force_ms');
    lame_get_force_ms := GetProcAddress(Libhandle, 'lame_get_force_ms');
    lame_set_free_format := GetProcAddress(Libhandle, 'lame_set_free_format');
    lame_get_free_format := GetProcAddress(Libhandle, 'lame_get_free_format');
    lame_set_brate := GetProcAddress(Libhandle, 'lame_set_brate');
    lame_get_brate := GetProcAddress(Libhandle, 'lame_get_brate');
    lame_set_compression_ratio := GetProcAddress(Libhandle, 'lame_set_compression_ratio');
    lame_get_compression_ratio := GetProcAddress(Libhandle, 'lame_get_compression_ratio');
    lame_set_preset := GetProcAddress(Libhandle, 'lame_set_preset');
    lame_set_asm_optimizations := GetProcAddress(Libhandle, 'lame_set_asm_optimizations');
    lame_set_copyright := GetProcAddress(Libhandle, 'lame_set_copyright');
    lame_get_copyright := GetProcAddress(Libhandle, 'lame_get_copyright');
    lame_set_original := GetProcAddress(Libhandle, 'lame_set_original');
    lame_get_original := GetProcAddress(Libhandle, 'lame_get_original');
    lame_set_error_protection := GetProcAddress(Libhandle, 'lame_set_error_protection');
    lame_get_error_protection := GetProcAddress(Libhandle, 'lame_get_error_protection');
    lame_set_padding_type := GetProcAddress(Libhandle, 'lame_set_padding_type');
    lame_get_padding_type := GetProcAddress(Libhandle, 'lame_get_padding_type');
    lame_set_extension := GetProcAddress(Libhandle, 'lame_set_extension');
    lame_get_extension := GetProcAddress(Libhandle, 'lame_get_extension');
    lame_set_strict_ISO := GetProcAddress(Libhandle, 'lame_set_strict_ISO');
    lame_get_strict_ISO := GetProcAddress(Libhandle, 'lame_get_strict_ISO');
    lame_set_VBR := GetProcAddress(Libhandle, 'lame_set_VBR');
    lame_get_VBR := GetProcAddress(Libhandle, 'lame_get_VBR');
    lame_set_VBR_q := GetProcAddress(Libhandle, 'lame_set_VBR_q');
    lame_get_VBR_q := GetProcAddress(Libhandle, 'lame_get_VBR_q');
    lame_set_VBR_mean_bitrate_kbps := GetProcAddress(Libhandle, 'lame_set_VBR_mean_bitrate_kbps');
    lame_get_VBR_mean_bitrate_kbps := GetProcAddress(Libhandle, 'lame_get_VBR_mean_bitrate_kbps');
    lame_set_VBR_min_bitrate_kbps := GetProcAddress(Libhandle, 'lame_set_VBR_min_bitrate_kbps');
    lame_get_VBR_min_bitrate_kbps := GetProcAddress(Libhandle, 'lame_get_VBR_min_bitrate_kbps');
    lame_set_VBR_max_bitrate_kbps := GetProcAddress(Libhandle, 'lame_set_VBR_max_bitrate_kbps');
    lame_get_VBR_max_bitrate_kbps := GetProcAddress(Libhandle, 'lame_get_VBR_max_bitrate_kbps');
    lame_set_VBR_hard_min := GetProcAddress(Libhandle, 'lame_set_VBR_hard_min');
    lame_get_VBR_hard_min := GetProcAddress(Libhandle, 'lame_get_VBR_hard_min');
    lame_set_lowpassfreq := GetProcAddress(Libhandle, 'lame_set_lowpassfreq');
    lame_get_lowpassfreq := GetProcAddress(Libhandle, 'lame_get_lowpassfreq');
    lame_set_lowpasswidth := GetProcAddress(Libhandle, 'lame_set_lowpasswidth');
    lame_get_lowpasswidth := GetProcAddress(Libhandle, 'lame_get_lowpasswidth');
    lame_set_highpassfreq := GetProcAddress(Libhandle, 'lame_set_highpassfreq');
    lame_get_highpassfreq := GetProcAddress(Libhandle, 'lame_get_highpassfreq');
    lame_set_highpasswidth := GetProcAddress(Libhandle, 'lame_set_highpasswidth');
    lame_get_highpasswidth := GetProcAddress(Libhandle, 'lame_get_highpasswidth');
    lame_get_version := GetProcAddress(Libhandle, 'lame_get_version');
    lame_get_encoder_delay := GetProcAddress(Libhandle, 'lame_get_encoder_delay');
    lame_get_encoder_padding := GetProcAddress(Libhandle, 'lame_get_encoder_padding');
    lame_get_framesize := GetProcAddress(Libhandle, 'lame_get_framesize');
    lame_get_mf_samples_to_encode := GetProcAddress(Libhandle, 'lame_get_mf_samples_to_encode');
    lame_get_size_mp3buffer := GetProcAddress(Libhandle, 'lame_get_size_mp3buffer');
    lame_get_frameNum := GetProcAddress(Libhandle, 'lame_get_frameNum');
    lame_get_totalframes := GetProcAddress(Libhandle, 'lame_get_totalframes');
    lame_init_params := GetProcAddress(Libhandle, 'lame_init_params');
    get_lame_version := GetProcAddress(Libhandle, 'get_lame_version');
    get_lame_short_version := GetProcAddress(Libhandle, 'get_lame_short_version');
    get_lame_very_short_version := GetProcAddress(Libhandle, 'get_lame_very_short_version');
    get_psy_version := GetProcAddress(Libhandle, 'get_psy_version');
    get_lame_url := GetProcAddress(Libhandle, 'get_lame_url');
    get_lame_version_numerical := GetProcAddress(Libhandle, 'get_lame_version_numerical');
    lame_encode_buffer := GetProcAddress(Libhandle, 'lame_encode_buffer');
    lame_encode_buffer_interleaved := GetProcAddress(Libhandle, 'lame_encode_buffer_interleaved');
    lame_encode_buffer_float := GetProcAddress(Libhandle, 'lame_encode_buffer_float');
    lame_encode_flush := GetProcAddress(Libhandle, 'lame_encode_flush');
    lame_encode_flush_nogap := GetProcAddress(Libhandle, 'lame_encode_flush_nogap');
    lame_init_bitstream := GetProcAddress(Libhandle, 'lame_init_bitstream');
    lame_close := GetProcAddress(Libhandle, 'lame_close');
    lame_decode_init := GetProcAddress(Libhandle, 'lame_decode_init');
    lame_decode := GetProcAddress(Libhandle, 'lame_decode');
    lame_decode_headers := GetProcAddress(Libhandle, 'lame_decode_headers');
    lame_decode1 := GetProcAddress(Libhandle, 'lame_decode1');
    lame_decode1_headers := GetProcAddress(Libhandle, 'lame_decode1_headers');
    id3tag_genre_list := GetProcAddress(Libhandle, 'id3tag_genre_list');
    id3tag_init := GetProcAddress(Libhandle, 'id3tag_init');
    id3tag_add_v2 := GetProcAddress(Libhandle, 'id3tag_add_v2');
    id3tag_v1_only := GetProcAddress(Libhandle, 'id3tag_v1_only');
    id3tag_v2_only := GetProcAddress(Libhandle, 'id3tag_v2_only');
    id3tag_space_v1 := GetProcAddress(Libhandle, 'id3tag_space_v1');
    id3tag_pad_v2 := GetProcAddress(Libhandle, 'id3tag_pad_v2');
    id3tag_set_title := GetProcAddress(Libhandle, 'id3tag_set_title');
    id3tag_set_artist := GetProcAddress(Libhandle, 'id3tag_set_artist');
    id3tag_set_album := GetProcAddress(Libhandle, 'id3tag_set_album');
    id3tag_set_year := GetProcAddress(Libhandle, 'id3tag_set_year');
    id3tag_set_comment := GetProcAddress(Libhandle, 'id3tag_set_comment');
    id3tag_set_track := GetProcAddress(Libhandle, 'id3tag_set_track');
    id3tag_set_genre := GetProcAddress(Libhandle, 'id3tag_set_genre');
  end;
{$ENDIF}
end;

procedure UnloadLAME;
begin

  LAMELoaded := False;

{$IFDEF LINUX}
  if Libhandle <> nil then dlclose(Libhandle);
{$ENDIF}

{$IFDEF WIN32}
  if Libhandle <> 0 then FreeLibrary(Libhandle);
{$ENDIF}

end;
end.

MOJA PROCEDURA ZAPISU STRUMIENIA wygląda tak :

PROCEDURE SaveStream(buffer:Pointer; len:DWORD);stdcall;
var
 sciezka :String;
Begin
 //zwalnia zmienną pliku strumieniowego by nie był w użyciu
 if SciezkaZapisu <> Form1.labTytul.Caption then FreeAndNil(FileStream);
 TRY
   //jeżeli ustawiona opcja nagrywania to...
   if RecordingStart = True then
   begin
     SciezkaZapisu:= Form1.labTytul.Caption;   //pobiera tytuł jako nazwę pliku
     //wykreowanie pliku do zapisu strumienia...           
     if (FileStream = nil)and(SciezkaZapisu > ' ') then
     begin
       //ustawia całkowitą i poprawną ścieżkę zapisu dla strumienia
       sciezka:= KatalogZapisu +'\'+ UsunNiedozwolonyZnak(SciezkaZapisu) +'.'+ LowerCase(Format);
       FileStream:= TFileStream.Create(sciezka,fmCreate);      //kreuje zmienną
       RecordingInfo:= 'Rozpoczęcie zapisywania';
     end;
   end else RecordingInfo:= '';
   //zwolnienie pliku lub zapełnianie strumieniem w zależnosci od opcji Recording
   if buffer = nil then
   begin
     FreeAndNil(FileStream); //zwalnia zmienną pliku strumieniowego by nie był w użyciu
   end else
   if (RecordingStart = True)and(SciezkaZapisu > ' ') then
   begin
      {W TYM MIEJSCU POWINNO BYĆ COŚ Z LAME_ENC.dll które zamieni dane na format mp3
      i nie wiem co ?  dlatego zapisuje jak leci i wychodzi taki format jaki jest
      aktualnie nadawany przez radio}
     FileStream.Write(buffer^,len);
     RecordingInfo:= 'Zapisywanie do pliku...';
   end;
   //zatrzymuje nagrywanie w przypadku braku tytułu
   if not (SciezkaZapisu > ' ') then Form1.sbtnStopRecordingClick(nil);
 EXCEPT
   RecordingInfo:= 'Błąd zapisu do pliku !';
 END
End; //ok.

Więc proszę o podpowiedź jaką funkcję umieścić w mojej procedurze aby zamieniać strumień radiowy na format mp3 ?

0

Zajrzyj na przyklad tutaj i przetlumacz sobie na Delphi. Ten kod naprawde nie jest zbyt skomplikowany.

0

Dzięki ale ten kod jest do konwersji wav na mp3.
Mam podobny kod w Delphi , a nawet komponenty do zamiany formatu z wav na mp3.
Ale nie o to chodzi.
Chcę przypomnieć iż strumień radiowy jest nadawany w formacie AAC plus (najczęściej) i te dane
nie są rozkodowywane na wav by potem móc je zakodować na mp3.
Zreszta prościej od razu by było z AAC na MP3 niż z AAC na WAV i dopiero z WAV na MP3.
Mimo wszystko bardzo dziękuje bo każda sugestia naprawdę mi pomaga i zachęca bym jednak nie rezygnował z dokończenia programu, tym bardziej że trochę czasu mnie kosztował :)

0

te dane nie są rozkodowywane

Skoro slyszysz radio, to strumien jest dekodowany :P Problem w tym, zeby zdekodowane dane skierowac nie do karty dzwiekowaj, a do encodera mp3. Bawilem sie tym kiedys i nawet cos mi wyszlo, tyle ze otwieralem lokalne pliki mp3, ogg i wma i wysylalem zdekodowany strumien do enkodera.

Radze popytac na forum un4seen jak mozna to zrobic ze strumieniem z radia - na pewno podobnie i nie bedzie to takie trudne.

1 użytkowników online, w tym zalogowanych: 0, gości: 1