Implements Module Player working in Form

* Implements Embedding .xm music in Final Application
This commit is contained in:
2025-06-02 15:15:16 +05:30
parent c09c434653
commit 6a1d80d3b8
342 changed files with 137595 additions and 146 deletions

47
UOS/src/laz_uos.lpk Normal file
View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<Package Version="5">
<PathDelim Value="\"/>
<Name Value="laz_uos"/>
<Author Value="Fred van Stappen"/>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<SearchPaths>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
</CompilerOptions>
<Description Value="uos : United OpenLib of Sound.
uos unifies the best open-source audio libraries.
For fpc, fpGUI, MSEgui and LCL.
With uos you can:
Listen to mp3, ogg, wav, flac, m4a, opus, cda ... audio files.
Deal with 16, 32 integer or float 32 bit resolution.
Do internet audio streaming.
Record all types of input into wav file with 16 or 32 bit resolution.
Add DSP effects and filters, however many you want and record it.
Listen to multiple input and output.
Produce sound from built-in synthesizer.
uos can use:
PortAudio, SndFile, Mpg123, Faad, Mp4ff, Opus, OpusFile audio libraries and
SoundTouch, Bs2b audio-effect libraries.
Included in the package:
Examples fpGUI, MSEgui, LCL and console.
Binaries of libraries for Linux, arm-Rapsberry Pi, Windows, Mac osX, FreeBSD."/>
<License Value="GNU Library or &quot;Lesser&quot; General Public License (LGPL)"/>
<Version Major="1"/>
<CompatibilityMode Value="True"/>
<RequiredPkgs Count="1">
<Item1>
<PackageName Value="FCL"/>
</Item1>
</RequiredPkgs>
<UsageOptions>
<UnitPath Value="$(PkgOutDir)"/>
</UsageOptions>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
</Package>
</CONFIG>

12
UOS/src/laz_uos.pas Normal file
View File

@@ -0,0 +1,12 @@
{ This file was automatically created by Lazarus. Do not edit!
This source is only used to compile and install the package.
}
unit laz_uos;
{$warn 5023 off : no warning about unused units}
interface
implementation
end.

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<Lazarus Version="4.0"/>
<Compiler Value="C:\lazarus\fpc\3.2.2\bin\x86_64-win64\fpc.exe" Date="1520657216"/>
<Params Value="-MObjFPC -Scghi -O1 -g -gl -l -vewnhibq -FuC:\Users\indrajith\Documents\projects\package-search\package-zerch\UOS\src\ -FuC:\lazarus\packager\units\x86_64-win64 -FUC:\Users\indrajith\Documents\projects\package-search\package-zerch\UOS\src\lib\x86_64-win64\ laz_uos.pas"/>
</CONFIG>

Binary file not shown.

12754
UOS/src/uos.pas Normal file

File diff suppressed because it is too large Load Diff

906
UOS/src/uos_aac.pas Normal file
View File

@@ -0,0 +1,906 @@
{This unit is part of United Openlibraries of Sound (uos)}
{This is the Dynamic loading version of FAAD2 Pascal Wrapper.
mcwNeAACDec.pas, mcwMP4FF.pas, mcwAAC.pas
By Franklyn A. Harlow Feb 2016
License : modified LGPL.
mcw* merged into uos_aac by Fred van Stappen / fiens@hotmail.com }
unit uos_aac;
{$mode objfpc}{$H+}
{$PACKRECORDS C}
interface
uses
Classes, SysUtils, ctypes, math,
dynlibs;
const
{$IFDEF unix}
{$IFDEF darwin}
libaa= 'libfaad.2.dylib';
libm4= 'libmp4ff.0.dylib';
{$ELSE}
libaa= 'libfaad.so.2';
libm4= 'libmp4ff.so.0.0.0';
{$ENDIF}
{$ELSE}
libaa= 'Faad2.dll';
libm4= 'mp4ff.dll';
{$ENDIF}
//////////// from mcwMP4FF.pas By Franklyn A. Harlow
type
ArSingle = array of Single;
PArSingle = ^ArSingle;
read_callback_t = function(user_data : Pointer; buffer : pcfloat; length : LongWord) : LongWord; cdecl;
write_callback_t = function(user_data : Pointer; buffer : pcfloat; length : LongWord) : LongWord; cdecl;
seek_callback_t = function(user_data : Pointer; Position : cInt64) : LongWord; cdecl;
truncate_callback_t = function(user_data : Pointer) : LongWord; cdecl;
mp4ff_callback_t = record
read : read_callback_t;
write : write_callback_t;
seek : seek_callback_t;
truncate : truncate_callback_t;
user_data : Pointer;
end;
p_mp4ff_callback_t = ^mp4ff_callback_t;
mp4ff_t = pointer;
int32_t = LongInt;
int64_t = cInt64;
uint32_t = LongWord;
var
mp4ff_open_read : function(f : p_mp4ff_callback_t) : mp4ff_t; cdecl;
mp4ff_open_read_metaonly : function(f : p_mp4ff_callback_t) : mp4ff_t; cdecl;
mp4ff_close : procedure(f : mp4ff_t); cdecl;
mp4ff_get_sample_duration : function(f : mp4ff_t; track, sample : int32_t) : int32_t; cdecl;
mp4ff_get_sample_duration_use_offsets : function(f : mp4ff_t; track, sample : int32_t) : int32_t; cdecl;
mp4ff_get_sample_position : function(f : mp4ff_t; track, sample : int32_t) : int64_t; cdecl;
mp4ff_get_sample_offset : function(f : mp4ff_t; track, sample : int32_t) : int32_t; cdecl;
mp4ff_find_sample : function(f : mp4ff_t; track : int32_t; offset : int64_t; var toskip : int32_t) : int32_t; cdecl;
mp4ff_find_sample_use_offsets : function(f : mp4ff_t; track : int32_t; offset : int64_t; var toskip : int32_t) : int32_t; cdecl;
mp4ff_set_sample_position : function(f : mp4ff_t; track : int32_t; sample : int64_t) : int32_t; cdecl;
mp4ff_read_sample : function(f : mp4ff_t; track, sample : int32_t; var audio_buffer : pcfloat; var bytes : LongWord) : int32_t; cdecl;
mp4ff_read_sample_v2 : function(f : mp4ff_t; track, sample : int32_t; buffer : pcfloat): int32_t; cdecl; //returns 0 on error, number of bytes read on success, use mp4ff_read_sample_getsize_t = function() to check buffer size needed
mp4ff_read_sample_getsize : function(f : mp4ff_t; track, sample : Integer) : int32_t; cdecl; //returns 0 on error, buffer size needed for mp4ff_read_sample_v2_t = function() on success
mp4ff_get_decoder_config : function(f : mp4ff_t; track : Integer; var ppBuf : pcfloat; var pBufSize : LongWord) : int32_t; cdecl;
mp4ff_free_decoder_config : procedure(Buf : pcfloat); cdecl;
mp4ff_get_track_type : function(f : mp4ff_t; const track : Integer) : int32_t; cdecl;
mp4ff_total_tracks : function(f : mp4ff_t) : int32_t; cdecl;
mp4ff_num_samples : function(f : mp4ff_t; track : Integer) : int32_t; cdecl;
mp4ff_time_scale : function(f : mp4ff_t; track : Integer) : int32_t; cdecl;
mp4ff_get_avg_bitrate : function(f : mp4ff_t; track : int32_t) : uint32_t; cdecl;
mp4ff_get_max_bitrate : function(f : mp4ff_t; track : int32_t) : uint32_t; cdecl;
mp4ff_get_track_duration : function(f : mp4ff_t; track : int32_t) : int64_t; cdecl; //returns _t = function(-1) if unknown
mp4ff_get_track_duration_use_offsets : function(f : mp4ff_t; track : int32_t) : Integer; cdecl; //returns _t = function(-1) if unknown
mp4ff_get_sample_rate : function(f : mp4ff_t; track : int32_t) : uint32_t; cdecl;
mp4ff_get_channel_count : function(f : mp4ff_t; track : int32_t) : uint32_t; cdecl;
mp4ff_get_audio_type : function(f : mp4ff_t; track : int32_t) : uint32_t; cdecl;
mp4ff_meta_get_num_items : function(f : mp4ff_t) : Integer; cdecl;
mp4ff_meta_get_by_index : function(f : mp4ff_t; index : LongWord; var item, value : PChar) : Integer; cdecl;
mp4ff_meta_get_title : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_artist : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_writer : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_album : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_date : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_tool : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_comment : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_genre : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_track : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_disc : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_totaltracks : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_totaldiscs : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_compilation : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_tempo : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
mp4ff_meta_get_coverart : function(f : mp4ff_t; var value : PChar) : Integer; cdecl;
function GetAACTrack(infile : mp4ff_t) : Integer;
procedure Loadmp4ff(mp4ff : AnsiString);
procedure UnLoadMp4ff;
Function isMp4ffLoaded : Boolean;
//////////// from mcwNeAACDec.pas by Franklyn A. Harlow
Const
{ object types for AAC }
MAIN = 1;
LC = 2;
SSR = 3;
LTP = 4;
HE_AAC = 5;
ER_LC = 17;
ER_LTP = 19;
LD = 23;
{ special object type for DRM }
DRM_ER_LC = 27;
{ header types }
RAW = 0;
ADIF = 1;
ADTS = 2;
LATM = 3;
{ SBR signalling }
NO_SBR = 0;
SBR_UPSAMPLED = 1;
SBR_DOWNSAMPLED = 2;
NO_SBR_UPSAMPLED = 3;
{ library output formats }
FAAD_FMT_16BIT = 1;
FAAD_FMT_24BIT = 2;
FAAD_FMT_32BIT = 3;
FAAD_FMT_FLOAT = 4;
FAAD_FMT_FIXED = FAAD_FMT_FLOAT;
FAAD_FMT_DOUBLE = 5;
{ Capabilities }
{ Can decode LC }
LC_DEC_CAP = 1 shl 0;
{ Can decode MAIN }
MAIN_DEC_CAP = 1 shl 1;
{ Can decode LTP }
LTP_DEC_CAP = 1 shl 2;
{ Can decode LD }
LD_DEC_CAP = 1 shl 3;
{ Can decode ER }
ERROR_RESILIENCE_CAP = 1 shl 4;
{ Fixed point }
FIXED_POINT_CAP = 1 shl 5;
{ Channel definitions }
FRONT_CHANNEL_CENTER = 1;
FRONT_CHANNEL_LEFT = 2;
FRONT_CHANNEL_RIGHT = 3;
SIDE_CHANNEL_LEFT = 4;
SIDE_CHANNEL_RIGHT = 5;
BACK_CHANNEL_LEFT = 6;
BACK_CHANNEL_RIGHT = 7;
BACK_CHANNEL_CENTER = 8;
LFE_CHANNEL = 9;
UNKNOWN_CHANNEL = 0;
{ DRM channel definitions }
DRMCH_MONO = 1;
DRMCH_STEREO = 2;
DRMCH_SBR_MONO = 3;
DRMCH_SBR_STEREO = 4;
DRMCH_SBR_PS_STEREO = 5;
{ A decode call can eat up to FAAD_MIN_STREAMSIZE bytes per decoded channel,
so at least so much bytes per channel should be available in this stream }
{ 6144 bits/channel }
FAAD_MIN_STREAMSIZE = 768;
Type
PNeAACDec = Pointer;
NeAAC_byte = {$IFDEF FPC}{$IFDEF CPU64}cuint32 {$ELSE}Byte {$ENDIF}{$ELSE}Byte {$ENDIF};
NeAAC_word = {$IFDEF FPC}{$IFDEF CPU64}cuint64{$ELSE}Word {$ENDIF}{$ELSE}Word {$ENDIF};
NeAAC_longword = {$IFDEF FPC}{$IFDEF CPU64}culong {$ELSE}LongWord{$ENDIF}{$ELSE}LongWord{$ENDIF};
NeAACDecConfiguration = record
defObjectType : NeAAC_byte;
defSampleRate : NeAAC_longword;
outputFormat : NeAAC_byte;
downMatrix : NeAAC_byte;
useOldADTSFormat : NeAAC_byte;
dontUpSampleImplicitSBR : NeAAC_byte;
end;
TNeAACDecConfiguration = NeAACDecConfiguration;
PNeAACDecConfiguration = ^NeAACDecConfiguration;
NeAACDecFrameInfo = record
bytesconsumed : NeAAC_longword;
samples : NeAAC_longword;
channels : NeAAC_byte;
error : NeAAC_byte;
samplerate : NeAAC_longword;
sbr : NeAAC_byte; //* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */
object_type : NeAAC_byte; //* MPEG-4 ObjectType */
header_type : NeAAC_byte; //* AAC header type; MP4 will be signalled as RAW also */
num_front_channels : NeAAC_byte; //* multichannel configuration */
num_side_channels : NeAAC_byte;
num_back_channels : NeAAC_byte;
num_lfe_channels : NeAAC_byte;
channel_position : array[0..63] of NeAAC_byte;
ps : NeAAC_byte; //* PS: 0: off, 1: on */
end;
TNeAACDecFrameInfo = NeAACDecFrameInfo;
PNeAACDecFrameInfo = ^NeAACDecFrameInfo;
mp4AudioSpecificConfig = record
objectTypeIndex : NeAAC_byte;
samplingFrequencyIndex : NeAAC_byte;
samplingFrequency : NeAAC_longword;
channelsConfiguration : NeAAC_byte;
frameLengthFlag : NeAAC_byte; //* GA Specific Info */
dependsOnCoreCoder : NeAAC_byte;
coreCoderDelay : NeAAC_word;
extensionFlag : NeAAC_byte;
aacSectionDataResilienceFlag : NeAAC_byte;
aacScalefactorDataResilienceFlag : NeAAC_byte;
aacSpectralDataResilienceFlag : NeAAC_byte;
epConfig : NeAAC_byte;
sbr_present_flag : NeAAC_byte;
forceUpSampling : NeAAC_byte;
downSampledSBR : NeAAC_byte;
end;
Tmp4AudioSpecificConfig = mp4AudioSpecificConfig;
Pmp4AudioSpecificConfig = ^mp4AudioSpecificConfig;
var
NeAACDecGetErrorMessage : function(ErrorCode : Byte) : PChar; cdecl;
NeAACDecGetCapabilities : function : LongWord; cdecl;
NeAACDecOpen : function : PNeAACDec; cdecl;
NeAACDecGetCurrentConfiguration : function( hDecoder : PNeAACDec) : PNeAACDecConfiguration; cdecl;
NeAACDecSetConfiguration : function( hDecoder : PNeAACDec; pConfig : PNeAACDecConfiguration) : Byte; cdecl;
NeAACDecInit : function( hDecoder : PNeAACDec; pBuffer : pcfloat; lwBufferLength : LongWord; var lwSampleRate : LongWord; var Channels : Byte) : LongInt; cdecl;
NeAACDecInit2 : function( hDecoder : PNeAACDec; pBuffer : pcfloat; SizeOfDecoderSpecificInfo : LongWord; var lwSampleRate : LongWord; var Channels : Byte) : Byte; cdecl;
NeAACDecPostSeekReset : procedure(hDecoder : PNeAACDec; Frame : LongInt); cdecl;
NeAACDecClose : procedure(hDecoder : PNeAACDec); cdecl;
NeAACDecDecode : function( hDecoder : PNeAACDec; hInfo : PNeAACDecFrameInfo; pBuffer : pcfloat; lwBufferLength : LongWord) : Pointer; cdecl;
NeAACDecDecode2 : function( hDecoder : PNeAACDec; hInfo : PNeAACDecFrameInfo; pBuffer : pcfloat; lwBufferLength : LongWord; var pSampleBuf : Pointer; lwSampleBufSize : LongWord) : Pointer; cdecl;
NeAACDecAudioSpecificConfig : function( pBuffer : pcfloat; lwBufferLength : LongWord; var mp4ASC : mp4AudioSpecificConfig) : Byte; cdecl;
procedure LoadNeAAC(NeAAC : AnsiString);
Procedure UnLoadNeAAC;
Function Is_NeAAC_Loaded : Boolean;
//////////////////
// from mcwAAC.pas from Franklyn A. Harlow
Const
kNeAAC_OK = 1;
kNeAAC_FAIL = 0;
Type
TAACIdata = array[0..2024*1024-1] of byte;
TAACInfo = class(TObject)
public
// libfaad control interface...
fsStream : TFileStream;
pDecoder : PNeAACDec;
hMP4 : mp4ff_t;
// output interface setup...
Channels : longword; // stereo = 2
BitsPerSample : longword; // ie short/smallint = 16
SampleRate : longword; // Frequency = 44100
outputFormat : byte; // See FAAD_FMT_16BIT etc...
Bitrate : longword; // 256000 = 256
TotalTime : double; // Length in Seconds
{$if not defined(fs32bit)}
TotalSamples : cint64;
Size : cint64; // in frames
Position : cint64; // in frames
{$else}
TotalSamples : cint;
Size : cint; // in frames
Position : cint; // in frames
{$endif}
// UoS interface
pData : pcfloat;
lwDataLen : longword;
// tag info...
Artist : AnsiString;
AlbumArtist : AnsiString;
Album : AnsiString;
Title : AnsiString;
Date : AnsiString;
Genre : AnsiString;
Track : AnsiString;
Comment : AnsiString;
// internal data...
cbs : mp4ff_callback_t;
_Buf : TAACIdata;
BufTmp : TAACIdata;
fTrack : longint;
fTimescale : longword; // Not actually used
fBufStart : longword;
fBufEnd : longword;
End;
Function aa_load(mp4ff, NeAAC: AnsiString): Boolean;
Procedure aa_Unload;
Function isLibAACLoaded : Boolean;
Function MP4OpenFile(fName : String; OutputFormat : Byte) : TAACInfo;
Procedure MP4CloseFile(var AACI: TAACInfo);
procedure MP4GetData(var AACI: TAACInfo; var Buffer: pcfloat; var Bytes: longword);
function MP4Seek(var AACI: TAACInfo; var SampleNum: longint) : Boolean;
implementation
var
// hNeAAC: {$IFDEF MSWINDOWS}longword{$ELSE}{$IFDEF CPU32}longword{$ELSE}PtrInt{$ENDIF}{$ENDIF};
hNeAAC:TLibHandle=dynlibs.NilHandle;
NeAACLoaded : Boolean;
Mp4ffLoaded : Boolean = False;
hMp4ff:TLibHandle=dynlibs.NilHandle;
//////////// from mcwNeAACDec.pas By Franklyn A. Harlow
function CBMP4Read(user_data : Pointer; buffer : pcfloat; length : LongWord) : LongWord; cdecl;
begin
try
Result := LongWord(TAACInfo(user_data).fsStream.Read(buffer^, Integer(length)));
except
Result := 0;
end;
end;
function CBMP4Write(user_data : Pointer; buffer : pcfloat; length : LongWord) : LongWord; cdecl;
begin
try
Result := LongWord(TAACInfo(user_data).fsStream.Write(buffer^, Integer(length)));
TAACInfo(user_data).fsStream.Position:=0;
except
Result := 0;
end;
end;
function CBMP4Seek(user_data : Pointer; Position : Int64) : LongWord; cdecl;
begin
try
Result := LongWord(TAACInfo(user_data).fsStream.Seek(Position, soBeginning));
except
Result := 0;
end;
end;
function CBMP4Truncate(user_data : Pointer) : LongWord; cdecl;
begin
Result := 0;
end;
//////////// from mcwAAC.pas By Franklyn A. Harlow
Function aa_load(mp4ff, NeAAC: AnsiString): Boolean;
Begin
// Safe To Call Multiple times, actual load of Lib checks to see if it is already loaded &
// returns true if it is...
LoadNeAAC(NeAAC);
Loadmp4ff(mp4ff);
Result:= Is_NeAAC_Loaded And isMp4ffLoaded;
End;
Procedure aa_Unload;
Begin
UnLoadNeAAC();
UnLoadMp4ff();
End;
Function isLibAACLoaded : Boolean;
Begin
Result:= Is_NeAAC_Loaded And isMp4ffLoaded;
end;
Function isFileAAC(fName : AnsiString): Boolean;
Begin
Result:= LowerCase(ExtractFileExt(fName)) = '.m4a';
end;
Function MP4OpenFile(fName : String; OutputFormat : Byte) : TAACInfo;
Var
pConfig : PNeAACDecConfiguration;
mp4ASC : mp4AudioSpecificConfig;
pBuf : pcfloat;
lwBufSize : longword;
lwBufSize2 : longword;
lwSampleRate : longword;
bChannels : byte;
bRet : Byte;
iRet : LongInt;
pID3 : PAnsiChar;
f : Double;
Begin
Result:= nil;
if not FileExists(fName) then
Exit;
if Not isFileAAC(fName) then
Exit;
// writeln('MP4OpenFileBegin');
Result:= TAACInfo.Create;
// writeln('MP4OpenFile3');
Result.fsStream:= TFileStream.Create(fName, fmOpenRead or fmShareDenyWrite);
sleep(1);
// writeln('MP4OpenFile4');
Result.cbs.read := @CBMP4Read;
Result.cbs.write := @CBMP4Write;
Result.cbs.seek := @CBMP4Seek;
Result.cbs.truncate := @CBMP4Truncate;
Result.cbs.user_data := Pointer(Result);
// writeln('MP4OpenFile5');
Result.pDecoder := NeAACDecOpen();
// writeln('MP4OpenFile6');
pConfig := NeAACDecGetCurrentConfiguration(Result.pDecoder);
// writeln('MP4OpenFile7');
pConfig^.defObjectType := LC;
pConfig^.defSampleRate := 44100;
pConfig^.outputFormat := OutputFormat; // FAAD_FMT_FLOAT FAAD_FMT_16BIT FAAD_FMT_32BIT
pConfig^.downMatrix := 1;
pConfig^.dontUpSampleImplicitSBR := 0;
NeAACDecSetConfiguration(Result.pDecoder, pConfig) ;
pConfig := NeAACDecGetCurrentConfiguration(Result.pDecoder);
// writeln('MP4OpenFile9');
case pConfig^.outputFormat of
FAAD_FMT_16BIT : Result.BitsPerSample := 16;
FAAD_FMT_24BIT : Result.BitsPerSample := 24;
FAAD_FMT_32BIT : Result.BitsPerSample := 32;
FAAD_FMT_FLOAT : Result.BitsPerSample := 32;
FAAD_FMT_DOUBLE: Result.BitsPerSample := 64;
end;
// writeln('MP4OpenFile10');
Result.outputFormat:= pConfig^.outputFormat;
Result.hMP4 := mp4ff_open_read(@Result.cbs);
// writeln('MP4OpenFile11');
Result.fTrack := GetAACTrack(Result.hMP4);
// writeln('MP4OpenFile12');
pBuf:= nil;
iRet:= mp4ff_get_decoder_config(Result.hMP4, Result.fTrack, pBuf, lwBufSize);
// writeln('MP4OpenFile13');
lwBufSize2:= lwBufSize;
// writeln('MP4OpenFile14');
bRet:= NeAACDecInit2(Result.pDecoder, pBuf, lwBufSize, lwSampleRate, bChannels);
// writeln('MP4OpenFile15');
Result.SampleRate := mp4ff_get_sample_rate(Result.hMP4, Result.fTrack);
Result.Channels := mp4ff_get_channel_count(Result.hMP4, Result.fTrack);
Result.fTimescale := mp4ff_time_scale(Result.hMP4, Result.fTrack);
Result.Bitrate := mp4ff_get_avg_bitrate(Result.hMP4, Result.fTrack);
Result.Size := mp4ff_num_samples(Result.hMP4, Result.fTrack);
// writeln('MP4OpenFile16');
if pBuf <> nil then
begin
bRet:= NeAACDecAudioSpecificConfig(pBuf, lwBufSize2, mp4ASC);
// writeln('MP4OpenFile17');
if bRet <> 0 then
Begin
// unix x64, NeAACDecAudioSpecificConfig Fails correct read,
// But if both previous SampleRates match, we'll use them...
{$IFDEF unix}{$IFDEF CPU64}
if Result.SampleRate = lwSampleRate then
Begin
mp4ASC.sbr_present_flag := 0;
mp4ASC.samplingFrequency := lwSampleRate;
End;
{$ENDIF}{$ENDIF}
End;
// writeln('MP4OpenFile18');
mp4ff_free_decoder_config(pBuf);
// writeln('MP4OpenFile19');
end;
f := 1024.0;
if mp4ASC.sbr_present_flag = 1 then
f := f * 2.0;
Result.TotalTime := Result.Size * (f-1.0) / mp4ASC.samplingFrequency;
{ ...End}
Result.TotalSamples := Trunc(Result.TotalTime * mp4ASC.samplingFrequency);
// writeln('MP4OpenFile20');
if mp4ASC.samplingFrequency > Result.SampleRate then
Result.SampleRate:= mp4ASC.samplingFrequency;
Result.Artist:= '';
iRet:= mp4ff_meta_get_writer(Result.hMP4, pID3);
if iRet = 1 then
Result.Artist:= pID3;
Result.AlbumArtist:= '';
iRet:= mp4ff_meta_get_artist(Result.hMP4, pID3);
if iRet = 1 then
Result.AlbumArtist:= pID3;
Result.Album:= '';
iRet:= mp4ff_meta_get_album(Result.hMP4, pID3);
if iRet = 1 then
Result.Album:= pID3;
Result.Title:= '';
iRet:= mp4ff_meta_get_title(Result.hMP4, pID3);
if iRet = 1 then
Result.Title:= pID3;
Result.Date:= '';
iRet:= mp4ff_meta_get_date(Result.hMP4, pID3);
if iRet = 1 then
Result.Date:= pID3;
Result.Genre:= '';
iRet:= mp4ff_meta_get_genre(Result.hMP4, pID3);
if iRet = 1 then
Result.Genre:= pID3;
Result.Track:= '';
iRet:= mp4ff_meta_get_track(Result.hMP4, pID3);
if iRet = 1 then
Result.Track:= pID3;
Result.Comment:= '';
iRet:= mp4ff_meta_get_comment(Result.hMP4, pID3);
if iRet = 1 then
Result.Comment:= pID3;
Result.Position := 0;
Result.fBufStart := 0;
Result.fBufEnd := 0;
// writeln('MP4OpenFile End');
end;
Procedure MP4CloseFile(var AACI: TAACInfo);
Begin
// writeln('MP4CloseFile1');
NeAACDecClose(AACI.pDecoder);
sleep(50);
// writeln('MP4CloseFile2');
mp4ff_close(AACI.hMP4);
// writeln('MP4CloseFile3');
sleep(50);
end;
procedure MP4GetData(var AACI: TAACInfo; var Buffer: pcfloat; var Bytes: longword);
var
ReqBytes : longword;
CurBufSize : longword;
NewSampleBuf : Pointer;
NewBytesRead : longword;
NewBytesDecoded : longword;
Function readNextSample(var audioBuf : pcfloat; var audioSize : longword): longword;
Begin
audioSize := 0;
Result:= 0;
audioBuf := nil;
// writeln('readNextSample');
if AACI.Position > AACI.Size then
Begin
Result:= 0;
Exit;
end;
Result := mp4ff_read_sample(AACI.hMP4, AACI.fTrack, AACI.Position, audioBuf, audioSize);
Inc(AACI.Position);
end;
Function getNextChunk(var SampBuf : Pointer; var NBR : longword) : longword;
Var
pAB : pcfloat;
iAB : longword;
frameInfo: NeAACDecFrameInfo;
Begin
NBR:= 0;
// writeln('getNextChunk');
Result:= 0;
Result:= readNextSample(pAB, iAB);
if Result = 0 then Exit;
SampBuf := NeAACDecDecode(AACI.pDecoder, @frameInfo, pAB, iAB);
if pAB <> nil then
mp4ff_free_decoder_config(pAB);
NBR:= frameInfo.samples * (AACI.BitsPerSample div 8);
end;
begin
// writeln('MP4GetData1');
ReqBytes:= Bytes;
// writeln('MP4GetDataBegin1-2');
CurBufSize:= AACI.fBufEnd - AACI.fBufStart;
While ReqBytes > CurBufSize do
Begin
// writeln('MP4GetData31');
// We need to put more data into Buffer...
// If We Have Left Over Data...
if CurBufSize > 0 then
Begin
// Save Existing Left over data..
Move(AACI._Buf[AACI.fBufStart], AACI.BufTmp[0], CurBufSize);
// Put Existing Data to Start of buffer...
Move(AACI.BufTmp[0], AACI._Buf[0], CurBufSize);
end;
// writeln('MP4GetData32');
// because we reshuffled buffers, AACI.fBufStart is now 0
AACI.fBufStart:= 0;
NewSampleBuf := nil;
// Read next block of data
NewBytesRead:= getNextChunk(NewSampleBuf, NewBytesDecoded);
// writeln('MP4GetData322');
if NewBytesRead = 0 then
begin
Buffer := nil;
Bytes := 0;
Exit;
end;
// writeln('MP4GetData33');
// Append new data to buffer
Move(NewSampleBuf^, AACI._Buf[CurBufSize], NewBytesDecoded);
// Update current unprocessed data count
CurBufSize:= CurBufSize + NewBytesDecoded;
// writeln('MP4GetData34');
end;
// writeln('MP4GetData4');
// set AACI.fBufEnd to last valid data byte in buffer
AACI.fBufEnd:= CurBufSize;
// writeln('MP4GetData5');
// If requested Byte count is more tha what we have, reduce requested count..
if Bytes > AACI.fBufEnd - AACI.fBufStart then
Bytes := AACI.fBufEnd - AACI.fBufStart;
// writeln('MP4GetData6');
// pass data back to calling function/procedure
Buffer := @AACI._Buf[AACI.fBufStart];
// writeln('MP4GetData7');
Inc(AACI.fBufStart, Bytes);
// writeln('MP4GetData8');
end;
function MP4Seek(var AACI: TAACInfo; var SampleNum: longint) : Boolean;
begin
Result := False;
if (AACI.Size = 0) or (AACI.TotalSamples = 0) then
Exit;
if SampleNum > AACI.TotalSamples then
SampleNum := AACI.TotalSamples;
AACI.Position:= Trunc(SampleNum / AACI.TotalSamples * AACI.Size);
Result := True;
end;
procedure LoadNeAAC(NeAAC : AnsiString);
var
thelib: string;
Begin
if Length(NeAAC) = 0 then thelib := libaa else thelib := NeAAC;
hNeAAC:= DynLibs.SafeLoadLibrary(PChar(thelib));
NeAACLoaded:= hNeAAC <> dynlibs.NilHandle;
Pointer(NeAACDecGetErrorMessage) :=
GetProcAddress(hNeAAC, PChar('NeAACDecGetErrorMessage'));
Pointer(NeAACDecGetCapabilities) :=
GetProcAddress(hNeAAC, PChar('NeAACDecGetCapabilities'));
Pointer(NeAACDecOpen) :=
GetProcAddress(hNeAAC, PChar('NeAACDecOpen'));
Pointer(NeAACDecGetCurrentConfiguration) :=
GetProcAddress(hNeAAC, PChar('NeAACDecGetCurrentConfiguration'));
Pointer(NeAACDecSetConfiguration) :=
GetProcAddress(hNeAAC, PChar('NeAACDecSetConfiguration'));
Pointer(NeAACDecInit) :=
GetProcAddress(hNeAAC, PChar('NeAACDecInit'));
Pointer(NeAACDecInit2) :=
GetProcAddress(hNeAAC, PChar('NeAACDecInit2'));
Pointer(NeAACDecPostSeekReset) :=
GetProcAddress(hNeAAC, PChar('NeAACDecPostSeekReset'));
Pointer(NeAACDecClose) :=
GetProcAddress(hNeAAC, PChar('NeAACDecClose'));
Pointer(NeAACDecDecode) :=
GetProcAddress(hNeAAC, PChar('NeAACDecDecode'));
Pointer(NeAACDecDecode2) :=
GetProcAddress(hNeAAC, PChar('NeAACDecDecode2'));
Pointer(NeAACDecPostSeekReset) :=
GetProcAddress(hNeAAC, PChar('NeAACDecPostSeekReset'));
Pointer(NeAACDecAudioSpecificConfig) :=
GetProcAddress(hNeAAC, PChar('NeAACDecAudioSpecificConfig'));
end;
Procedure UnLoadNeAAC;
Begin
if NeAACLoaded then
DynLibs.UnloadLibrary(hNeAAC);
NeAACLoaded:= False;
end;
Function Is_NeAAC_Loaded : Boolean;
Begin
Result:= NeAACLoaded;
end;
////////////////////////////// from mcwMP4FF.pas by Franklyn A. Harlow
function GetAACTrack(infile : mp4ff_t) : Integer;
var
i, rc, numTracks : Integer;
buff : pcfloat;
buff_size : LongWord;
mp4ASC : mp4AudioSpecificConfig;
begin
numTracks := mp4ff_total_tracks(infile);
for i := 0 to numTracks - 1 do
begin
buff := nil;
buff_size:=0;
mp4ff_get_decoder_config(infile, i, buff, buff_size);
if buff <> nil then
begin
rc := NeAACDecAudioSpecificConfig(buff, buff_size, mp4ASC);
mp4ff_free_decoder_config(buff);
if rc < 0 then
continue;
Result := i;
Exit;
end;
end;
Result := -1;
end;
procedure UnLoadMp4ff;
begin
if Mp4ffLoaded then
DynLibs.UnloadLibrary(hMp4ff);
Mp4ffLoaded := False;
end;
Function isMp4ffLoaded : Boolean;
Begin
Result:= Mp4ffLoaded;
end;
procedure Loadmp4ff(mp4ff : AnsiString);
var
thelib: string;
begin
if Mp4ffLoaded then
Exit;
if Length(mp4ff) = 0 then thelib := libm4 else thelib := mp4ff;
hMp4ff := DynLibs.SafeLoadLibrary(PChar(thelib));
Mp4ffLoaded := hMp4ff <> dynlibs.NilHandle;
// writeln('hMp4ff' + inttostr(hMp4ff));
Pointer(mp4ff_open_read) :=
GetProcAddress(hMp4ff, pchar('mp4ff_open_read'));
// if Pointer(mp4ff_open_read) <> nil then
// writeln('mp4ff_open_read OK') else
// writeln('mp4ff_open_read NOT OK');
Pointer(mp4ff_open_read_metaonly) :=
GetProcAddress(hMp4ff, PChar('mp4ff_open_read_metaonly'));
Pointer(mp4ff_close) :=
GetProcAddress(hMp4ff, PChar('mp4ff_close'));
Pointer(mp4ff_get_sample_duration) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_duration'));
Pointer(mp4ff_get_sample_duration_use_offsets) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_duration_use_offsets'));
Pointer(mp4ff_get_sample_position) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_position'));
Pointer(mp4ff_get_sample_offset) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_offset'));
Pointer(mp4ff_find_sample) :=
GetProcAddress(hMp4ff, PChar('mp4ff_find_sample'));
Pointer(mp4ff_find_sample_use_offsets) :=
GetProcAddress(hMp4ff, PChar('mp4ff_find_sample_use_offsets'));
Pointer(mp4ff_set_sample_position) :=
GetProcAddress(hMp4ff, PChar('mp4ff_set_sample_position'));
Pointer(mp4ff_read_sample) :=
GetProcAddress(hMp4ff, PChar('mp4ff_read_sample'));
Pointer(mp4ff_read_sample_v2) :=
GetProcAddress(hMp4ff, PChar('mp4ff_read_sample_v2'));
Pointer(mp4ff_read_sample_getsize) :=
GetProcAddress(hMp4ff, PChar('mp4ff_read_sample_getsize'));
Pointer(mp4ff_get_sample_position) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_position'));
Pointer(mp4ff_get_sample_offset) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_offset'));
Pointer(mp4ff_find_sample) :=
GetProcAddress(hMp4ff, PChar('mp4ff_find_sample'));
Pointer(mp4ff_get_decoder_config) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_decoder_config'));
Pointer(mp4ff_get_track_type) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_track_type'));
Pointer(mp4ff_total_tracks) :=
GetProcAddress(hMp4ff, PChar('mp4ff_total_tracks'));
Pointer(mp4ff_num_samples) :=
GetProcAddress(hMp4ff, PChar('mp4ff_num_samples'));
Pointer(mp4ff_time_scale) :=
GetProcAddress(hMp4ff, PChar('mp4ff_time_scale'));
Pointer(mp4ff_get_avg_bitrate) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_avg_bitrate'));
Pointer(mp4ff_get_max_bitrate) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_max_bitrate'));
Pointer(mp4ff_get_track_duration) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_track_duration'));
Pointer(mp4ff_get_track_duration_use_offsets) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_track_duration_use_offsets'));
Pointer(mp4ff_get_sample_rate) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_sample_rate'));
Pointer(mp4ff_get_channel_count) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_channel_count'));
Pointer(mp4ff_get_audio_type) :=
GetProcAddress(hMp4ff, PChar('mp4ff_get_audio_type'));
Pointer(mp4ff_free_decoder_config) :=
GetProcAddress(hMp4ff, PChar('mp4ff_free_decoder_config'));
Pointer(mp4ff_meta_get_num_items) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_num_items'));
Pointer(mp4ff_meta_get_by_index) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_by_index'));
Pointer(mp4ff_meta_get_title) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_title'));
Pointer(mp4ff_meta_get_artist) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_artist'));
Pointer(mp4ff_meta_get_writer) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_writer'));
Pointer(mp4ff_meta_get_album) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_album'));
Pointer(mp4ff_meta_get_date) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_date'));
Pointer(mp4ff_meta_get_tool) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_tool'));
Pointer(mp4ff_meta_get_comment) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_comment'));
Pointer(mp4ff_meta_get_genre) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_genre'));
Pointer(mp4ff_meta_get_track) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_track'));
Pointer(mp4ff_meta_get_disc) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_disc'));
Pointer(mp4ff_meta_get_totaltracks) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_totaltracks'));
Pointer(mp4ff_meta_get_totaldiscs) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_totaldiscs'));
Pointer(mp4ff_meta_get_compilation) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_compilation'));
Pointer(mp4ff_meta_get_tempo) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_tempo'));
Pointer(mp4ff_meta_get_coverart) :=
GetProcAddress(hMp4ff, PChar('mp4ff_meta_get_coverart'));
end;
initialization
NeAACLoaded:= False;
SetExceptionMask(GetExceptionMask + [exZeroDivide] + [exInvalidOp] +
[exDenormalized] + [exOverflow] + [exPrecision]);
finalization
end.

394
UOS/src/uos_bs2b.pas Normal file
View File

@@ -0,0 +1,394 @@
{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.

797
UOS/src/uos_cdrom.pas Normal file
View File

@@ -0,0 +1,797 @@
{This unit is part of United Openlibraries of Sound (uos)}
{
From CDRom, CDromLinux, CDRomWindows
By Franklyn A. Harlow Feb 2016
License : modified LGPL.
Merged by Fred van Stappen fiens/hotmail.com }
unit uos_cdrom;
{$mode objfpc}{$H+}
interface
uses
{$IFDEF FPC}cdrom,{$ENDIF}
{$IFDEF MSWINDOWS}
Windows,
{$ENDIF}
{$IFDEF unix}
baseunix,
{$ENDIF}
Classes, SysUtils, math;
Const
CDROM_OK = 0;
CDROM_UNKNOWNERR = -1;
CD_FRAMESIZE_RAW = 2352;
BUF_SIZE = 75 * CD_FRAMESIZE_RAW; // 75 frames - 1 sec
kCDDA_Base = 'cdda://sr';
kCDDA_Track = 'Track%20';
kCDDA_TrackWin = 'Track';
Type
TCDDATrackType = (cdtAudio, cdtData, cdtMixed);
Tmsf = record
min : Byte;
sec : Byte;
Frame : Byte;
end;
TCDDAPosition = record
Track : LongInt;
msf : Tmsf;
end;
TCDDATrackInfo = record
TrackLength : Tmsf;
TrackType : TCDDATrackType;
end;
TCDStatus = (cdsNotReady, cdsReady, cdsPlaying, cdsPaused);
TCDDATOCEntry = record
dwStartSector : LongInt; // Start sector of the track
btFlag : Byte; // Track flags (i.e. data or audio track)
btTrackNumber : Byte; // Track number
end;
PCDROMInfo = ^TCDROMInfo;
TCDROMInfo = Record
Channels : longword; // stereo = 2
BitsPerSample : longword; // ie short/smallint = 16
SampleRate : longword; // Frequency = 44100
TotalSamples : Int64;
TotalTime : LongWord; // Seconds
pData : pByte;
pDataLen : longword;
Size : Int64;
Position : Int64;
StartPos : TCDDAPosition;
EndPos : TCDDAPosition;
BufStart : LongWord;
BufEnd : LongWord;
BufSize : LongInt;
Buf : array[1..BUF_SIZE*2] of Byte;
BufTmp : array[1..BUF_SIZE*2] of Byte;
fHandleVaild : longint; // 0< : Impossible, 0: Not Valid, >0 : Valid/Available
CurrentPosition : Tmsf; // Current Position Of Track Being Read
{$IFDEF LIBCDRIP}
Opened : LongInt;
Busy : Boolean;
CurrentDrive : LongInt;
EnableJitterCorrection : Boolean;
LastJitterErrors : LongInt;
ReadSectors : LongInt;
OverlapSectors : LongInt;
CompareSectors : LongInt;
MultiReadCount : LongInt;
Paranoid : Boolean;
ParanoiaMode : LongInt;
LockTray : Boolean;
Status : TCDStatus;
RipSize : LongInt;
{$ENDIF}
{$IFDEF MSWINDOWS}
hCDROM : longword; // CDROM CreateFile Handle
{$ENDIF}
{$IFDEF unix}
hCDROM : longint; // CDROM fpOpen Handle
{$ENDIF}
End;
Const
EndOfDisc : TCDDAPosition = (Track : 100; msf : (min : 0; sec : 0; frame : 0));
Function Frames2MSF(Frames : LongInt) : Tmsf;
Function MSF2Frames(const msf : Tmsf) : LongInt;
Function AddressToSectors (msf : Tmsf): int64;
Function LoadCDROM(Lib : AnsiString): LongWord;
Function UnloadCDROM: LongWord;
Function isCDROMLoaded : Boolean;
Function CDROM_GetFileNameDrive(FileName : AnsiString): Byte;
Function CDROM_GetFileNameTrack(FileName : AnsiString): Byte;
Function CDROM_OpenFile(FileName : AnsiString): PCDROMInfo;
Function CDROM_Open(Drive, Track : Byte): PCDROMInfo;
Function CDROM_Close(var pCDROMI: PCDROMInfo): LongWord;
Function CDROM_GetData(var pCDROMI: PCDROMInfo; var pData: Pointer; var DataLength: longword): LongWord;
Function GetSystemCDRoms: AnsiString;
implementation
Function LoadCDROM(Lib : AnsiString): LongWord;
Begin
Result:= 32767;
end;
Function UnloadCDROM: LongWord;
Begin
Result:= 32767;
end;
Function isCDROMLoaded : Boolean;
Begin
Result:= True;
end;
{$IFDEF unix}
Const
CDROM_LBA = $01; // 'logical block': first frame is #0
CDROM_MSF = $02; // 'minute-second-frame': binary, not bcd here!
CDROM_DATA_TRACK = $40;
CDROM_LEADOUT = $AA;
CDROMREADTOCHDR = $5305; // Read TOC header
CDROMREADTOCENTRY = $5306; // Read TOC entry
CDROMREADAUDIO = $530E; // (struct cdrom_read_audio)
CDROM_DRIVE_STATUS = $5326; // Get tray position, etc.
CDROM_DISC_STATUS = $5327; // Get disc type, etc.
CDS_NO_DISC = 1;
CDS_TRAY_OPEN = 2;
CDS_DRIVE_NOT_READY = 3;
CDS_DISC_OK = 4;
CDS_AUDIO = 100;
CDS_MIXED = 105;
type
cdrom_addr = record
case Word of
1: (msf: Tmsf;);
2: (lba: longint;);
end;
cdrom_read_audio = record
addr : cdrom_addr; // frame address
addr_format : Byte; // CDROM_LBA or CDROM_MSF
nframes : LongInt; // number of 2352-byte-frames to read at once
buf : PByte; // frame buffer (size: nframes*2352 bytes)
end;
cdrom_tocentry = record
cdte_track : Byte;
cdte_adr_ctrl : Byte;
cdte_format : Byte;
cdte_addr : cdrom_addr;
cdte_datamode : Byte;
end;
cdrom_tochdr = record
cdth_trk0: Byte; // start track
cdth_trk1: Byte; // end track
end;
// ********************** Private Linux SUPPORT Functions **************************************************************
function GetTrackInfo(hCDROM: LongInt; Track : LongInt): TCDDATrackInfo;
var
Entry : cdrom_tocentry;
TOC : cdrom_tochdr;
F1 : LongInt;
F2 : LongInt;
Ret : LongInt;
begin
Ret:= fpioctl(hCDROM, CDROMREADTOCHDR, @TOC);
if Ret <> 0 then
raise Exception.Create('mcwCDROM_Linux.GetTrackInfo.fpioctl(CDROMREADTOCHDR) Error : ' + IntToStr(Ret));
Entry.cdte_format := CDROM_MSF;
Entry.cdte_track := Track + TOC.cdth_trk0 - 1;
Ret:= fpioctl(hCDROM, CDROMREADTOCENTRY, @Entry);
if Ret <> 0 then
raise Exception.Create('mcwCDROM_Linux.GetTrackInfo.fpioctl(CDROMREADTOCENTRY) Error : ' + IntToStr(Ret));
F1 := MSF2Frames(Entry.cdte_addr.msf);
if (Entry.cdte_adr_ctrl and CDROM_DATA_TRACK) <> 0 then
Result.TrackType := cdtData
else
Result.TrackType := cdtAudio;
if Entry.cdte_track < toc.cdth_trk1 then
Inc(Entry.cdte_track)
else
Entry.cdte_track := CDROM_LEADOUT;
Ret:= fpioctl(hCDROM, CDROMREADTOCENTRY, @Entry);
if Ret <> 0 then
raise Exception.Create('mcwCDROM_Linux.GetTrackInfo.fpioctl(CDROMREADTOCENTRY) #2 Error : ' + IntToStr(Ret));
F2 := MSF2Frames(Entry.cdte_addr.msf);
Result.TrackLength:= Frames2MSF(F2 - F1);
end;
function GetTrackMSF(hCDROM, Track : LongInt): Tmsf;
var
entry : cdrom_tocentry;
hdr : cdrom_tochdr;
Ret : LongInt;
begin
Ret:= fpioctl(hCDROM, CDROMREADTOCHDR, @hdr);
if Ret <> 0 then
raise Exception.Create('mcwCDROM_Linux.GetTrackMSF.fpioctl(CDROMREADTOCHDR) Error : ' + IntToStr(Ret));
entry.cdte_format := CDROM_MSF;
entry.cdte_track := Track + hdr.cdth_trk0 - 1;
if entry.cdte_track > hdr.cdth_trk1 then
entry.cdte_track := CDROM_LEADOUT;
Ret:= fpioctl(hCDROM, CDROMREADTOCENTRY, @entry);
if Ret <> 0 then
raise Exception.Create('mcwCDROM_Linux.GetTrackMSF.fpioctl(CDROMREADTOCENTRY) Error : ' + IntToStr(Ret));
Result := entry.cdte_addr.msf;
end;
function GetPosMSF(hCDROM: LongInt; Pos : TCDDAPosition): Tmsf;
var
msf1 : Tmsf;
frames : longint;
begin
msf1 := GetTrackMSF(hCDROM, Pos.Track);
frames := MSF2Frames(msf1);
frames := frames + MSF2Frames(Pos.msf);
Result := Frames2MSF(frames);
end;
function GetSize(pCDROMI: PCDROMInfo): Int64;
var
F1 : LongWord;
F2 : LongWord;
begin
F1:= (((pCDROMI^.StartPos.msf.min * 60) + pCDROMI^.StartPos.msf.sec) * 75) + pCDROMI^.StartPos.msf.Frame;
F2:= (((pCDROMI^.EndPos.msf.min * 60) + pCDROMI^.EndPos.msf.sec) * 75) + pCDROMI^.EndPos.msf.Frame;
Result := (F2 - F1) * CD_FRAMESIZE_RAW;
end;
// *********************************************************************************************************************
Function CDROM_GetFileNameDrive(FileName : AnsiString): Byte;
Begin
Result:= 255; // Assume Error
if Copy(FileName, 1, Length(kCDDA_Base)) = kCDDA_Base then
Result:= StrToIntDef(FileName[10], 256);
end;
Function CDROM_GetFileNameTrack(FileName : AnsiString): Byte;
Var
s : AnsiString;
Begin
Result:= 0;
if Pos(kCDDA_Track, FileName) > 0 then
Begin
s:= Copy(FileName, Pos(kCDDA_Track, FileName) + Length(kCDDA_Track), Length(FileName));
s:= Copy(s, 1, Pos('.', s) -1);
Result:= StrToIntDef(s, 0);
end;
end;
Function CDROM_OpenFile(FileName : AnsiString): PCDROMInfo;
Var
Drive, Track : Byte;
Begin
Result:= CDROM_Open(CDROM_GetFileNameDrive(FileName),
CDROM_GetFileNameTrack(FileName));
end;
Function CDROM_Open(Drive, Track : Byte): PCDROMInfo;
Var
CDRomPath : AnsiString;
slCDROMS : TStringList;
Res : longint;
Data : longint;
CDTI : TCDDATrackInfo;
CDTrackCount : LongInt;
CDTOC : Array of TTocEntry;
Begin
Result:= nil;
if (Drive = 255) or (Track < 1) then
Exit;
New(Result);
// Read Only, CDROMI uses constants and ignores changes to these...
Result^.Channels := 2;
Result^.BitsPerSample:= 16;
Result^.SampleRate := 44100;
CDRomPath:= '/dev/sr' + IntToStr(Drive);
slCDROMS := TStringList.Create;
Try
slCDROMS.Text:= GetSystemCDRoms;
if slCDROMS.IndexOf(CDRomPath) = -1 then
raise Exception.Create('mcwCDROM_Linux.CDROM_Open.GetSystemCDRoms Error : ' + CDRomPath + ' Not Found.');
finally
slCDROMS.Free;
end;
Result^.hCDROM:= fpopen(PAnsiChar(CDRomPath), O_RDONLY or O_NONBLOCK);;
if Result^.hCDROM < 0 then
raise Exception.Create('mcwCDROM_Linux.CDROM_Open.fpopen Error : (' + IntToStr(Result^.hCDROM) + ') On ' + CDRomPath);
// What State Is CDROM in ?
Res:= fpioctl(Result^.hCDROM, CDROM_DRIVE_STATUS, @Data);
if Res <> CDS_DISC_OK then
Begin
CDROM_Close(Result);
Dispose(Result);
Result:= nil;
Exit;
end;
// CDRom OK, What Kind Of Disk Do We Have?
Res := fpioctl(Result^.hCDROM, CDROM_DISC_STATUS, @Data);
if (Res <> CDS_AUDIO) And (Res <> CDS_MIXED) Then
Begin
CDROM_Close(Result);
Dispose(Result);
Result:= nil;
Exit;
end;
CDTI := GetTrackInfo(Result^.hCDROM, Track);
if CDTI.TrackType = cdtData then
raise Exception.Create('mcwCDROM_Linux.CDROM_Open : Trying to rip a data track');
Result^.StartPos.Track := Track;
Result^.StartPos.msf := GetTrackMSF(Result^.hCDROM, Result^.StartPos.Track);
Result^.EndPos.Track := Track +1;
Result^.EndPos.msf := GetTrackMSF(Result^.hCDROM, Result^.EndPos.Track);
CDTrackCount := cdrom.ReadCDTOC(CDRomPath, CDTOC);
if (Result^.EndPos.Track in [1..CDTrackCount]) = False then
raise Exception.Create('mcwCDROM_Linux.CDROM_Open : The end track out of range' + #13 +
IntToStr(Result^.EndPos.Track) + ' Requested, 1..' + IntToStr(CDTrackCount) + ' Allowed...');
Result^.CurrentPosition := Result^.StartPos.msf;
Result^.Position := 0;
Result^.Size := GetSize(Result);
Result^.BufStart := 1;
Result^.BufEnd := 0;
Result^.BufSize := BUF_SIZE;
Result^.TotalSamples := Result^.Size div 4;
Result^.TotalTime := floor(Result^.TotalSamples / 44100);
Inc(Result^.fHandleVaild);
end;
Function CDROM_Close(var pCDROMI: PCDROMInfo): LongWord;
Begin
Result := CDROM_UNKNOWNERR;
if pCDROMI^.fHandleVaild = 1 then
fpclose(pCDROMI^.hCDROM);
if pCDROMI^.fHandleVaild > 0 then
Dec(pCDROMI^.fHandleVaild);
Result := CDROM_OK;
end;
Function CDROM_GetData(var pCDROMI: PCDROMInfo; var pData: Pointer; var DataLength: longword): LongWord;
var
ReqLen : LongWord;
ReqFrames : LongInt;
cdaudio : cdrom_read_audio;
Ret : LongWord;
Res : LongInt;
TmpCount : longword;
Procedure getNextChunk;
Begin
TmpCount:= 0;
// Have We Reached End On Track ?
if MSF2Frames(pCDROMI^.CurrentPosition) >= MSF2Frames(pCDROMI^.EndPos.msf) then
Begin
pCDROMI^.BufEnd := 0;
pCDROMI^.BufStart := 0;
Exit;
End;
// This is not first call
if pCDROMI^.BufEnd > 0 then
Begin
// Copy Leftover Data to Start of buffer...
TmpCount:= pCDROMI^.BufEnd - pCDROMI^.BufStart;
Move(pCDROMI^.Buf[pCDROMI^.BufStart], pCDROMI^.BufTmp[1], TmpCount);
Move(pCDROMI^.BufTmp[1], pCDROMI^.Buf[1], TmpCount);
End;
ReqFrames:= 75; // BUF_SIZE = 1 Sec Worth Data = 75 Frames = In Bytes
if MSF2Frames(pCDROMI^.CurrentPosition) + ReqFrames > MSF2Frames(pCDROMI^.EndPos.msf) then
ReqFrames:= MSF2Frames(pCDROMI^.EndPos.msf) - MSF2Frames(pCDROMI^.CurrentPosition);
// *** Rip Next Chunk ******************************************
cdaudio.nframes := ReqFrames; // BUF_SIZE = 1 Sec Worth Data = 75 Frames = In Bytes
cdaudio.addr_format := CDROM_MSF;
cdaudio.addr.msf := pCDROMI^.CurrentPosition;
cdaudio.buf := @pCDROMI^.Buf[TmpCount +1];
Res:= fpioctl(pCDROMI^.hCDROM, CDROMREADAUDIO, @cdaudio);
if Res <> 0 then
raise Exception.Create('mcwCDROM_Linux.CDROM_GetData.getNextChunk.fpioctl(CDROMREADAUDIO) Error : ' + IntToStr(fpgeterrno));
pCDROMI^.CurrentPosition:= Frames2MSF(MSF2Frames(pCDROMI^.CurrentPosition) + cdaudio.nframes);
Ret := cdaudio.nframes * CD_FRAMESIZE_RAW;
// *** End Rip Next Chunk ***************************************
pCDROMI^.BufEnd:= TmpCount + Ret + 1;
pCDROMI^.BufStart := 1;
end;
begin
// PortAudio expects exact amount of data, anything less causes "Blips"
// pCDROMI.BufStart = Start Byte of Current Valid, Not Sent Buffer...
// pCDROMI.BufEnd = Last Byte of Current Valid, Not sent Buffer...
ReqLen:= DataLength;
if pCDROMI^.fHandleVaild = 0 then
raise Exception.Create('mcwCDROM_Linux.CDROM_GetData Error : Call To GetData Without Vaild CDROM Handle.');
// We don't read CDROM every call, only when we need new data...
if (pCDROMI^.BufStart + ReqLen) > pCDROMI^.BufEnd then
getNextChunk;
// is the amount in buffer less than what was requested...
if DataLength > (pCDROMI^.BufEnd - pCDROMI^.BufStart + 1) then
DataLength := pCDROMI^.BufEnd - pCDROMI^.BufStart + 1;
// Have We Finished Reading Track ?
if pCDROMI^.BufEnd = 0 then
DataLength:= 0;
pData:= @pCDROMI^.Buf[pCDROMI^.BufStart];
If DataLength > 0 Then
Begin
Inc(pCDROMI^.BufStart, DataLength);
Inc(pCDROMI^.Position, DataLength);
end;
Result:= DataLength;
end;
{$ENDIF}
//////////////////////
{$IFDEF MSWINDOWS}
const
CDDA = 2;
IOCTL_CDROM_READ_TOC = $00024000;
IOCTL_CDROM_RAW_READ = $0002403E;
IOCTL_STORAGE_CHECK_VERIFY2 = $0002D0800;
MAXIMUM_NUMBER_TRACKS = 100;
CB_CDROMSECTOR = 2048;
Type
_TRACK_DATA = record
Reserved : UCHAR;
Control_and_Adr: UCHAR;
TrackNumber : UCHAR;
Reserved1 : UCHAR;
Address : array[0..3] of UCHAR;
end;
TRACK_DATA = _TRACK_DATA;
PTRACK_DATA = ^_TRACK_DATA;
_CDROM_TOC = record
Length : WORD;
FirstTrack : UCHAR;
LastTrack : UCHAR;
TrackData : array[0..(MAXIMUM_NUMBER_TRACKS)-1] of TRACK_DATA;
end;
CDROM_TOC = _CDROM_TOC;
PCDROM_TOC = ^_CDROM_TOC;
RAW_READ_INFO = record
DiskOffset : Int64;
SectorCount : Cardinal;
TrackMode : Cardinal;
end;
Function fpgeterrno(): LongWord;
Begin
Result:= GetLastOSError;
end;
// ********************** Private Windows SUPPORT Functions ************************************************************
function GetTrackMSF(Table: CDROM_TOC; Track : LongInt): Tmsf;
begin
Result.min := Table.TrackData[Track -1].Address[1];
Result.sec := Table.TrackData[Track -1].Address[2];
Result.Frame:= Table.TrackData[Track -1].Address[3];
end;
function GetPosMSF(Table: CDROM_TOC; Pos : TCDDAPosition): Tmsf;
var
msf1 : Tmsf;
frames : longint;
begin
msf1 := GetTrackMSF(Table, Pos.Track);
frames := MSF2Frames(msf1);
frames := frames + MSF2Frames(Pos.msf);
Result := Frames2MSF(frames);
end;
function GetSize(pCDROMI: PCDROMInfo): Int64;
var
F1 : LongWord;
F2 : LongWord;
begin
F1:= (((pCDROMI^.StartPos.msf.min * 60) + pCDROMI^.StartPos.msf.sec) * 75) + pCDROMI^.StartPos.msf.Frame;
F2:= (((pCDROMI^.EndPos.msf.min * 60) + pCDROMI^.EndPos.msf.sec) * 75) + pCDROMI^.EndPos.msf.Frame;
Result := (F2 - F1) * CD_FRAMESIZE_RAW;
end;
// *********************************************************************************************************************
Function CDROM_GetFileNameDrive(FileName : AnsiString): Byte;
Var
driveLetter : Char;
drive : Char;
cdromcount : Byte;
found : Boolean;
Begin
found := False;
driveLetter:= FileName[1];
cdromcount := 255;
For drive := 'A' to 'Z' do
if GetDriveType(PChar(drive + ':\')) = DRIVE_CDROM then
Begin
Inc(cdromcount);
if drive = driveLetter then
Begin
found:= True;
break;
end;
end;
if not found then
raise Exception.Create('CDROM (BDROM) Drive Not Found !');
Result := cdromcount;
end;
Function CDROM_GetFileNameTrack(FileName : AnsiString): Byte;
Var
s : AnsiString;
Begin
// This works on Win7...
s := Copy(Filename, Pos(kCDDA_TrackWin, Filename) + 5, Length(Filename));
s := Copy(s, 1, Pos('.', s) -1);
Result:= StrToIntDef(s , 0);
end;
Function CDROM_OpenFile(FileName : AnsiString): PCDROMInfo;
Var
Drive, Track : Byte;
Begin
Result:= CDROM_Open(CDROM_GetFileNameDrive(FileName),
CDROM_GetFileNameTrack(FileName));
end;
Function CDROM_Open(Drive, Track : Byte): PCDROMInfo;
Var
CDRomPath : AnsiString;
Table : CDROM_TOC;
BytesRead : LongWord;
Ret : BOOL;
flags : longword;
// Index : LongInt;
Begin
Result:= nil;
if (Drive = 255) or (Track < 1) then
Exit;
New(Result);
// Read Only, CDROMI uses constants and ignores changes to these...
Result^.Channels := 2;
Result^.BitsPerSample:= 16;
Result^.SampleRate := 44100;
CDRomPath:= UpperCase('\\.\CDROM') + IntToStr(Drive);
flags := longword(GENERIC_READ);
Result^.hCDROM:= CreateFileA(PAnsiChar(CDRomPath), Flags, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0 );
if (Result^.hCDROM = INVALID_HANDLE_VALUE) then
raise Exception.Create('mcwCDROM_Win.CDROM_Open.CreateFileA Error : (' + IntToStr(Result^.hCDROM) + ') On ' + CDRomPath);
// What State Is CDROM in ?
Ret:= DeviceIoControl(Result^.hCDROM, IOCTL_STORAGE_CHECK_VERIFY2, nil, 0, nil, 0, BytesRead, nil);
if Not Ret then
Begin
CDROM_Close(Result);
Dispose(Result);
Result:= nil;
Exit;
end;
Ret:= DeviceIoControl(Result^.hCDROM, IOCTL_CDROM_READ_TOC, nil, 0, @Table, sizeof(Table), BytesRead, nil);
if Ret = False then
raise Exception.Create('mcwCDROM_Win.CDROM_Open.DeviceIoControl(IOCTL_CDROM_READ_TOC) Error ');
Result^.StartPos.Track := Track;
Result^.StartPos.msf := GetTrackMSF(Table, Result^.StartPos.Track);
Result^.EndPos.Track := Track +1;
Result^.EndPos.msf := GetTrackMSF(Table, Result^.EndPos.Track);
Result^.CurrentPosition := Result^.StartPos.msf;
Result^.Position := 0;
Result^.Size := GetSize(Result);
Result^.BufStart := 1;
Result^.BufEnd := 0;
Result^.BufSize := BUF_SIZE;
Result^.TotalSamples := Result^.Size div 4;
Result^.TotalTime := floor(Result^.TotalSamples / 44100);
Inc(Result^.fHandleVaild);
end;
Function CDROM_Close(var pCDROMI: PCDROMInfo): LongWord;
Begin
Result := CDROM_UNKNOWNERR;
if pCDROMI^.fHandleVaild = 1 then
CloseHandle(pCDROMI^.hCDROM);
if pCDROMI^.fHandleVaild > 0 then
Dec(pCDROMI^.fHandleVaild);
Result := CDROM_OK;
end;
Function CDROM_GetData(var pCDROMI: PCDROMInfo; var pData: Pointer; var DataLength: longword): LongWord;
var
ReqLen : LongWord;
ReqFrames : LongInt;
Info : RAW_READ_INFO;
BytesRead : LongWord;
Address : Int64;
Ret : LongWord;
Res : BOOL;
TmpCount : longword;
Procedure getNextChunk;
Begin
TmpCount:= 0;
// Have We Reached End On Track ?
if MSF2Frames(pCDROMI^.CurrentPosition) >= MSF2Frames(pCDROMI^.EndPos.msf) then
Begin
pCDROMI^.BufEnd := 0;
pCDROMI^.BufStart := 0;
Exit;
End;
// This is not first call
if pCDROMI^.BufEnd > 0 then
Begin
// Copy Leftover Data to Start of buffer...
TmpCount:= pCDROMI^.BufEnd - pCDROMI^.BufStart;
Move(pCDROMI^.Buf[pCDROMI^.BufStart], pCDROMI^.BufTmp[1], TmpCount);
Move(pCDROMI^.BufTmp[1], pCDROMI^.Buf[1], TmpCount);
End;
// While Linux Can deal With 75 Frame Request, Windows Only 20 (?)
ReqFrames:= 20; // BUF_SIZE = 1 Sec Worth Data = 75 Frames = In Bytes
if MSF2Frames(pCDROMI^.CurrentPosition) + ReqFrames > MSF2Frames(pCDROMI^.EndPos.msf) then
ReqFrames:= MSF2Frames(pCDROMI^.EndPos.msf) - MSF2Frames(pCDROMI^.CurrentPosition);
// *** Rip Next Chunk ******************************************
Address:= AddressToSectors(pCDROMI^.CurrentPosition);
Info.TrackMode := CDDA;
Info.SectorCount:= ReqFrames;
Info.DiskOffset := Address * CB_CDROMSECTOR;
Res:= DeviceIoControl(pCDROMI^.hCDROM,
IOCTL_CDROM_RAW_READ,
@Info,
sizeof(Info),
@pCDROMI^.Buf[TmpCount +1],
ReqFrames * CD_FRAMESIZE_RAW,
BytesRead,
nil);
if Res = False then
raise Exception.Create('mcwCDROM_Win.CDROM_GetData.getNextChunk.fpioctl(CDROMREADAUDIO) Error : ' + IntToStr(fpgeterrno));
pCDROMI^.CurrentPosition:= Frames2MSF(MSF2Frames(pCDROMI^.CurrentPosition) + ReqFrames);
Ret := BytesRead; // Should Be The same as "ReqFrames * CD_FRAMESIZE_RAW"
// *** End Rip Next Chunk ***************************************
pCDROMI^.BufEnd:= TmpCount + Ret + 1;
pCDROMI^.BufStart := 1;
end;
begin
// PortAudio expects exact amount of data, anything less causes "Blips"
// pCDROMI.BufStart = Start Byte of Current Valid, Not Sent Buffer...
// pCDROMI.BufEnd = Last Byte of Current Valid, Not sent Buffer...
ReqLen:= DataLength;
if pCDROMI^.fHandleVaild = 0 then
raise Exception.Create('mcwCDROM_Win.CDROM_GetData Error : Call To GetData Without Vaild CDROM Handle.');
// We don't read CDROM every call, only when we need new data...
if (pCDROMI^.BufStart + ReqLen) > pCDROMI^.BufEnd then
getNextChunk;
// is the amount in buffer less than what was requested...
if DataLength > (pCDROMI^.BufEnd - pCDROMI^.BufStart + 1) then
DataLength := pCDROMI^.BufEnd - pCDROMI^.BufStart + 1;
// Have We Finished Reading Track ?
if pCDROMI^.BufEnd = 0 then
DataLength:= 0;
pData:= @pCDROMI^.Buf[pCDROMI^.BufStart];
If DataLength > 0 Then
Begin
Inc(pCDROMI^.BufStart, DataLength);
Inc(pCDROMI^.Position, DataLength);
end;
Result:= DataLength;
end;
{$ENDIF}
/////////////////////
Function GetSystemCDRoms: AnsiString;
var
Index : longint;
Ret : LongInt;
Devices : Array of string;
sl : TStringList;
begin
Result:= '';
sl:= TStringList.Create;
SetLength(Devices, 99);
Ret:= cdrom.GetCDRomDevices(Devices);
If Ret > 0 Then
For Index := 0 To Ret -1 do
sl.Add(Devices[Index]);
Result:= sl.Text;
sl.Free;
end;
// ********************** Common Linux/Windows SUPPORT Functions *******************************************************
Function Frames2MSF(Frames : LongInt) : Tmsf;
var
Temp : Integer;
begin
Temp := Frames div 75;
Result.min := Temp div 60;
Result.sec := Temp mod 60;
Result.Frame := Frames mod 75;
end;
function MSF2Frames(const msf : Tmsf) : LongInt;
begin
Result := ((msf.min * 60) + msf.sec) * 75 + msf.Frame;
end;
Function AddressToSectors (msf : Tmsf): int64;
begin
Result:= MSF2Frames(msf) - 150;
end;
// *********************************************************************************************************************
end.

35
UOS/src/uos_define.inc Normal file
View File

@@ -0,0 +1,35 @@
{ United Openlibraries of Sound (uos)
License : modified LGPL.
Fred van Stappen fiens@hotmail.com }
// Compiler definitions
{.$DEFINE uos_debug} // uncomment for debugging. For console and Unix applications only.
{.$DEFINE consoleapp} // if FPC version < 2.7.1 uncomment for console application
{.$DEFINE library} // uncomment for building uos library (native and java)
{.$DEFINE java} // uncomment for building uos java library
{.$DEFINE fpgui} // uncomment if FPC version < 2.7.1 and using fpGUI widget
{.$DEFINE mse} // uncomment when using a mse project, use mse mseThread in place of fpc TThread.
{.$DEFINE usequeue} // uncomment to use Thread.Queue instead of Thread.Synchronize for fpc threads, better for LCL widgets.
{$DEFINE portaudio} // uncomment to enable portaudio In/Out sound port
{$DEFINE sndfile} // uncomment to enable sndfile (wav, ogg, flac audio file)
{$DEFINE mpg123} // uncomment to enable mpg123 (mp3 audio file)
{$DEFINE neaac} // uncomment to enable neaac (m4a audio file)
{$DEFINE fdkaac} // uncomment to enable aacdecoder (acc audio webstream)
{$DEFINE opus} // uncomment to enable opus (opus audio file)
{$DEFINE xmp} // uncomment to enable xmp (mod, it, mods, audio file)
{.$DEFINE cdrom} // uncomment to enable cdrom audio decoder (cda)
{$DEFINE soundtouch} // uncomment to enable Soundtouch tempo plugin
{$DEFINE bs2b} // uncomment to enable bs2b stereo to binaural plugin
{$DEFINE webstream} // uncomment to enable Internet Audio Streaming
{.$DEFINE shout} // uncomment to enable IceCast-Shout audio web server.
{$DEFINE noiseremoval} // uncomment to enable Noise Removal DSP
{$DEFINE synthesizer} // uncomment to enable Synthesizer

File diff suppressed because it is too large Load Diff

328
UOS/src/uos_dsp_utils.pas Normal file
View File

@@ -0,0 +1,328 @@
{This unit is part of United Openlibraries of Sound (uos)}
{
This unit uses part of Pascal Audio IO package.
(paio_channelhelper, pa_ringbuffer, pa_utils)
Copyright (c) 2016 by Andrew Haines.
Fred van Stappen fiens@hotmail.com
}
unit uos_dsp_utils;
{$mode objfpc}{$H+}
{$interfaces corba}
interface
uses
Classes, SysUtils;
const
AUDIO_BUFFER_SIZE = 8192;
AUDIO_BUFFER_FLOAT_SAMPLES = AUDIO_BUFFER_SIZE div 4;
type
PPSingle = ^PSingle;
TSingleArray = array of Single;
TChannelArray = array of TSingleArray;
{ TRingBuffer }
TRingBuffer = class
private
FMem: PByte;
FWritePos: Integer;
FReadPos: Integer;
FUsedSpace: Integer;
FTotalSpace: Integer;
function GetFreeSpace: Integer;
public
constructor Create(ASize: Integer);
destructor Destroy; override;
function Write(const ASource; ASize: Integer): Integer;
function Read(var ADest; ASize: Integer): Integer;
property FreeSpace: Integer read GetFreeSpace;
property UsedSpace: Integer read FUsedSpace;
end;
type
IPAIODataIOInterface = interface
['IPAIODataIOInterface']
procedure WriteDataIO(ASender: IPAIODataIOInterface; AData: PSingle; ASamples: Integer);
end;
{ TPAIOChannelHelper }
TPAIOChannelHelper = class(IPAIODataIOInterface)
private
FOutputs: TList;
FTarget: IPAIODataIOInterface; // where we will send plexed data.
FBuffers: TChannelArray;
FPos: array of Integer;
// called by the individual channel objects.
procedure WriteDataIO(ASender: IPAIODataIOInterface; AData: PSingle; ASamples: Integer);
procedure AllocateBuffers;
procedure SendDataToTarget;
public
constructor Create(APlexedTarget: IPAIODataIOInterface);
destructor Destroy; override;
property Outputs: TList read FOutputs;// of IPAIOSplitterJoinerInterface. Each is a channel in order.
procedure Write(AData: PSingle; ASamples: Integer); // this expects interleaved data.
end;
function NewChannelArray(AChannels: Integer; ASamplesPerChannel: Integer): TChannelArray;
function SplitChannels(AData: PSingle; ASamples: Integer; AChannels: Integer): TChannelArray;
function JoinChannels(AChannelData: TChannelArray; ASamples: Integer = -1): TSingleArray;
function JoinChannels(AChannelData: PPSingle; AChannels: Integer; ASamples: Integer): TSingleArray;
function Min(A,B: Integer): Integer;
function Max(A,B: Integer): Integer;
implementation
{ TPAIOChannelHelper }
procedure TPAIOChannelHelper.WriteDataIO(ASender: IPAIODataIOInterface; AData: PSingle; ASamples: Integer);
var
BufIndex: Integer;
BufSize, WCount: Integer;
Written: Integer = 0;
begin
BufIndex := FOutputs.IndexOf(Pointer(ASender));
if BufIndex = -1 then
raise Exception.Create('Trying to write data from an unknown instance');
AllocateBuffers;
BufSize := Length(FBuffers[0]);
While ASamples > 0 do
begin
WCount := Min(BufSize-FPos[BufIndex], ASamples);
Move(AData[Written], FBuffers[BufIndex][0], WCount*SizeOf(Single));
Inc(Written, WCount);
Dec(ASamples, WCount);
Inc(FPos[BufIndex], WCount);
if BufIndex = High(FBuffers) then
SendDataToTarget;
end;
end;
procedure TPAIOChannelHelper.AllocateBuffers;
begin
if Length(FBuffers) <> FOutputs.Count then
begin
SetLength(FBuffers, 0);
FBuffers := NewChannelArray(FOutputs.Count, AUDIO_BUFFER_SIZE*2);
SetLength(FPos, FOutputs.Count);
end;
end;
procedure TPAIOChannelHelper.SendDataToTarget;
var
Plexed: TSingleArray;
HighestCount: Integer = 0;
i: Integer;
begin
for i := 0 to High(FPos) do
if FPos[i] > HighestCount then
HighestCount:=FPos[i];
Plexed := JoinChannels(FBuffers, HighestCount);
FTarget.WriteDataIO(Self, @Plexed[0], Length(Plexed));
for i := 0 to High(FPos) do
Dec(FPos[i], HighestCount);
end;
constructor TPAIOChannelHelper.Create(APlexedTarget: IPAIODataIOInterface);
begin
FOutputs := TList.Create;
FTarget := APlexedTarget;
end;
destructor TPAIOChannelHelper.Destroy;
begin
FOutputs.Free;
inherited Destroy;
end;
procedure TPAIOChannelHelper.Write(AData: PSingle; ASamples: Integer);
var
Channels: TChannelArray;
i: Integer;
Pos: Integer = 0;
WCount: Integer;
begin
AllocateBuffers;
Channels := SplitChannels(AData, ASamples, Outputs.Count);
while ASamples > 0 do
begin
WCount := Min(1024, ASamples div Outputs.Count);
for i := 0 to Outputs.Count-1 do
begin
IPAIODataIOInterface(Outputs.Items[i]).WriteDataIO(Self, @Channels[i][Pos], WCount);
end;
Dec(ASamples, WCount * Outputs.Count);
Inc(Pos, WCount);
end;
end;
{ TRingBuffer }
function TRingBuffer.GetFreeSpace: Integer;
begin
Result := FTotalSpace-FUsedSpace;
end;
constructor TRingBuffer.Create(ASize: Integer);
begin
FMem:=Getmem(ASize);
FTotalSpace:=ASize;
end;
destructor TRingBuffer.Destroy;
begin
Freemem(FMem);
inherited Destroy;
end;
function TRingBuffer.Write(const ASource; ASize: Integer): Integer;
var
EOB: Integer; // end of buffer
WSize: Integer;
WTotal: Integer = 0;
begin
if FUsedSpace = 0 then
begin
// give the best chance of not splitting the data at buffer end.
FWritePos:=0;
FReadPos:=0;
end;
if ASize > FreeSpace then
raise Exception.Create('Ring buffer overflow');
Result := ASize;
Inc(FUsedSpace, ASize);
while ASize > 0 do
begin
EOB := FTotalSpace - FWritePos;
WSize := Min(ASize, EOB);
Move(PByte(@ASource)[WTotal], FMem[FWritePos], WSize);
Inc(FWritePos, WSize);
Dec(ASize, WSize);
if FWritePos >= FTotalSpace then
FWritePos:= 0;
end;
end;
function TRingBuffer.Read(var ADest; ASize: Integer): Integer;
var
EOB: Integer; // end of buffer
RSize: Integer;
RTotal: Integer = 0;
begin
if ASize > UsedSpace then
raise Exception.Create('Ring buffer underflow');
ASize := Min(ASize, UsedSpace);
Result := ASize;
Dec(FUsedSpace, ASize);
while ASize > 0 do
begin
EOB := FTotalSpace - FReadPos;
RSize := Min(EOB, ASize);
Move(FMem[FReadPos], PByte(@ADest)[RTotal],RSize);
Dec(ASize, RSize);
Inc(FReadPos, RSize);
if FReadPos >= FTotalSpace then
FReadPos:=0;
end;
end;
function Min(A,B: Integer): Integer;
begin
if A < B then Exit(A);
Result := B;
end;
function Max(A,B: Integer): Integer;
begin
if A > B then Exit(A);
Result := B;
end;
function NewChannelArray(AChannels: Integer; ASamplesPerChannel: Integer): TChannelArray;
var
i: Integer;
begin
SetLength(Result, AChannels);
for i := 0 to AChannels-1 do
SetLength(Result[i], ASamplesPerChannel);
end;
// Samples is total samples not samples per channel.
// So Samples = 1000 if 2 Channels have 500 each
function SplitChannels(AData: PSingle; ASamples: Integer; AChannels: Integer): TChannelArray;
var
SamplesPerChannel: Integer;
i, j: Integer;
begin
SamplesPerChannel:=ASamples div AChannels;
//SetLength(Result, AChannels);
Result := NewChannelArray(AChannels, SamplesPerChannel);
for i := 0 to AChannels-1 do
begin
//SetLength(Result[i], SamplesPerChannel);
for j := 0 to SamplesPerChannel-1 do
begin
Result[i][j] := AData[j*AChannels+i];
end;
end;
end;
function JoinChannels(AChannelData: TChannelArray; ASamples: Integer): TSingleArray;
var
i: Integer;
j: Integer;
Samples: Integer;
begin
if Length(AChannelData) > 0 then
begin
if ASamples <> -1 then
Samples := ASamples
else
Samples := Length(AChannelData[0]);
SetLength(Result, Length(AChannelData) * Samples);
for i := 0 to High(AChannelData) do
for j := 0 to Samples-1 do
Result[j*Length(AChannelData)+i] := AChannelData[i][j];
end
else
SetLength(Result, 0);
end;
function JoinChannels(AChannelData: PPSingle; AChannels: Integer;
ASamples: Integer): TSingleArray;
var
i: Integer;
j: Integer;
begin
if ASamples > 0 then
begin
SetLength(Result, AChannels * ASamples);
for i := 0 to AChannels-1 do
for j := 0 to ASamples-1 do
Result[j*AChannels+i] := AChannelData[i][j];
end
else
SetLength(Result, 0);
end;
end.

File diff suppressed because it is too large Load Diff

2547
UOS/src/uos_flat.pas Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,158 @@
{This unit is part of United Openlibraries of Sound (uos)}
{ This is HTTP Thread Getter
created by Andrew Haines -> andrewd207@aol.com
License : modified LGPL.
Fred van Stappen / fiens@hotmail.com}
unit uos_httpgetthread;
{$mode objfpc}{$H+}
interface
uses
Classes,
SysUtils,
Pipes;
type
{ TThreadHttpGetter }
TThreadHttpGetter = class(TThread)
private
FOutStream: TOutputPipeStream;
FWantedURL: string;
FIcyMetaInt: int64;
FOnIcyMetaInt: TNotifyEvent;
property OnIcyMetaInt: TNotifyEvent read FOnIcyMetaInt write FOnIcyMetaInt;
procedure DoIcyMetaInt;
function GetRedirectURL(AResponseStrings: TStrings): string;
procedure Headers(Sender: TObject);
protected
procedure Execute; override;
public
FIsRunning: Boolean;
ICYenabled: Boolean;
property IcyMetaInt: int64 read FIcyMetaInt;
property IsRunning: Boolean read FIsRunning;
constructor Create(AWantedURL: string; AOutputStream: TOutputPipeStream);
end;
implementation
uses
fphttpclient,
openssl, { This implements the procedure InitSSLInterface }
opensslsockets;
{ TThreadHttpGetter }
function TThreadHttpGetter.GetRedirectURL(AResponseStrings: TStrings): string;
var
S: string;
F: integer;
Search: string = 'location:';
begin
Result := '';
for S in AResponseStrings do
begin
// WriteLn(S);
F := Pos(Search, Lowercase(s));
if F > 0 then
begin
Inc(F, Length(Search));
Exit(Trim(Copy(S, F, Length(S) - F + 1)));
end;
end;
end;
procedure TThreadHttpGetter.DoIcyMetaInt;
begin
if Assigned(FOnIcyMetaInt) then
FOnIcyMetaInt(Self);
end;
procedure TThreadHttpGetter.Headers(Sender: TObject);
begin
FIcyMetaInt := StrToInt64Def(TFPHTTPClient(Sender).GetHeader(TFPHTTPClient(Sender).ResponseHeaders, 'icy-metaint'), 0);
if (FIcyMetaInt > 0) and (FOnIcyMetaInt <> nil) then
Synchronize(@DoIcyMetaInt);
end;
procedure TThreadHttpGetter.Execute;
var
Http: TFPHTTPClient;
URL: string;
err: shortint = 0;
begin
URL := FWantedURL;
if pos(' ', URL) > 0 then
FIsRunning := False
else
begin
InitSSLInterface;
Http := TFPHTTPClient.Create(nil);
http.AllowRedirect := True;
http.IOTimeout := 2000;
repeat
try
Http.RequestHeaders.Clear;
if ICYenabled = True then
Http.OnHeaders := @Headers;
// writeln(' avant http.get');
Http.Get(URL, FOutStream);
// writeln(' apres http.get');
except
on e: EHTTPClient do
begin
// writeln(' Http.ResponseStatusCode ' +inttostr(Http.ResponseStatusCode));
if (Http.ResponseStatusCode > 399) or (Http.ResponseStatusCode < 1) then // not accessible
begin
FIsRunning := False;
break;
end;
if Http.ResponseStatusCode = 302 then
begin
URL := GetRedirectURL(Http.ResponseHeaders);
if URL <> '' then
Continue;
end
else
Break;
// raise E;
end;
on e: Exception do
begin
// WriteLn(e.Message);
end
else
// Raise;
Break;
end;
Break;
until (False);
try
//FOutStream.Free;
Http.Free;
finally
// make sure this is set to false when done
FIsRunning := False;
end;
end;
end;
constructor TThreadHttpGetter.Create(AWantedURL: string; AOutputStream: TOutputPipeStream);
begin
inherited Create(True);
ICYenabled := False;
FIsRunning := True;
FWantedURL := AWantedURL;
FOutStream := AOutputStream;
// Start;
end;
end.

573
UOS/src/uos_jni.pas Normal file
View File

@@ -0,0 +1,573 @@
unit uos_jni;
{$ifdef fpc}
{$mode delphi}
{$packrecords c}
{$endif}
{$macro on}
{$ifdef mswindows}
{$define jnicall:=stdcall}
{$else}
{$define jnicall:=cdecl}
{$endif}
interface
(*
* Manifest constants.
*)
const JNI_FALSE=0;
JNI_TRUE=1;
JNI_VERSION_1_1=$00010001;
JNI_VERSION_1_2=$00010002;
JNI_VERSION_1_4=$00010004;
JNI_VERSION_1_6=$00010006;
JNI_OK=0; // no error
JNI_ERR=-1; // generic error
JNI_EDETACHED=-2; // thread detached from the VM
JNI_EVERSION=-3; // JNI version error
JNI_COMMIT=1; // copy content, do not free buffer
JNI_ABORT=2; // free buffer w/o copying back
(*
* Type definitions.
*)
type va_list=pointer;
jboolean=byte; // unsigned 8 bits
jbyte=shortint; // signed 8 bits
jchar=word; // unsigned 16 bits
jshort=smallint; // signed 16 bits
jint=longint; // signed 32 bits
jlong=int64; // signed 64 bits
jfloat=single; // 32-bit IEEE 754
jdouble=double; // 64-bit IEEE 754
jsize=jint; // "cardinal indices and sizes"
Pjboolean=^jboolean;
Pjbyte=^jbyte;
Pjchar=^jchar;
Pjshort=^jshort;
Pjint=^jint;
Pjlong=^jlong;
Pjfloat=^jfloat;
Pjdouble=^jdouble;
Pjsize=^jsize;
// Reference type
jobject=pointer;
jclass=jobject;
jstring=jobject;
jarray=jobject;
jobjectArray=jarray;
jbooleanArray=jarray;
jbyteArray=jarray;
jcharArray=jarray;
jshortArray=jarray;
jintArray=jarray;
jlongArray=jarray;
jfloatArray=jarray;
jdoubleArray=jarray;
jthrowable=jobject;
jweak=jobject;
jref=jobject;
PPointer=^pointer;
Pjobject=^jobject;
Pjclass=^jclass;
Pjstring=^jstring;
Pjarray=^jarray;
PjobjectArray=^jobjectArray;
PjbooleanArray=^jbooleanArray;
PjbyteArray=^jbyteArray;
PjcharArray=^jcharArray;
PjshortArray=^jshortArray;
PjintArray=^jintArray;
PjlongArray=^jlongArray;
PjfloatArray=^jfloatArray;
PjdoubleArray=^jdoubleArray;
Pjthrowable=^jthrowable;
Pjweak=^jweak;
Pjref=^jref;
_jfieldID=record // opaque structure
end;
jfieldID=^_jfieldID;// field IDs
PjfieldID=^jfieldID;
_jmethodID=record // opaque structure
end;
jmethodID=^_jmethodID;// method IDs
PjmethodID=^jmethodID;
PJNIInvokeInterface=^JNIInvokeInterface;
Pjvalue=^jvalue;
jvalue={$ifdef packedrecords}packed{$endif} record
case integer of
0:(z:jboolean);
1:(b:jbyte);
2:(c:jchar);
3:(s:jshort);
4:(i:jint);
5:(j:jlong);
6:(f:jfloat);
7:(d:jdouble);
8:(l:jobject);
end;
jobjectRefType=(
JNIInvalidRefType=0,
JNILocalRefType=1,
JNIGlobalRefType=2,
JNIWeakGlobalRefType=3);
PJNINativeMethod=^JNINativeMethod;
JNINativeMethod={$ifdef packedrecords}packed{$endif} record
name:pchar;
signature:pchar;
fnPtr:pointer;
end;
PJNINativeInterface=^JNINativeInterface;
_JNIEnv={$ifdef packedrecords}packed{$endif} record
functions:PJNINativeInterface;
end;
_JavaVM={$ifdef packedrecords}packed{$endif} record
functions:PJNIInvokeInterface;
end;
C_JNIEnv=^JNINativeInterface;
JNIEnv=^JNINativeInterface;
JavaVM=^JNIInvokeInterface;
PPJNIEnv=^PJNIEnv;
PJNIEnv=^JNIEnv;
PPJavaVM=^PJavaVM;
PJavaVM=^JavaVM;
JNINativeInterface={$ifdef packedrecords}packed{$endif} record
reserved0:pointer;
reserved1:pointer;
reserved2:pointer;
reserved3:pointer;
GetVersion:function(Env:PJNIEnv):JInt; jnicall;
DefineClass:function(Env:PJNIEnv;const Name:pchar;Loader:JObject;const Buf:PJByte;Len:JSize):JClass; jnicall;
FindClass:function(Env:PJNIEnv;const Name:pchar):JClass; jnicall;
// Reflection Support
FromReflectedMethod:function(Env:PJNIEnv;Method:JObject):JMethodID; jnicall;
FromReflectedField:function(Env:PJNIEnv;Field:JObject):JFieldID; jnicall;
ToReflectedMethod:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;IsStatic:JBoolean):JObject; jnicall;
GetSuperclass:function(Env:PJNIEnv;Sub:JClass):JClass; jnicall;
IsAssignableFrom:function(Env:PJNIEnv;Sub:JClass;Sup:JClass):JBoolean; jnicall;
// Reflection Support
ToReflectedField:function(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID;IsStatic:JBoolean):JObject; jnicall;
Throw:function(Env:PJNIEnv;Obj:JThrowable):JInt; jnicall;
ThrowNew:function(Env:PJNIEnv;AClass:JClass;const Msg:pchar):JInt; jnicall;
ExceptionOccurred:function(Env:PJNIEnv):JThrowable; jnicall;
ExceptionDescribe:procedure(Env:PJNIEnv); jnicall;
ExceptionClear:procedure(Env:PJNIEnv); jnicall;
FatalError:procedure(Env:PJNIEnv;const Msg:pchar); jnicall;
// Local Reference Management
PushLocalFrame:function(Env:PJNIEnv;Capacity:JInt):JInt; jnicall;
PopLocalFrame:function(Env:PJNIEnv;Result:JObject):JObject; jnicall;
NewGlobalRef:function(Env:PJNIEnv;LObj:JObject):JObject; jnicall;
DeleteGlobalRef:procedure(Env:PJNIEnv;GRef:JObject); jnicall;
DeleteLocalRef:procedure(Env:PJNIEnv;Obj:JObject); jnicall;
IsSameObject:function(Env:PJNIEnv;Obj1:JObject;Obj2:JObject):JBoolean; jnicall;
// Local Reference Management
NewLocalRef:function(Env:PJNIEnv;Ref:JObject):JObject; jnicall;
EnsureLocalCapacity:function(Env:PJNIEnv;Capacity:JInt):JObject; jnicall;
AllocObject:function(Env:PJNIEnv;AClass:JClass):JObject; jnicall;
NewObject:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID):JObject; jnicall;
NewObjectV:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:va_list):JObject; jnicall;
NewObjectA:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:PJValue):JObject; jnicall;
GetObjectClass:function(Env:PJNIEnv;Obj:JObject):JClass; jnicall;
IsInstanceOf:function(Env:PJNIEnv;Obj:JObject;AClass:JClass):JBoolean; jnicall;
GetMethodID:function(Env:PJNIEnv;AClass:JClass;const Name:pchar;const Sig:pchar):JMethodID; jnicall;
CallObjectMethod:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID):JObject; jnicall;
CallObjectMethodV:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:va_list):JObject; jnicall;
CallObjectMethodA:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:PJValue):JObject; jnicall;
CallBooleanMethod:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID):JBoolean; jnicall;
CallBooleanMethodV:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:va_list):JBoolean; jnicall;
CallBooleanMethodA:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:PJValue):JBoolean; jnicall;
CallByteMethod:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID):JByte; jnicall;
CallByteMethodV:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:va_list):JByte; jnicall;
CallByteMethodA:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:PJValue):JByte; jnicall;
CallCharMethod:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID):JChar; jnicall;
CallCharMethodV:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:va_list):JChar; jnicall;
CallCharMethodA:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:PJValue):JChar; jnicall;
CallShortMethod:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID):JShort; jnicall;
CallShortMethodV:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:va_list):JShort; jnicall;
CallShortMethodA:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:PJValue):JShort; jnicall;
CallIntMethod:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID):JInt; jnicall;
CallIntMethodV:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:va_list):JInt; jnicall;
CallIntMethodA:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:PJValue):JInt; jnicall;
CallLongMethod:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID):JLong; jnicall;
CallLongMethodV:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:va_list):JLong; jnicall;
CallLongMethodA:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:PJValue):JLong; jnicall;
CallFloatMethod:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID):JFloat; jnicall;
CallFloatMethodV:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:va_list):JFloat; jnicall;
CallFloatMethodA:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:PJValue):JFloat; jnicall;
CallDoubleMethod:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID):JDouble; jnicall;
CallDoubleMethodV:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:va_list):JDouble; jnicall;
CallDoubleMethodA:function(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:PJValue):JDouble; jnicall;
CallVoidMethod:procedure(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID); jnicall;
CallVoidMethodV:procedure(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:va_list); jnicall;
CallVoidMethodA:procedure(Env:PJNIEnv;Obj:JObject;MethodID:JMethodID;Args:PJValue); jnicall;
CallNonvirtualObjectMethod:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID):JObject; jnicall;
CallNonvirtualObjectMethodV:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:va_list):JObject; jnicall;
CallNonvirtualObjectMethodA:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:PJValue):JObject; jnicall;
CallNonvirtualBooleanMethod:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID):JBoolean; jnicall;
CallNonvirtualBooleanMethodV:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:va_list):JBoolean; jnicall;
CallNonvirtualBooleanMethodA:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:PJValue):JBoolean; jnicall;
CallNonvirtualByteMethod:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID):JByte; jnicall;
CallNonvirtualByteMethodV:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:va_list):JByte; jnicall;
CallNonvirtualByteMethodA:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:PJValue):JByte; jnicall;
CallNonvirtualCharMethod:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID):JChar; jnicall;
CallNonvirtualCharMethodV:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:va_list):JChar; jnicall;
CallNonvirtualCharMethodA:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:PJValue):JChar; jnicall;
CallNonvirtualShortMethod:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID):JShort; jnicall;
CallNonvirtualShortMethodV:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:va_list):JShort; jnicall;
CallNonvirtualShortMethodA:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:PJValue):JShort; jnicall;
CallNonvirtualIntMethod:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID):JInt; jnicall;
CallNonvirtualIntMethodV:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:va_list):JInt; jnicall;
CallNonvirtualIntMethodA:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:PJValue):JInt; jnicall;
CallNonvirtualLongMethod:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID):JLong; jnicall;
CallNonvirtualLongMethodV:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:va_list):JLong; jnicall;
CallNonvirtualLongMethodA:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:PJValue):JLong; jnicall;
CallNonvirtualFloatMethod:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID):JFloat; jnicall;
CallNonvirtualFloatMethodV:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:va_list):JFloat; jnicall;
CallNonvirtualFloatMethodA:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:PJValue):JFloat; jnicall;
CallNonvirtualDoubleMethod:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID):JDouble; jnicall;
CallNonvirtualDoubleMethodV:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:va_list):JDouble; jnicall;
CallNonvirtualDoubleMethodA:function(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:PJValue):JDouble; jnicall;
CallNonvirtualVoidMethod:procedure(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID); jnicall;
CallNonvirtualVoidMethodV:procedure(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:va_list); jnicall;
CallNonvirtualVoidMethodA:procedure(Env:PJNIEnv;Obj:JObject;AClass:JClass;MethodID:JMethodID;Args:PJValue); jnicall;
GetFieldID:function(Env:PJNIEnv;AClass:JClass;const Name:pchar;const Sig:pchar):JFieldID; jnicall;
GetObjectField:function(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID):JObject; jnicall;
GetBooleanField:function(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID):JBoolean; jnicall;
GetByteField:function(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID):JByte; jnicall;
GetCharField:function(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID):JChar; jnicall;
GetShortField:function(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID):JShort; jnicall;
GetIntField:function(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID):JInt; jnicall;
GetLongField:function(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID):JLong; jnicall;
GetFloatField:function(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID):JFloat; jnicall;
GetDoubleField:function(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID):JDouble; jnicall;
SetObjectField:procedure(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID;Val:JObject); jnicall;
SetBooleanField:procedure(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID;Val:JBoolean); jnicall;
SetByteField:procedure(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID;Val:JByte); jnicall;
SetCharField:procedure(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID;Val:JChar); jnicall;
SetShortField:procedure(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID;Val:JShort); jnicall;
SetIntField:procedure(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID;Val:JInt); jnicall;
SetLongField:procedure(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID;Val:JLong); jnicall;
SetFloatField:procedure(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID;Val:JFloat); jnicall;
SetDoubleField:procedure(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID;Val:JDouble); jnicall;
GetStaticMethodID:function(Env:PJNIEnv;AClass:JClass;const Name:pchar;const Sig:pchar):JMethodID; jnicall;
CallStaticObjectMethod:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID):JObject; jnicall;
CallStaticObjectMethodV:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:va_list):JObject; jnicall;
CallStaticObjectMethodA:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:PJValue):JObject; jnicall;
CallStaticBooleanMethod:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID):JBoolean; jnicall;
CallStaticBooleanMethodV:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:va_list):JBoolean; jnicall;
CallStaticBooleanMethodA:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:PJValue):JBoolean; jnicall;
CallStaticByteMethod:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID):JByte; jnicall;
CallStaticByteMethodV:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:va_list):JByte; jnicall;
CallStaticByteMethodA:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:PJValue):JByte; jnicall;
CallStaticCharMethod:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID):JChar; jnicall;
CallStaticCharMethodV:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:va_list):JChar; jnicall;
CallStaticCharMethodA:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:PJValue):JChar; jnicall;
CallStaticShortMethod:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID):JShort; jnicall;
CallStaticShortMethodV:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:va_list):JShort; jnicall;
CallStaticShortMethodA:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:PJValue):JShort; jnicall;
CallStaticIntMethod:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID):JInt; jnicall;
CallStaticIntMethodV:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:va_list):JInt; jnicall;
CallStaticIntMethodA:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:PJValue):JInt; jnicall;
CallStaticLongMethod:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID):JLong; jnicall;
CallStaticLongMethodV:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:va_list):JLong; jnicall;
CallStaticLongMethodA:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:PJValue):JLong; jnicall;
CallStaticFloatMethod:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID):JFloat; jnicall;
CallStaticFloatMethodV:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:va_list):JFloat; jnicall;
CallStaticFloatMethodA:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:PJValue):JFloat; jnicall;
CallStaticDoubleMethod:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID):JDouble; jnicall;
CallStaticDoubleMethodV:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:va_list):JDouble; jnicall;
CallStaticDoubleMethodA:function(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:PJValue):JDouble; jnicall;
CallStaticVoidMethod:procedure(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID); jnicall;
CallStaticVoidMethodV:procedure(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:va_list); jnicall;
CallStaticVoidMethodA:procedure(Env:PJNIEnv;AClass:JClass;MethodID:JMethodID;Args:PJValue); jnicall;
GetStaticFieldID:function(Env:PJNIEnv;AClass:JClass;const Name:pchar;const Sig:pchar):JFieldID; jnicall;
GetStaticObjectField:function(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID):JObject; jnicall;
GetStaticBooleanField:function(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID):JBoolean; jnicall;
GetStaticByteField:function(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID):JByte; jnicall;
GetStaticCharField:function(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID):JChar; jnicall;
GetStaticShortField:function(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID):JShort; jnicall;
GetStaticIntField:function(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID):JInt; jnicall;
GetStaticLongField:function(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID):JLong; jnicall;
GetStaticFloatField:function(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID):JFloat; jnicall;
GetStaticDoubleField:function(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID):JDouble; jnicall;
SetStaticObjectField:procedure(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID;Val:JObject); jnicall;
SetStaticBooleanField:procedure(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID;Val:JBoolean); jnicall;
SetStaticByteField:procedure(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID;Val:JByte); jnicall;
SetStaticCharField:procedure(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID;Val:JChar); jnicall;
SetStaticShortField:procedure(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID;Val:JShort); jnicall;
SetStaticIntField:procedure(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID;Val:JInt); jnicall;
SetStaticLongField:procedure(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID;Val:JLong); jnicall;
SetStaticFloatField:procedure(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID;Val:JFloat); jnicall;
SetStaticDoubleField:procedure(Env:PJNIEnv;AClass:JClass;FieldID:JFieldID;Val:JDouble); jnicall;
NewString:function(Env:PJNIEnv;const Unicode:PJChar;Len:JSize):JString; jnicall;
GetStringLength:function(Env:PJNIEnv;Str:JString):JSize; jnicall;
GetStringChars:function(Env:PJNIEnv;Str:JString;IsCopy:PJBoolean):PJChar; jnicall;
ReleaseStringChars:procedure(Env:PJNIEnv;Str:JString;const Chars:PJChar); jnicall;
NewStringUTF:function(Env:PJNIEnv;const UTF:pchar):JString; jnicall;
GetStringUTFLength:function(Env:PJNIEnv;Str:JString):JSize; jnicall;
GetStringUTFChars:function(Env:PJNIEnv;Str:JString;IsCopy:PJBoolean):pchar; jnicall;
ReleaseStringUTFChars:procedure(Env:PJNIEnv;Str:JString;const Chars:pchar); jnicall;
GetArrayLength:function(Env:PJNIEnv;AArray:JArray):JSize; jnicall;
NewObjectArray:function(Env:PJNIEnv;Len:JSize;AClass:JClass;Init:JObject):JObjectArray; jnicall;
GetObjectArrayElement:function(Env:PJNIEnv;AArray:JObjectArray;Index:JSize):JObject; jnicall;
SetObjectArrayElement:procedure(Env:PJNIEnv;AArray:JObjectArray;Index:JSize;Val:JObject); jnicall;
NewBooleanArray:function(Env:PJNIEnv;Len:JSize):JBooleanArray; jnicall;
NewByteArray:function(Env:PJNIEnv;Len:JSize):JByteArray; jnicall;
NewCharArray:function(Env:PJNIEnv;Len:JSize):JCharArray; jnicall;
NewShortArray:function(Env:PJNIEnv;Len:JSize):JShortArray; jnicall;
NewIntArray:function(Env:PJNIEnv;Len:JSize):JIntArray; jnicall;
NewLongArray:function(Env:PJNIEnv;Len:JSize):JLongArray; jnicall;
NewFloatArray:function(Env:PJNIEnv;Len:JSize):JFloatArray; jnicall;
NewDoubleArray:function(Env:PJNIEnv;Len:JSize):JDoubleArray; jnicall;
GetBooleanArrayElements:function(Env:PJNIEnv;AArray:JBooleanArray;IsCopy:PJBoolean):PJBoolean; jnicall;
GetByteArrayElements:function(Env:PJNIEnv;AArray:JByteArray;IsCopy:PJBoolean):PJByte; jnicall;
GetCharArrayElements:function(Env:PJNIEnv;AArray:JCharArray;IsCopy:PJBoolean):PJChar; jnicall;
GetShortArrayElements:function(Env:PJNIEnv;AArray:JShortArray;IsCopy:PJBoolean):PJShort; jnicall;
GetIntArrayElements:function(Env:PJNIEnv;AArray:JIntArray;IsCopy:PJBoolean):PJInt; jnicall;
GetLongArrayElements:function(Env:PJNIEnv;AArray:JLongArray;IsCopy:PJBoolean):PJLong; jnicall;
GetFloatArrayElements:function(Env:PJNIEnv;AArray:JFloatArray;IsCopy:PJBoolean):PJFloat; jnicall;
GetDoubleArrayElements:function(Env:PJNIEnv;AArray:JDoubleArray;IsCopy:PJBoolean):PJDouble; jnicall;
ReleaseBooleanArrayElements:procedure(Env:PJNIEnv;AArray:JBooleanArray;Elems:PJBoolean;Mode:JInt); jnicall;
ReleaseByteArrayElements:procedure(Env:PJNIEnv;AArray:JByteArray;Elems:PJByte;Mode:JInt); jnicall;
ReleaseCharArrayElements:procedure(Env:PJNIEnv;AArray:JCharArray;Elems:PJChar;Mode:JInt); jnicall;
ReleaseShortArrayElements:procedure(Env:PJNIEnv;AArray:JShortArray;Elems:PJShort;Mode:JInt); jnicall;
ReleaseIntArrayElements:procedure(Env:PJNIEnv;AArray:JIntArray;Elems:PJInt;Mode:JInt); jnicall;
ReleaseLongArrayElements:procedure(Env:PJNIEnv;AArray:JLongArray;Elems:PJLong;Mode:JInt); jnicall;
ReleaseFloatArrayElements:procedure(Env:PJNIEnv;AArray:JFloatArray;Elems:PJFloat;Mode:JInt); jnicall;
ReleaseDoubleArrayElements:procedure(Env:PJNIEnv;AArray:JDoubleArray;Elems:PJDouble;Mode:JInt); jnicall;
GetBooleanArrayRegion:procedure(Env:PJNIEnv;AArray:JBooleanArray;Start:JSize;Len:JSize;Buf:PJBoolean); jnicall;
GetByteArrayRegion:procedure(Env:PJNIEnv;AArray:JByteArray;Start:JSize;Len:JSize;Buf:PJByte); jnicall;
GetCharArrayRegion:procedure(Env:PJNIEnv;AArray:JCharArray;Start:JSize;Len:JSize;Buf:PJChar); jnicall;
GetShortArrayRegion:procedure(Env:PJNIEnv;AArray:JShortArray;Start:JSize;Len:JSize;Buf:PJShort); jnicall;
GetIntArrayRegion:procedure(Env:PJNIEnv;AArray:JIntArray;Start:JSize;Len:JSize;Buf:PJInt); jnicall;
GetLongArrayRegion:procedure(Env:PJNIEnv;AArray:JLongArray;Start:JSize;Len:JSize;Buf:PJLong); jnicall;
GetFloatArrayRegion:procedure(Env:PJNIEnv;AArray:JFloatArray;Start:JSize;Len:JSize;Buf:PJFloat); jnicall;
GetDoubleArrayRegion:procedure(Env:PJNIEnv;AArray:JDoubleArray;Start:JSize;Len:JSize;Buf:PJDouble); jnicall;
SetBooleanArrayRegion:procedure(Env:PJNIEnv;AArray:JBooleanArray;Start:JSize;Len:JSize;Buf:PJBoolean); jnicall;
SetByteArrayRegion:procedure(Env:PJNIEnv;AArray:JByteArray;Start:JSize;Len:JSize;Buf:PJByte); jnicall;
SetCharArrayRegion:procedure(Env:PJNIEnv;AArray:JCharArray;Start:JSize;Len:JSize;Buf:PJChar); jnicall;
SetShortArrayRegion:procedure(Env:PJNIEnv;AArray:JShortArray;Start:JSize;Len:JSize;Buf:PJShort); jnicall;
SetIntArrayRegion:procedure(Env:PJNIEnv;AArray:JIntArray;Start:JSize;Len:JSize;Buf:PJInt); jnicall;
SetLongArrayRegion:procedure(Env:PJNIEnv;AArray:JLongArray;Start:JSize;Len:JSize;Buf:PJLong); jnicall;
SetFloatArrayRegion:procedure(Env:PJNIEnv;AArray:JFloatArray;Start:JSize;Len:JSize;Buf:PJFloat); jnicall;
SetDoubleArrayRegion:procedure(Env:PJNIEnv;AArray:JDoubleArray;Start:JSize;Len:JSize;Buf:PJDouble); jnicall;
RegisterNatives:function(Env:PJNIEnv;AClass:JClass;const Methods:PJNINativeMethod;NMethods:JInt):JInt; jnicall;
UnregisterNatives:function(Env:PJNIEnv;AClass:JClass):JInt; jnicall;
MonitorEnter:function(Env:PJNIEnv;Obj:JObject):JInt; jnicall;
MonitorExit:function(Env:PJNIEnv;Obj:JObject):JInt; jnicall;
GetJavaVM:function(Env:PJNIEnv;VM:PJavaVM):JInt; jnicall;
// String Operations
GetStringRegion:procedure(Env:PJNIEnv;Str:JString;Start:JSize;Len:JSize;Buf:PJChar); jnicall;
GetStringUTFRegion:procedure(Env:PJNIEnv;Str:JString;Start:JSize;Len:JSize;Buf:pchar); jnicall;
// Array Operations
GetPrimitiveArrayCritical:function(Env:PJNIEnv;AArray:JArray;IsCopy:PJBoolean):pointer; jnicall;
ReleasePrimitiveArrayCritical:procedure(Env:PJNIEnv;AArray:JArray;CArray:pointer;Mode:JInt); jnicall;
// String Operations
GetStringCritical:function(Env:PJNIEnv;Str:JString;IsCopy:PJBoolean):PJChar; jnicall;
ReleaseStringCritical:procedure(Env:PJNIEnv;Str:JString;CString:PJChar); jnicall;
// Weak Global References
NewWeakGlobalRef:function(Env:PJNIEnv;Obj:JObject):JWeak; jnicall;
DeleteWeakGlobalRef:procedure(Env:PJNIEnv;Ref:JWeak); jnicall;
// Exceptions
ExceptionCheck:function(Env:PJNIEnv):JBoolean; jnicall;
// J2SDK1_4
NewDirectByteBuffer:function(Env:PJNIEnv;Address:pointer;Capacity:JLong):JObject; jnicall;
GetDirectBufferAddress:function(Env:PJNIEnv;Buf:JObject):pointer; jnicall;
GetDirectBufferCapacity:function(Env:PJNIEnv;Buf:JObject):JLong; jnicall;
// added in JNI 1.6
GetObjectRefType:function(Env:PJNIEnv;AObject:JObject):jobjectRefType; jnicall;
end;
JNIInvokeInterface={$ifdef packedrecords}packed{$endif} record
reserved0:pointer;
reserved1:pointer;
reserved2:pointer;
DestroyJavaVM:function(PVM:PJavaVM):JInt; jnicall;
AttachCurrentThread:function(PVM:PJavaVM;PEnv:PPJNIEnv;Args:pointer):JInt; jnicall;
DetachCurrentThread:function(PVM:PJavaVM):JInt; jnicall;
GetEnv:function(PVM:PJavaVM;PEnv:Ppointer;Version:JInt):JInt; jnicall;
AttachCurrentThreadAsDaemon:function(PVM:PJavaVM;PEnv:PPJNIEnv;Args:pointer):JInt; jnicall;
end;
JavaVMAttachArgs={$ifdef packedrecords}packed{$endif} record
version:jint; // must be >= JNI_VERSION_1_2
name:pchar; // NULL or name of thread as modified UTF-8 str
group:jobject; // global ref of a ThreadGroup object, or NULL
end;
(**
* JNI 1.2+ initialization. (As of 1.6, the pre-1.2 structures are no
* longer supported.)
*)
PJavaVMOption=^JavaVMOption;
JavaVMOption={$ifdef packedrecords}packed{$endif} record
optionString:pchar;
extraInfo:pointer;
end;
JavaVMInitArgs={$ifdef packedrecords}packed{$endif} record
version:jint; // use JNI_VERSION_1_2 or later
nOptions:jint;
options:PJavaVMOption;
ignoreUnrecognized:Pjboolean;
end;
(*
* VM initialization functions.
*
* Note these are the only symbols exported for JNI by the VM.
*)
{$ifdef jniexternals}
function JNI_GetDefaultJavaVMInitArgs(p:pointer):jint; jnicall;external 'jni' name 'JNI_GetDefaultJavaVMInitArgs';
function JNI_CreateJavaVM(vm:PPJavaVM;AEnv:PPJNIEnv;p:pointer):jint; jnicall;external 'jni' name 'JNI_CreateJavaVM';
function JNI_GetCreatedJavaVMs(vm:PPJavaVM;ASize:jsize;p:Pjsize):jint; jnicall;external 'jni' name 'JNI_GetCreatedJavaVMs';
{$endif}
(*
* Prototypes for functions exported by loadable shared libs. These are
* called by JNI, not provided by JNI.
*)
const curVM:PJavaVM=nil;
curEnv:PJNIEnv=nil;
(*
function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; jnicall;
procedure JNI_OnUnload(vm:PJavaVM;reserved:pointer); jnicall;
*)
(* Helper Routines *)
function JNI_JStringToString( PEnv : PJNIEnv; JStr : JString ) : string;
function JNI_StringToJString( PEnv : PJNIEnv; const AString : PAnsiChar ) : JString;
implementation
function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; jnicall;
begin
curVM:=vm;
result:=JNI_VERSION_1_6;
end;
procedure JNI_OnUnload(vm:PJavaVM;reserved:pointer); jnicall;
begin
end;
function JNI_JStringToString( PEnv : PJNIEnv; JStr : JString ) : string;
var
IsCopy: PJBoolean;
Chars: PAnsiChar;
begin
if JStr = nil then
begin
Result := '';
Exit;
end;
Chars := PEnv^.GetStringUTFChars(PEnv, JStr, IsCopy);
if Chars = nil then
Result := ''
else
begin
Result := string(Chars);
PEnv^.ReleaseStringUTFChars(PEnv, JStr, Chars);
end;
end;
function JNI_StringToJString( PEnv : PJNIEnv; const AString : PAnsiChar ) : JString;
begin
Result := PEnv^.NewStringUTF( PEnv, PAnsiChar( AString ) );
end;
end.

785
UOS/src/uos_libsndfile.pas Normal file
View File

@@ -0,0 +1,785 @@
{This unit is part of United Openlibraries of Sound (uos)}
{This is the Dynamic loading version with reference counting of LibSndFile.pas.
Load the library with sf_load() and release with sf_unload().
Thanks to Phoenix for sf_open_virtual (TMemoryStream as input)
License : modified LGPL.
Fred van Stappen / fiens@hotmail.com }
unit uos_libsndfile;
{$IFDEF FPC}
{$mode objfpc}{$H+}
{$PACKENUM 4}(* use 4-byte enums *)
{$PACKRECORDS C}(* C/C++-compatible record packing *)
{$MACRO ON}//don't know whatfor !
{$ELSE}
{$MINENUMSIZE 4}(* use 4-byte enums *)
{** MINENUMSIZE is equivalent to Z+}
{$ENDIF}
{$LONGSTRINGS ON}
{** LONGSTRINGS is equivalent to H+}
interface
uses
dynlibs, classes,
ctypes;
const
libsf=
{$IFDEF unix}
{$IFDEF darwin}
'libsndfile.1.dylib';
{$ELSE}
'libsndfile.so.1';
{$ENDIF}
{$ELSE}
'sndfile.dll';
{$ENDIF}
type
PMemoryStream = ^TMemoryStream;
type
{$IF Defined(MSWINDOWS)}
off_t = int64;
{$ELSE}
off_t = clonglong;
size_t = culong;
{$ENDIF}
const
//* Major formats. *//
SF_FORMAT_WAV = $010000; // Microsoft WAV format (little endian default).
SF_FORMAT_AIFF = $020000; // Apple/SGI AIFF format (big endian).
SF_FORMAT_AU = $030000; // Sun/NeXT AU format (big endian).
SF_FORMAT_RAW = $040000; // RAW PCM data.
SF_FORMAT_PAF = $050000; // Ensoniq PARIS file format.
SF_FORMAT_SVX = $060000; // Amiga IFF / SVX8 / SV16 format.
SF_FORMAT_NIST = $070000; // Sphere NIST format.
SF_FORMAT_VOC = $080000; // VOC files.
SF_FORMAT_IRCAM = $0A0000; // Berkeley/IRCAM/CARL
SF_FORMAT_W64 = $0B0000; // Sonic Foundry's 64 bit RIFF/WAV
SF_FORMAT_MAT4 = $0C0000; // Matlab (tm) V4.2 / GNU Octave 2.0
SF_FORMAT_MAT5 = $0D0000; // Matlab (tm) V5.0 / GNU Octave 2.1
SF_FORMAT_PVF = $0E0000; // Portable Voice Format
SF_FORMAT_XI = $0F0000; // Fasttracker 2 Extended Instrument
SF_FORMAT_HTK = $100000; // HMM Tool Kit format
SF_FORMAT_SDS = $110000; // Midi Sample Dump Standard
SF_FORMAT_AVR = $120000; // Audio Visual Research
SF_FORMAT_WAVEX = $130000; // MS WAVE with WAVEFORMATEX
SF_FORMAT_SD2 = $160000; // Sound Designer 2
SF_FORMAT_FLAC = $170000; // FLAC lossless file format
SF_FORMAT_CAF = $180000; // Core Audio File format
SF_FORMAT_OGG = $200000; // Xiph OGG container
const
//Subtypes from here on.
SF_FORMAT_PCM_S8 = $0001; // Signed 8 bit data
SF_FORMAT_PCM_16 = $0002; // Signed 16 bit data
SF_FORMAT_PCM_24 = $0003; // Signed 24 bit data
SF_FORMAT_PCM_32 = $0004; // Signed 32 bit data
SF_FORMAT_PCM_U8 = $0005; // Unsigned 8 bit data (WAV and RAW only)
SF_FORMAT_FLOAT = $0006; // 32 bit float data
SF_FORMAT_DOUBLE = $0007; // 64 bit float data
SF_FORMAT_ULAW = $0010; // U-Law encoded.
SF_FORMAT_ALAW = $0011; // A-Law encoded.
SF_FORMAT_IMA_ADPCM = $0012; // IMA ADPCM.
SF_FORMAT_MS_ADPCM = $0013; // Microsoft ADPCM.
SF_FORMAT_GSM610 = $0020; // GSM 6.10 encoding.
SF_FORMAT_VOX_ADPCM = $0021; // OKI / Dialogix ADPCM
SF_FORMAT_G721_32 = $0030; // 32kbs G721 ADPCM encoding.
SF_FORMAT_G723_24 = $0031; // 24kbs G723 ADPCM encoding.
SF_FORMAT_G723_40 = $0032; // 40kbs G723 ADPCM encoding.
SF_FORMAT_DWVW_12 = $0040; // 12 bit Delta Width Variable Word encoding.
SF_FORMAT_DWVW_16 = $0041; // 16 bit Delta Width Variable Word encoding.
SF_FORMAT_DWVW_24 = $0042; // 24 bit Delta Width Variable Word encoding.
SF_FORMAT_DWVW_N = $0043; // N bit Delta Width Variable Word encoding.
SF_FORMAT_DPCM_8 = $0050; // 8 bit differential PCM (XI only)
SF_FORMAT_DPCM_16 = $0051; // 16 bit differential PCM (XI only)
SF_FORMAT_VORBIS = $0060; // Xiph Vorbis encoding.
const
//* Endian-ness options. *//
SF_ENDIAN_FILE = $00000000; // Default file endian-ness.
SF_ENDIAN_LITTLE = $10000000; // Force little endian-ness.
SF_ENDIAN_BIG = $20000000; // Force big endian-ness.
SF_ENDIAN_CPU = $30000000; // Force CPU endian-ness.
SF_FORMAT_SUBMASK = $0000FFFF;
SF_FORMAT_TYPEMASK = $0FFF0000;
SF_FORMAT_ENDMASK = $30000000;
{
** The following are the valid command numbers for the sf_command()
** interface. The use of these commands is documented in the file
** command.html in the doc directory of the source code distribution.
}
const
SFC_GET_LIB_VERSION = $1000;
SFC_GET_LOG_INFO = $1001;
SFC_GET_NORM_DOUBLE = $1010;
SFC_GET_NORM_FLOAT = $1011;
SFC_SET_NORM_DOUBLE = $1012;
SFC_SET_NORM_FLOAT = $1013;
SFC_SET_SCALE_FLOAT_INT_READ = $1014;
SFC_GET_SIMPLE_FORMAT_COUNT = $1020;
SFC_GET_SIMPLE_FORMAT = $1021;
SFC_GET_FORMAT_INFO = $1028;
SFC_GET_FORMAT_MAJOR_COUNT = $1030;
SFC_GET_FORMAT_MAJOR = $1031;
SFC_GET_FORMAT_SUBTYPE_COUNT = $1032;
SFC_GET_FORMAT_SUBTYPE = $1033;
SFC_CALC_SIGNAL_MAX = $1040;
SFC_CALC_NORM_SIGNAL_MAX = $1041;
SFC_CALC_MAX_ALL_CHANNELS = $1042;
SFC_CALC_NORM_MAX_ALL_CHANNELS = $1043;
SFC_GET_SIGNAL_MAX = $1044;
SFC_GET_MAX_ALL_CHANNELS = $1045;
SFC_SET_ADD_PEAK_CHUNK = $1050;
SFC_UPDATE_HEADER_NOW = $1060;
SFC_SET_UPDATE_HEADER_AUTO = $1061;
SFC_FILE_TRUNCATE = $1080;
SFC_SET_RAW_START_OFFSET = $1090;
SFC_SET_DITHER_ON_WRITE = $10A0;
SFC_SET_DITHER_ON_READ = $10A1;
SFC_GET_DITHER_INFO_COUNT = $10A2;
SFC_GET_DITHER_INFO = $10A3;
SFC_GET_EMBED_FILE_INFO = $10B0;
SFC_SET_CLIPPING = $10C0;
SFC_GET_CLIPPING = $10C1;
SFC_GET_INSTRUMENT = $10D0;
SFC_SET_INSTRUMENT = $10D1;
SFC_GET_LOOP_INFO = $10E0;
SFC_GET_BROADCAST_INFO = $10F0;
SFC_SET_BROADCAST_INFO = $10F1;
// Following commands for testing only.
SFC_TEST_IEEE_FLOAT_REPLACE = $6001;
{
** SFC_SET_ADD_* values are deprecated and will disappear at some
** time in the future. They are guaranteed to be here up to and
** including version 1.0.8 to avoid breakage of existing software.
** They currently do nothing and will continue to do nothing.
}
SFC_SET_ADD_DITHER_ON_WRITE = $1070;
SFC_SET_ADD_DITHER_ON_READ = $1071;
{
** String types that can be set and read from files. Not all file types
** support this and even the file types which support one, may not support
** all string types.
}
const
SF_STR_TITLE = $01;
SF_STR_COPYRIGHT = $02;
SF_STR_SOFTWARE = $03;
SF_STR_ARTIST = $04;
SF_STR_COMMENT = $05;
SF_STR_DATE = $06;
SF_STR_ALBUM = $07;
SF_STR_LICENSE = $08;
SF_STR_TRACKNUMBER = $09;
SF_STR_GENRE = $10;
{
** Use the following as the start and end index when doing metadata
** transcoding.
}
SF_STR_FIRST = SF_STR_TITLE;
SF_STR_LAST = SF_STR_GENRE;
const
// True and false
SF_FALSE = 0;
SF_TRUE = 1;
const
// Modes for opening files.
SFM_READ = $10;
SFM_WRITE = $20;
SFM_RDWR = $30;
{
** Public error values. These are guaranteed to remain unchanged
** for the duration of the library major version number.
** There are also a large number of private error numbers which are
** internal to the library which can change at any time.
}
const
SF_ERR_NO_ERROR = 0;
SF_ERR_UNRECOGNISED_FORMAT = 1;
SF_ERR_SYSTEM = 2;
SF_ERR_MALFORMED_FILE = 3;
SF_ERR_UNSUPPORTED_ENCODING = 4;
//A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer.
type
TSNDFILE_HANDLE = pointer; // this is not a usual pointer, more like a THandle ..
// so NOT called "PSndFile_handle"
// => we never access members of the internal
// structure where the pointer points to !
// Everything is managed by the DLL internally !!!
//PSNDFILE_tag = PSNDFILE;
{
** The following typedef is system specific and is defined when libsndfile is.
** compiled. uos_count_t can be one of loff_t (Linux), off_t (*BSD),
** off64_t (Solaris), __int64_t (Win32) etc.
}
type
Puos_count_t = ^Tuos_count_t;
Tuos_count_t = off_t;
const
SF_COUNT_MAX = ctypes.clonglong($7FFFFFFFFFFFFFFF);
{
** A pointer to a SF_INFO structure is passed to sf_open_read () and filled in.
** On write, the SF_INFO structure is filled in by the user and passed into
** sf_open_write ().
}
type
PSF_INFO = ^TSF_INFO;
TSF_INFO = record
frames: Tuos_count_t;
// Used to be called samples. Changed to avoid confusion.
samplerate: ctypes.cint;
channels: ctypes.cint;
format: ctypes.cint;
sections: ctypes.cint;
seekable: ctypes.cint;
end;
{
** The SF_FORMAT_INFO struct is used to retrieve information about the sound
** file formats libsndfile supports using the sf_command () interface.
**
** Using this interface will allow applications to support new file formats
** and encoding types when libsndfile is upgraded, without requiring
** re-compilation of the application.
**
** Please consult the libsndfile documentation (particularly the information
** on the sf_command () interface) for examples of its use.
}
type
PSF_FORMAT_INFO = ^TSF_FORMAT_INFO;
TSF_FORMAT_INFO = record
format: ctypes.cint;
Name: ctypes.pcchar;
extention: ctypes.pcchar;
end;
{
** Enums and typedefs for adding dither on read and write.
** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE
** and SFC_SET_DITHER_ON_READ.
}
const
SFD_DEFAULT_LEVEL = 0;
SFD_CUSTOM_LEVEL = $40000000;
SFD_NO_DITHER = 500;
SFD_WHITE = 501;
SFD_TRIANGULAR_PDF = 502;
type
PSF_DITHER_INFO = ^TSF_DITHER_INFO;
TSF_DITHER_INFO = record
type_: ctypes.cint;
level: ctypes.cdouble;
Name: ctypes.pcchar;
end;
{
** Struct used to retrieve information about a file embedded within a
** larger file. See SFC_GET_EMBED_FILE_INFO.
}
type
PSF_EMBED_FILE_INFO = ^TSF_EMBED_FILE_INFO;
TSF_EMBED_FILE_INFO = record
offset: Tuos_count_t;
length: Tuos_count_t;
end;
// Structs used to retrieve music sample information from a file.
const
// The loop mode field in SF_INSTRUMENT will be one of the following.
SF_LOOP_NONE = 800;
SF_LOOP_FORWARD = 801;
SF_LOOP_BACKWARD = 802;
SF_LOOP_ALTERNATING = 803;
type
PSF_INSTRUMENT = ^TSF_INSTRUMENT;
TSF_INSTRUMENT = record
gain: ctypes.cint;
basenote,
detune: ctypes.cchar;
velocity_lo,
velocity_hi: ctypes.cchar;
loop_count: ctypes.cint;
loops: array[0..15] of record
mode: ctypes.cint;
start: ctypes.cuint;
end_: ctypes.cuint;
Count: ctypes.cuint;
end;
end;
// Struct used to retrieve loop information from a file.
type
PSF_LOOP_INFO = ^TSF_LOOP_INFO;
TSF_LOOP_INFO = record
time_sig_num: ctypes.cushort;
// any positive integer > 0
time_sig_den: ctypes.cushort;
// any positive power of 2 > 0
loop_mode: ctypes.cint; // see SF_LOOP enum
num_beats: ctypes.cint;
// this is NOT the amount of quarter notes !!!
// a full bar of 4/4 is 4 beats
// a full bar of 7/8 is 7 beats
bpm: ctypes.cfloat;
// suggestion, as it can be calculated using other fields:
// file's lenght, file's sampleRate and our time_sig_den
// -> bpms are always the amount of _quarter notes_ per minute
root_key: ctypes.cint;
// MIDI note, or -1 for None
future: array[0..5] of ctypes.cint;
end;
{
** Struct used to retrieve broadcast (EBU) information from a file.
** Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE.
}
type
PSF_BROADCAST_INFO = ^TSF_BROADCAST_INFO;
TSF_BROADCAST_INFO = record
description: array[0..255] of char;//ctypes.cchar;
originator: array[0..31] of char;//ctypes.cchar;
originator_reference: array[0..31] of char;//ctypes.cchar;
origination_date: array[0..9] of char;//ctypes.cchar;
origination_time: array[0..7] of char;//ctypes.cchar;
time_reference_low: ctypes.cuint;//ctypes.cint;
time_reference_high: ctypes.cuint;//ctypes.cint;
version: ctypes.cshort;
umid: array[0..63] of char;//ctypes.cchar;
reserved: array[0..189] of char;//ctypes.cchar;
coding_history_size: ctypes.cuint;
coding_history: array[0..255] of char;//ctypes.cchar;
end;
// Thanks to Phoenix
type
//pm_get_filelen = ^tm_get_filelen;
tm_get_filelen =
function (pms: PMemoryStream): Tuos_count_t; cdecl;
//pm_seek = ^tm_seek;
tm_seek =
function (offset: Tuos_count_t; whence: cint32; pms: PMemoryStream): Tuos_count_t; cdecl;
//pm_read = ^tm_read;
tm_read =
function (const buf: Pointer; count: Tuos_count_t; pms: PMemoryStream): Tuos_count_t; cdecl;
//pm_write = ^tm_write;
tm_write =
function (const buf: Pointer; count: Tuos_count_t; pms: PMemoryStream): Tuos_count_t; cdecl;
//pm_tell = ^tm_tell;
tm_tell =
function (pms: PMemoryStream): Tuos_count_t; cdecl;
TSF_VIRTUAL = packed record
sf_vio_get_filelen : tm_get_filelen;
seek : tm_seek;
read : tm_read;
write : tm_write;
tell : tm_tell;
end;
PSF_VIRTUAL = ^TSF_VIRTUAL;
{
** Open the specified file for read, write or both. On error, this will
** return a NULL pointer. To find the error number, pass a NULL SNDFILE
** to sf_perror () or sf_error_str ().
** All calls to sf_open() should be matched with a call to sf_close().
}
////////////////////////////////////////////////////////////////////////////////////////
function sf_open(path: string; mode: ctypes.cint;
var sfinfo: TSF_INFO): TSNDFILE_HANDLE;
////// Dynamic load : Vars that will hold our dynamically loaded functions..
var
sf_open_native: function(path: PChar;
mode: ctypes.cint; sfinfo: PSF_INFO): TSNDFILE_HANDLE; cdecl;
var
sf_version_string: function(): PChar; cdecl;
var
sf_open_fd: function(fd: ctypes.cint; mode: ctypes.cint; sfinfo: PSF_INFO;
close_desc: ctypes.cint): TSNDFILE_HANDLE; cdecl;
var
sf_open_virtual: function(sfvirtual: PSF_VIRTUAL; mode: ctypes.cint;
sfinfo: PSF_INFO; user_data: Pointer): TSNDFILE_HANDLE; cdecl;
var
sf_error: function(sndfile: TSNDFILE_HANDLE): ctypes.cint; cdecl;
var
sf_strerror: function(sndfile: TSNDFILE_HANDLE): PChar; cdecl;
var
sf_error_number: function(errnum: ctypes.cint): PChar; cdecl;
var
sf_perror: function(sndfile: TSNDFILE_HANDLE): ctypes.cint; cdecl;
var
sf_error_str: function(sndfile: TSNDFILE_HANDLE;
str: ctypes.pcchar; len: size_t): ctypes.cint; cdecl;
{
In libsndfile there are 4 functions with the same name (sf_command), 3 of them use the parameter "overload".
In dynamic loading (because of var) we use 4 different names for the 4 functions sf_command :
sf_command_pointer, sf_command_double, sf_command_array, sf_command_tsf. All that 4 functions gonna point
to sf_command in libsndfile library.
}
var
sf_command_pointer: function(sndfile: TSNDFILE_HANDLE; command: ctypes.cint;
Data: Pointer; datasize: ctypes.cint): ctypes.cint; cdecl;
var
sf_command_double: function(sndfile: TSNDFILE_HANDLE; command: ctypes.cint;
var Data: double; datasize: ctypes.cint): ctypes.cint; cdecl;
var
sf_command_array: function(sndfile: TSNDFILE_HANDLE; command: ctypes.cint;
var Data: array of char; datasize: ctypes.cint): ctypes.cint; cdecl;
var
sf_command_tsf: function(sndfile: TSNDFILE_HANDLE; command: ctypes.cint;
var Data: TSF_BROADCAST_INFO; datasize: ctypes.cint): ctypes.cint; cdecl;
var
sf_format_check: function(var info: TSF_INFO): ctypes.cint; cdecl;
{
** Seek within the waveform data chunk of the SNDFILE. sf_seek () uses
** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as
** stdio.h function fseek ().
** An offset of zero with whence set to SEEK_SET will position the
** read / write pointer to the first data sample.
** On success sf_seek returns the current position in (multi-channel)
** samples from the start of the file.
** Please see the libsndfile documentation for moving the read pointer
** separately from the write pointer on files open in mode SFM_RDWR.
** On error all of these functions return -1.
}
//the following CONST values originally are NOT in libsndfile.pas:
const
SEEK_SET = 0; //* seek relative to beginning of file */
const
SEEK_CUR = 1; //* seek relative to current file position */
const
SEEK_END = 2; //* seek relative to end of file */
const
SEEK_DATA = 3; //* seek to the next data */
const
SEEK_HOLE = 4; //* seek to the next hole */
const
SEEK_MAX = SEEK_HOLE;
var
sf_seek: function(sndfile: TSNDFILE_HANDLE; frame: Tuos_count_t;
whence: ctypes.cint): Tuos_count_t; cdecl;
{
** Functions for retrieving and setting string data within sound files.
** Not all file types support this features; AIFF and WAV do. For both
** functions, the str_type parameter must be one of the SF_STR_* values
** defined above.
** On error, sf_set_string() returns non-zero while sf_get_string()
** returns NULL.
}
var
sf_set_string: function(sndfile: TSNDFILE_HANDLE; str_type: ctypes.cint;
str: ctypes.pcchar): ctypes.cint; cdecl;
var
sf_get_string: function(sndfile: TSNDFILE_HANDLE;
str_type: ctypes.cint): PChar; cdecl;
var
sf_read_raw: function(sndfile: TSNDFILE_HANDLE; ptr: Pointer;
bytes: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_write_raw: function(sndfile: TSNDFILE_HANDLE; ptr: Pointer;
bytes: Tuos_count_t): Tuos_count_t; cdecl;
{
** Functions for reading and writing the data chunk in terms of frames.
** The number of items actually read/written = frames * number of channels.
** sf_xxxx_raw read/writes the raw data bytes from/to the file
** sf_xxxx_short passes data in the native short format
** sf_xxxx_int passes data in the native int format
** sf_xxxx_float passes data in the native float format
** sf_xxxx_double passes data in the native double format
** All of these read/write function return number of frames read/written.
}
var
sf_readf_short: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcshort;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_writef_short: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcshort;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_readf_int: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcint;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_writef_int: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcint;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_readf_float: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcfloat;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_writef_float: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcfloat;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_readf_double: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcdouble;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_writef_double: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcdouble;
frames: Tuos_count_t): Tuos_count_t; cdecl;
{
** Functions for reading and writing the data chunk in terms of items.
** Otherwise similar to above.
** All of these read/write function return number of items read/written.
}
var
sf_read_short: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcshort;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_write_short: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcshort;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_read_int: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcint;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_write_int: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcint;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_read_float: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcfloat;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_write_float: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcfloat;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_read_double: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcdouble;
frames: Tuos_count_t): Tuos_count_t; cdecl;
var
sf_write_double: function(sndfile: TSNDFILE_HANDLE; ptr: ctypes.pcdouble;
frames: Tuos_count_t): Tuos_count_t; cdecl;
{
** Close the SNDFILE and clean up all memory allocations associated
** with this file.
** Returns 0 on success, or an error number.
}
var
sf_close: function(sndfile: TSNDFILE_HANDLE): ctypes.cint; cdecl;
{
** If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file
** to force the writing of data to disk. If the file is opened SFM_READ
** no action is taken.
}
var
sf_write_sync: function(sndfile: TSNDFILE_HANDLE): ctypes.cint; cdecl;
{Special function for dynamic loading of lib ...}
var
sf_Handle: TLibHandle;
// this will hold our handle for the lib; it functions nicely as a mutli-lib prevention unit as well...
function sf_Load(const libfilename: string): boolean; // load the lib
procedure sf_Unload();
// unload and frees the lib from memory : do not forget to call it before close application.
function sf_IsLoaded: boolean;
implementation
var
ReferenceCounter: cardinal = 0; // Reference counter
function sf_Load(const libfilename: string): boolean;
var
thelib: string;
begin
Result := False;
if sf_Handle <> 0 then
begin
Result := True {is it already there ?};
//Reference counting
Inc(ReferenceCounter);
end
else
begin {go & load the library}
if Length(libfilename) = 0 then thelib := libsf else thelib := libfilename;
sf_Handle := DynLibs.SafeLoadLibrary(thelib); // obtain the handle we want
if sf_Handle <> DynLibs.NilHandle then
begin {now we tie the functions to the VARs from above}
Pointer(sf_version_string) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_version_string'));
Pointer(sf_open_native) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_open'));
Pointer(sf_open_fd) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_open_fd'));
Pointer(sf_open_virtual) := DynLibs.GetProcedureAddress(
sf_Handle, PChar('sf_open_virtual'));
Pointer(sf_error) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_error'));
Pointer(sf_strerror) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_strerror'));
Pointer(sf_error_number) := DynLibs.GetProcedureAddress(
sf_Handle, PChar('sf_error_number'));
Pointer(sf_perror) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_perror'));
Pointer(sf_error_str) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_error_str'));
Pointer(sf_command_pointer) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_command'));
Pointer(sf_command_array) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_command'));
Pointer(sf_command_double) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_command'));
Pointer(sf_command_tsf) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_command'));
Pointer(sf_format_check) := DynLibs.GetProcedureAddress(
sf_Handle, PChar('sf_format_check'));
Pointer(sf_seek) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_seek'));
Pointer(sf_set_string) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_set_string'));
Pointer(sf_get_string) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_get_string'));
Pointer(sf_read_raw) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_read_raw'));
Pointer(sf_write_raw) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_write_raw'));
Pointer(sf_readf_short) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_readf_short'));
Pointer(sf_writef_short) := DynLibs.GetProcedureAddress(
sf_Handle, PChar('sf_writef_short'));
Pointer(sf_readf_int) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_readf_int'));
Pointer(sf_writef_int) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_writef_int'));
Pointer(sf_readf_float) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_readf_float'));
Pointer(sf_writef_float) := DynLibs.GetProcedureAddress(
sf_Handle, PChar('sf_writef_float'));
Pointer(sf_readf_double) := DynLibs.GetProcedureAddress(
sf_Handle, PChar('sf_readf_double'));
Pointer(sf_writef_double) := DynLibs.GetProcedureAddress(
sf_Handle, PChar('sf_writef_double'));
Pointer(sf_read_short) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_read_short'));
Pointer(sf_write_short) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_write_short'));
Pointer(sf_read_int) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_read_int'));
Pointer(sf_write_int) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_write_int'));
Pointer(sf_read_float) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_read_float'));
Pointer(sf_write_float) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_write_float'));
Pointer(sf_read_double) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_read_double'));
Pointer(sf_write_double) := DynLibs.GetProcedureAddress(
sf_Handle, PChar('sf_write_double'));
Pointer(sf_close) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_close'));
Pointer(sf_write_sync) := DynLibs.GetProcedureAddress(sf_Handle, PChar('sf_write_sync'));
end;
Result := sf_IsLoaded;
ReferenceCounter := 1;
end;
end;
procedure sf_Unload;
begin
// < Reference counting
if ReferenceCounter > 0 then
Dec(ReferenceCounter);
if ReferenceCounter > 0 then
exit;
// >
if sf_IsLoaded then
begin
DynLibs.UnloadLibrary(sf_Handle);
sf_Handle := DynLibs.NilHandle;
end;
end;
function sf_open(path: string; mode: ctypes.cint;
var sfinfo: TSF_INFO): TSNDFILE_HANDLE;
begin
Result := sf_open_native(PChar(path), mode, @sfinfo);
end;
function sf_IsLoaded: boolean;
begin
Result := (sf_Handle <> dynlibs.NilHandle);
end;
end.

428
UOS/src/uos_libxmp.pas Normal file
View File

@@ -0,0 +1,428 @@
unit uos_libxmp;
{This unit is part of United Openlibraries of Sound (uos)}
{This is the Pascal Wrapper + Dynamic loading of libxmp library.
Load library with xmp_load() and release with xmp_unload().
License : modified LGPL.
by Fred vS | fiens@hotmail.com | 2024}
{$mode objfpc}{$H+}
{$PACKRECORDS C}
interface
uses
dynlibs,
sysutils,
CTypes;
const
XMP_VERSION = '4.6.0';
XMP_VERCODE = $040600;
XMP_VER_MAJOR = 4;
XMP_VER_MINOR = 6;
XMP_VER_RELEASE = 0;
const
{$IFDEF windows}
XMP_LIB_NAME = 'libxmp.dll';
{$ENDIF}
{$IFDEF unix}
{$IFDEF darwin}
XMP_LIB_NAME = 'libxmp.dylib';
{$ELSE}
XMP_LIB_NAME = 'libxmp.so.4.6.0';
{$ENDIF}
{$ENDIF}
const
XMP_NAME_SIZE = 64;
// Note event constants
XMP_KEY_OFF = $81;
XMP_KEY_CUT = $82;
XMP_KEY_FADE = $83;
// Sample format flags
XMP_FORMAT_8BIT = 1 shl 0;
XMP_FORMAT_UNSIGNED = 1 shl 1;
XMP_FORMAT_MONO = 1 shl 2;
// Player parameters
XMP_PLAYER_AMP = 0;
XMP_PLAYER_MIX = 1;
XMP_PLAYER_INTERP = 2;
XMP_PLAYER_DSP = 3;
XMP_PLAYER_FLAGS = 4;
XMP_PLAYER_CFLAGS = 5;
XMP_PLAYER_SMPCTL = 6;
XMP_PLAYER_VOLUME = 7;
XMP_PLAYER_STATE = 8;
XMP_PLAYER_SMIX_VOLUME = 9;
XMP_PLAYER_DEFPAN = 10;
XMP_PLAYER_MODE = 11;
XMP_PLAYER_MIXER_TYPE = 12;
XMP_PLAYER_VOICES = 13;
// Interpolation types
XMP_INTERP_NEAREST = 0;
XMP_INTERP_LINEAR = 1;
XMP_INTERP_SPLINE = 2;
// DSP effect types
XMP_DSP_LOWPASS = 1 shl 0;
XMP_DSP_ALL = XMP_DSP_LOWPASS;
// Player state
XMP_STATE_UNLOADED = 0;
XMP_STATE_LOADED = 1;
XMP_STATE_PLAYING = 2;
// Player flags
XMP_FLAGS_VBLANK = 1 shl 0;
XMP_FLAGS_FX9BUG = 1 shl 1;
XMP_FLAGS_FIXLOOP = 1 shl 2;
XMP_FLAGS_A500 = 1 shl 3;
// Player modes
XMP_MODE_AUTO = 0;
XMP_MODE_MOD = 1;
XMP_MODE_NOISETRACKER = 2;
XMP_MODE_PROTRACKER = 3;
XMP_MODE_S3M = 4;
XMP_MODE_ST3 = 5;
XMP_MODE_ST3GUS = 6;
XMP_MODE_XM = 7;
XMP_MODE_FT2 = 8;
XMP_MODE_IT = 9;
XMP_MODE_ITSMP = 10;
// Mixer types
XMP_MIXER_STANDARD = 0;
XMP_MIXER_A500 = 1;
XMP_MIXER_A500F = 2;
// Sample flags
XMP_SMPCTL_SKIP = 1 shl 0;
// Limits
XMP_MAX_KEYS = 121;
XMP_MAX_ENV_POINTS = 32;
XMP_MAX_MOD_LENGTH = 256;
XMP_MAX_CHANNELS = 64;
XMP_MAX_SRATE = 49170;
XMP_MIN_SRATE = 4000;
XMP_MIN_BPM = 20;
XMP_MAX_FRAMESIZE = 5 * XMP_MAX_SRATE * 2 div XMP_MIN_BPM;
// Error codes
XMP_END = 1;
XMP_ERROR_INTERNAL = 2;
XMP_ERROR_FORMAT = 3;
XMP_ERROR_LOAD = 4;
XMP_ERROR_DEPACK = 5;
XMP_ERROR_SYSTEM = 6;
XMP_ERROR_INVALID = 7;
XMP_ERROR_STATE = 8;
type
xmp_context = PChar;
type
xmp_channel = record
pan: integer; // Pan de canal (0x80 centrum)
vol: integer; // Volume of canal
flg: integer; // Flags of canal
end;
xmp_pattern = record
rows: integer;
index: array[1..1] of integer;
end;
xmp_event = record
note: byte;
ins: byte;
vol: byte;
fxt: byte;
fxp: byte;
f2t: byte;
f2p: byte;
_flag: byte;
end;
xmp_track = record
rows: integer;
event: array[1..1] of xmp_event;
end;
xmp_envelope = record
flg: integer;
npt: integer;
scl: integer;
sus: integer;
sue: integer;
lps: integer;
lpe: integer;
Data: array[1..XMP_MAX_ENV_POINTS * 2] of smallint;
end;
xmp_subinstrument = record
vol: integer;
gvl: integer;
pan: integer;
xpo: integer;
fin: integer;
vwf: integer;
vde: integer;
vra: integer;
vsw: integer;
rvv: integer;
sid: integer;
nna: integer;
dct: integer;
dca: integer;
ifc: integer;
ifr: integer;
end;
xmp_instrument = record
Name: array[0..31] of char;
vol: integer;
nsm: integer;
rls: integer;
aei: xmp_envelope;
pei: xmp_envelope;
fei: xmp_envelope;
map: array[0..XMP_MAX_KEYS] of record
ins: byte;
xpo: shortint;
end;
sub: ^xmp_subinstrument;
extra: Pointer;
end;
xmp_sample = record
Name: array[0..31] of char;
len: integer;
lps: integer;
lpe: integer;
flg: integer;
Data: PByte;
end;
xmp_sequence = record
entry_point: integer;
duration: integer;
end;
xmp_module = record
Name: array[0..XMP_NAME_SIZE - 1] of char;
typ: array[0..XMP_NAME_SIZE - 1] of char;
pat: integer;
trk: integer;
chn: integer;
ins: integer;
smp: integer;
spd: integer;
bpm: integer;
len: integer;
rst: integer;
gvl: integer;
xxp: ^xmp_pattern;
xxt: ^xmp_track;
xxi: ^xmp_instrument;
xxs: ^xmp_sample;
xxc: array[0..XMP_MAX_CHANNELS - 1] of xmp_channel;
xxo: array[0..XMP_MAX_MOD_LENGTH] of byte;
end;
xmp_test_info = record
Name: array[0..XMP_NAME_SIZE - 1] of char;
type_: array[0..XMP_NAME_SIZE - 1] of char;
end;
xmp_module_info = record
md5: array[0..15] of byte;
vol_base: integer;
module: ^xmp_module;
comment: PChar;
num_sequences: integer;
seq_data: ^xmp_sequence;
end;
xmp_channel_info = record
period: longword;
position: longword;
pitchbend: smallint;
note: byte;
instrument: byte;
sample: byte;
volume: byte;
pan: byte;
reserved: byte;
event: xmp_event;
end;
xmp_frame_info = record
pos: integer;
pattern: integer;
row: integer;
num_rows: integer;
frame: integer;
speed: integer;
bpm: integer;
time: integer;
total_time: integer;
frame_time: integer;
buffer: Pointer;
buffer_size: integer;
total_size: integer;
volume: integer;
loop_count: integer;
virt_channels: integer;
virt_used: integer;
sequence: integer;
channel_info: array[0..XMP_MAX_CHANNELS - 1] of xmp_channel_info;
end;
xmp_callbacks = record
read_func: function(dest: Pointer; len, nmemb: longword; priv: Pointer): longword;
seek_func: function(priv: Pointer; offset: longint; whence: integer): integer;
tell_func: function(priv: Pointer): longint;
close_func: function(priv: Pointer): integer;
end;
{ Dynamic load : Vars that will hold our dynamically loaded functions...
*************************** functions ******************************* }
var
xmp_create_context: function: pointer; cdecl;
xmp_free_context: procedure(ctx: Pointer); cdecl;
xmp_load_module: function(ctx: Pointer; const filename: PChar): Integer; cdecl;
xmp_load_module_from_memory: function(ctx: xmp_context; const Data: Pointer; size: longint): integer; cdecl;
xmp_load_module_from_file: function(ctx: xmp_context; file_: Pointer; size: longint): integer; cdecl;
xmp_load_module_from_callbacks: function(ctx: xmp_context; file_: Pointer; callbacks: xmp_callbacks): integer; cdecl;
xmp_test_module: function(const filename: PChar; info: xmp_test_info): Integer; cdecl;
xmp_release_module: procedure(ctx: xmp_context); cdecl;
xmp_start_player: function(ctx: xmp_context; rate: Integer; flags: Integer): Integer; cdecl;
xmp_play_buffer: function(ctx: xmp_context; buffer: Pointer; size: Integer; loop: Integer): Integer; cdecl;
xmp_get_frame_info: procedure(ctx: xmp_context; var info: xmp_frame_info); cdecl;
xmp_end_player: procedure(ctx: xmp_context); cdecl;
xmp_get_module_info: procedure(ctx: xmp_context; var info: xmp_module_info); cdecl;
xmp_get_format_list: function(): PAnsiChar; cdecl;
xmp_stop_module: procedure(ctx: xmp_context); cdecl;
xmp_restart_module: procedure(ctx: xmp_context); cdecl;
xmp_channel_vol: function(ctx: xmp_context; channel: Integer; volume: Integer): Integer; cdecl;
xmp_set_player: function(ctx: xmp_context; param: Integer; value: Integer): Integer; cdecl;
// Not used yet...
//function xmp_test_module_from_memory(const data: Pointer; size: LongInt; info: xmp_test_info): Integer; cdecl; external 'xmp';
//function xmp_test_module_from_file(file_: Pointer; info: xmp_test_info): Integer; cdecl; external 'xmp';
//function xmp_test_module_from_callbacks(file_: Pointer; callbacks: xmp_callbacks; info: xmp_test_info): Integer; cdecl; external 'xmp';
//procedure xmp_scan_module(ctx: xmp_context); cdecl; external 'xmp';
//function xmp_play_frame(ctx: xmp_context): Integer; cdecl; external 'xmp';
//procedure xmp_inject_event(ctx: xmp_context; channel: Integer; var event: xmp_event); cdecl; external 'xmp';//function xmp_next_position(ctx: xmp_context): Integer; cdecl; external 'xmp';
//function xmp_prev_position(ctx: xmp_context): Integer; cdecl; external 'xmp';
//function xmp_set_position(ctx: xmp_context; pos: Integer): Integer; cdecl; external 'xmp';
//function xmp_set_row(ctx: xmp_context; row: Integer): Integer; cdecl; external 'xmp';
//function xmp_set_tempo_factor(ctx: xmp_context; factor: Double): Integer; cdecl; external 'xmp';//function xmp_seek_time(ctx: xmp_context; time: Integer): Integer; cdecl; external 'xmp';
//function xmp_channel_mute(ctx: xmp_context; channel: Integer; mute: Integer): Integer; cdecl; external 'xmp';//function xmp_get_player(ctx: xmp_context; param: Integer): Integer; cdecl; external 'xmp';
//function xmp_set_instrument_path(ctx: xmp_context; const path: PChar): Integer; cdecl; external 'xmp';
{Special function for dynamic loading of lib ...}
var
xmp_Handle: TLibHandle = dynlibs.NilHandle;
{$if defined(cpu32) and defined(windows)} // try load dependency if not in /windows/system32/
gc_Handle :TLibHandle=dynlibs.NilHandle;
{$endif}
var
ReferenceCounter: cardinal = 0; // Reference counter
function xmp_IsLoaded: Boolean; inline;
function xmp_Load(const libfilename: string): Boolean; // load the lib
procedure xmp_Unload(); // unload and frees the lib from memory : do not forget to call it before close application.
implementation
function xmp_IsLoaded: boolean;
begin
Result := (xmp_Handle <> dynlibs.NilHandle);
end;
Function xmp_Load(const libfilename:string) :boolean;
var
thelib, thelibgcc: string;
begin
Result := False;
if xmp_Handle<>0 then
begin
Inc(ReferenceCounter);
result:=true {is it already there ?}
end else
begin
{$if defined(cpu32) and defined(windows)}
if Length(libfilename) = 0 then thelibgcc := 'libgcc_s_dw2-1.dll' else
thelibgcc := IncludeTrailingBackslash(ExtractFilePath(libfilename)) + 'libgcc_s_dw2-1.dll';
gc_Handle:= DynLibs.SafeLoadLibrary(thelibgcc);
{$endif}
{go & load the library}
if Length(libfilename) = 0 then thelib := XMP_LIB_NAME else thelib := libfilename;
xmp_Handle:=DynLibs.LoadLibrary(thelib); // obtain the handle we want
if xmp_Handle <> DynLibs.NilHandle then
begin {now we tie the functions to the VARs from above}
Pointer(xmp_create_context):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_create_context'));
Pointer(xmp_free_context):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_free_context'));
Pointer(xmp_load_module):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_load_module'));
Pointer(xmp_load_module_from_memory):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_load_module_from_memory'));
Pointer(xmp_load_module_from_file):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_load_module_from_file'));
Pointer(xmp_load_module_from_callbacks):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_load_module_from_callbacks'));
Pointer(xmp_test_module):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_test_module'));
Pointer(xmp_release_module):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_release_module'));
Pointer(xmp_start_player):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_start_player'));
Pointer(xmp_play_buffer):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_play_buffer'));
Pointer(xmp_get_frame_info):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_get_frame_info'));
Pointer(xmp_end_player):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_end_player'));
Pointer(xmp_get_module_info):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_get_module_info'));
Pointer(xmp_get_format_list):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_get_format_list'));
Pointer(xmp_stop_module):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_stop_module'));
Pointer(xmp_restart_module):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_restart_module'));
Pointer(xmp_channel_vol):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_channel_vol'));
Pointer(xmp_set_player):=DynLibs.GetProcedureAddress(xmp_Handle,PChar('xmp_set_player'));
end;
Result := xmp_IsLoaded;
ReferenceCounter:=1;
end;
end;
Procedure xmp_Unload;
begin
if ReferenceCounter > 0 then
dec(ReferenceCounter);
if ReferenceCounter > 0 then
exit;
if xmp_IsLoaded then
begin
DynLibs.UnloadLibrary(xmp_Handle);
xmp_Handle:=DynLibs.NilHandle;
{$if defined(cpu32) and defined(windows)}
if gc_Handle <> DynLibs.NilHandle then begin
DynLibs.UnloadLibrary(gc_Handle);
gc_Handle:=DynLibs.NilHandle;
end;
{$endif}
end;
end;
end.

1117
UOS/src/uos_mpg123.pas Normal file

File diff suppressed because it is too large Load Diff

693
UOS/src/uos_opus.pas Normal file
View File

@@ -0,0 +1,693 @@
{This unit is part of United Openlibraries of Sound (uos)}
{This is the Pascal Wrapper + Dynamic loading of Opus library.
Load library with op_load() and release with op_unload().
License : modified LGPL.
Fred van Stappen / fiens@hotmail.com}
unit uos_opus;
{$mode objfpc}{$H+}
{$PACKRECORDS C}
interface
uses
dynlibs, CTypes, SysUtils;
const
OPUS_OK = 0;
OPUS_BAD_ARG = -1;
OPUS_BUFFER_TOO_SMALL = -2;
OPUS_INTERNAL_ERROR = -3;
OPUS_INVALID_PACKET = -4;
OPUS_UNIMPLEMENTED = -5;
OPUS_INVALID_STATE = -6;
OPUS_ALLOC_FAIL = -7;
OPUS_APPLICATION_VOIP = 2048;
OPUS_APPLICATION_AUDIO = 2049;
OPUS_APPLICATION_RESTRICTED_LOWDELAY = 2051;
OPUS_SIGNAL_VOICE = 3001; // Signal being encoded is voice
OPUS_SIGNAL_MUSIC = 3002; // Signal being encoded is music
OPUS_BANDWIDTH_NARROWBAND = 1101; // 4 kHz bandpass @hideinitializer
OPUS_BANDWIDTH_MEDIUMBAND = 1102; // 6 kHz bandpass @hideinitializer
OPUS_BANDWIDTH_WIDEBAND = 1103; // 8 kHz bandpass @hideinitializer
OPUS_BANDWIDTH_SUPERWIDEBAND = 1104; // 12 kHz bandpass @hideinitializer
OPUS_BANDWIDTH_FULLBAND = 1105; // 20 kHz bandpass @hideinitializer
OPUS_FRAMESIZE_ARG = 5000; // Select frame size from the argument (default)
OPUS_FRAMESIZE_2_5_MS = 5001; // Use 2.5 ms frames
OPUS_FRAMESIZE_5_MS = 5002; // Use 5 ms frames
OPUS_FRAMESIZE_10_MS = 5003; // Use 10 ms frames
OPUS_FRAMESIZE_20_MS = 5004; // Use 20 ms frames
OPUS_FRAMESIZE_40_MS = 5005; // Use 40 ms frames
OPUS_FRAMESIZE_60_MS = 5006; // Use 60 ms frames
const
OPUS_SET_APPLICATION_REQUEST = 4000;
OPUS_GET_APPLICATION_REQUEST = 4001;
OPUS_SET_BITRATE_REQUEST = 4002;
OPUS_GET_BITRATE_REQUEST = 4003;
OPUS_SET_MAX_BANDWIDTH_REQUEST = 4004;
OPUS_GET_MAX_BANDWIDTH_REQUEST = 4005;
OPUS_SET_VBR_REQUEST = 4006;
OPUS_GET_VBR_REQUEST = 4007;
OPUS_SET_BANDWIDTH_REQUEST = 4008;
OPUS_GET_BANDWIDTH_REQUEST = 4009;
OPUS_SET_COMPLEXITY_REQUEST = 4010;
OPUS_GET_COMPLEXITY_REQUEST = 4011;
OPUS_SET_INBAND_FEC_REQUEST = 4012;
OPUS_GET_INBAND_FEC_REQUEST = 4013;
OPUS_SET_PACKET_LOSS_PERC_REQUEST = 4014;
OPUS_GET_PACKET_LOSS_PERC_REQUEST = 4015;
OPUS_SET_DTX_REQUEST = 4016;
OPUS_GET_DTX_REQUEST = 4017;
OPUS_SET_VBR_CONSTRAINT_REQUEST = 4020;
OPUS_GET_VBR_CONSTRAINT_REQUEST = 4021;
OPUS_SET_FORCE_CHANNELS_REQUEST = 4022;
OPUS_GET_FORCE_CHANNELS_REQUEST = 4023;
OPUS_SET_SIGNAL_REQUEST = 4024;
OPUS_GET_SIGNAL_REQUEST = 4025;
OPUS_GET_LOOKAHEAD_REQUEST = 4027;
OPUS_RESET_STATE_REQUEST = 4028;
OPUS_GET_SAMPLE_RATE_REQUEST = 4029;
OPUS_GET_FINAL_RANGE_REQUEST = 4031;
OPUS_GET_PITCH_REQUEST = 4033;
OPUS_SET_GAIN_REQUEST = 4034;
OPUS_GET_GAIN_REQUEST = 4045;
OPUS_SET_LSB_DEPTH_REQUEST = 4036;
OPUS_GET_LSB_DEPTH_REQUEST = 4037;
OPUS_GET_LAST_PACKET_DURATION_REQUEST = 4039;
OPUS_SET_EXPERT_FRAME_DURATION_REQUEST = 4040;
OPUS_GET_EXPERT_FRAME_DURATION_REQUEST = 4041;
OPUS_SET_PREDICTION_DISABLED_REQUEST = 4042;
OPUS_GET_PREDICTION_DISABLED_REQUEST = 4043;
OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST = 5120;
OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST = 5122;
type
TOpusEncoder = Pointer;
TOpusDecoder = Pointer;
TOpusRepacketizer = Pointer;
TOpusMSDecoder = pointer;
TOpusMSEncoder = pointer;
TOpusFrames = array [0..47] of Pointer;
TOpusFrameSizes = array [0..47] of cint;
type
TRequestValueType = (orPointer, orInteger, orXY, orNoValue);
TOpusCTLRequestRecord = record
Request: Word;
case ReqType: TRequestValueType of
orPointer: (PtrValue: Pointer);
orInteger: (IntValue: cint);
orXY: (XValue: cint; YValue: pointer);
end;
var
opus_get_version_string: function(): PAnsiChar; cdecl; opus_strerror: function(error: cint): PAnsiChar; cdecl;
opus_encode: function(st: TOpusEncoder; pcm : pcfloat; frame_size: cint;
var data; max_data_bytes: cint): cint; cdecl;
opus_encode_float: function(st: TOpusEncoder; pcm : pcfloat; frame_size: cint; var data; max_data_bytes: cint): cint; cdecl;
opus_encoder_create: function(Fs: cint; channels, application: cint; out error: cint): TOpusEncoder; cdecl;
opus_encoder_ctli: function(st: TOpusEncoder; const reqrequest: word ; reqval : cint ): cint; cdecl;
opus_encoder_ctlp: function(st: TOpusEncoder; const reqrequest: word ; reqval : pointer ): cint; cdecl;
opus_encoder_ctlxy: function(st: TOpusEncoder; const reqrequest: word ; reqx : cint ; reqy : pointer ): cint; cdecl;
opus_encoder_ctln: function(st: TOpusEncoder; const reqrequest: word): cint; cdecl;
opus_encoder_destroy: procedure(st: TOpusEncoder); cdecl;
opus_encoder_get_size: function(channels: cint): cint; cdecl;
opus_encoder_init: function(st: TOpusEncoder; Fs: cint; channels, application: cint): cint; cdecl;
opus_decode: function(st: TOpusDecoder; const data; len: cint; pcm : pcfloat; frame_size, decode_fec: cint): cint; cdecl;
opus_decode_float: function(st: TOpusDecoder; const data; len: cint; pcm : pcfloat; frame_size, decode_fec: cint): cint; cdecl;
opus_decoder_create: function(fs: cint; channels: cint; out error: cint): TOpusDecoder; cdecl;
opus_decoder_ctli: function(st: TOpusDecoder; const reqrequest: word ; reqval : cint ): cint; cdecl;
opus_decoder_ctlp: function(st: TOpusDecoder; const reqrequest: word ; reqval : pointer ): cint; cdecl;
opus_decoder_ctlxy: function(st: TOpusDecoder; const reqrequest: word ; reqx : cint ; reqy : pointer ): cint; cdecl;
opus_decoder_ctln: function(st: TOpusDecoder; const reqrequest: word): cint; cdecl;
opus_decoder_destroy: procedure(st: TOpusDecoder); cdecl;
opus_decoder_get_nb_samples: function(st: TOpusDecoder; const packet; len: cint): cint; cdecl;
opus_decoder_get_size: function(channels: cint): cint; cdecl;
opus_decoder_init: function(st: TOpusDecoder; Fs: cint; channels: cint): cint; cdecl;
opus_packet_get_bandwidth: function(const packet): cint; cdecl;
opus_packet_get_nb_channels: function(const packet): cint; cdecl;
opus_packet_get_nb_frames: function(const packet; len: cint): cint; cdecl;
opus_packet_get_nb_samples: function(const packet; len, fs: cint): cint; cdecl;
opus_packet_get_samples_per_frame: function(const packet; fs: cint): cint; cdecl;
opus_packet_parse: function(const packet; var out_toc: Pointer; var frames: TOpusFrames; var size: TOpusFrameSizes; var payload_offset: cint): cint; cdecl;
opus_pcm_soft_clip: procedure(pcm : pcfloat; frame_size, channels: cint; var softclip_mem: Double); cdecl;
opus_multistream_packet_pad: function(var data; len, new_len, nb_streams: cint): cint; cdecl;
opus_multistream_packet_unpad: function(var data; len, nb_streams: cint): cint; cdecl;
opus_packet_pad: function(var data; len, new_len: cint): cint; cdecl;
opus_packet_unpad: function(var data; len: cint): cint; cdecl;
opus_repacketizer_cat: function(rp: TOpusRepacketizer; const data; len: cint): cint; cdecl;
opus_repacketizer_create: function: TOpusRepacketizer; cdecl;
opus_repacketizer_destroy: procedure(rp: TOpusRepacketizer); cdecl;
opus_repacketizer_get_nb_frames: function(rp: TOpusRepacketizer): cint; cdecl;
opus_repacketizer_get_size: function: cint; cdecl;
opus_repacketizer_init: function(rp: TOpusRepacketizer): TOpusRepacketizer; cdecl;
opus_repacketizer_out: function(rp: TOpusRepacketizer; var data; maxlen: cint): cint; cdecl;
opus_repacketizer_out_range: function(rp: TOpusRepacketizer; var data; maxlen: cint): cint; cdecl;
opus_multistream_decode: function(st: TOpusMSDecoder; const data; len: cint; pcm : pcfloat; frame_size, decode_fec: cint): cint; cdecl;
opus_multistream_decode_float: function(st: TOpusMSDecoder; const data; len: cint; pcm : pcfloat; frame_size, decode_fec: cint): cint; cdecl;
opus_multistream_decoder_create: function(fs: cint; channels, streams, coupled_streams: cint; const mapping: array of Byte; out error: cint): TOpusMSDecoder; cdecl;
opus_multistream_decoder_ctli: function(st: TOpusMSDecoder; const reqrequest: word ; reqval : cint ): cint; cdecl;
opus_multistream_decoder_ctlp: function(st: TOpusMSDecoder; const reqrequest: word ; reqval : pointer ): cint; cdecl;
opus_multistream_decoder_ctlxy: function(st: TOpusMSDecoder; const reqrequest: word ; reqx : cint ; reqy : pointer ): cint; cdecl;
opus_multistream_decoder_ctln: function(st: TOpusMSDecoder; const reqrequest: word): cint; cdecl;
opus_multistream_decoder_destroy: procedure(st: TOpusMSDecoder); cdecl;
opus_multistream_decoder_get_size: function(streams, coupled_streams: cint): cint; cdecl;
opus_multistream_decoder_init: function(st: TOpusMSDecoder; fs: cint; channels, streams, coupled_streams: cint; const mapping: array of Byte): cint; cdecl;
opus_multistream_encode: function(st: TOpusMSEncoder; pcm : pcfloat; frame_size: cint; var data; max_data_bytes: cint): cint; cdecl;
opus_multistream_encode_float: function(st: TOpusMSEncoder; pcm : pcfloat; frame_size: cint; var data; max_data_bytes: cint): cint; cdecl;
opus_multistream_encoder_create: function(Fs: cint; channels, streams, coupled_streams: cint; const mapping: array of Byte; application: cint; out error: cint): TOpusMSEncoder; cdecl;
opus_multistream_encoder_ctli: function(st: TOpusMSEncoder; const reqrequest: word ; reqval : cint ): cint; cdecl;
opus_multistream_encoder_ctlp: function(st: TOpusMSEncoder; const reqrequest: word ; reqval : pointer ): cint; cdecl;
opus_multistream_encoder_ctlxy: function(st: TOpusMSEncoder; const reqrequest: word ; reqx : cint ; reqy : pointer ): cint; cdecl;
opus_multistream_encoder_ctln: function(st: TOpusMSEncoder; const reqrequest: word ): cint; cdecl;
opus_multistream_encoder_destroy: procedure(st: TOpusMSEncoder); cdecl;
opus_multistream_encoder_get_size: function(streams, coupled_streams: cint): cint; cdecl;
opus_multistream_encoder_init: function(st: TOpusMSEncoder; fs: cint; channels, streams, coupled_streams: cint; const mapping: array of Byte; application: cint): cint; cdecl;
opus_multistream_surround_encoder_create: function(Fs: cint; channels, mapping_family, streams, coupled_streams: cint; const mapping: array of Byte; application: cint; out error: cint): TOpusMSEncoder; cdecl;
opus_multistream_surround_encoder_get_size: function(channels, mapping_family: cint): cint; cdecl;
opus_multistream_surround_encoder_init: function(st: TOpusMSEncoder; fs: cint; channels, mapping_family, streams, coupled_streams: cint; const mapping: array of Byte; application: cint): cint; cdecl;
function opus_encoder_ctl(st: TOpusEncoder; const req: TOpusCTLRequestRecord): Integer; inline;
function opus_decoder_ctl(st: TOpusdecoder; const req: TOpusCTLRequestRecord): Integer; inline;
function opus_multistream_encoder_ctl(st: TOpusMSEncoder; const req: TOpusCTLRequestRecord): cint; inline;
function opus_multistream_decoder_ctl(st: TOpusMSdecoder; const req: TOpusCTLRequestRecord): cint; inline;
// Macros for opus_encode_ctl.
function OPUS_GET_APPLICATION(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_BITRATE(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_COMPLEXITY(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_DTX(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_EXPERT_FRAME_DURATION(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_FORCE_CHANNELS(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_LOOKAHEAD(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_LSB_DEPTH(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_MAX_BANDWIDTH(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_PACKET_LOSS_PERC(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_PREDICTION_DISABLED(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_SIGNAL(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_VBR(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_VBR_CONSTRAINT(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_APPLICATION(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_BANDWIDTH(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_BITRATE(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_COMPLEXITY(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_DTX(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_EXPERT_FRAME_DURATION(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_FORCE_CHANNELS(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_INBAND_FEC(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_LSB_DEPTH(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_MAX_BANDWIDTH(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_PACKET_LOSS_PERC(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_PREDICTION_DISABLED(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_SIGNAL(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_VBR(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_VBR_CONSTRAINT(x: cint): TOpusCTLRequestRecord; inline;
// For opus_decoder_ctl and opus_encoder_ctl.
function OPUS_GET_BANDWIDTH(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_FINAL_RANGE(var x: Cardinal): TOpusCTLRequestRecord; inline;
function OPUS_GET_SAMPLE_RATE(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_RESET_STATE: TOpusCTLRequestRecord; inline;
// For the opus_decode_ctl.
function OPUS_GET_GAIN(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_LAST_PACKET_DURATION(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_GET_PITCH(var x: cint): TOpusCTLRequestRecord; inline;
function OPUS_SET_GAIN(x: cint): TOpusCTLRequestRecord; inline;
function OPUS_MULTISTREAM_GET_DECODER_STATE(x: cint; var y: cint): TOpusCTLRequestRecord; inline;
function OPUS_MULTISTREAM_GET_ENCODER_STATE(x: cint; var y: cint): TOpusCTLRequestRecord; inline;
var op_Handle:TLibHandle=dynlibs.NilHandle;
var ReferenceCounter : cardinal = 0;
function op_IsLoaded : boolean; inline;
Function op_Load(const libfilename:string) :boolean;
Procedure op_Unload;
implementation
function op_IsLoaded: boolean;
begin
Result := (op_Handle <> dynlibs.NilHandle);
end;
Procedure op_Unload;
begin
// < Reference counting
if ReferenceCounter > 0 then
dec(ReferenceCounter);
if ReferenceCounter > 0 then
exit;
// >
if op_IsLoaded then
begin
DynLibs.UnloadLibrary(op_Handle);
op_Handle:=DynLibs.NilHandle;
end;
end;
Function op_Load (const libfilename:string) :boolean;
begin
Result := False;
if op_Handle<>0 then
begin
Inc(ReferenceCounter);
result:=true {is it already there ?}
end else
begin {go & load the library}
if Length(libfilename) = 0 then exit;
op_Handle:=DynLibs.SafeLoadLibrary(libfilename); // obtain the handle we want
if op_Handle <> DynLibs.NilHandle then
begin {now we tie the functions to the VARs from above}
Pointer(opus_get_version_string):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_get_version_string'));
Pointer(opus_strerror):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_strerror'));
Pointer(opus_encode):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_encode'));
Pointer(opus_encode_float):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_encode_float'));
Pointer(opus_encoder_create):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_encoder_create'));
Pointer(opus_encoder_ctli):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_encoder_ctl'));
Pointer(opus_encoder_ctlp):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_encoder_ctl'));
Pointer(opus_encoder_ctlxy):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_encoder_ctl'));
Pointer(opus_encoder_ctln):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_encoder_ctl'));
Pointer(opus_encoder_destroy):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_encoder_destroy'));
Pointer(opus_encoder_get_size):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_encoder_get_size'));
Pointer(opus_encoder_init):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_encoder_init'));
Pointer(opus_decode):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_decode'));
Pointer(opus_decode_float):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_decode_float'));
Pointer(opus_decoder_create):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_decoder_create'));
Pointer(opus_decoder_ctli):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_decoder_ctl'));
Pointer(opus_decoder_ctlp):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_decoder_ctl'));
Pointer(opus_decoder_ctlxy):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_decoder_ctl'));
Pointer(opus_decoder_ctln):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_decoder_ctl'));
Pointer(opus_decoder_destroy):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_decoder_destroy'));
Pointer(opus_decoder_get_nb_samples):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_decoder_get_nb_samples'));
Pointer(opus_decoder_get_size):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_decoder_get_size'));
Pointer(opus_decoder_init):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_decoder_init'));
Pointer(opus_packet_get_bandwidth):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_packet_get_bandwidth'));
Pointer(opus_packet_get_nb_channels):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_packet_get_nb_channels'));
Pointer(opus_packet_get_nb_frames):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_packet_get_nb_frames'));
Pointer(opus_packet_get_nb_samples):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_packet_get_nb_samples'));
Pointer(opus_packet_get_samples_per_frame):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_packet_get_samples_per_frame'));
Pointer( opus_packet_parse):=DynLibs.GetProcedureAddress(OP_Handle,PChar(' opus_packet_parse'));
Pointer(opus_pcm_soft_clip):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_pcm_soft_clip'));
Pointer(opus_multistream_packet_pad):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_packet_pad'));
Pointer(opus_multistream_packet_unpad):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_packet_unpad'));
Pointer(opus_packet_pad):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_packet_pad'));
Pointer(opus_packet_unpad):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_packet_unpad'));
Pointer(opus_repacketizer_cat):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_repacketizer_cat'));
Pointer(opus_repacketizer_create):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_repacketizer_create'));
Pointer(opus_repacketizer_destroy):=DynLibs.GetProcedureAddress(OP_Handle,PChar('oopus_repacketizer_destroy'));
Pointer(opus_repacketizer_get_nb_frames):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_repacketizer_get_nb_frames'));
Pointer(opus_repacketizer_get_size):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_repacketizer_get_size'));
Pointer(opus_repacketizer_init):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_repacketizer_init'));
Pointer(opus_repacketizer_out):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_repacketizer_out'));
Pointer(opus_repacketizer_out_range):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_repacketizer_out_range'));
Pointer(opus_multistream_decode):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_decode'));
Pointer(opus_multistream_decode_float):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_decode_float'));
Pointer(opus_multistream_decoder_create):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_decoder_create'));
Pointer(opus_multistream_decoder_ctli):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_decoder_ctl'));
Pointer(opus_multistream_decoder_ctlp):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_decoder_ctl'));
Pointer(opus_multistream_decoder_ctlxy):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_decoder_ctl'));
Pointer(opus_multistream_decoder_ctln):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_decoder_ctl'));
Pointer(opus_multistream_decoder_destroy):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_decoder_destroy'));
Pointer(opus_multistream_decoder_get_size):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_decoder_get_size'));
Pointer(opus_multistream_decoder_init):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_decoder_init'));
Pointer(opus_multistream_encode):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_encode'));
Pointer(opus_multistream_encode_float):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_encode_float'));
Pointer(opus_multistream_encoder_create):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_encoder_create'));
Pointer(opus_multistream_encoder_ctli):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_encoder_ctl'));
Pointer(opus_multistream_encoder_ctlp):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_encoder_ctl'));
Pointer(opus_multistream_encoder_ctlxy):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_encoder_ctl'));
Pointer(opus_multistream_encoder_ctln):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_encoder_ctl'));
Pointer(opus_multistream_encoder_destroy):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_encoder_destroy'));
Pointer(opus_multistream_encoder_get_size):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_encoder_get_size'));
Pointer(opus_multistream_encoder_init):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_encoder_init'));
Pointer(opus_multistream_surround_encoder_create):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_surround_encoder_create'));
Pointer(opus_multistream_surround_encoder_get_size):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_surround_encoder_get_size'));
Pointer(opus_multistream_surround_encoder_init):=DynLibs.GetProcedureAddress(OP_Handle,PChar('opus_multistream_surround_encoder_init'));
end;
Result := op_IsLoaded;
ReferenceCounter:=1;
end;
end;
function OPUS_GET_APPLICATION(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_APPLICATION_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_BITRATE(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_BITRATE_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_COMPLEXITY(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_COMPLEXITY_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_DTX(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_DTX_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_EXPERT_FRAME_DURATION(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_EXPERT_FRAME_DURATION_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_FORCE_CHANNELS(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_FORCE_CHANNELS_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_LOOKAHEAD(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_LOOKAHEAD_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_LSB_DEPTH(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_LSB_DEPTH_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_MAX_BANDWIDTH(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_MAX_BANDWIDTH_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_PACKET_LOSS_PERC(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_PACKET_LOSS_PERC_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_PREDICTION_DISABLED(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_PREDICTION_DISABLED_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_SIGNAL(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_SIGNAL_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_VBR(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_VBR_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_VBR_CONSTRAINT(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_VBR_CONSTRAINT_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_SET_APPLICATION(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_APPLICATION_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_BANDWIDTH(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_BANDWIDTH_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_BITRATE(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_BITRATE_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_COMPLEXITY(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_COMPLEXITY_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_DTX(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_DTX_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_EXPERT_FRAME_DURATION(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_EXPERT_FRAME_DURATION_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_FORCE_CHANNELS(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_FORCE_CHANNELS_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_INBAND_FEC(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_INBAND_FEC_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_LSB_DEPTH(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_LSB_DEPTH_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_MAX_BANDWIDTH(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_MAX_BANDWIDTH_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_PACKET_LOSS_PERC(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_PACKET_LOSS_PERC_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_PREDICTION_DISABLED(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_PREDICTION_DISABLED_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_SIGNAL(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_SIGNAL_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_VBR(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_VBR_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_SET_VBR_CONSTRAINT(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_VBR_CONSTRAINT_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_GET_BANDWIDTH(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_BANDWIDTH_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_FINAL_RANGE(var x: Cardinal): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_BANDWIDTH_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_SAMPLE_RATE(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_BANDWIDTH_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_RESET_STATE: TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_RESET_STATE_REQUEST;
Result.ReqType := orNoValue;
end;
function OPUS_GET_GAIN(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_GAIN_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_LAST_PACKET_DURATION(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_LAST_PACKET_DURATION_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_GET_PITCH(var x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_GET_PITCH_REQUEST;
Result.ReqType := orPointer;
Result.PtrValue := @x;
end;
function OPUS_SET_GAIN(x: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_SET_GAIN_REQUEST;
Result.ReqType := orInteger;
Result.IntValue := x;
end;
function OPUS_MULTISTREAM_GET_DECODER_STATE(x: cint; var y: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST;
Result.ReqType := orXY;
Result.XValue := x;
Result.YValue := @y;
end;
function OPUS_MULTISTREAM_GET_ENCODER_STATE(x: cint; var y: cint): TOpusCTLRequestRecord; inline;
begin
Result.Request := OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST;
Result.ReqType := orXY;
Result.XValue := x;
Result.YValue := @y;
end;
function opus_encoder_ctl(st: TOpusEncoder; const req: TOpusCTLRequestRecord): Integer; inline;
begin
case req.ReqType of
orPointer: Result := opus_encoder_ctlp(st, req.Request, req.PtrValue);
orInteger: Result := opus_encoder_ctli(st, req.Request, req.IntValue);
orXY: Result := opus_encoder_ctlxy(st, req.Request, req.XValue, req.YValue);
orNoValue: Result := opus_encoder_ctln(st, req.Request);
else
Result := OPUS_BAD_ARG;
end;
end;
function opus_decoder_ctl(st: TOpusDecoder; const req: TOpusCTLRequestRecord): Integer; inline;
begin
case req.ReqType of
orPointer: Result := opus_decoder_ctlp(st, req.Request, req.PtrValue);
orInteger: Result := opus_decoder_ctli(st, req.Request, req.IntValue);
orXY: Result := opus_decoder_ctlxy(st, req.Request, req.XValue, req.YValue);
orNoValue: Result := opus_decoder_ctln(st, req.Request);
else
Result := OPUS_BAD_ARG;
end;
end;
function opus_multistream_encoder_ctl(st: TOpusMSEncoder; const req: TOpusCTLRequestRecord): Integer; inline;
begin
case req.ReqType of
orPointer: Result := opus_multistream_encoder_ctlp(st, req.Request, req.PtrValue);
orInteger: Result := opus_multistream_encoder_ctli(st, req.Request, req.IntValue);
orXY: Result := opus_multistream_encoder_ctlxy(st, req.Request, req.XValue, req.YValue);
orNoValue: Result := opus_multistream_encoder_ctln(st, req.Request);
else
Result := OPUS_BAD_ARG;
end;
end;
function opus_multistream_decoder_ctl(st: TOpusMSDecoder; const req: TOpusCTLRequestRecord): Integer; inline;
begin
case req.ReqType of
orPointer: Result := opus_multistream_decoder_ctlp(st, req.Request, req.PtrValue);
orInteger: Result := opus_multistream_decoder_ctli(st, req.Request, req.IntValue);
orXY: Result := opus_multistream_decoder_ctlxy(st, req.Request, req.XValue, req.YValue);
orNoValue: Result := opus_multistream_decoder_ctln(st, req.Request);
else
Result := OPUS_BAD_ARG;
end;
end;
end.

471
UOS/src/uos_opusfile.pas Normal file
View File

@@ -0,0 +1,471 @@
{This unit is part of United Openlibraries of Sound (uos)}
{This is the Pascal Wrapper + Dynamic loading of OpusFile library.
Load library with of_load() and release with of_unload().
License : modified LGPL.
Fred van Stappen / fiens@hotmail.com}
unit uos_OpusFile;
{$mode objfpc}{$H+}
{$PACKRECORDS C}
interface
uses
ctypes, dynlibs, classes, pipes, SysUtils;
type
TOpusFile = ^OpusFile;
OpusFile = record
end;
const
libop=
{$IFDEF unix}
{$IFDEF darwin}
'libopusfile.0.dylib';
{$ELSE}
'libopusfile.so.0';
{$ENDIF}
{$ELSE}
'opusfile.dll';
{$ENDIF}
// Error Codes
const
OP_FALSE = -1;
OP_HOLE = -3;
OP_EREAD = -128;
OP_EFAULT = -129;
OP_EIMPL = -130;
OP_EINVAL = -131;
OP_ENOTVORBIS = -132;
OP_EBADHEADER = -133;
OP_EVERSION = -134;
OP_ENOTAUDIO = -135;
OP_EBADPACKET = -136;
OP_EBADLINK = -137;
OP_ENOSEEK = -138;
OP_EBADTIMESTAMP = -139;
{
/**A request did not succeed.*/
#define OP_FALSE (-1)
/*Currently not used externally.*/
#define OP_EOF (-2)
/**There was a hole in the page sequence numbers (e.g., a page was corrupt or
missing).*/
#define OP_HOLE (-3)
/**An underlying read, seek, or tell operation failed when it should have
succeeded.*/
#define OP_EREAD (-128)
/**A <code>NULL</code> pointer was passed where one was unexpected, or an
internal memory allocation failed, or an internal library error was
encountered.*/
#define OP_EFAULT (-129)
/**The stream used a feature that is not implemented, such as an unsupported
channel family.*/
#define OP_EIMPL (-130)
/**One or more parameters to a function were invalid.*/
#define OP_EINVAL (-131)
/**A purported Ogg Opus stream did not begin with an Ogg page, a purported
header packet did not start with one of the required strings, "OpusHead" or
"OpusTags", or a link in a chained file was encountered that did not
contain any logical Opus streams.*/
#define OP_ENOTFORMAT (-132)
/**A required header packet was not properly formatted, contained illegal
values, or was missing altogether.*/
#define OP_EBADHEADER (-133)
/**The ID header contained an unrecognized version number.*/
#define OP_EVERSION (-134)
/*Currently not used at all.*/
#define OP_ENOTAUDIO (-135)
/**An audio packet failed to decode properly.
This is usually caused by a multistream Ogg packet where the durations of
the individual Opus packets contained in it are not all the same.*/
#define OP_EBADPACKET (-136)
/**We failed to find data we had seen before, or the bitstream structure was
sufficiently malformed that seeking to the target destination was
impossible.*/
#define OP_EBADLINK (-137)
/**An operation that requires seeking was requested on an unseekable stream.*/
#define OP_ENOSEEK (-138)
/**The first or last granule position of a link failed basic validity checks.*/
#define OP_EBADTIMESTAMP (-139)
}
type
TOP_PIC_FORMAT = (OP_PIC_FORMAT_UNKNOWN = -1, OP_PIC_FORMAT_URL, OP_PIC_FORMAT_JPEG,
OP_PIC_FORMAT_PNG, OP_PIC_FORMAT_GIF);
type
TOpusHead = THandle;
TOpusStream = THandle;
op_read_func = function (stream: Pointer; var buffer; nbytes: cint): cint; cdecl;
op_seek_func = function (stream: Pointer; offset: Int64; whence: cint): cint; cdecl;
op_tell_func = function (stream: Pointer): Int64; cdecl;
op_close_func = function (stream: Pointer): cint; cdecl;
TOpusFileCallbacks = record
read: op_read_func;
seek: op_seek_func;
tell: op_tell_func;
close: op_close_func;
end;
function OpusReadCB(stream: Pointer; var buffer; nbytes: cint): cint; cdecl;
function OpusReadCBuosURL(stream: Pointer; var buffer; nbytes: cint): cint; cdecl;
function OpusReadCBuosMS(stream: Pointer; var buffer; nbytes: cint): cint; cdecl;
function OpusSeekCB(stream: Pointer; offset: Int64; whence: cint): cint; cdecl;
function OpusTellCB(stream: Pointer): Int64; cdecl;
function OpusCloseCB(stream: Pointer): cint; cdecl;
function OpusSeekCBMS(stream: Pointer; offset: Int64; whence: cint): cint; cdecl;
function OpusTellCBMS(stream: Pointer): Int64; cdecl;
const
op_callbacks: TOpusFileCallbacks = (read: @OpusReadCB;
seek: @OpusSeekCB;
tell: @OpusTellCB;
close: nil);
uos_callbacks: TOpusFileCallbacks = (read: @OpusReadCBuosURL;
seek: @OpusSeekCB;
tell: @OpusTellCB;
close: nil);
uos_callbacksms: TOpusFileCallbacks = (read: @OpusReadCBuosms;
seek: @OpusSeekCBms;
tell: @OpusTellCBms;
close: nil);
type
TOpusMSDecoder = Pointer;
op_decode_cb_func = function(ctx: Pointer; decoder: TOpusMSDecoder; pcm : pcfloat; op: Pointer;
nsamples, nchannels, format, li: pcint): cint; cdecl;
TOpusTags = record
user_comments: PPAnsiChar; // The array of comment string vectors
comment_lengths: Pcint; // An array of the corresponding length of each vector, in bytes
comments: cint; // The total number of comment streams
vendor: PAnsiChar; // The null-terminated vendor string. This identifies the software used to encode the stream.
end;
POpusTags = ^TOpusTags;
TOpusPictureTag = record
Pic_Type: cint; { The picture type according to the ID3v2 APIC frame:
<ol start="0">
<li>Other</li>
<li>32x32 pixels 'file icon' (PNG only)</li>
<li>Other file icon</li>
<li>Cover (front)</li>
<li>Cover (back)</li>
<li>Leaflet page</li>
<li>Media (e.g. label side of CD)</li>
<li>Lead artist/lead performer/soloist</li>
<li>Artist/performer</li>
<li>Conductor</li>
<li>Band/Orchestra</li>
<li>Composer</li>
<li>Lyricist/text writer</li>
<li>Recording Location</li>
<li>During recording</li>
<li>During performance</li>
<li>Movie/video screen capture</li>
<li>A bright colored fish</li>
<li>Illustration</li>
<li>Band/artist logotype</li>
<li>Publisher/Studio logotype</li>
</ol> }
mime_type: PAnsiChar; // The MIME type of the picture, in printable ASCII characters 0x20-0x7E.
description: PAnsiChar; // The description of the picture, in UTF-8
width: Cardinal;
height: Cardinal;
depth: Cardinal; // The color depth of the picture in bits-per-pixel
colors: Cardinal; // For indexed-color pictures (e.g., GIF), the number of colors used, or 0
data_length: Cardinal;
data: Pointer;
format: TOP_PIC_FORMAT; // The format of the picture data, if known. OP_PIC_FORMAT_UNKNOWN..OP_PIC_FORMAT_GIF
end;
var
op_fopen: function(out cb: TOpusFileCallbacks; path: PAnsiChar; mode: PAnsiChar): TOpusStream; cdecl;
op_freopen: function(out cb: TOpusFileCallbacks; path: PAnsiChar; mode: PAnsiChar; stream: TOpusStream): TOpusStream;cdecl;
op_mem_stream_create: function(out cb: TOpusFileCallbacks; const data; size: cuint): TOpusStream; cdecl;
opus_head_parse: function(head: TOpusHead; const data; len: cuint): cint;cdecl;
opus_granule_sample: function(head: TOpusHead; gp: Int64): Int64;cdecl;
opus_tags_parse: function(out tags: TOpusTags; const data; len: cuint): cint;cdecl;
opus_tags_copy: function(var dst: TOpusTags; const src: TOpusTags): cint;cdecl;
opus_tags_init: procedure(var tags: TOpusTags);cdecl;
opus_tags_add: function(var dst: TOpusTags; tag, value: PAnsiChar): cint;cdecl;
opus_tags_add_comment: function(var dst: TOpusTags; comment: PAnsiChar): cint;cdecl;
opus_tags_set_binary_suffix: function(var tags: TOpusTags; const data; len: cint): cint;cdecl;
opus_tags_query: function(const tags: TOpusTags; tag: PAnsiChar; count: cint): cint;cdecl;
opus_tags_query_count: function(const tags: TOpusTags; tag: PAnsiChar): cint;cdecl;
opus_tags_get_binary_suffix: function(const tags: TOpusTags; out len: cint): cint;cdecl;
opus_tags_get_album_gain: function(const tags: TOpusTags; out gain_q8: cint): cint;cdecl;
opus_tags_get_track_gain: function(const tags: TOpusTags; out gain_q8: cint): cint;cdecl;
opus_tags_clear: procedure(var tags: TOpusTags);cdecl;
opus_tagcompare: function(tag_name, comment: PAnsiChar): cint;cdecl;
opus_tagncompare: function(tag_name: PAnsiChar; tag_len: cint; comment: PAnsiChar): cint;cdecl;
opus_picture_tag_parse: function(out pic: TOpusPictureTag; tag: PAnsiChar): cint;cdecl;
opus_picture_tag_init: procedure(var pic: TOpusPictureTag);cdecl;
opus_picture_tag_clear: procedure(var pic: TOpusPictureTag);cdecl;
op_test: function(head: TOpusHead; const initial_data; initial_bytes: cuint): cint;cdecl;
op_open_file: function(path: PAnsiChar; out error: cint): TOpusFile;cdecl;
op_open_memory: function(const data; const _size: cuint; out error: cint): TOpusFile;cdecl;
op_open_callbacks: function(const source; const cb: TOpusFileCallbacks;
const initial_data; initial_bytes: cuint; out error: cint): TOpusFile; {$IFDEF windows} cdecl;{$ENDIF} // with cdecl ---> crash in linux, strange ???
op_test_file: function(path: PAnsiChar; out error: cint): TOpusFile;cdecl;
// op_test_url: function(path: PAnsiChar; out error: cint): TOpusFile;
op_test_memory: function(const data; const size: cuint; out error: cint): TOpusFile;cdecl;
op_test_callbacks: function(const source; const cb: TOpusFileCallbacks; const initial_data; initial_bytes: cuint;
out error: cint): TOpusFile; {$IFDEF windows} cdecl;{$ENDIF} // with cdecl ---> crash in linux, strange ???
op_test_open: function(OpusFile: TOpusFile): cint; cdecl;
op_free: function(OpusFile: TOpusFile): cint; cdecl;
op_seekable: function(OpusFile: TOpusFile): cint;cdecl;
op_link_count: function(OpusFile: TOpusFile): cint;cdecl;
op_serialno: function(OpusFile: TOpusFile; li: pcint): Cardinal;cdecl;
op_channel_count: function(OpusFile: TOpusFile; li: pcint): cint;cdecl;
op_raw_total: function(OpusFile: TOpusFile; li: pcint): Int64;cdecl;
op_pcm_total: function(OpusFile: TOpusFile; li: pcint): Int64;cdecl;
op_head: function(OpusFile: TOpusFile; li: pcint): TOpusHead;cdecl;
op_tags: function(OpusFile: TOpusFile; li: pcint): POpusTags;cdecl;
op_current_link: function(OpusFile: TOpusFile): cint;cdecl;
op_bitrate: function(OpusFile: TOpusFile; li: pcint): cint;cdecl;
op_bitrate_instant: function(OpusFile: TOpusFile): cint;cdecl;
op_raw_tell: function(OpusFile: TOpusFile): Int64;cdecl;
op_pcm_tell: function(OpusFile: TOpusFile): Int64;cdecl;
op_raw_seek: function(OpusFile: TOpusFile; byte_offset: cInt64): cint;cdecl;
op_pcm_seek: function(OpusFile: TOpusFile; pcm_offset: cInt64): cint;cdecl;
op_set_gain_offset: function(OpusFile: TOpusFile; gain_type: cint; gain_offset_q8: cint): cint;cdecl;
op_set_dither_enabled: procedure(OpusFile: TOpusFile; enabled: cint);cdecl;
op_read: function(OpusFile: TOpusFile; pcm : pcint; SampleCount: cint; li: pcint): cint;cdecl;
op_read_float: function(OpusFile: TOpusFile; pcm : pcfloat; SampleCount: cint; li: pcint): cint;cdecl;
op_read_stereo: function(OpusFile: TOpusFile; pcm : pcint; SampleCount: cint): cint;cdecl;
op_read_float_stereo: function(OpusFile: TOpusFile; pcm : pcfloat; SampleCount: cint): cint;cdecl;
of_Handle:TLibHandle=dynlibs.NilHandle;
op_Handle:TLibHandle=dynlibs.NilHandle;
{$IFDEF windows}
lc_Handle:TLibHandle=dynlibs.NilHandle;
wt_Handle:TLibHandle=dynlibs.NilHandle;
og_Handle:TLibHandle=dynlibs.NilHandle;
{$endif}
ReferenceCounter : cardinal = 0;
function of_IsLoaded : boolean; inline;
Function of_Load(const libfilename:string) :boolean; // load the lib
Procedure of_Unload;
implementation
function of_IsLoaded: boolean;
begin
Result := (of_Handle <> dynlibs.NilHandle);
end;
Procedure of_Unload;
begin
// < Reference counting
if ReferenceCounter > 0 then
dec(ReferenceCounter);
if ReferenceCounter > 0 then
exit;
// >
if of_IsLoaded then
begin
DynLibs.UnloadLibrary(of_Handle);
of_Handle:=DynLibs.NilHandle;
DynLibs.UnloadLibrary(op_Handle);
op_Handle:=DynLibs.NilHandle;
{$IFDEF windows}
DynLibs.UnloadLibrary(lc_Handle);
lc_Handle:=DynLibs.NilHandle;
DynLibs.UnloadLibrary(wt_Handle);
wt_Handle:=DynLibs.NilHandle;
DynLibs.UnloadLibrary(og_Handle);
og_Handle:=DynLibs.NilHandle;
{$endif}
end;
end;
Function of_Load (const libfilename:string) :boolean;
begin
Result := False;
if of_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}
wt_Handle:= DynLibs.SafeLoadLibrary('libwinpthread-1.dll');
lc_Handle:= DynLibs.SafeLoadLibrary('libgcc_s_sjlj-1.dll');
og_Handle:= DynLibs.SafeLoadLibrary('libogg-0.dll');
op_Handle:= DynLibs.SafeLoadLibrary('libopus-0.dll');
{$else}
op_Handle:= DynLibs.SafeLoadLibrary('libopus.so');
{$endif}
of_Handle:=DynLibs.SafeLoadLibrary(libop);
end
else
begin
{$IFDEF windows}
wt_Handle:= DynLibs.SafeLoadLibrary(ExtractFilePath(libfilename)+'libwinpthread-1.dll');
lc_Handle:= DynLibs.SafeLoadLibrary(ExtractFilePath(libfilename)+'libgcc_s_sjlj-1.dll');
og_Handle:= DynLibs.SafeLoadLibrary(ExtractFilePath(libfilename)+'libogg-0.dll');
op_Handle:= DynLibs.SafeLoadLibrary(ExtractFilePath(libfilename)+'libopus-0.dll');
{$else}
op_Handle:= DynLibs.SafeLoadLibrary(ExtractFilePath(libfilename)+'libopus.so');
{$endif}
of_Handle:=DynLibs.SafeLoadLibrary(libfilename);
end;
if of_Handle <> DynLibs.NilHandle then
begin {now we tie the functions to the VARs from above}
Pointer(op_fopen):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_fopen'));
Pointer(op_freopen):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_freopen'));
Pointer(op_mem_stream_create):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_mem_stream_create'));
Pointer(opus_head_parse):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_head_parse'));
Pointer(opus_granule_sample):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_granule_sample'));
Pointer(opus_tags_parse):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tags_parse'));
Pointer(opus_tags_copy):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tags_copy'));
Pointer(opus_tags_init):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tags_init'));
Pointer(opus_tags_add):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tags_add'));
Pointer(opus_tags_add_comment):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tags_add_comment'));
Pointer(opus_tags_set_binary_suffix):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tags_set_binary_suffix'));
Pointer(opus_tags_query):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tags_query'));
Pointer(opus_tags_query_count):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tags_query_count'));
Pointer(opus_tags_get_binary_suffix):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tags_get_binary_suffix'));
Pointer(opus_tags_get_album_gain):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tags_get_album_gain'));
Pointer(opus_tags_get_track_gain):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tags_get_track_gain'));
Pointer(opus_tags_clear):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tags_clear'));
Pointer(opus_tagcompare):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tagcompare'));
Pointer(opus_tagncompare):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_tagncompare'));
Pointer(opus_picture_tag_parse):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_picture_tag_parse'));
Pointer(opus_picture_tag_init):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_picture_tag_init'));
Pointer(opus_picture_tag_clear):=DynLibs.GetProcedureAddress(OF_Handle,PChar('opus_picture_tag_clear'));
Pointer(op_test):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_test'));
Pointer(op_free):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_free'));
Pointer(op_open_file):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_open_file'));
Pointer(op_open_memory):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_open_memory'));
Pointer(op_open_callbacks):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_open_callbacks'));
Pointer(op_test_file):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_test_file'));
//Pointer(op_test_url):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_test_url'));
Pointer(op_test_memory):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_test_memory'));
Pointer(op_test_callbacks):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_test_callbacks'));
Pointer(op_test_open):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_test_open'));
Pointer(op_seekable):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_seekable'));
Pointer(op_link_count):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_link_count'));
Pointer(op_serialno):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_serialno'));
Pointer(op_channel_count):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_channel_count'));
Pointer(op_raw_total):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_raw_total'));
Pointer(op_pcm_total):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_pcm_total'));
Pointer(op_head):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_head'));
Pointer(op_tags):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_tags'));
Pointer(op_current_link):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_current_link'));
Pointer(op_bitrate):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_bitrate'));
Pointer(op_bitrate_instant):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_bitrate_instant'));
Pointer(op_raw_tell):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_raw_tell'));
Pointer(op_raw_seek):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_raw_seek'));
Pointer(op_pcm_seek):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_pcm_seek'));
Pointer(op_set_gain_offset):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_set_gain_offset'));
Pointer(op_set_dither_enabled):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_set_dither_enabled'));
Pointer(op_read):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_read'));
Pointer(op_read_float):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_read_float'));
Pointer(op_read_stereo):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_read_stereo'));
Pointer(op_read_float_stereo):=DynLibs.GetProcedureAddress(OF_Handle,PChar('op_read_float_stereo'));
end;
Result := of_IsLoaded;
ReferenceCounter:=1;
end;
end;
function OpusReadCB(stream: Pointer; var buffer; nbytes: cint): cint; cdecl;
begin
if nbytes<>0
then
result := FileRead(THandle(stream^), Buffer, nbytes)
else
result := 0;
end;
function OpusReadCBuosURL(stream: Pointer; var buffer; nbytes: cint): cint; cdecl;
begin
if nbytes<>0
then
result := TInputPipeStream(stream^).read(Buffer, nbytes)
else
result := 0;
end;
function OpusReadCBuosMS(stream: Pointer; var buffer; nbytes: cint): cint; cdecl;
begin
if nbytes<>0
then
result := TMemoryStream(stream^).read(Buffer, nbytes)
else
result := 0;
end;
function OpusSeekCB(stream: Pointer; offset: Int64; whence: cint): cint; cdecl;
var
Seek_Result: Int64;
begin
Seek_Result := FileSeek(THandle(stream^), offset, whence);
if Seek_Result=-1
then
Result := -1
else
Result := 0;
end;
function OpusTellCB(stream: Pointer): Int64; cdecl;
begin
Result := FileSeek(THandle(stream^), 0, 1);
end;
function OpusSeekCBms(stream: Pointer; offset: Int64; whence: cint): cint; cdecl;
var
Seek_Result: Int64;
begin
Seek_Result := TMemoryStream(stream^).seek(offset, whence);
if Seek_Result=-1
then
Result := -1
else
Result := 0;
end;
function OpusTellCBms(stream: Pointer): Int64; cdecl;
begin
Result := TMemoryStream(stream^).seek(0, 1);
end;
function OpusCloseCB(stream: Pointer): cint; cdecl;
begin
FileClose(THandle(stream^));
Result := 0;
end;
end.

93
UOS/src/uos_opusurl.pas Normal file
View File

@@ -0,0 +1,93 @@
{This unit is part of United Openlibraries of Sound (uos)}
{This is the Pascal Wrapper + Dynamic loading of OpusURL library.
Load library with ou_load() and release with ou_unload().
License : modified LGPL.
Fred van Stappen / fiens@hotmail.com}
unit uos_Opusurl;
{$mode objfpc}{$H+}
interface
uses
ctypes, uos_Opusfile, dynlibs, SysUtils;
// Error Codes
const
OP_FALSE = -1;
OP_HOLE = -3;
OP_EREAD = -128;
OP_EFAULT = -129;
OP_EIMPL = -130;
OP_EINVAL = -131;
OP_ENOTVORBIS = -132;
OP_EBADHEADER = -133;
OP_EVERSION = -134;
OP_ENOTAUDIO = -135;
OP_EBADPACKET = -136;
OP_EBADLINK = -137;
OP_ENOSEEK = -138;
OP_EBADTIMESTAMP = -139;
var
op_open_url: function(path: PAnsiChar; out error: Integer): TOpusFile;
op_test_url: function(path: PAnsiChar; out error: Integer): TOpusFile;
ou_Handle:TLibHandle=dynlibs.NilHandle;
ReferenceCounter : cardinal = 0; // Reference counter
function ou_IsLoaded : boolean; inline;
Function ou_Load(const libfilename:string) :boolean; // load the lib
Procedure ou_Unload;
implementation
function ou_IsLoaded: boolean;
begin
Result := (ou_Handle <> dynlibs.NilHandle);
end;
Procedure ou_Unload;
begin
// < Reference counting
if ReferenceCounter > 0 then
dec(ReferenceCounter);
if ReferenceCounter > 0 then
exit;
// >
if ou_IsLoaded then
begin
DynLibs.UnloadLibrary(ou_Handle);
ou_Handle:=DynLibs.NilHandle;
end;
end;
Function ou_Load (const libfilename:string) :boolean;
begin
Result := False;
if ou_Handle<>0 then
begin
Inc(ReferenceCounter);
result:=true {is it already there ?}
end else
begin {go & load the library}
if Length(libfilename) = 0 then exit;
ou_Handle:=DynLibs.SafeLoadLibrary(libfilename); // obtain the handle we want
if ou_Handle <> DynLibs.NilHandle then
begin {now we tie the functions to the VARs from above}
Pointer(op_open_url):=DynLibs.GetProcedureAddress(OU_Handle,PChar('op_open_url'));
Pointer(op_test_url):=DynLibs.GetProcedureAddress(OU_Handle,PChar('op_test_url'));
end;
Result := ou_IsLoaded;
ReferenceCounter:=1;
end;
end;
end.

389
UOS/src/uos_portaudio.pas Normal file
View File

@@ -0,0 +1,389 @@
{This unit is part of United Openlibraries of Sound (uos)}
{This is the Dynamic loading version of PortAudio Pascal Wrapper.
Load library with pa_load() and release with pa_unload().
License : modified LGPL.
Fred van Stappen / fiens@hotmail.com
Reference counting added by Max Karpushin / homeplaner@yandex.ru}
unit uos_portaudio;
{$mode objfpc}{$H+}
{$PACKRECORDS C}
interface
uses
dynlibs, CTypes;
const
libpa=
{$IFDEF unix}
{$IFDEF darwin}
'libportaudio.2.dylib';
{$ELSE}
'libportaudio.so.2';
{$ENDIF}
{$ELSE}
'portaudio.dll';
{$ENDIF}
type
PaError = CInt32;
PaErrorCode =(
paNotInitialized := -10000,
paUnanticipatedHostError,
paInvalidChannelCount,
paInvalidSampleRate,
paInvalidDevice,
paInvalidFlag,
paSampleFormatNotSupported,
paBadIODeviceCombination,
paInsufficientMemory,
paBufferTooBig,
paBufferTooSmall,
paNullCallback,
paBadStreamPtr,
paTimedOut,
paInternalError,
paDeviceUnavailable,
paIncompatibleHostApiSpecificStreamInfo,
paStreamIsStopped,
paStreamIsNotStopped,
paInputOverflowed,
paOutputUnderflowed,
paHostApiNotFound,
paInvalidHostApi,
paCanNotReadFromACallbackStream,
paCanNotWriteToACallbackStream,
paCanNotReadFromAnOutputOnlyStream,
paCanNotWriteToAnInputOnlyStream,
paIncompatibleStreamHostApi,
paBadBufferPtr,
paNoError := 0
);
PaDeviceIndex = CInt32;
PaHostApiIndex = CInt32;
PaHostApiTypeId =(paInDevelopment := 0,
paDirectSound := 1,
paMME := 2,
paASIO := 3,
paSoundManager := 4,
paCoreAudio := 5,
paOSS := 7,
paALSA := 8,
paAL := 9,
paBeOS := 10,
paWDMKS := 11,
paJACK := 12,
paWASAPI := 13,
paAudioScienceHPI := 14
);
PaHostApiInfo = record
structVersion : CInt32;
_type : PaHostApiTypeId ;
_name : Pchar;
deviceCount : CInt32;
defaultInputDevice : PaDeviceIndex;
defaultOutputDevice : PaDeviceIndex;
end;
PPaHostApiInfo = ^PaHostApiInfo;
PaHostErrorInfo = record
hostApiType : PaHostApiTypeId;
errorCode : CLong;
errorText : PChar;
end;
PPaHostErrorInfo = ^PaHostErrorInfo;
PaTime = CDouble;
PaSampleFormat = pCULongLong;
PaDeviceInfo = record
structVersion : CInt32;
_name : PChar;
hostApi : PaHostApiIndex;
maxInputChannels : CInt32;
maxOutputChannels : CInt32;
defaultLowInputLatency : PaTime;
defaultLowOutputLatency : PaTime;
defaultHighInputLatency : PaTime;
defaultHighOutputLatency : PaTime;
defaultSampleRate : CDouble;
end;
PPaDeviceInfo = ^PaDeviceInfo;
PaStreamParameters = record
device : PaDeviceIndex;
channelCount : CInt32;
sampleFormat : PaSampleFormat;
suggestedLatency : PaTime;
hostApiSpecificStreamInfo : Pointer;
end;
PPaStreamParameters = ^PaStreamParameters;
// ************************* Streaming types *************************
PaStream = Pointer;
PPaStream = ^PaStream;
PPPaStream = ^PPaStream;
PaStreamFlags = CULong;
PaStreamCallbackTimeInfo = record
inputBufferAdcTime : PaTime;
currentTime : PaTime;
outputBufferDacTime : PaTime;
end;
PPaStreamCallbackTimeInfo = ^PaStreamCallbackTimeInfo;
PaStreamCallbackFlags = CULong;
PaStreamCallbackResult =(
paContinue := 0,
paComplete := 1,
paAbort := 2);
PaStreamCallback = function(
input : Pointer;
output : Pointer;
frameCount : CULong;
timeInfo : PPaStreamCallbackTimeInfo;
statusFlags : PaStreamCallbackFlags;
userData : Pointer) : CInt32;
PPaStreamCallback = ^PaStreamCallback;
PaStreamFinishedCallback = procedure(userData : Pointer);
PPaStreamFinishedCallback = ^PaStreamFinishedCallback;
PaStreamInfo = record
structVersion : CInt32;
inputLatency : PaTime;
outputLatency : PaTime;
sampleRate : CDouble;
end;
PPaStreamInfo = ^PaStreamInfo;
const
paFormatIsSupported = 0;
paFramesPerBufferUnspecified = 0;
paNoDevice = PaDeviceIndex(-1);
paUseHostApiSpecificDeviceSpecification = PaDeviceIndex(-2);
paFloat32 = PaSampleFormat($00000001);
paInt32 = PaSampleFormat($00000002);
paInt24 = PaSampleFormat($00000004);
paInt16 = PaSampleFormat($00000008);
paInt8 = PaSampleFormat($00000010);
paUInt8 = PaSampleFormat($00000020);
paCustomFormat = PaSampleFormat($00010000);
paNonInterleaved = PaSampleFormat($80000000);
paNoFlag = PaStreamFlags(0);
paClipOff = PaStreamFlags($00000001);
paDitherOff = PaStreamFlags($00000002);
paNeverDropInput = PaStreamFlags($00000004);
paPrimeOutputBuffersUsingStreamCallback = PaStreamFlags($00000008);
paPlatformSpecificFlags = PaStreamFlags($FFFF0000);
paInputUnderflow = PaStreamCallbackFlags($00000001);
paInputOverflow = PaStreamCallbackFlags($00000002);
paOutputUnderflow = PaStreamCallbackFlags($00000004);
paOutputOverflow = PaStreamCallbackFlags($00000008);
paPrimingOutput = PaStreamCallbackFlags($00000010);
////// Dynamic load : Vars that will hold our dynamically loaded functions...
// *************************** functions *******************************
var Pa_GetVersion: function():CInt32 ; cdecl;
var Pa_GetVersionText: function():PChar ; cdecl;
var Pa_GetErrorText: function(errorCode : PaError):PChar ; cdecl;
var Pa_Initialize: function():PaError ; cdecl;
var Pa_Terminate: function():PaError ; cdecl;
var Pa_GetHostApiCount: function():PaHostApiIndex ; cdecl;
var Pa_GetDefaultHostApi: function():PaHostApiIndex ; cdecl;
var Pa_GetHostApiInfo: function(hostApi : PaHostApiIndex):PPaHostApiInfo ; cdecl;
var Pa_HostApiTypeIdToHostApiIndex: function(_type : PaHostApiTypeId):PaHostApiIndex ; cdecl;
var Pa_HostApiDeviceIndexToDeviceIndex: function(hostApi : PaHostApiIndex;hostApiDeviceIndex : CInt32):PaDeviceIndex ; cdecl;
var Pa_GetLastHostErrorInfo: function():PPaHostErrorInfo ; cdecl;
// ************** Device enumeration and capabilities ******************
var Pa_GetDeviceCount: function:PaDeviceIndex ; cdecl;
var Pa_GetDefaultInputDevice: function:PaDeviceIndex ; cdecl;
var Pa_GetDefaultOutputDevice: function:PaDeviceIndex ; cdecl;
var Pa_GetDeviceInfo: function(device : PaDeviceIndex):PPaDeviceInfo ; cdecl;
var Pa_IsFormatSupported: function(inputParameters,outputParameters : PPaStreamParameters; sampleRate : CDouble):PaError ; cdecl;
// *********************** Stream function *****************************
var Pa_OpenStream: function(stream : PPPaStream;
inputParameters : PPaStreamParameters;
outputParameters : PPaStreamParameters;
sampleRate : CDouble;
framesPerBuffer : CULong;
streamFlags : PaStreamFlags;
streamCallback : PPaStreamCallback;
userData : Pointer):PaError ; cdecl;
var Pa_OpenDefaultStream: function(stream : PPPaStream;
numInputChannels : CInt32;
numOutputChannels : CInt32;
sampleFormat : PaSampleFormat;
sampleRate : CDouble;
framesPerBuffer : CULong;
streamCallback : PPaStreamCallback;
userData : Pointer):PaError ; cdecl;
var Pa_CloseStream: function(stream : PPaStream):PaError ; cdecl;
var Pa_SetStreamFinishedCallback: function(stream : PPaStream;
streamFinishedCallback : PPaStreamFinishedCallback):PaError ; cdecl;
var Pa_StartStream: function(stream : PPaStream):PaError ; cdecl;
var Pa_StopStream: function(stream : PPaStream):PaError ; cdecl;
var Pa_AbortStream: function(stream : PPaStream):PaError ; cdecl;
var Pa_IsStreamStopped: function(stream : PPaStream):PaError ; cdecl;
var Pa_IsStreamActive: function(stream : PPaStream):PaError ; cdecl;
var Pa_GetStreamInfo: function(stream : PPaStream):PPaStreamInfo ; cdecl;
var Pa_GetStreamTime: function(stream : PPaStream):Patime ; cdecl;
var Pa_GetStreamCpuLoad: function(stream : PPaStream):CDouble ; cdecl;
var Pa_ReadStream: function(stream : PPaStream; buffer : pcfloat ;frames : CULong):PaError ; cdecl;
var Pa_WriteStream: function(stream : PPaStream; buffer : pcfloat ;frames : CULong):PaError ; cdecl;
var Pa_GetStreamReadAvailable: function(stream : PPaStream):CSLong ; cdecl;
var Pa_GetStreamWriteAvailable: function(stream : PPaStream):CSLong ; cdecl;
// ****************** Miscellaneous utilities **************************
var Pa_GetSampleSize: function(format : PaSampleFormat):PaError ; cdecl;
var Pa_Sleep: function(msec : CLong) : integer; cdecl;
///////////////////////////////////////////////
{Special function for dynamic loading of lib ...}
var Pa_Handle:TLibHandle=dynlibs.NilHandle; // this will hold our handle for the lib; it functions nicely as a mutli-lib prevention unit as well...
var ReferenceCounter : cardinal = 0; // Reference counter
function Pa_IsLoaded : boolean; inline;
Function Pa_Load(const libfilename:string) :boolean; // load the lib
Procedure Pa_Unload(); // unload and frees the lib from memory : do not forget to call it before close application.
/////////////////////////////////////////////////////////////////////////////////////////////////
implementation
function Pa_IsLoaded: boolean;
begin
Result := (Pa_Handle <> dynlibs.NilHandle);
end;
Function Pa_Load (const libfilename:string) :boolean;
var
thelib: string;
begin
Result := False;
if Pa_Handle<>0 then
begin
Inc(ReferenceCounter);
result:=true {is it already there ?}
end else
begin {go & load the library}
if Length(libfilename) = 0 then thelib := libpa else thelib := libfilename;
Pa_Handle:=DynLibs.SafeLoadLibrary(thelib); // obtain the handle we want
if Pa_Handle <> DynLibs.NilHandle then
begin {now we tie the functions to the VARs from above}
Pointer(Pa_GetVersion):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetVersion'));
Pointer(Pa_GetVersionText):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetVersionText'));
Pointer(Pa_GetErrorText):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetErrorText'));
Pointer(Pa_Initialize):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_Initialize'));
Pointer(Pa_Terminate):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_Terminate'));
Pointer(Pa_GetHostApiCount):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetHostApiCount'));
Pointer(Pa_GetDefaultHostApi):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDefaultHostApi'));
Pointer(Pa_GetHostApiInfo):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetHostApiInfo'));
Pointer(Pa_HostApiTypeIdToHostApiIndex):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_HostApiTypeIdToHostApiIndex'));
Pointer(Pa_HostApiDeviceIndexToDeviceIndex):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_HostApiDeviceIndexToDeviceIndex'));
Pointer(Pa_GetLastHostErrorInfo):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetLastHostErrorInfo'));
//////////////////
Pointer(Pa_GetDeviceCount):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDeviceCount'));
Pointer(Pa_GetDefaultInputDevice):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDefaultInputDevice'));
Pointer(Pa_GetDefaultOutputDevice):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDefaultOutputDevice'));
Pointer(Pa_GetDeviceInfo):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDeviceInfo'));
Pointer(Pa_IsFormatSupported):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_IsFormatSupported'));
//////////////////////
Pointer(Pa_OpenStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_OpenStream'));
Pointer(Pa_OpenDefaultStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_OpenDefaultStream'));
Pointer(Pa_CloseStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_CloseStream'));
Pointer(Pa_SetStreamFinishedCallback):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_SetStreamFinishedCallback'));
Pointer(Pa_StartStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_StartStream'));
Pointer(Pa_StopStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_StopStream'));
Pointer(Pa_AbortStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_AbortStream'));
Pointer(Pa_IsStreamStopped):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_IsStreamStopped'));
Pointer(Pa_IsStreamActive):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_IsStreamActive'));
Pointer(Pa_GetStreamInfo):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamInfo'));
Pointer(Pa_GetStreamTime):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamTime'));
Pointer(Pa_GetStreamCpuLoad):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamCpuLoad'));
Pointer(Pa_ReadStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_ReadStream'));
Pointer(Pa_WriteStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_WriteStream'));
Pointer(Pa_GetStreamReadAvailable):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamReadAvailable'));
Pointer(Pa_GetStreamWriteAvailable):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamWriteAvailable'));
Pointer(Pa_GetSampleSize):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetSampleSize'));
Pointer(Pa_Sleep):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_Sleep'));
end;
Result := Pa_IsLoaded;
ReferenceCounter:=1;
end;
end;
Procedure Pa_Unload;
begin
// < Reference counting
if ReferenceCounter > 0 then
dec(ReferenceCounter);
if ReferenceCounter > 0 then
exit;
// >
if Pa_IsLoaded then
begin
Pa_Terminate();
DynLibs.UnloadLibrary(Pa_Handle);
Pa_Handle:=DynLibs.NilHandle;
end;
end;
end.

264
UOS/src/uos_shout.pas Normal file
View File

@@ -0,0 +1,264 @@
{This unit is part of United Openlibraries of Sound (uos)}
{This is the Dynamic loading version of IceCast_Shout Pascal Wrapper.
Load library with sha_load() and release with sh_unload().
License : modified LGPL.
Fred van Stappen / fiens@hotmail.com }
unit uos_shout;
{$mode objfpc}{$H+}
{$PACKRECORDS C}
interface
uses
dynlibs, CTypes, sysutils;
const
SHOUT_THREADSAFE = 1;
SHOUT_TLS = 1;
SHOUTERR_SUCCESS = 0;
SHOUTERR_INSANE = -1;
SHOUTERR_NOCONNECT = -2;
SHOUTERR_NOLOGIN = -3;
SHOUTERR_SOCKET = -4;
SHOUTERR_MALLOC = -5;
SHOUTERR_METADATA = -6;
SHOUTERR_CONNECTED = -7;
SHOUTERR_UNCONNECTED = -8;
SHOUTERR_UNSUPPORTED = -9;
SHOUTERR_BUSY = -10;
SHOUTERR_NOTLS = -11;
SHOUTERR_TLSBADCERT = -12;
SHOUTERR_RETRY = -13;
SHOUT_FORMAT_OGG = 0;
SHOUT_FORMAT_MP3 = 1;
SHOUT_FORMAT_WEBM = 2;
SHOUT_FORMAT_WEBMAUDIO = 3;
SHOUT_FORMAT_VORBIS = SHOUT_FORMAT_OGG;
SHOUT_PROTOCOL_HTTP = 0;
SHOUT_PROTOCOL_XAUDIOCAST = 1;
SHOUT_PROTOCOL_ICY = 2;
SHOUT_PROTOCOL_ROARAUDIO = 3;
SHOUT_TLS_DISABLED = 0;
SHOUT_TLS_AUTO = 1;
SHOUT_TLS_AUTO_NO_PLAIN = 2;
SHOUT_TLS_RFC2818 = 11;
SHOUT_TLS_RFC2817 = 12;
SHOUT_AI_BITRATE = 'bitrate';
SHOUT_AI_SAMPLERATE = 'samplerate';
SHOUT_AI_CHANNELS = 'channels';
SHOUT_AI_QUALITY = 'quality';
SHOUT_META_NAME = 'name';
SHOUT_META_URL = 'url';
SHOUT_META_GENRE = 'genre';
SHOUT_META_DESCRIPTION = 'description';
SHOUT_META_IRC = 'irc';
SHOUT_META_AIM = 'aim';
SHOUT_META_ICQ = 'icq';
type
shout_t = pointer;
Pshout_t = ^shout_t;
{$if defined(cpu64)}
cuint64 = qword;
size_t = cuint64;
{$else}
cuint32 = longword;
size_t = cuint32;
{$endif}
psize_t = ^size_t;
shout_metadata_t = pointer;
Pshout_metadata_t = ^shout_metadata_t;
// methods
var
shout_init: procedure();cdecl;
shout_shutdown: procedure();cdecl;
shout_version: function(var major:cint; var minor:cint; var patch:cint):pchar;cdecl;
shout_new: function(): Pshout_t;cdecl;
shout_free: procedure(shhandle :Pshout_t);cdecl;
shout_get_error: function(shhandle :Pshout_t):pchar;cdecl;
shout_get_errno: function(shhandle :Pshout_t):cint;cdecl;
shout_get_connected: function(shhandle :Pshout_t):cint;cdecl;
shout_set_host: function(shhandle :Pshout_t; host: pchar):cint;cdecl;
shout_get_host: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_port: function(shhandle :Pshout_t; port:cushort):cint;cdecl;
shout_get_port: function(shhandle :Pshout_t):cushort;cdecl;
shout_set_agent: function(shhandle :Pshout_t; agent:pchar):cint;cdecl;
shout_get_agent: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_tls: function(shhandle :Pshout_t; mode:cint):cint;cdecl;
shout_get_tls: function(shhandle :Pshout_t):cint;cdecl;
shout_set_ca_directory: function(shhandle :Pshout_t; directory:pchar):cint;cdecl;
shout_get_ca_directory: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_ca_file: function(shhandle :Pshout_t; thefile:pchar):cint;cdecl;
shout_get_ca_file: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_allowed_ciphers: function(shhandle :Pshout_t; ciphers:pchar):cint;cdecl;
shout_get_allowed_ciphers: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_user: function(shhandle :Pshout_t; username:pchar):cint;cdecl;
shout_get_user: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_password: function(shhandle :Pshout_t; password:pchar):cint;cdecl;
shout_get_password: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_client_certificate: function(shhandle :Pshout_t; certificate:pchar):cint;cdecl;
shout_get_client_certificate: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_mount: function(shhandle :Pshout_t; mount:pchar):cint;cdecl;
shout_get_mount: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_name: function(shhandle :Pshout_t; name:pchar):cint;cdecl;
shout_get_name: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_url: function(shhandle :Pshout_t; url:pchar):cint;cdecl;
shout_get_url: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_genre: function(shhandle :Pshout_t; genre:pchar):cint;cdecl;
shout_get_genre: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_description: function(shhandle :Pshout_t; description:pchar):cint;cdecl;
shout_get_description: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_dumpfile: function(shhandle :Pshout_t; dumpfile:pchar):cint;cdecl;
shout_get_dumpfile: function(shhandle :Pshout_t):pchar;cdecl;
shout_set_audio_info: function(shhandle :Pshout_t; name:pchar; value:pchar):cint;cdecl;
shout_get_audio_info: function(shhandle :Pshout_t; name:pchar):pchar;cdecl;
shout_set_meta: function(shhandle :Pshout_t; name:pchar; value:pchar):cint;cdecl;
shout_get_meta: function(shhandle :Pshout_t; name:pchar):pchar;cdecl;
shout_set_public: function(shhandle :Pshout_t; make_public:cuint):cint;cdecl;
shout_get_public: function(shhandle :Pshout_t):cuint;cdecl;
shout_set_format: function(shhandle :Pshout_t; format:cuint):cint;cdecl;
shout_get_format: function(shhandle :Pshout_t):cuint;cdecl;
shout_set_protocol: function(shhandle :Pshout_t; protocol:cuint):cint;cdecl;
shout_get_protocol: function(shhandle :Pshout_t):cuint;cdecl;
shout_set_nonblocking: function(shhandle :Pshout_t; nonblocking:cuint):cint;cdecl;
shout_get_nonblocking: function(shhandle :Pshout_t):cuint;cdecl;
shout_open: function(shhandle :Pshout_t):cint;cdecl;
shout_close: function(shhandle :Pshout_t):cint;cdecl;
//shout_send: function(shhandle :Pshout_t; data:pcuchar; len:size_t):cint;cdecl;
shout_send: function(shhandle :Pshout_t; data:pbyte; len:size_t):cint;cdecl;
shout_send_raw: function(shhandle :Pshout_t; data:pcuchar; len:size_t):size_t;cdecl;
shout_queuelen: function(shhandle :Pshout_t):size_t;cdecl;
shout_sync: procedure(shhandle :Pshout_t);cdecl;
shout_delay: function(shhandle :Pshout_t):cint;cdecl;
shout_set_metadata: function(shhandle :Pshout_t; var metadata:shout_metadata_t):cint;cdecl;
shout_metadata_new: function():Pshout_metadata_t;cdecl;
shout_metadata_free: procedure(var shhandle:shout_metadata_t);cdecl;
shout_metadata_add: function(var shhandle:shout_metadata_t; name:pchar; value:pchar):cint;cdecl;
sh_Handle:TLibHandle=dynlibs.NilHandle; // this will hold our handle for the lib; it functions nicely as a mutli-lib prevention unit as well...
ReferenceCounter : cardinal = 0; // Reference counter
function sh_IsLoaded : boolean; inline;
Function sh_Load(const libfilename:string) :boolean; // load the lib
Procedure sh_Unload(); // unload and frees the lib from memory : do not forget to call it before close application.
implementation
function sh_IsLoaded: boolean;
begin
Result := (sh_Handle <> dynlibs.NilHandle);
end;
Function sh_Load (const libfilename:string) :boolean;
begin
Result := False;
if sh_Handle<>0 then
begin
Inc(ReferenceCounter);
result:=true {is it already there ?}
end else
begin {go & load the library}
if Length(libfilename) = 0 then exit;
sh_Handle:=DynLibs.SafeLoadLibrary(libfilename); // obtain the handle we want
if sh_Handle <> DynLibs.NilHandle then
begin {now we tie the functions to the VARs from above}
Pointer(shout_init):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_init'));
Pointer(shout_shutdown):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_shutdown'));
Pointer(shout_version):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_version'));
Pointer(shout_new):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_new'));
Pointer(shout_free):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_free'));
Pointer(shout_get_error):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_error'));
Pointer(shout_get_errno):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_errno'));
Pointer(shout_get_connected):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_connected'));
Pointer(shout_set_host):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_host'));
Pointer(shout_get_host):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_host'));
Pointer(shout_set_port):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_port'));
Pointer(shout_get_port):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_port'));
Pointer(shout_set_agent):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_agent'));
Pointer(shout_get_agent):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_agent'));
Pointer(shout_set_tls):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_tls'));
Pointer(shout_get_tls):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_tls'));
Pointer(shout_set_ca_directory):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_ca_directory'));
Pointer(shout_get_ca_directory):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_ca_directory'));
Pointer(shout_set_ca_file):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_ca_file'));
Pointer(shout_get_ca_file):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_ca_file'));
Pointer(shout_set_allowed_ciphers):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_allowed_ciphers'));
Pointer(shout_get_allowed_ciphers):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_allowed_ciphers'));
Pointer(shout_set_user):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_user'));
Pointer(shout_get_user):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_user'));
Pointer(shout_set_password):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_password'));
Pointer(shout_get_password):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_password'));
Pointer(shout_set_client_certificate):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_client_certificate'));
Pointer(shout_get_client_certificate):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_client_certificate'));
Pointer(shout_set_mount):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_mount'));
Pointer(shout_get_mount):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_mount'));
Pointer(shout_set_name):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_name'));
Pointer(shout_get_name):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_name'));
Pointer(shout_set_url):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_url'));
Pointer(shout_get_url):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_url'));
Pointer(shout_set_genre):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_genre'));
Pointer(shout_get_genre):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_genre'));
Pointer(shout_set_description):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_description'));
Pointer(shout_get_description):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_description'));
Pointer(shout_set_dumpfile):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_dumpfile'));
Pointer(shout_get_dumpfile):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_dumpfile'));
Pointer(shout_set_audio_info):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_audio_info'));
Pointer(shout_get_audio_info):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_audio_info'));
Pointer(shout_set_meta):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_meta'));
Pointer(shout_get_meta):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_meta'));
Pointer(shout_set_public):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_public'));
Pointer(shout_get_public):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_public'));
Pointer(shout_set_format):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_format'));
Pointer(shout_get_format):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_format'));
Pointer(shout_set_protocol):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_protocol'));
Pointer(shout_get_protocol):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_protocol'));
Pointer(shout_set_nonblocking):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_nonblocking'));
Pointer(shout_get_nonblocking):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_get_nonblocking'));
Pointer(shout_open):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_open'));
Pointer(shout_close):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_close'));
Pointer(shout_send):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_send'));
Pointer(shout_send_raw):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_send_raw'));
Pointer(shout_queuelen):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_queuelen'));
Pointer(shout_sync):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_sync'));
Pointer(shout_delay):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_delay'));
Pointer(shout_set_metadata):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_set_metadata'));
Pointer(shout_metadata_new):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_metadata_new'));
Pointer(shout_metadata_free):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_metadata_free'));
Pointer(shout_metadata_add):=DynLibs.GetProcedureAddress(sh_Handle,PChar('shout_metadata_add'));
end;
Result := sh_IsLoaded;
ReferenceCounter:=1;
end;
end;
Procedure sh_Unload;
begin
// < Reference counting
if ReferenceCounter > 0 then
dec(ReferenceCounter);
if ReferenceCounter > 0 then
exit;
// >
if sh_IsLoaded then
begin
shout_shutdown();
DynLibs.UnloadLibrary(sh_Handle);
sh_Handle:=DynLibs.NilHandle;
end;
end;
end.

216
UOS/src/uos_soundtouch.pas Normal file
View File

@@ -0,0 +1,216 @@
{This unit is part of United Openlibraries of Sound (uos)}
{This is the Dynamic loading + Unix compatible version of SoundTouch Pascal Wrapper
from Sandro Cumerlato <sandro.cumerlato@gmail.com>.
of the original C version of Olli Parviainen <oparviai@iki.fi>.
Added BPMdetect method too.
Load library with St_load() and release with St_unload().
License : modified LGPL.
Fred van Stappen / fiens@hotmail.com}
unit uos_soundtouch;
{$mode objfpc}{$H+}
{$PACKRECORDS C}
interface
uses
ctypes, DynLibs;
const
libst=
{$IFDEF darwin}
'libSoundTouchDLL.dylib';
{$ELSE}
{$IFDEF unix}
'libSoundTouch.so.1';
{$ELSE}
{$if defined(cpu64)}
'SoundTouch_x64.dll';
{$else}
'SoundTouch.dll';
{$endif}
{$ENDIF}
{$ENDIF}
{$IF not DEFINED(windows)}
type
THandle = pointer;
{$endif}
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;
var
bpm_createInstance: function(chan: CInt32; sampleRate : CInt32): THandle; cdecl;
bpm_destroyInstance: procedure(h: THandle); cdecl;
bpm_getBpm: function(h: THandle): cfloat; cdecl;
bpm_putSamples: procedure(h: THandle; const samples: pcfloat;
numSamples: cardinal); cdecl;
soundtouch_clear: procedure(h: THandle); cdecl;
soundtouch_createInstance: function(): THandle; cdecl;
soundtouch_flush: procedure(h: THandle); cdecl;
soundtouch_getSetting: function(h: THandle; settingId: integer): integer; cdecl;
soundtouch_getVersionId: function(): cardinal; cdecl;
soundtouch_getVersionString2: procedure(VersionString: PAnsiChar;
bufferSize: integer); cdecl;
soundtouch_getVersionString: function(): PAnsiChar; cdecl;
soundtouch_isEmpty: function(h: THandle): integer; cdecl;
soundtouch_numSamples: function(h: THandle): cardinal; cdecl;
soundtouch_numUnprocessedSamples: function(h: THandle): cardinal; cdecl;
soundtouch_putSamples: procedure(h: THandle; const samples: pcfloat;
numSamples: cardinal); cdecl;
soundtouch_receiveSamples: function(h: THandle; outBuffer: pcfloat;
maxSamples: cardinal): cardinal; cdecl;
soundtouch_setChannels: procedure(h: THandle; numChannels: cardinal); cdecl;
soundtouch_setPitch: procedure(h: THandle; newPitch: single); cdecl;
soundtouch_setPitchOctaves: procedure(h: THandle; newPitch: single); cdecl;
soundtouch_setPitchSemiTones: procedure(h: THandle; newPitch: single); cdecl;
soundtouch_setRate: procedure(h: THandle; newRate: single); cdecl;
soundtouch_setRateChange: procedure(h: THandle; newRate: single); cdecl;
soundtouch_setSampleRate: procedure(h: THandle; srate: cardinal); cdecl;
soundtouch_destroyInstance: procedure(h: THandle); cdecl;
soundtouch_setSetting: function(h: THandle; settingId: integer; Value: integer): boolean; cdecl;
soundtouch_setTempo: procedure(h: THandle; newTempo: single); cdecl;
soundtouch_setTempoChange: procedure(h: THandle; newTempo: single); cdecl;
LibHandle:TLibHandle=dynlibs.NilHandle; // this will hold our handle for the lib
ReferenceCounter : cardinal = 0; // Reference counter
function ST_IsLoaded : boolean; inline;
function ST_Load(const libfilename: string): boolean; // load the lib
procedure ST_Unload(); // unload and frees the lib from memory : do not forget to call it before close application.
implementation
function ST_IsLoaded: boolean;
begin
Result := (LibHandle <> dynlibs.NilHandle);
end;
function ST_Load(const libfilename: string): boolean;
var
thelib: string;
begin
Result := False;
if LibHandle<>0 then
begin
Inc(ReferenceCounter);
result:=true
end else begin
if Length(libfilename) = 0 then thelib := libst else thelib := libfilename;
LibHandle:=DynLibs.SafeLoadLibrary(thelib); // obtain the handle we want.
if LibHandle <> DynLibs.NilHandle then
begin
try
Pointer(soundtouch_createInstance) :=
GetProcAddress(LibHandle, 'soundtouch_createInstance');
if Pointer(soundtouch_createInstance) = nil then // not the SoundTouchDLL library.
begin
ST_Unload;
result := false end
else
begin
Pointer(soundtouch_clear) :=
GetProcAddress(LibHandle, 'soundtouch_clear');
Pointer(soundtouch_destroyInstance) :=
GetProcAddress(LibHandle, 'soundtouch_destroyInstance');
Pointer(soundtouch_flush) :=
GetProcAddress(LibHandle, 'soundtouch_flush');
Pointer(soundtouch_getSetting) :=
GetProcAddress(LibHandle, 'soundtouch_getSetting');
Pointer(soundtouch_getVersionId) :=
GetProcAddress(LibHandle, 'soundtouch_getVersionId');
Pointer(soundtouch_getVersionString2) :=
GetProcAddress(LibHandle, 'soundtouch_getVersionString2');
Pointer(soundtouch_getVersionString) :=
GetProcAddress(LibHandle, 'soundtouch_getVersionString');
Pointer(soundtouch_isEmpty) :=
GetProcAddress(LibHandle, 'soundtouch_isEmpty');
Pointer(soundtouch_numSamples) :=
GetProcAddress(LibHandle, 'soundtouch_numSamples');
Pointer(soundtouch_numUnprocessedSamples) :=
GetProcAddress(LibHandle, 'soundtouch_numUnprocessedSamples');
Pointer(soundtouch_putSamples) :=
GetProcAddress(LibHandle, 'soundtouch_putSamples');
Pointer(soundtouch_receiveSamples) :=
GetProcAddress(LibHandle, 'soundtouch_receiveSamples');
Pointer(soundtouch_setChannels) :=
GetProcAddress(LibHandle, 'soundtouch_setChannels');
Pointer(soundtouch_setPitch) :=
GetProcAddress(LibHandle, 'soundtouch_setPitch');
Pointer(soundtouch_setPitchOctaves) :=
GetProcAddress(LibHandle, 'soundtouch_setPitchOctaves');
Pointer(soundtouch_setPitchSemiTones) :=
GetProcAddress(LibHandle, 'soundtouch_setPitchSemiTones');
Pointer(soundtouch_setRate) :=
GetProcAddress(LibHandle, 'soundtouch_setRate');
Pointer(soundtouch_setRateChange) :=
GetProcAddress(LibHandle, 'soundtouch_setRateChange');
Pointer(soundtouch_setSampleRate) :=
GetProcAddress(LibHandle, 'soundtouch_setSampleRate');
Pointer(soundtouch_setSetting) :=
GetProcAddress(LibHandle, 'soundtouch_setSetting');
Pointer(soundtouch_setTempo) :=
GetProcAddress(LibHandle, 'soundtouch_setTempo');
Pointer(soundtouch_setTempoChange) :=
GetProcAddress(LibHandle, 'soundtouch_setTempoChange');
Pointer(bpm_createInstance) :=
GetProcAddress(LibHandle, 'bpm_createInstance');
Pointer(bpm_destroyInstance) :=
GetProcAddress(LibHandle, 'bpm_destroyInstance');
Pointer(bpm_getBpm) :=
GetProcAddress(LibHandle, 'bpm_getBpm');
Pointer(bpm_putSamples) :=
GetProcAddress(LibHandle, 'bpm_putSamples');
Result := St_IsLoaded;
ReferenceCounter:=1;
end;
except
ST_Unload;
end;
end;
end;
end;
procedure ST_Unload;
begin
// < Reference counting
if ReferenceCounter > 0 then
dec(ReferenceCounter);
if ReferenceCounter > 0 then
exit;
// >
if LibHandle <> DynLibs.NilHandle then
begin
DynLibs.UnloadLibrary(LibHandle);
LibHandle := DynLibs.NilHandle;
end;
end;
end.