mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
feat(dmr): add receive frontend and AMBE adapter
This commit is contained in:
+159
@@ -0,0 +1,159 @@
|
||||
unit DMRBindings;
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$MODE Delphi}
|
||||
{$ENDIF}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, DynLibs;
|
||||
|
||||
const
|
||||
DMR_ABI_VERSION = 1;
|
||||
DMR_AMBE_BITS = 96;
|
||||
DMR_PCM_SAMPLES = 160;
|
||||
|
||||
type
|
||||
TDMRMbeResult = packed record
|
||||
ErrorsC0: LongInt;
|
||||
ErrorsTotal: LongInt;
|
||||
end;
|
||||
PDMRMbeResult = ^TDMRMbeResult;
|
||||
|
||||
function DMRLoad: Boolean;
|
||||
procedure DMRUnload;
|
||||
function DMRLoaded: Boolean;
|
||||
function DMRLastError: string;
|
||||
|
||||
function DMRMbeCreate(UVQuality: Integer): Pointer;
|
||||
procedure DMRMbeDestroy(Decoder: Pointer);
|
||||
procedure DMRMbeReset(Decoder: Pointer);
|
||||
function DMRMbeDecode(Decoder: Pointer; Bits: PByte; PCM: PSingle;
|
||||
ResultInfo: PDMRMbeResult): Integer;
|
||||
|
||||
implementation
|
||||
|
||||
type
|
||||
TAbiVersion = function: LongWord; cdecl;
|
||||
TMbeCreate = function(UVQuality: LongInt): Pointer; cdecl;
|
||||
TMbeDestroy = procedure(Decoder: Pointer); cdecl;
|
||||
TMbeReset = procedure(Decoder: Pointer); cdecl;
|
||||
TMbeDecode = function(Decoder: Pointer; Bits: PByte; PCM: PSingle;
|
||||
ResultInfo: Pointer): LongInt; cdecl;
|
||||
|
||||
var
|
||||
GLib: TLibHandle = dynlibs.NilHandle;
|
||||
GLastError: string = '';
|
||||
GAbiVersion: TAbiVersion = nil;
|
||||
GMbeCreate: TMbeCreate = nil;
|
||||
GMbeDestroy: TMbeDestroy = nil;
|
||||
GMbeReset: TMbeReset = nil;
|
||||
GMbeDecode: TMbeDecode = nil;
|
||||
|
||||
function Symbol(const Name: PChar): Pointer;
|
||||
begin
|
||||
Result := GetProcedureAddress(GLib, Name);
|
||||
if Result = nil then
|
||||
GLastError := 'Missing DMR symbol: ' + string(Name);
|
||||
end;
|
||||
|
||||
function DMRLoad: Boolean;
|
||||
const
|
||||
{$IFDEF WINDOWS}
|
||||
Names: array[0..0] of string = ('ewsdr_dmr.dll');
|
||||
{$ELSE}
|
||||
{$IFDEF DARWIN}
|
||||
Names: array[0..0] of string = ('libewsdr_dmr.dylib');
|
||||
{$ELSE}
|
||||
Names: array[0..1] of string = ('libewsdr_dmr.so', 'libewsdr_dmr.so.1');
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
var
|
||||
i: Integer;
|
||||
LocalName: string;
|
||||
begin
|
||||
if GLib <> dynlibs.NilHandle then Exit(True);
|
||||
GLastError := '';
|
||||
for i := Low(Names) to High(Names) do
|
||||
begin
|
||||
LocalName := ExtractFilePath(ParamStr(0)) + Names[i];
|
||||
GLib := LoadLibrary(LocalName);
|
||||
if GLib = dynlibs.NilHandle then GLib := LoadLibrary(Names[i]);
|
||||
if GLib <> dynlibs.NilHandle then Break;
|
||||
end;
|
||||
if GLib = dynlibs.NilHandle then
|
||||
begin
|
||||
GLastError := 'Optional EWSDR DMR library not found';
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
GAbiVersion := TAbiVersion(Symbol('ewsdr_dmr_abi_version'));
|
||||
GMbeCreate := TMbeCreate(Symbol('ewsdr_dmr_mbe_create'));
|
||||
GMbeDestroy := TMbeDestroy(Symbol('ewsdr_dmr_mbe_destroy'));
|
||||
GMbeReset := TMbeReset(Symbol('ewsdr_dmr_mbe_reset'));
|
||||
GMbeDecode := TMbeDecode(Symbol('ewsdr_dmr_mbe_decode'));
|
||||
if not Assigned(GAbiVersion) or not Assigned(GMbeCreate) or
|
||||
not Assigned(GMbeDestroy) or not Assigned(GMbeReset) or
|
||||
not Assigned(GMbeDecode) then
|
||||
begin
|
||||
DMRUnload;
|
||||
Exit(False);
|
||||
end;
|
||||
if GAbiVersion() <> DMR_ABI_VERSION then
|
||||
begin
|
||||
GLastError := Format('Unsupported EWSDR DMR ABI: %d', [GAbiVersion()]);
|
||||
DMRUnload;
|
||||
Exit(False);
|
||||
end;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
procedure DMRUnload;
|
||||
begin
|
||||
GAbiVersion := nil;
|
||||
GMbeCreate := nil;
|
||||
GMbeDestroy := nil;
|
||||
GMbeReset := nil;
|
||||
GMbeDecode := nil;
|
||||
if GLib <> dynlibs.NilHandle then
|
||||
begin
|
||||
UnloadLibrary(GLib);
|
||||
GLib := dynlibs.NilHandle;
|
||||
end;
|
||||
end;
|
||||
|
||||
function DMRLoaded: Boolean;
|
||||
begin
|
||||
Result := GLib <> dynlibs.NilHandle;
|
||||
end;
|
||||
|
||||
function DMRLastError: string;
|
||||
begin
|
||||
Result := GLastError;
|
||||
end;
|
||||
|
||||
function DMRMbeCreate(UVQuality: Integer): Pointer;
|
||||
begin
|
||||
if Assigned(GMbeCreate) then Result := GMbeCreate(UVQuality)
|
||||
else Result := nil;
|
||||
end;
|
||||
|
||||
procedure DMRMbeDestroy(Decoder: Pointer);
|
||||
begin
|
||||
if Assigned(GMbeDestroy) and (Decoder <> nil) then GMbeDestroy(Decoder);
|
||||
end;
|
||||
|
||||
procedure DMRMbeReset(Decoder: Pointer);
|
||||
begin
|
||||
if Assigned(GMbeReset) and (Decoder <> nil) then GMbeReset(Decoder);
|
||||
end;
|
||||
|
||||
function DMRMbeDecode(Decoder: Pointer; Bits: PByte; PCM: PSingle;
|
||||
ResultInfo: PDMRMbeResult): Integer;
|
||||
begin
|
||||
if not Assigned(GMbeDecode) then Exit(-1);
|
||||
Result := GMbeDecode(Decoder, Bits, PCM, ResultInfo);
|
||||
end;
|
||||
|
||||
end.
|
||||
Reference in New Issue
Block a user