unit UADE;
{$mode objfpc}{$H+}
interface
uses
SysUtils;
const
UADELIB = 'UADE.dll';
UADE_CHANNELS = 2;
UADE_BYTES_PER_SAMPLE = 2;
UADE_BYTES_PER_FRAME = UADE_CHANNELS * UADE_BYTES_PER_SAMPLE;
UADE_MAX_EXT_LEN = 16;
RMC_MAGIC: array[0..8] of AnsiChar = 'rmc'#0#251#19#246#31#162;
RMC_MAGIC_LEN = 9;
UADE_DEFAULT_FREQUENCY = 44100;
PATH_MAX = 4096;
UADE_MAX_MESSAGE_SIZE = 4096;
HEADPHONE2_DELAY_MAX_LENGTH = 48;
UADE_EFFECT_HEADPHONES_DELAY_LENGTH = 22;
HEADPHONE2_DELAY_TIME = 0.49e-3;
MAXIMUM_SAMPLING_RATE =96000;
UADE_PLAY_CURRENT = 0;
UADE_PLAY_NEXT = 1;
UADE_PLAY_FAILURE = -1;
UADE_PLAY_EXIT = -2;
ES_A1200 = 1 shl 0;
ES_A500 = 1 shl 1;
ES_ALWAYS_ENDS = 1 shl 2;
ES_BROKEN_SONG_END = 1 shl 3;
ES_CONTENT_DETECTION = 1 shl 4;
ES_EP_OPTION = 1 shl 5;
ES_GAIN = 1 shl 6;
ES_IGNORE_PLAYER_CHECK = 1 shl 7;
ES_LED_OFF = 1 shl 8;
ES_LED_ON = 1 shl 9;
ES_NEVER_ENDS = 1 shl 10;
ES_NO_FILTER = 1 shl 11;
ES_NO_HEADPHONES = 1 shl 12;
ES_NO_PANNING = 1 shl 13;
ES_NO_POSTPROCESSING = 1 shl 14;
ES_NTSC = 1 shl 15;
ES_ONE_SUBSONG = 1 shl 16;
ES_PAL = 1 shl 17;
ES_PANNING = 1 shl 18;
ES_PLAYER = 1 shl 19;
ES_REJECT = 1 shl 20;
ES_RESAMPLER = 1 shl 21;
ES_SILENCE_TIMEOUT = 1 shl 22;
ES_SPEED_HACK = 1 shl 23;
ES_SUBSONGS = 1 shl 24;
ES_SUBSONG_TIMEOUT = 1 shl 25;
ES_TIMEOUT = 1 shl 26;
UADE_WS_DELIMITERS = ' '#9#10;
type
size_t = Int64;
int64_t = Int64;
// Structure Path
TUADEPath = record
Name: array[0..PATH_MAX - 1] of AnsiChar;
end;
// Options eagleplayer
TUADEEPOptions = record
O: array[0..255] of AnsiChar;
S: size_t;
end;
// Options audio output
TUADEAOOptions = record
O: array[0..255] of AnsiChar;
end;
// configurations
TUADECharConfig = record
Value: AnsiChar;
IsSet: Boolean;
end;
TUADEFloatConfig = record
Value: Single;
IsSet: Boolean;
end;
TUADEIntConfig = record
Value: Integer;
IsSet: Boolean;
end;
TUADEPathConfig = record
Path: TUADEPath;
IsSet: Boolean ;
end;
TUadeBiquad = record
b0: Single;
b1: Single;
b2: Single;
a1: Single;
a2: Single;
x: array[0..1] of Single;
y: array[0..1] of Single;
end;
PUadeBiquad = ^TUadeBiquad;
PUadeEffectState = ^TUadeEffectState;
TUadeEffectState = record
enabled: boolean;
gain: Integer;
pan: Integer;
rate: Integer;
headphones_ap_l: array[0..UADE_EFFECT_HEADPHONES_DELAY_LENGTH - 1] of Single;
headphones_ap_r: array[0..UADE_EFFECT_HEADPHONES_DELAY_LENGTH - 1] of Single;
headphones_rc_l: array[0..3] of Single;
headphones_rc_r: array[0..3] of Single;
headphone2_ap_l: array[0..HEADPHONE2_DELAY_MAX_LENGTH - 1] of Single;
headphone2_ap_r: array[0..HEADPHONE2_DELAY_MAX_LENGTH - 1] of Single;
headphone2_delay_length: Integer;
headphone2_shelve_l: PUadeBiquad;
headphone2_shelve_r: PUadeBiquad;
headphone2_rc_l: PUadeBiquad;
headphone2_rc_r: PUadeBiquad;
end;
PUADEAttribute = ^TUADEAttribute;
TUADEAttribute = record
Next: PUADEAttribute;
Flag: Integer;
S: PChar;
I: Integer;
D: Double;
end;
// Structure pour eagleplayer
PEaglePlayer = ^TEaglePlayer;
TEaglePlayer = record
PlayerName: PChar;
Nextensions: Integer;
Extensions: Pchar;
Flags: Integer;
AttributeList: PUADEAttribute;
end;
// Structure pour eagleplayermap
PEaglePlayerMap = ^TEaglePlayerMap;
TEaglePlayerMap = record
Extension: PChar;
Player: PEaglePlayer;
end;
// Structure eagleplayerstore
PEaglePlayerStore = ^TEaglePlayerStore;
TEaglePlayerStore = record
NPlayers: SizeUInt;
Players: PEaglePlayer ; // Tableau players
NExtensions: SizeUInt;
Map: PEaglePlayerMap; // Tableau de maps
end;
// Structure pour epconfattr
TEPConfAttr = record
S: PChar;
E: Integer;
O: Integer;
C: PChar;
end;
// Structure fichier
PUADEFile = ^TUADEFile;
TUADEFile = record
Name: PChar; // Filename
Data: PChar; // File data or null
Size: integer; // File size
end;
// Subsong information
TUADESubsongInfo = record
Cur: Integer; // Current subsong:
Min: Integer; // Minimum subsong number
Def: Integer; // Default subsong -1
Max: Integer; // Maximum subsong
end;
// Detection information
PUADEDetectionInfo = ^TUADEDetectionInfo;
TUADEDetectionInfo = record
Custom: Integer; // 1 if the file is custom, 0 otherwise
Content: Integer; // 1 if detected by content, 0 otherwise
Ext: array[0..UADE_MAX_EXT_LEN - 1] of AnsiChar; // File extension
EP: PEaglePlayer; // (don't touch)
end;
// Extension to format and version mapping
TUADEExtToFormatVersion = record
FileExt: PChar;
Format: PChar;
Version: PChar;
end;
// Song information
PUADESongInfo = ^TUADESongInfo;
TUADESongInfo = record
Subsongs: TUADESubsongInfo;
DetectionInfo: TUADEDetectionInfo;
ModuleBytes: size_t; // Size of song file in bytes
ModuleMD5: array[0..32] of AnsiChar; // Hexadecimal string of MD5 sum
Duration: Double; // Duration in seconds, 0 if unknown
SubsongBytes: int64_t; // Bytes synthesized in current subsong
SongBytes: int64_t; // Bytes synthesized in current song (all subsongs)
ModuleFName: array[0..4096 - 1] of AnsiChar;
PlayerFName: array[0..4096 - 1] of AnsiChar;
FormatName: array[0..255] of AnsiChar;
ModuleName: array[0..255] of AnsiChar;
PlayerName: array[0..255] of AnsiChar;
end;
PUADEConfig = ^TUADEConfig;
TUADEConfig = record
//// Path configurations
BaseDir: TUADEPathConfig;
PlayerFile: TUADEPathConfig;
ScoreFile: TUADEPathConfig;
UadeCoreFile: TUADEPathConfig;
UAEConfigFile: TUADEPathConfig;
// Char configurations
ContentDetection: TUADECharConfig;
// Eagleplayer options
EPOptions: TUADEEPOptions;
EPOptionsSet: Boolean;
// Filter and frequency
FilterType: TUADECharConfig;
Frequency: TUADEIntConfig;
// LED settings
LEDForced: TUADECharConfig;
LEDState: TUADECharConfig;
// Gain configuration
GainEnable: TUADECharConfig;
Gain: TUADEFloatConfig;
// Headphones configuration
Headphones: TUADECharConfig;
Headphones2: TUADECharConfig;
// Player check
IgnorePlayerCheck: TUADECharConfig;
// Resampler
Resampler: PChar;
ResamplerSet: Boolean;
// Other configurations
NoContentDB: TUADECharConfig;
NoEPEnd: TUADECharConfig;
NoFilter: TUADECharConfig;
NoPostProcessing: TUADECharConfig;
OneSubsong: TUADECharConfig;
Panning: TUADEFloatConfig;
PanningEnable: TUADECharConfig;
SilenceTimeout: TUADEIntConfig;
SpeedHack: TUADECharConfig;
SubsongTimeout: TUADEIntConfig;
Timeout: TUADEIntConfig;
UseTextScope: TUADECharConfig;
UseTimeouts: TUADECharConfig;
UseNTSC: TUADECharConfig;
Verbose: TUADECharConfig;
WriteAudioFile: TUADEPathConfig;
// Audio output options
AOOptions: TUADEAOOptions;
AOOptionsSet: Boolean;
end;
// Enum for song info type
TUADESongInfoType = (
UADE_MODULE_INFO = 1,
UADE_HEX_DUMP_INFO,
UADE_NUMBER_OF_INFOS
);
// Enum for seek modes
TUADESeekMode = (
UADE_SEEK_NOT_SEEKING = 0,
UADE_SEEK_SONG_RELATIVE,
UADE_SEEK_SUBSONG_RELATIVE,
UADE_SEEK_POSITION_RELATIVE
);
// Enum uade options
TUADEOption = (
UC_NO_OPTION = $1000,
UC_BASE_DIR,
UC_CONTENT_DETECTION,
UC_DISABLE_TIMEOUTS,
UC_ENABLE_TIMEOUTS,
UC_EAGLEPLAYER_OPTION,
UC_FILTER_TYPE,
UC_FORCE_LED_OFF,
UC_FORCE_LED_ON,
UC_FORCE_LED,
UC_FREQUENCY,
UC_GAIN,
UC_HEADPHONES,
UC_HEADPHONES2,
UC_IGNORE_PLAYER_CHECK,
UC_NO_CONTENT_DB,
UC_NO_FILTER,
UC_NO_HEADPHONES,
UC_NO_PANNING,
UC_NO_POSTPROCESSING,
UC_NO_EP_END,
UC_NTSC,
UC_ONE_SUBSONG,
UC_PAL,
UC_PANNING_VALUE,
UC_PLAYER_FILE,
UC_RESAMPLER,
UC_SCORE_FILE,
UC_SILENCE_TIMEOUT_VALUE,
UC_SPEED_HACK,
UC_SUBSONG_TIMEOUT_VALUE,
UC_TIMEOUT_VALUE,
UC_UADECORE_FILE,
UC_UAE_CONFIG_FILE,
UC_USE_TEXT_SCOPE,
UC_VERBOSE,
UC_AO_OPTION,
UC_WRITE_AUDIO_FILE
);
// Enum for audio effects
TUADEEffect = (
UADE_EFFECT_ALLOW,
UADE_EFFECT_GAIN,
UADE_EFFECT_HEADPHONES,
UADE_EFFECT_HEADPHONES2,
UADE_EFFECT_PAN
);
TUADEEventType = (
UADE_EVENT_INVALID = 0,
UADE_EVENT_DATA,
UADE_EVENT_EAGAIN,
UADE_EVENT_FORMAT_NAME,
UADE_EVENT_MESSAGE,
UADE_EVENT_MODULE_NAME,
UADE_EVENT_PLAYER_NAME,
UADE_EVENT_READY,
UADE_EVENT_REQUEST_AMIGA_FILE,
UADE_EVENT_SONG_END,
UADE_EVENT_SUBSONG_INFO
);
// Struct event
TUADEEventData = record
Size: SizeUInt;
Data: array[0..UADE_MAX_MESSAGE_SIZE - 1] of Byte;
end;
// Structure end module
TUADEEventSongEnd = record
Happy: Integer;
StopNow: Integer;
TailBytes: Integer;
Reason: array[0..255] of AnsiChar;
end;
// Structure des événements
TUADEEvent = record
EventType: TUADEEventType;
case Byte of
0: (Data: TUADEEventData);
1: (Message: array[0..1023] of AnsiChar);
2: (SongEnd: TUADEEventSongEnd);
3: (SubSongs: TUADESubSongInfo);
end;
// Énumdes symboles d'état
TUADEStateSymbol = (
UADE_STATE_INVALID = 0,
UADE_STATE_INITIALIZED,
UADE_STATE_RECEIVE_MSGS,
UADE_STATE_SONG_END_PENDING,
UADE_STATE_WAIT_SUBSONG_CHANGE,
UADE_STATE_ERROR
);
PUADESong = ^TUADESong;
TUADESong = record
MD5: array[0..32] of AnsiChar; // MD5
ModuleFilename: array[0..PATH_MAX - 1] of AnsiChar; // Nom du fichier module
PlayerName: array[0..255] of AnsiChar; // Nom du lecteur Eagleplayer
ModuleName: array[0..255] of AnsiChar; // Nom du module provenant du score
FormatName: array[0..255] of AnsiChar; // Nom du format
Buf: PByte;
BufSize: SizeUInt;
MinSubsong: Integer;
MaxSubsong: Integer;
CurSubsong: Integer;
PlayTime: Integer;
Flags: Integer;
NSubSongs: Integer;
SubSongs: PByte;
SongAttributes: PUADEAttribute;
EPOptions: TUADEEPOptions;
Normalisation: PChar;
OutBytes: Int64;
SilenceCount: Int64;
end;
// Struct song state
PUADESongState = ^TUADESongState;
TUADESongState = record
Info: TUADESongInfo;
// Membres internes
State: TUADEStateSymbol;
SeekModeTrigger: TUADESeekMode;
SeekSubSongTrigger: Integer;
SeekOffsetTrigger: UInt64;
NextSubSongTrigger: Integer;
SeekMode: TUADESeekMode;
SeekSubSong: Integer;
SeekSongOffset: UInt64;
SeekSubSongOffset: UInt64;
BytesRequested: Cardinal;
EndEvent: TUADEEvent;
SilenceCount: Int64;
EPOptions: TUADEEPOptions;
Flags: Integer;
SongAttributes: Pointer;
RecordSongTime: Integer;
RecordSubSongTime: Integer;
CollectLogs: Integer;
end;
TUadeControlState = (
UCS_UNKNOWN,
UCS_IDLE,
UCS_BUSY,
UCS_ERROR
);
TUADEIPC = record
InFD: Integer;
OutFD: Integer;
InputBytes: Cardinal;
InputBuffer: array[0..UADE_MAX_MESSAGE_SIZE - 1] of AnsiChar;
State: TUadeControlState;
end;
// Forward declarations for structures
PBEncode = record
car : AnsiChar;
end;
PFifo = ^TFifo;
TFifo = record
Lower: SizeUInt;
Upper: SizeUInt;
Capacity: SizeUInt;
Buf: PByte;
end;
TRMC = record
RMC_MAGIC: array[0..8] of AnsiChar;// = 'rmc'#0#251#19#246#31#162;
end;
// Structure de l'Ă©tat principal
PUADEState = ^TUADEState ;
TAmigaLoader = function( name: PChar; playerdir: PChar;context: Pointer;state: PUadeState): TUADEFile; cdecl;
TUADEState = record
Config: TUADEConfig;
EffectState: TUadeEffectState;
Song: TUADESongState;
RMC: TRMC;
// Membres permanents
ValidConfig: Integer;
PermConfig: TUADEConfig;
PermConfigName: array[0..PATH_MAX - 1] of AnsiChar;
SetDebug: Integer;
HasEnded: Integer;
ExtraConfig: TUADEConfig;
PlayerStore: TEaglePlayerStore;
IPC: TUADEIPC;
UserData: Pointer;
SongDB: Pointer; // Type pour uade_songdb
SongDBName: array[0..PATH_MAX - 1] of AnsiChar;
AmigaLoader: function( name: PChar; playerdir: PChar;context: Pointer;state: PUadeState): PUADEFile; cdecl;
AmigaLoaderContext: Pointer;
ReadStash: Pfifo;
Notifications: Pfifo;
WriteQueue: Pfifo;
end;
TUADENotificationType = (
UADE_NOTIFICATION_MESSAGE,
UADE_NOTIFICATION_SONG_END
);
TUADENotificationSongEnd = record
Happy: Integer;
StopNow: Integer;
SubSong: Integer;
SubSongBytes: Int64;
Reason: PChar;
end;
// Structure notification
PUADENotification = ^TUADENotification;
TUADENotification = record
NotificationType: TUADENotificationType;
case Integer of
0: (Msg: PChar);
1: (SongEnd: TUADENotificationSongEnd);
end;
procedure uade_cleanup_state(st: PUADEState); cdecl; external 'uade.dll' name 'uade_cleanup_state';
procedure uade_enable_uadecore_log_collection(st: PUADEState); cdecl; external 'uade.dll';
procedure uade_effect_disable(st: TUADEState; effect: TUADEEffect); cdecl; external 'uade.dll';
procedure uade_effect_disable_all(st: TUADEState); cdecl; external 'uade.dll';
procedure uade_effect_enable(st: TUADEState; effect: TUADEEffect); cdecl; external 'uade.dll';
function uade_effect_is_enabled(st: TUADEState; effect: TUADEEffect): Integer; cdecl; external 'uade.dll';
procedure uade_effect_toggle(st: TUADEState; effect: TUADEEffect); cdecl; external 'uade.dll';
procedure uade_effect_gain_set_amount(st: TUADEState; amount: Single); cdecl; external 'uade.dll';
procedure uade_effect_pan_set_amount(st: TUADEState; amount: Single); cdecl; external 'uade.dll';
function uade_event_name(event: TUADENotification): PChar; cdecl; external 'uade.dll';
function uade_get_effective_config(st: TUADEState): TUADEConfig; cdecl; external 'uade.dll';
function uade_get_event(event: TUADENotification; st: PUADEState): Integer; cdecl; external 'uade.dll';
function uade_get_fd(st: TUADEState): Integer; cdecl; external 'uade.dll';
function uade_get_filter_state(st: TUADEState): Integer; cdecl; external 'uade.dll';
function uade_read(buff: Pointer; bufferSize: Integer; st: Pointer): Integer; cdecl; external 'uade.dll' name 'uade_read';
function uade_read_notification(notification: TUADENotification; st: TUADEState): Integer; cdecl; external 'uade.dll';
procedure uade_cleanup_notification(notification: TUADENotification); cdecl; external 'uade.dll';
function uade_get_sampling_rate(st: PUADEState): Integer; cdecl; external 'uade.dll';
function uade_get_song_info(st: PUADEState): PUADESongInfo; cdecl; external 'uade.dll';
function uade_is_our_file(fname: PChar; st: PUADEState): integer; cdecl; external 'uade.dll';
function uade_is_our_file_from_buffer(fname: PChar; buf: Pointer; size: SizeInt; st: PUADEState): Integer; cdecl; external 'uade.dll';
function uade_is_rmc(buf: PChar; size: SizeInt): Integer; cdecl; external 'uade.dll';
function uade_is_rmc_file(fname: PChar): Integer; cdecl; external 'uade.dll';
function uade_is_verbose(st: TUADEState): Integer; cdecl; external 'uade.dll';
function uade_rmc_decode(buff : pointer; sz : integer):Pointer; cdecl; external 'uade.dll';
///
function uade_get_rmc_from_state(st: PUADEState): Pointer; cdecl; external 'uade.dll';
function uade_next_subsong(st: TUADEState): Integer; cdecl; external 'uade.dll';
function uade_play(fname: PChar; subsong: Integer; st: PUADEState): Integer; cdecl; external 'uade.dll' name 'uade_play';
function uade_play_from_buffer( fname: PChar; buf: Pointer; size: SizeUInt; subsong: Integer; st: PUADEState): Integer; cdecl; external 'uade.dll';
function uade_load_amiga_file(name: PChar; playerdir: PChar; st: PUADEState): PUADEFile; cdecl; external 'uade.dll';
function uade_new_state( const uc: PUADEConfig): PUADEState; cdecl; external 'uade.dll' name 'uade_new_state';
function uade_stop(st: PUADEState): Integer; cdecl; external 'uade.dll' name 'uade_stop';
function uade_file(name : Pchar; data : Pointer; size : integer):PUADEFile; cdecl; external 'uade.dll';
function uade_file_load(fname : Pchar):PUADEFile; cdecl; external 'uade.dll';
procedure uade_file_free(fl :PUADEFile);cdecl; external 'uade.dll';
procedure uade_read_file(fsize: integer; filename:Pchar);cdecl; external 'uade.dll';
// config
procedure uade_config_set_defaults(uc: PUADEConfig); cdecl; external 'uade.dll';
function uade_convert_to_double(value: PChar; def, low, high: Double; typ: PChar): Double; cdecl; external 'uade.dll';
function uade_load_config(st: PUADEState; filename: PChar): Integer; cdecl; external 'uade.dll';
function uade_load_initial_config(st: PUADEState ; bdir: PChar): Integer; cdecl; external 'uade.dll';
function uade_load_initial_song_conf(songconfname: PChar; maxlen: SizeUInt; uc: PUADEConfig): Integer; cdecl; external 'uade.dll';
procedure uade_merge_configs(ucd: PUADEConfig; const ucs: PUADEConfig); cdecl; external 'uade.dll';
function uade_open_create_home: PChar; cdecl; external 'uade.dll';
function uade_parse_subsongs(subsongs: Integer; option: PChar): Integer; cdecl; external 'uade.dll';
procedure uade_config_set_option(uc: PUADEConfig; opt: TUADEOption; value: PChar); cdecl; external 'uade.dll';
procedure uade_set_effects(st: PUADEState); cdecl; external 'uade.dll';
procedure uade_set_ep_attributes(st: PUADEState); cdecl; external 'uade.dll';
function uade_set_song_attributes(st: PUADEState; playername: PChar; playernamelen: SizeUInt): Integer; cdecl; external 'uade.dll';
procedure uade_set_filter_type(uc: PUADEConfig; value: PChar); cdecl; external 'uade.dll';
function uade_set_song_options(sfile: PChar; sopt: PChar; state: PUADEState): Integer; cdecl; external 'uade.dll';
function uade_new_config: PUADEConfig; cdecl; external 'uade.dll' name 'uade_new_config';
//function uade_config_toggle_boolean(uc: TUADEConfig; opt: TUADEOption): Integer; cdecl; external 'uade.dll';
function uade_analyze_eagleplayer(detect_info: PUADEDetectionInfo;data: Pointer; data_size: integer; filename: PChar;filename_len: integer;st: PUADEState): Integer; cdecl; external 'uade.dll';
implementation
end.