Files
package-zearch-temp/UOS/examples/uos_libsndfile.pas
Indrajith K L 6a1d80d3b8 Implements Module Player working in Form
* Implements Embedding .xm music in Final Application
2025-06-02 15:15:16 +05:30

786 lines
25 KiB
ObjectPascal

{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.