{This unit is part of United Openlibraries of Sound (uos)} {This is the Dynamic loading Pascal Wrapper of bs2b library of Boris Mikhaylov Load library with bs_load() and release with bs_unload(). License : modified LGPL. Fred van Stappen / fiens@hotmail.com } unit uos_bs2b; {$mode objfpc}{$H+} {$PACKRECORDS C} interface uses SysUtils, dynlibs, ctypes, math; const libsb= {$IFDEF unix} 'libbs2b.so.0'; {$ELSE} 'bs2b.dll'; {$ENDIF} { Minimum/maximum sample rate (Hz) } BS2B_MINSRATE = 2000; BS2B_MAXSRATE = 384000; { Minimum/maximum cut frequency (Hz) } { bs2b_set_level_fcut() } BS2B_MINFCUT = 300; BS2B_MAXFCUT = 2000; { Minimum/maximum feed level (dB * 10 @ low frequencies) } { bs2b_set_level_feed() } { 1 dB } BS2B_MINFEED = 10; { 15 dB } BS2B_MAXFEED = 150; const // for using with bs2b_set_level BS2B_HIGH_CLEVEL = (CInt32(700)) or ((CInt32(30)) shl 16); BS2B_MIDDLE_CLEVEL = (CInt32(500)) or ((CInt32(45)) shl 16); BS2B_LOW_CLEVEL = (CInt32(360)) or ((CInt32(60)) shl 16); { Easy crossfeed levels (Obsolete) } BS2B_HIGH_ECLEVEL = (CInt32(700)) or ((CInt32(60)) shl 16); BS2B_MIDDLE_ECLEVEL = (CInt32(500)) or ((CInt32(72)) shl 16); BS2B_LOW_ECLEVEL = (CInt32(360)) or ((CInt32(84)) shl 16); BS2B_DEFAULT_CLEVEL = (CInt32(700)) or ((CInt32(45)) shl 16); BS2B_CMOY_CLEVEL =(CInt32(700)) or ((CInt32(60)) shl 16); BS2B_JMEIER_CLEVEL = (CInt32(650)) or ((CInt32(95)) shl 16); { Default sample rate (Hz) } const BS2B_DEFAULT_SRATE = 44100; { A delay at low frequency by microseconds according to cut frequency } function bs2b_level_delay(fcut : longint) : longint; { Crossfeed level } { Sample rate (Hz) } { Lowpass IIR filter coefficients } { Highboost IIR filter coefficients } { Global gain against overloading } { Buffer of last filtered sample: [0] 1-st channel, [1] 2-d channel } type Tt_bs2bdp = ^Tt_bs2bd; Tt_bs2bd = packed record level : CInt32; srate : CInt32; a0_lo : CDouble; b1_lo : CDouble; a0_hi : CDouble; a1_hi : CDouble; b1_hi : CDouble; gain : CDouble; lfs : packed record asis : array[0..1] of cdouble; lo : array[0..1] of cdouble; hi : array[0..1] of cdouble; end; end; ////// Dynamic load : Vars that will hold our dynamically loaded functions... // *************************** functions ******************************* var { Open } bs2b_open : function():Tt_bs2bdp; cdecl; { Close } bs2b_close : procedure(bs2bdp:Tt_bs2bdp); cdecl; { Sets a new coefficients by new crossfeed value. * level = ( fcut | feed << 16 ) ) * where 'feed' is crossfeeding level at low frequencies (dB * 10) * and 'fcut' is cut frecuency (Hz) } bs2b_set_level : procedure(bs2bdp:Tt_bs2bdp; level: CInt32); cdecl; { Return a current crossfeed level value. } bs2b_get_level : function(bs2bdp:Tt_bs2bdp): CInt32; cdecl; { Sets a new coefficients by new cut frecuency value (Hz). } bs2b_set_level_fcut : procedure(bs2bdp:Tt_bs2bdp; fcut: CInt32); cdecl; { Return a current cut frecuency value (Hz). } bs2b_get_level_fcut : function(bs2bdp:Tt_bs2bdp): CInt32; cdecl; { Sets a new coefficients by new crossfeeding level value (dB * 10). } bs2b_set_level_feed : procedure(bs2bdp:Tt_bs2bdp; feed: CInt32); cdecl; { Return a current crossfeeding level value (dB * 10). } bs2b_get_level_feed : function(bs2bdp:Tt_bs2bdp): CInt32; cdecl; { Return a current delay value at low frequencies (micro seconds). } bs2b_get_level_delay : function(bs2bdp:Tt_bs2bdp): CInt32; cdecl; { Clear buffers and sets a new coefficients with new sample rate value. * srate - sample rate by Hz. } bs2b_set_srate : procedure(bs2bdp:Tt_bs2bdp; srate: CInt32); cdecl; { Return current sample rate value } bs2b_get_srate : function(bs2bdp:Tt_bs2bdp): CInt32; cdecl; { Clear buffer } bs2b_clear : procedure(bs2bdp:Tt_bs2bdp); cdecl; { Return 1 if buffer is clear } bs2b_is_clear : function(bs2bdp:Tt_bs2bdp): CInt32; cdecl; { Return bs2b version string } (* Const before declarator ignored *) bs2b_runtime_version : function():pchar; cdecl; { Return bs2b version integer } bs2b_runtime_version_int : function(): CInt32; cdecl; { 'bs2b_cross_feed_*' crossfeeds buffer of 'n' stereo samples * pointed by 'sample'. * sample[i] - first channel, * sample[i+1] - second channel. * Where 'i' is ( i = 0; i < n * 2; i += 2 ) } { sample poits to double floats native endians } bs2b_cross_feed_d : procedure(bs2bdp:Tt_bs2bdp; var sample:Cdouble; n: CInt32); cdecl; { sample poits to double floats big endians } bs2b_cross_feed_dbe : procedure(bs2bdp:Tt_bs2bdp; var sample:Cdouble; n: CInt32); cdecl; { sample poits to double floats little endians } bs2b_cross_feed_dle : procedure(bs2bdp:Tt_bs2bdp; var sample:Cdouble; n: CInt32); cdecl; { sample poits to floats native endians } bs2b_cross_feed_f : procedure(bs2bdp:Tt_bs2bdp; var sample:Cfloat; n:CInt32); cdecl; { sample poits to floats big endians } bs2b_cross_feed_fbe : procedure(bs2bdp:Tt_bs2bdp; var sample:Cfloat; n:CInt32); cdecl; { sample poits to floats little endians } bs2b_cross_feed_fle : procedure(bs2bdp:Tt_bs2bdp; var sample:cfloat; n:CInt32); cdecl; { sample poits to 32bit signed integers native endians } bs2b_cross_feed_s32 : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt32); cdecl; { sample poits to 32bit unsigned integers native endians } bs2b_cross_feed_u32 : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt32); cdecl; { sample poits to 32bit signed integers big endians } bs2b_cross_feed_s32be : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt32); cdecl; { sample poits to 32bit unsigned integers big endians } bs2b_cross_feed_u32be : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt32); cdecl; { sample poits to 32bit signed integers little endians } bs2b_cross_feed_s32le : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt32); cdecl; { sample poits to 32bit unsigned integers little endians } bs2b_cross_feed_u32le : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt32); cdecl; { sample poits to 16bit signed integers native endians } bs2b_cross_feed_s16 : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt16; n:CInt); cdecl; { sample poits to 16bit unsigned integers native endians } bs2b_cross_feed_u16 : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt); cdecl; { sample poits to 16bit signed integers big endians } bs2b_cross_feed_s16be : procedure(bs2bdp:Tt_bs2bdp; var sample:cint16; n:cint); cdecl; { sample poits to 16bit unsigned integers big endians } bs2b_cross_feed_u16be : procedure(bs2bdp:Tt_bs2bdp; var sample:cint16; n:cint); cdecl; { sample poits to 16bit signed integers little endians } bs2b_cross_feed_s16le : procedure(bs2bdp:Tt_bs2bdp; var sample:cint16; n:cint); cdecl; { sample poits to 16bit unsigned integers little endians } bs2b_cross_feed_u16le : procedure(bs2bdp:Tt_bs2bdp; var sample:cint16; n:cint); cdecl; { sample poits to 8bit signed integers } bs2b_cross_feed_s8 : procedure(bs2bdp:Tt_bs2bdp; var sample:cint8; n:cint); cdecl; { sample poits to 8bit unsigned integers } bs2b_cross_feed_u8 : procedure(bs2bdp:Tt_bs2bdp; var sample:cint8; n:cint); cdecl; { sample poits to 24bit signed integers native endians } bs2b_cross_feed_s24 : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt); cdecl; { sample poits to 24bit unsigned integers native endians } bs2b_cross_feed_u24 : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt); cdecl; { sample poits to 24bit signed integers be endians } bs2b_cross_feed_s24be : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt); cdecl; { sample poits to 24bit unsigned integers be endians } bs2b_cross_feed_u24be : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt); cdecl; { sample poits to 24bit signed integers little endians } bs2b_cross_feed_s24le : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt); cdecl; { sample poits to 24bit unsigned integers little endians } bs2b_cross_feed_u24le : procedure(bs2bdp:Tt_bs2bdp; var sample:CInt32; n:CInt); cdecl; function bs_IsLoaded() : boolean; inline; Function bs_Load(const libfilename:string) :boolean; // load the lib Procedure bs_Unload(); // unload and frees the lib from memory : do not forget to call it before close application. implementation function bs2b_level_delay(fcut : longint) : longint; begin result:=floor((18700/fcut)*10); end; var bs_Handle :TLibHandle=dynlibs.NilHandle; {$IFDEF windows} // try load dependency if not in /windows/system32/ gc_Handle :TLibHandle=dynlibs.NilHandle; {$endif} ReferenceCounter : cardinal = 0; // Reference counter function bs_IsLoaded(): boolean; begin Result := (bs_Handle <> dynlibs.NilHandle); end; Procedure bs_Unload(); begin // < Reference counting if ReferenceCounter > 0 then dec(ReferenceCounter); if ReferenceCounter > 0 then exit; // > if bs_IsLoaded() then begin DynLibs.UnloadLibrary(bs_Handle); bs_Handle:=DynLibs.NilHandle; {$IFDEF windows} if gc_Handle <> DynLibs.NilHandle then begin DynLibs.UnloadLibrary(gc_Handle); gc_Handle:=DynLibs.NilHandle; end; {$endif} bs2b_open:=nil; bs2b_close:=nil; bs2b_set_level:=nil; bs2b_get_level:=nil; bs2b_set_level_fcut:=nil; bs2b_get_level_fcut:=nil; bs2b_set_level_feed:=nil; bs2b_get_level_feed:=nil; bs2b_get_level_delay:=nil; bs2b_set_srate:=nil; bs2b_get_srate:=nil; bs2b_clear:=nil; bs2b_is_clear:=nil; bs2b_runtime_version:=nil; bs2b_runtime_version_int:=nil; bs2b_cross_feed_d:=nil; bs2b_cross_feed_dbe:=nil; bs2b_cross_feed_dle:=nil; bs2b_cross_feed_f:=nil; bs2b_cross_feed_fbe:=nil; bs2b_cross_feed_fle:=nil; bs2b_cross_feed_s32:=nil; bs2b_cross_feed_u32:=nil; bs2b_cross_feed_s32be:=nil; bs2b_cross_feed_u32be:=nil; bs2b_cross_feed_s32le:=nil; bs2b_cross_feed_u32le:=nil; bs2b_cross_feed_s16:=nil; bs2b_cross_feed_u16:=nil; bs2b_cross_feed_s16be:=nil; bs2b_cross_feed_u16be:=nil; bs2b_cross_feed_s16le:=nil; bs2b_cross_feed_u16le:=nil; bs2b_cross_feed_s8:=nil; bs2b_cross_feed_u8:=nil; bs2b_cross_feed_s24:=nil; bs2b_cross_feed_u24:=nil; bs2b_cross_feed_s24be:=nil; bs2b_cross_feed_u24be:=nil; bs2b_cross_feed_s24le:=nil; bs2b_cross_feed_u24le:=nil; end; end; Function bs_Load(const libfilename:string) :boolean; begin Result := False; if bs_Handle<>0 then begin Inc(ReferenceCounter); result:=true {is it already there ?} end else begin {go & load the library} if Length(libfilename) = 0 then begin {$IFDEF windows} gc_Handle:= DynLibs.SafeLoadLibrary('libgcc_s_dw2-1.dll'); {$endif} bs_Handle:=DynLibs.SafeLoadLibrary(libsb); end else begin {$IFDEF windows} gc_Handle:= DynLibs.SafeLoadLibrary(ExtractFilePath(libfilename)+'libgcc_s_dw2-1.dll'); {$endif} bs_Handle:=DynLibs.SafeLoadLibrary(libfilename); end; if bs_Handle <> DynLibs.NilHandle then begin {now we tie the functions to the VARs from above} pointer(bs2b_open):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_open')); pointer(bs2b_close):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_close')); pointer(bs2b_set_level):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_set_level')); pointer(bs2b_get_level):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_get_level')); pointer(bs2b_set_level_fcut):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_set_level_fcut')); pointer(bs2b_get_level_fcut):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_get_level_fcut')); pointer(bs2b_set_level_feed):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_set_level_feed')); pointer(bs2b_get_level_feed):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_get_level_feed')); pointer(bs2b_get_level_delay):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_get_level_delay')); pointer(bs2b_set_srate):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_set_srate')); pointer(bs2b_get_srate):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_get_srate')); pointer(bs2b_clear):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_clear')); pointer(bs2b_is_clear):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_is_clear')); pointer(bs2b_runtime_version):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_runtime_version')); pointer(bs2b_runtime_version_int):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_runtime_version_int')); pointer(bs2b_cross_feed_d):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_d')); pointer(bs2b_cross_feed_dbe):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_dbe')); pointer(bs2b_cross_feed_dle):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_dle')); pointer(bs2b_cross_feed_f):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_f')); pointer(bs2b_cross_feed_fbe):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_fbe')); pointer(bs2b_cross_feed_fle):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_fle')); pointer(bs2b_cross_feed_s32):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_s32')); pointer(bs2b_cross_feed_u32):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_u32')); pointer(bs2b_cross_feed_s32be):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_s32be')); pointer(bs2b_cross_feed_u32be):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_u32be')); pointer(bs2b_cross_feed_s32le):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_s32le')); pointer(bs2b_cross_feed_u32le):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_u32le')); pointer(bs2b_cross_feed_s16):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_s16')); pointer(bs2b_cross_feed_u16):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_u16')); pointer(bs2b_cross_feed_s16be):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_s16be')); pointer(bs2b_cross_feed_u16be):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_u16be')); pointer(bs2b_cross_feed_s16le):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_s16le')); pointer(bs2b_cross_feed_u16le):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_u16le')); pointer(bs2b_cross_feed_s8):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_s8')); pointer(bs2b_cross_feed_u8):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_u8')); pointer(bs2b_cross_feed_s24):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_s24')); pointer(bs2b_cross_feed_u24):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_u24')); pointer(bs2b_cross_feed_s24be):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_s24be')); pointer(bs2b_cross_feed_u24be):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_u24be')); pointer(bs2b_cross_feed_s24le):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_s24le')); pointer(bs2b_cross_feed_u24le):=DynLibs.GetProcAddress(bs_handle,PChar('bs2b_cross_feed_u24le')); end; Result := bs_IsLoaded; ReferenceCounter:=1; end; end; end.