Files
package-zearch-temp/UOS/examples/uos.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

12755 lines
460 KiB
ObjectPascal

{This unit is part of United Openlibraries of Sound (uos)
This is the main uos unit.
License : modified LGPL.3
Fred van Stappen fiens@hotmail.com }
unit uos;
{$mode objfpc}{$H+}{$inline on}
{$PACKRECORDS C}
// For custom configuration of directive to compiler ---> uos_define.inc
{$I uos_define.inc}
interface
uses
{$IF DEFINED(mse)}
msegui, msethread,
{$endif}
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
fpg_base, fpg_main,
{$endif}
{$IF DEFINED(Java)}
uos_jni,
{$endif}
{$IF DEFINED(webstream)}
uos_httpgetthread, Pipes,
{$ENDIF}
{$IF DEFINED(portaudio)}
uos_portaudio,
{$endif}
{$IF DEFINED(xmp)}
uos_libxmp,
{$endif}
{$IF DEFINED(sndfile)}
uos_LibSndFile,
{$endif}
{$IF DEFINED(mpg123)}
uos_Mpg123,
{$endif}
{$IF DEFINED(soundtouch)}
uos_soundtouch,
{$endif}
{$IF DEFINED(bs2b)}
uos_bs2b,
{$endif}
{$IF DEFINED(noiseremoval)}
uos_dsp_noiseremoval,
{$endif}
{$IF DEFINED(neaac)}
uos_aac,
{$endif}
{$IF DEFINED(fdkaac)}
uos_fdkaacdecoder,
{$endif}
{$IF DEFINED(opus)}
uos_opusfile,
{$endif}
{$IF DEFINED(shout)}
uos_shout, uos_opus,
{$endif}
{$IF DEFINED(cdrom)}
uos_cdrom,
{$endif}
Classes, DynLibs, ctypes, Math, sysutils;
const
uos_version : cint32 = 2241001;
{$IF DEFINED(bs2b)}
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);
{$endif}
{$IF DEFINED(synthesizer)}
const
// musical note ==> frequency in hertz
// Latin: Do, Ré, Mi, Fa, Sol, La, Si
// Dièse = _d example la0_d
la0 = 55.0;
la0_d = 58.3;
si0 = 61.7;
do0 = 65.4;
do0_d = 69.3;
re0 = 73.4;
re0_d = 77.8;
mi0 = 82.4;
fa0 = 87.3;
fa0_d = 92.5;
sol0 = 98.0;
sol0_d = 103.8;
la1 = 110.0;
la1_d = 116.5;
si1 = 123.5;
do1 = 130.8;
do1_d = 138.6;
re1 = 146.8;
re1_d = 155.6;
mi1 = 164.8;
fa1 = 174.6;
fa1_d = 185.0;
sol1 = 196.0;
sol1_d = 207.7;
la2 = 220.0;
la2_d = 233.1;
si2 = 2246.9;
do2 = 261.6;
do2_d = 277.2;
re2 = 293.7;
re2_d = 311.1;
mi2 = 329.6;
fa2 = 349.2;
fa2_d = 370.0;
sol2 = 392.0;
sol2_d = 415.3;
la3 = 440.0;
la3_d = 466.2;
si3 = 493.9;
do3 = 523.3;
do3_d = 554.4;
re3 = 587.3;
re3_d = 622.3;
mi3 = 659.3;
fa3 = 698.5;
fa3_d = 740.0;
sol3 = 784.0;
sol3_d = 830.6;
la4 = 880.0;
la4_d = 932.4;
si4 = 987.8;
do4 = 1046.6;
do4_d = 1108.8;
re4 = 1174.6;
re4_d = 1244.6;
mi4 = 1318.6;
fa4 = 1397.0;
fa4_d = 1480.0;
sol4 = 1568.0;
sol4_d = 1661.2;
la5 = 1760.0;
// English musique note
// A, B, C, D, E, F, G
a0 = 55.0;
a0_s = 58.3;
b0 = 61.7;
c0 = 65.4;
c0_s = 69.3;
d0 = 73.4;
d0_s = 77.8;
e0 = 82.4;
f0 = 87.3;
f0_s = 92.5;
g0 = 98.0;
g0_s = 103.8;
a1 = 110.0;
a1_s = 116.5;
b1 = 123.5;
c1 = 130.8;
c1_s = 138.6;
d1 = 146.8;
d1_s = 155.6;
e1 = 164.8;
f1 = 174.6;
f1_s = 185.0;
g1 = 196.0;
g1_s = 207.7;
a2 = 220.0;
a2_s = 233.1;
b2 = 2246.9;
c2 = 261.6;
c2_s = 277.2;
d2 = 293.7;
d2_s = 311.1;
e2 = 329.6;
f2 = 349.2;
f2_s = 370.0;
g2 = 392.0;
g2_s = 415.3;
a3 = 440.0;
a3_s = 466.2;
b3 = 493.9;
c3 = 523.3;
c3_s = 554.4;
d3 = 587.3;
d3_s = 622.3;
e3 = 659.3;
f3 = 698.5;
f3_s = 740.0;
g3 = 784.0;
g3_s = 830.6;
a4 = 880.0;
a4_s = 932.4;
b4 = 987.8;
c4 = 1046.6;
c4_s = 1108.8;
d4 = 1174.6;
d4_s = 1244.6;
e4 = 1318.6;
f4 = 1397.0;
f4_s = 1480.0;
g4 = 1568.0;
g4_s = 1661.2;
a5 = 1760.0;
{$endif}
{$IF DEFINED(shout)}
cFRAME_SIZE = 960;
cSAMPLE_RATE = 48000;
cAPPLICATION = OPUS_APPLICATION_AUDIO;
cBITRATE = 64000;
cMAX_FRAME_SIZE = 6 * 960;
cMAX_PACKET_SIZE = 3 * 1276;
{$endif}
type
TDummyThread = class(TThread)
protected
procedure execute;
override;
end;
{$IF DEFINED(mse)}
{$else}
type
TuosThread = class(TThread)
protected
procedure execute;
override;
public
theparent : Tobject;
constructor Create(CreateSuspended: boolean; AParent: TObject;
Const StackSize: SizeUInt = DefaultStackSize);
overload;
virtual;
procedure DoTerminate;
override;
end;
{$endif}
type
TDArFloat = array of cfloat;
TDArShort = array of cInt16;
TDArLong = array of cInt32;
TDArPARFloat = array of TDArFloat;
TDArIARFloat = array of TDArPARFloat;
PDArFloat = ^TDArFloat;
PDArShort = ^TDArShort;
PDArLong = ^TDArLong;
{$IF not DEFINED(windows)}
THandle = pointer;
TArray = single;
{$endif}
type
Tuos_BufferInfos = record
SampleRate: CDouble;
SampleRateRoot: CDouble;
SampleFormat: cint32;
Channels: cint32;
Filename: UTF8String;
Title: UTF8String;
Copyright: UTF8String;
Software: UTF8String;
Artist: UTF8String;
Comment: UTF8String;
Date: string;
Tag: array[0..2] of char;
Album: UTF8String;
Genre: string;
Track: string;
HDFormat: cint32;
Sections: cint32;
Encoding: cint32;
bitrate: cint32;
Length: cint32;
// length samples total
LibOpen: shortint;
Ratio: byte;
end;
type
{$if not defined(fs32bit)}
Tcount_t = cint64; { used for file sizes }
{$else}
Tcount_t = cint32;
{$endif}
type
Tuos_LoadResult = record
PAloadError: shortint;
SFloadError: shortint;
MPloadError: shortint;
PCloadError: shortint;
STloadError: shortint;
BSloadError: shortint;
AAloadError: shortint;
OPloadError: shortint;
XMloadError: shortint;
FAloadError: shortint;
PAinitError: shortint;
MPinitError: shortint;
end;
type
Tuos_Init = class(TObject)
public
evGlobalPause: PRTLEvent;
// for global pausing
constructor Create;
private
PA_FileName: pchar;
// PortAudio
SF_FileName: pchar;
// SndFile
MP_FileName: pchar;
// Mpg123
AA_FileName : PChar;
// Faad
M4_FileName : PChar;
// Mp4ff
OF_FileName : PChar;
// opusfile
XM_FileName : PChar;
// XMP
FA_FileName : PChar;
// Fdkaac
Plug_ST_FileName: pchar;
// Plugin SoundTouch + GetBMP
Plug_BS_FileName: pchar;
// Plugin bs2b
{$IF DEFINED(portaudio)}
DefDevOut: PaDeviceIndex;
DefDevOutInfo: PPaDeviceInfo;
DefDevOutAPIInfo: PPaHostApiInfo;
DefDevIn: PaDeviceIndex;
DefDevInInfo: PPaDeviceInfo;
DefDevInAPIInfo: PPaHostApiInfo;
{$endif}
function loadlib: cint32;
procedure unloadlib;
procedure unloadlibCust(PortAudio, SndFile, Mpg123, AAC, opus, xmp, fdkaac: boolean);
function InitLib: cint32;
procedure unloadPlugin(PluginName: Pchar);
end;
type
Tuos_DeviceInfos = record
DeviceNum: cint32;
DeviceName: UTF8String;
DeviceType: UTF8String;
DefaultDevIn: boolean;
DefaultDevOut: boolean;
ChannelsIn: cint32;
ChannelsOut: cint32;
SampleRate: CDouble;
LatencyHighIn: CDouble;
LatencyLowIn: CDouble;
LatencyHighOut: CDouble;
LatencyLowOut: CDouble;
HostAPIName: UTF8String;
end;
type
Tuos_WaveHeaderChunk = packed record
wFormatTag: smallint;
wChannels: word;
wSamplesPerSec: cint32;
wAvgBytesPerSec: cint32;
wBlockAlign: word;
wBitsPerSample: word;
wcbSize: word;
end;
type
Tuos_FileBuffer = record
ERROR: word;
wSamplesPerSec: cint32;
wBitsPerSample: word;
wChannels: word;
FileFormat: shortint;
Data: TFileStream;
DataMS: TMemoryStream;
end;
type
Tuos_Data = record
// Global data
Enabled: boolean;
TypePut: shortint;
// -1 : nothing.
// for Input : 0: from audio encoded file, 1: from input device (like mic),
// 2: from internet audio stream, 3: from Synthesizer, 4: from memory buffer,
// 5: from endless-muted, 6: from decoded memorystream
// for Output : 0: into wav file from filestream, 1: into output device Portaudio, 2: into stream server,
// 3: into memory buffer, 4: into wav file from memorystream, 5: into memorystream,
// 6: into ogg file from filestream, 7: into ogg memorystream
Seekable: boolean;
Status: byte;
Buffer: TDArFloat;
MemoryBuffer: TDArFloat;
MemoryStream : Tmemorystream;
posmem : longint;
{$IF DEFINED(opus)}
BufferTMP: tbytes;
{$endif}
DSPVolumeIndex : cint32;
DSPNoiseIndex : cint32;
VLeft, VRight: double;
hasfilters : boolean;
nbfilters : cint32;
incfilters : cint32;
levelfilters : string;
levelfiltersar : TDArFloat;
PositionEnable : shortint;
LevelEnable : shortint;
LevelLeft, LevelRight: cfloat;
levelArrayEnable : shortint;
{$IF DEFINED(synthesizer)}
LookupTableLeft, LookupTableRight: array [0..1023] of CFloat;
PosInTableLeft, PosInTableRight: Double;
typLsine, typRsine: cint32;
freqLsine, freqRsine: cfloat;
dursine, posdursine: cint32;
harmonic: cint32;
evenharm: shortint;
{$endif}
{$if defined(cpu64)}
Wantframes: Tcount_t;
OutFrames: Tcount_t;
{$else}
Wantframes: cint32;
OutFrames: cint32;
{$endif}
SamplerateRoot: CDouble;
SampleRate: CDouble;
SampleFormat: cint32;
Channels: cint32;
lastbuf: shortint;
// audio file data
HandleSt: pointer;
{$IF DEFINED(opus)}
HandleOP: TOpusFile;
{$endif}
Filename: UTF8String;
Title: UTF8String;
Copyright: UTF8String;
Software: UTF8String;
Artist: UTF8String;
Comment: UTF8String;
Date: string;
Tag: array[0..2] of char;
Album: UTF8String;
Genre: string;
Track: string;
HDFormat: cint32;
{$IF DEFINED(sndfile)}
Frames: Tcount_t;
{$else}
Frames: cint32;
{$endif}
Sections: cint32;
Encoding: cint32;
bitrate: cint32;
Length: cint32;
// length samples total
LibOpen: shortint;
// -1: nothing open, 0: sndfile open, 1: mpg123 open, 2: aac open, 3: cdrom, 4: opus, 5: xmp
Ratio: byte;
// if mpg123 or aac then ratio := 2
BPM : cfloat;
numbuf : integer;
Output: cint32;
{$if defined(cpu64)}
// TO CHECK
Position: cint32;
Poseek: cint32;
{$else}
Position: cint32;
Poseek: cint32;
{$endif}
end;
type
TArray01 = array[0..1] of cfloat;
Tuos_FFT = class(TObject)
public
TypeFilterL, TypeFilterR: byte;
LowFrequencyL, HighFrequencyL: cfloat;
LowFrequencyR, HighFrequencyR: cfloat;
GainL, GainR: cfloat;
// Left
a3, a32: array[0..2] of cfloat;
b2, x0, x1, y0, y1, b22, x02, x12, y02, y12: TArray01;
C, D, C2, D2 : cfloat;
// Right
a3R, a32R: array[0..2] of cfloat;
b2R, x0R, x1R, y0R, y1R, b22R, x02R, x12R, y02R, y12R: TArray01;
CR, DR, C2R, D2R : cfloat;
AlsoBuf: boolean;
VirtualBuffer: TDArFloat;
levelstring : string;
{$IF DEFINED(noiseremoval)}
FNoise : TuosNoiseRemoval;
{$endif}
constructor Create;
end;
type
TFunc = function (Var Data: Tuos_Data; Var FFT: Tuos_FFT): TDArFloat;
{$if DEFINED(java)}
TProc = JMethodID ;
{$else}
TProc = procedure of object;
{$endif}
TProcOnly = procedure ;
{$IF DEFINED(bs2b) or DEFINED(soundtouch)}
TPlugFunc = function (bufferin: TDArFloat; plugHandle: THandle; Abs2bd : Tt_bs2bdp; Var inputData:
Tuos_Data;
param1: float; param2: float; param3: float; param4: float;
param5: float; param6: float; param7: float; param8: float): TDArFloat;
{$endif}
type
Tuos_DSP = class(TObject)
public
Enabled: boolean;
BefFunc: TFunc;
// function to execute before buffer is filled
AftFunc: TFunc;
// function to execute after buffer is filled
EndFunc: TFunc;
// function to execute at end of thread;
LoopProc: TProc;
// External Procedure of object to synchronize after buffer is filled
// for FFT
fftdata: Tuos_FFT;
{$IF DEFINED(Java)}
procedure LoopProcjava;
{$endif}
constructor Create;
destructor Destroy;
override;
end;
type
Tuos_InStream = class(TObject)
{$IF DEFINED(webstream)}
private
procedure UpdateIcyMetaInterval;
{$endif}
public
Data: Tuos_Data;
DSP: array of Tuos_DSP;
MemoryStreamDec : TMemoryStream;
{$IF DEFINED(neaac)}
AACI: TAACInfo;
{$endif}
{$IF DEFINED(cdrom)}
pCD: PCDROMInfo;
{$endif}
// for web streaming
{$IF DEFINED(webstream)}
httpget: TThreadHttpGetter;
// threaded http getter
{$IF DEFINED(windows)}
{$if defined(cpu64)}
InHandle : Qword;
OutHandle: Qword;
{$else}
InHandle : longword;
OutHandle: longword;
{$ENDIF}
{$else}
InHandle : cint32;
OutHandle: cint32;
{$endif}
InPipe: TInputPipeStream;
OutPipe: TOutputPipeStream;
{$ENDIF}
{$IF DEFINED(portaudio)}
PAParam: PaStreamParameters;
{$endif}
LoopProc: TProc;
// External Procedure of object to synchronize after buffer is filled
{$IF DEFINED(Java)}
procedure LoopProcjava;
{$endif}
constructor Create;
destructor Destroy;
override;
end;
type
Tuos_OutStream = class(TObject)
public
Data: Tuos_Data;
BufferOut: PDArFloat;
MemorySteamOut: TMemoryStream;
DSP: array of Tuos_DSP;
{$IF DEFINED(portaudio)}
PAParam: PaStreamParameters;
{$endif}
{$IF DEFINED(shout)}
encoder: TOpusEncoder;
cbits: array [0..cMAX_PACKET_SIZE - 1] of Byte;
// cbits: tbytes;
{$endif}
FileBuffer: Tuos_FileBuffer;
LoopProc: TProc;
// External Procedure of object to synchronize after buffer is filled
{$IF DEFINED(Java)}
procedure LoopProcjava;
{$endif}
constructor Create;
destructor Destroy;
override;
end;
Tuos_Plugin = class(TObject)
public
Enabled: boolean;
Name: string;
PlugHandle: THandle;
{$IF DEFINED(bs2b) or DEFINED(soundtouch)}
Abs2b : Tt_bs2bdp;
PlugFunc: TPlugFunc;
{$endif}
param1: float;
param2: float;
param3: float;
param4: float;
param5: float;
param6: float;
param7: float;
param8: float;
Buffer: TDArFloat;
constructor Create;
end;
type
Tuos_Player = class(tobject)
protected
{$IF DEFINED(mse)}
thethread : tmsethread;
{$else}
thethread : TuosThread;
{$endif}
evPause: PRTLEvent;
// for pausing
procedure ReadFile(x : integer);
inline;
{$IF DEFINED(webstream)}
procedure ReadUrl(x : integer);
inline;
{$endif}
{$IF DEFINED(synthesizer)}
procedure ReadSynth(x : integer);
inline;
procedure FillLookupTable(x, typewave, channel,
AHarmonics: Integer; EvenHarmonics: shortint);
inline;
{$endif}
procedure ReadEndless(x : integer);
inline;
procedure ReadMem(x : integer);
inline;
procedure ReadMemDec(x : integer);
inline;
{$IF DEFINED(portaudio)}
procedure ReadDevice(x : integer);
inline;
{$endif}
procedure WriteOutPlug(x:integer; x2 : integer);
inline;
procedure WriteOut(x:integer; x2 : integer);
inline;
procedure CheckIfPaused ;
inline;
procedure DoBeginMethods;
inline;
procedure DoLoopBeginMethods;
inline;
procedure DoLoopEndMethods;
inline;
procedure DoArrayLevel(x: integer);
inline;
procedure DoSeek(x: integer);
inline;
procedure DoDSPinBeforeBufProc(x: integer);
inline;
procedure DoDSPinAfterBufProc(x: integer);
inline;
procedure DoDSPOutAfterBufProc(x: integer);
inline;
procedure DoMainLoopProc(x: integer);
inline;
procedure SeekIfTerminated;
inline;
procedure DoTerminateNoFreePlayer;
inline;
procedure DoTerminatePlayer;
inline;
procedure DoEndProc;
inline;
{$IF DEFINED(mse)}
function execute(thread: tmsethread): integer;
inline;
{$endif}
public
isAssigned: boolean ;
isGlobalPause: boolean ;
Status: cint32;
//if use -1 value (default) -> not alterate uosPlayers[],..
Index: cint32;
intobuf : boolean;
// to check, needed for filetobuf
NLooped : Integer;
// -1 infinite loop; 0 no loop; > 0 n-loop
NoFree : boolean;
// Do not free the player at end of thread.
BeginProc: TProc ;
// External procedure of object to execute at begin of thread
LoopBeginProc: TProc;
// External procedure of object to execute at each begin of loop
LoopEndProc: TProc;
// External procedure of object to execute at each end of loop
EndProc: TProc;
// Procedure of object to execute at end of thread
EndProcOnly: TProcOnly ;
// Procedure to execute at end of thread (not of object)
StreamIn: array of Tuos_InStream;
StreamOut: array of Tuos_OutStream;
PlugIn: array of Tuos_Plugin;
{$IF DEFINED(Java)}
PEnv : PJNIEnv;
Obj: JObject;
procedure beginprocjava;
procedure endprocjava;
procedure LoopBeginProcjava;
procedure LoopEndProcjava;
{$endif}
constructor create();
destructor Destroy;
override;
function IsLooped: Boolean;
function SetGlobalEvent(isenabled : boolean) : boolean;
// Set the RTL Events Global (will pause/start/replay all the players synchro with same rtl event))
// result : true if set ok.
// Audio methods
procedure PlayEx(no_free: Boolean; nloop: Integer; paused: boolean= false);
// Start playing with free at end as parameter and assign loop
procedure Play(nloop: Integer = 0) ;
// Start playing with loop
procedure PlayPaused(nloop: Integer = 0) ;
// Start play paused with loop
procedure RePlay();
// Resume playing after pause
procedure Stop();
// Stop playing and free thread
procedure Pause();
// Pause playing
procedure PlayNoFree(nloop: Integer = 0) ;
// Starting but do not free the player after stop with loop
procedure PlayNoFreePaused(nloop: Integer = 0) ;
// Start play paused with loop but not free player at end
procedure FreePlayer() ;
// Free the player: works only when PlayNoFree() was called.
{$IF DEFINED(portaudio)}
function AddIntoDevOut(Device: cint32; Latency: CDouble;
SampleRate: CDouble; Channels: cint32; SampleFormat: cint32 ;
FramesCount: cint32 ; ChunkCount: cint32 ): cint32;
// Add a Output into Device Output
// Device ( -1 is default device )
// Latency ( -1 is latency suggested )
// SampleRate : delault : -1 (44100)
// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (= 65536)
// ChunkCount : default : -1 (= 512)
// result : Output Index in array -1 = error
// example : OutputIndex1 := AddIntoDevOut(-1,-1,-1,-1,0,-1,-1);
{$endif}
function AddIntoFile(Filenamepath: PChar; SampleRate: CDouble;
Channels: cint32; SampleFormat: cint32 ; FramesCount: cint32 ; FileFormat
: cint32): cint32;
// Add a Output into audio wav file with custom parameters from TFileStream
// FileName : filename of saved audio wav file
// SampleRate : delault : -1 (44100)
// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
// SampleFormat : default : -1 (2:Int16) ( 1:Int32, 2:Int16)
// FramesCount : default : -1 (= 4096)
// FileFormat : default : -1 (wav) (0:wav, 1:pcm, 2:custom, 3:ogg);
// result : Output Index in array -1 = error
// example : OutputIndex1 := AddIntoFile(edit5.Text,-1,-1, 0, -1, -1);
function AddIntoFileFromMem(Filenamepath: PChar; SampleRate: CDouble;
Channels: LongInt; SampleFormat: LongInt ; FramesCount: LongInt;
FileFormat: cint32): LongInt;
// Add a Output into audio wav file with custom parameters from TMemoryStream
// FileName : filename of saved audio wav file
// SampleRate : delault : -1 (44100)
// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
// SampleFormat : default : -1 (2:Int16) ( 1:Int32, 2:Int16)
// FramesCount : default : -1 (= 4096)
// FileFormat : default : -1 (wav) (0:wav, 1:pcm, 2:custom);
// result : Output Index in array -1 = error
// example : OutputIndex1 := AddIntoFileFromBuf(edit5.Text,-1,-1, 0, -1);
function AddIntoMemoryBuffer(outmemory: PDArFloat) : cint32;
// Add a Output into memory buffer
// outmemory : pointer of buffer to use to store memory.
// example : OutputIndex1 := AddIntoMemoryBuffer(bufmemory);
function AddIntoMemoryBuffer(outmemory: PDArFloat; SampleRate: CDouble; SampleFormat:
LongInt;
Channels: LongInt; FramesCount: LongInt): LongInt;
// Add a Output into TMemoryStream
// outmemory : pointer of buffer to use to store memory.
// SampleRate : delault : -1 (44100)
// SampleFormat : default : -1 (0:float32) ( 1:Int32, 2:Int16)
// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
// FramesCount : default : -1 (= 65536)
function AddIntoMemoryStream(Var MemoryStream: TMemoryStream; SampleRate: CDouble;
SampleFormat: LongInt ; Channels: LongInt; FramesCount: LongInt;
AudioFormat: cint32): LongInt;
// Add a Output into TMemoryStream
// MemoryStream : the TMemoryStream to use to store memory.
// SampleRate : delault : -1 (44100)
// SampleFormat : default : -1 (2:Int16) ( 1:Int32, 2:Int16)
// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
// FramesCount : default : -1 (= 4096)
// AudioFormat : default : -1 (wav) (0:wav, 1:ogg);
{$IF DEFINED(shout)}
function AddIntoIceServer(SampleRate : CDouble; Channels: cint; SampleFormat: cint;
EncodeType: cint; Port: cint; Host: pchar; User: pchar; Password:
pchar; MountFile :pchar): cint32;
// Add a Output into a IceCast server for audio-web-streaming
// SampleRate : delault : -1 (48000)
// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
// SampleFormat : -1 default : float32 : (0:float32, 1:Int16)
// EncodeType : default : -1 (0:Music) (0: Music, 1:Voice)
// Port : default : -1 (= 8000)
// Host : default : 'def' (= '127.0.0.1')
// User : default : 'def' (= 'source')
// Password : default : 'def' (= 'hackme')
// MountFile : default : 'def' (= '/example.opus')
// result : Output Index in array -1 = error
{$endif}
{$IF DEFINED(portaudio)}
function AddFromDevIn(Device: cint32; Latency: CDouble;
SampleRate: CDouble; OutputIndex: cint32;
SampleFormat: cint32; FramesCount : cint32 ; ChunkCount: cint32): cint32
;
// Add a Input from Device Input with custom parameters
// Device ( -1 is default Input device )
// Latency ( -1 is latency suggested ) )
// SampleRate : delault : -1 (44100)
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (4096)
// ChunkCount : default : -1 (= 512)
// result : otherwise Output Index in array -1 = error
// example : OutputIndex1 := AddFromDevice(-1,-1,-1,-1,-1, -1);
{$endif}
function AddFromEndlessMuted(Channels : cint32; FramesCount: cint32): cint32;
// Add a input from Endless Muted dummy sine wav
// FramesCount = FramesCount of input-to-follow
// Channels = Channels of input-to-follow.
function InputGetBuffer(InputIndex: cint32): TDArFloat;
// Get current buffer
{$IF DEFINED(synthesizer)}
function AddFromSynth(Channels: integer; WaveTypeL, WaveTypeR: shortint;
FrequencyL, FrequencyR: float; VolumeL, VolumeR: float;
duration : cint32; NbHarmonics: cint32; EvenHarmonics: cint32;
OutputIndex: cint32; SampleFormat: cint32 ; SampleRate: CDouble ;
FramesCount : cint32): cint32;
// Add a input from Synthesizer with custom parameters
// Channels: default: -1 (2) (1 = mono, 2 = stereo)
// WaveTypeL: default: -1 (0) (0 = sine-wave, 1 = square-wave, 2= triangle, 3=sawtooth used for mono and stereo)
// WaveTypeR: default: -1 (0) (0 = sine-wave, 1 = square-wave, 2= triangle, , 3=sawtooth used for stereo, ignored for mono)
// FrequencyL: default: -1 (440 htz) (Left frequency, used for mono)
// FrequencyR: default: -1 (440 htz) (Right frequency, used for stereo, ignored for mono)
// VolumeL: default: -1 (= 1) (from 0 to 1) => volume left
// VolumeR: default: -1 (= 1) (from 0 to 1) => volume rigth (ignored for mono)
// Duration: default: -1 (= 1000) => duration in msec (0 = endless)
// NbHarmonics: default: -1 (= 0) Number of Harmonics
// EvenHarmonics: default: -1 (= 0) (0 = all harmonics, 1 = Only even harmonics)
// OutputIndex: Output index of used output
// -1: all output, -2: no output, other cint32 refer to
// a existing OutputIndex
// (if multi-output then OutName = name of each output separeted by ';')
// SampleFormat: default : -1 (0: Float32) (0: Float32, 1:Int32, 2:Int16)
// SampleRate: delault : -1 (44100)
// FramesCount: -1 default : 1024
// result: Input Index in array -1 = error
procedure InputSetSynth(InputIndex: cint32; WaveTypeL, WaveTypeR: shortint;
FrequencyL, FrequencyR: float; VolumeL, VolumeR: float; duration:
cint32;
NbHarmonic: cint32; EvenHarmonics: cint32; Enable: boolean);
// InputIndex: one existing input index
// WaveTypeL: do not change: -1 (0 = sine-wave 1 = square-wave, 2= triangle, 3=sawtooth used for mono and stereo)
// WaveTypeR: do not change: -1 (0 = sine-wave 1 = square-wave, 2= triangle, 3=sawtooth used for stereo, ignored for mono)
// FrequencyL: do not change: -1 (Left frequency, used for mono)
// FrequencyR: do not change: -1 (440 htz) (Right frequency, used for stereo, ignored for mono)
// VolumeL: do not change: -1 (= 1) (from 0 to 1) => volume left
// VolumeR: do not change: -1 (from 0 to 1) => volume rigth (ignored for mono)
// Duration: in msec (-1 = do not change)
// NbHarmonic: Number of Harmonics (-1 not change)
// EvenHarmonics: default: -1 (= 0) (0 = all harmonics, 1 = Only even harmonics)
// Enable: true or false ;
{$endif}
function AddFromFile(Filename: Pchar; OutputIndex: cint32;
SampleFormat: cint32 ; FramesCount: cint32): cint32;
// Add a input from audio file with custom parameters
// FileName : filename of audio file
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (4096)
// result : Input Index in array -1 = error
// example : InputIndex1 := AddFromFile(edit5.Text,-1,0,-1);
function AddFromFileIntoMemory(Filename: Pchar; OutputIndex: cint32;
SampleFormat: cint32 ; FramesCount: cint32 ; numbuf : cint):
cint32
;
// Add a input from audio file and store it into memory with custom parameters
// FileName : filename of audio file
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (4096)
// numbuf : number of buffer to add to outmemory (default : -1 = all, otherwise number max of buffers)
// result : Input Index in array -1 = error
// example : InputIndex1 := AddFromFileIntoMemory(edit5.Text,-1,0,-1, -1);
function AddFromMemoryBuffer(Var MemoryBuffer: TDArFloat; Var Bufferinfos: Tuos_bufferinfos;
OutputIndex: cint32; FramesCount: cint32): cint32;
// Add a input from memory buffer with custom parameters
// MemoryBuffer : the buffer
// Bufferinfos : infos of the buffer
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)// SampleRate : delault : -1 (44100)// FramesCount : default : -1 (4096)
// FramesCount : default : -1 (65536 div Channels)
// result : Input Index in array -1 = error
// example : InputIndex1 := AddFromMemoryBuffer(mybuffer, buffinfos,-1,1024);
function AddFromMemoryStream(Var MemoryStream: TMemoryStream;
TypeAudio: cint32; OutputIndex: cint32; SampleFormat: cint32 ;
FramesCount: cint32): cint32;
// MemoryStream : Memory stream of encoded audio.
// TypeAudio : default : -1 --> 0 (0: flac, ogg, wav; 1: mp3; 2:opus)
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (4096)
// result : Input Index in array -1 = error
// example : InputIndex1 := AddFromMemoryStream(mymemorystream,-1,-1,0,1024);
function AddFromMemoryStreamDec(Var MemoryStream: TMemoryStream; Var Bufferinfos:
Tuos_bufferinfos;
OutputIndex: cint32; FramesCount: cint32): cint32;
// MemoryStream : Memory-stream of decoded audio (like created by AddIntoMemoryStream)
// Bufferinfos : infos of the Memory-stream
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')
// FramesCount : default : -1 (4096)
// result : Input Index in array -1 = error
{$IF DEFINED(webstream)}
function AddFromURL(URL: PChar; OutputIndex: cint32;
SampleFormat: cint32 ; FramesCount: cint32 ; AudioFormat: cint32 ; ICYon:
boolean): cint32;
// Add a Input from Audio URL
// URL : URL of audio file
// OutputIndex : OutputIndex of existing Output// -1: all output, -2: no output, other cint32 : existing Output
// SampleFormat : -1 default : Int16 (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (4096)
// AudioFormat : default : -1 (mp3) (0: mp3, 1: opus)
// ICYon : ICY data on/off
// example : InputIndex := AddFromURL('http://someserver/somesound.mp3',-1,-1,-1,-1,false);
{$ENDIF}
function AddPlugin(PlugName: Pchar; SampleRate: CDouble;
Channels: cint32): cint32;
// Add a plugin , result is PluginIndex
// SampleRate : delault : -1 (44100)
// Channels : delault : -1 (2:stereo) (1:mono, 2:stereo, ...)
// 'soundtouch' 'getbpm' and 'bs2b' PlugName are registred.
{$IF DEFINED(soundtouch)}
procedure SetPluginSoundTouch(PluginIndex: cint32; Tempo: cfloat;
Pitch: cfloat; Enable: boolean);
// PluginIndex : PluginIndex Index of a existing Plugin.
procedure SetPluginGetBPM(PluginIndex: cint32; numofframes: integer; loop : boolean;
Enable: boolean);
// PluginIndex : PluginIndex Index of a existing Plugin.
// numofframes: number of frames to analyse (-1 = 512 x frames)
// loop: do new detection after previous.
{$endif}
{$IF DEFINED(bs2b)}
procedure SetPluginBs2b(PluginIndex: cint32; level: CInt32; fcut: CInt32;
feed: CInt32; Enable: boolean);
// PluginIndex : PluginIndex Index of a existing Plugin.
{$endif}
function GetStatus() : cint32 ;
// Get the status of the player : 0 => has stopped, 1 => is running, 2 => is paused,
// -1 => error or not yet played, only created.
procedure InputSeek(InputIndex: cint32; pos: Tcount_t);
// change position in sample
procedure InputSeekSeconds(InputIndex: cint32; pos: cfloat);
// change position in seconds
procedure InputSeekTime(InputIndex: cint32; pos: TTime);
// change position in time format
procedure InputSetEnable(InputIndex: cint32; enabled: boolean);
// set enable true or false
function InputLength(InputIndex: cint32): cint32;
inline;
// InputIndex : InputIndex of existing input
// result : Length of Input in samples
function InputLengthSeconds(InputIndex: cint32): cfloat;
inline;
// InputIndex : InputIndex of existing input
// result : Length of Input in seconds
function InputLengthTime(InputIndex: cint32): TTime;
inline;
// InputIndex : InputIndex of existing input
// result : Length of Input in time format
function InputPosition(InputIndex: cint32): cint32;
inline;
// InputIndex : InputIndex of existing input
// result : current postion in sample
function InputPositionSeconds(InputIndex: cint32): float;
inline;
// InputIndex : InputIndex of existing input
// result : current postion of Input in seconds
function InputPositionTime(InputIndex: cint32): TTime;
inline;
// InputIndex : InputIndex of existing input
// result : current postion of Input in time format
procedure InputSetFrameCount(InputIndex: cint32 ; framecount : cint32);
inline;
// set number of frames to be done. (usefull for recording and level precision)
procedure InputSetLevelEnable(InputIndex: cint32 ; levelcalc : cint32);
// set level calculation (default is 0)
// 0 => no calcul
// 1 => calcul before all DSP procedures.
// 2 => calcul after all DSP procedures.
// 3 => calcul before and after all DSP procedures.
procedure InputSetPositionEnable(InputIndex: cint32 ; poscalc : cint32);
// set position calculation (default is 0)
// 0 => no calcul
// 1 => calcul of position.
procedure InputSetLevelArrayEnable(InputIndex: cint32 ; levelcalc : cint32);
// set add level calculation in level-array (default is 0)
// 0 => no calcul
// 1 => calcul before all DSP procedures.
// 2 => calcul after all DSP procedures.
function InputGetLevelLeft(InputIndex: cint32): double;
inline;
// InputIndex : InputIndex of existing input
// result : left level from 0 to 1
function InputGetLevelRight(InputIndex: cint32): double;
inline;
// InputIndex : InputIndex of existing input
// result : right level from 0 to 1
function InputFiltersGetLevelString(InputIndex: cint32): string;
inline;
// InputIndex : InputIndex of existing input
// filterIndex : Filterindex of existing filter
// result : list of left|right levels separed by $ character
function InputFiltersGetLevelArray(InputIndex: cint32): TDArFloat;
inline;
// InputIndex : InputIndex of existing input
// result : array of float of each filter.
//in format levelfilter0left,levelfilter0right,levelfilter1left,levelfilter2right,...
{$IF DEFINED(soundtouch)}
function InputGetBPM(InputIndex: cint32): CDouble;
inline;
// InputIndex : InputIndex of existing input
// result : left level from 0 to 1
{$endif}
function InputUpdateTag(InputIndex: cint32): boolean;
inline;
{$IF DEFINED(webstream) and DEFINED(mpg123)}
function InputUpdateICY(InputIndex: cint32; Var icy_data : pchar): integer;
inline;
{$endif}
function InputGetTagTitle(InputIndex: cint32): pchar;
inline;
function InputGetTagArtist(InputIndex: cint32): pchar;
inline;
function InputGetTagAlbum(InputIndex: cint32): pchar;
inline;
function InputGetTagDate(InputIndex: cint32): pchar;
inline;
function InputGetTagComment(InputIndex: cint32): pchar;
inline;
function InputGetTagTrack(InputIndex: cint32): pchar;
inline;
function InputGetTagGenre(InputIndex: cint32): pchar;
inline;
function InputGetTagTag(InputIndex: cint32): pchar;
inline;
// Tag infos
function InputAddDSP(InputIndex: cint32; BeforeFunc: TFunc;
AfterFunc: TFunc; EndedFunc: TFunc; LoopProc: TProc ): cint32;
// add a DSP procedure for input
// InputIndex d: Input Index of a existing input
// BeforeFunc : function to do before the buffer is filled
// AfterFunc : function to do after the buffer is filled
// EndedFunc : function to do after thread is finish
// LoopProc : external procedure of object to synchronize after the buffer is filled
// result : index of DSPin in array (DSPinIndex)
// example : DSPinIndex1 := InputAddDSP(InputIndex1,@beforereverse,@afterreverse,nil);
procedure InputSetDSP(InputIndex: cint32; DSPinIndex: cint32; Enable: boolean);
// InputIndex : Input Index of a existing input
// DSPIndexIn : DSP Index of a existing DSP In
// Enable : DSP enabled
// example : InputSetDSP(InputIndex1,DSPinIndex1,True);
procedure OutputSetEnable(OutputIndex: cint32; enabled: boolean);
// set enable true or false
function OutputAddDSP(OutputIndex: cint32; BeforeFunc: TFunc;
AfterFunc: TFunc; EndedFunc: TFunc; LoopProc: TProc): cint32;
// usefull if multi output
// OutputIndex : OutputIndex of a existing Output
// BeforeFunc : function to do before the buffer is filled
// AfterFunc : function to do after the buffer is filled just before to give to output
// EndedFunc : function to do after thread is finish
// LoopProc : external procedure of object to synchronize after the buffer is filled
// result : index of DSPout in array
// example :DSPoutIndex1 := OutputAddDSP(OutputIndex1,@volumeproc,nil,nil);
procedure OutPutSetDSP(OutputIndex: cint32; DSPoutIndex: cint32; Enable: boolean);
// OutputIndex : OutputIndex of a existing Output
// DSPoutIndex : DSPoutIndex of existing DSPout
// Enable : DSP enabled
// example : OutPutSetDSP(OutputIndex1,DSPoutIndex1,True);
function InputAddFilter(InputIndex: cint32;
TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL: cfloat;
TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR: cfloat;
AlsoBuf: boolean; LoopProc: TProc): cint32;
// InputIndex : InputIndex of a existing Input
// TypeFilterL: Type of filter left:
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// fBandPass = 3, fLowPass = 4, fHighPass = 5)
// LowFrequencyL : Lowest frequency left( -1 : current LowFrequency )
// HighFrequencyL : Highest frequency left( -1 : current HighFrequency )
// GainL : gain left to apply to filter
// TypeFilterR: Type of filter right (ignored if mono):
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
// HighFrequencyR : Highest frequency left( -1 : current HighFrequency )
// GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
// AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
// LoopProc : external procedure of object to synchronize after DSP done
// result : index of DSPIn in array
procedure InputSetFilter(InputIndex: cint32; FilterIndex: cint32;
TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL: cfloat;
TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR: cfloat;
AlsoBuf: boolean; LoopProc: TProc; Enable: boolean);
// InputIndex : InputIndex of a existing Input
// DSPInIndex : DSPInIndex of existing DSPIn
// TypeFilterL: Type of filter left:
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// fBandPass = 3, fLowPass = 4, fHighPass = 5)
// LowFrequencyL : Lowest frequency left( -1 : current LowFrequency )
// HighFrequencyL : Highest frequency left( -1 : current HighFrequency )
// GainL : gain left to apply to filter
// TypeFilterR: Type of filter right (ignored if mono):
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
// HighFrequencyR : Highest frequency left( -1 : current HighFrequency )
// GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
// AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
// LoopProc : external procedure of object to synchronize after DSP done
// Enable : Filter enabled
function OutputAddFilter(OutputIndex: cint32;
TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL: cfloat;
TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR: cfloat;
AlsoBuf: boolean; LoopProc: TProc): cint32;
// Output : InputIndex of a existing Output
// TypeFilterL: Type of filter left:
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// fBandPass = 3, fLowPass = 4, fHighPass = 5)
// LowFrequencyL : Lowest frequency left( -1 : current LowFrequency )
// HighFrequencyL : Highest frequency left( -1 : current HighFrequency )
// GainL : gain left to apply to filter
// TypeFilterR: Type of filter right (ignored if mono):
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
// HighFrequencyR : Highest frequency left( -1 : current HighFrequency )
// GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
// AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
// LoopProc : external procedure of object to synchronize after DSP done
// result : index of DSPIn in array
procedure OutputSetFilter(OutputIndex: cint32; FilterIndex: cint32;
TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL: cfloat;
TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR: cfloat;
AlsoBuf: boolean; LoopProc: TProc; Enable: boolean);
// OuputIndex : InputIndex of a existing Output
// DSPInIndex : DSPInIndex of existing DSPIn
// TypeFilterL: Type of filter left:
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// fBandPass = 3, fLowPass = 4, fHighPass = 5)
// LowFrequencyL : Lowest frequency left( -1 : current LowFrequency )
// HighFrequencyL : Highest frequency left( -1 : current HighFrequency )
// GainL : gain left to apply to filter
// TypeFilterR: Type of filter right (ignored if mono):
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
// HighFrequencyR : Highest frequency left( -1 : current HighFrequency )
// GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
// AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
// LoopProc : external procedure of object to synchronize after DSP done
// Enable : Filter enabled
function DSPLevel(Data: Tuos_Data): Tuos_Data;
inline;
// to get level of buffer (volume)
function InputAddDSP1ChanTo2Chan(InputIndex: cint32): cint32;
// Convert mono 1 channel input to stereo 2 channels input.
// Works only if the input is mono 1 channel othewise stereo 2 chan is keeped.
// InputIndex : InputIndex of a existing Input
// result : index of DSPIn in array
// example DSPIndex1 := InputAddDSP1ChanTo2Chan(InputIndex1);
function InputAddDSPVolume(InputIndex: cint32; VolLeft: double;
VolRight: double): cint32;
// DSP Volume changer
// InputIndex : InputIndex of a existing Input
// VolLeft : Left volume
// VolRight : Right volume
// result : index of DSPIn in array
// example DSPIndex1 := InputAddDSPVolume(InputIndex1,1,1);
function OutputAddDSPVolume(OutputIndex: cint32; VolLeft: double;
VolRight: double): cint32;
// DSP Volume changer
// OutputIndex : OutputIndex of a existing Output
// VolLeft : Left volume
// VolRight : Right volume
// result : otherwise index of DSPIn in array
// example DSPIndex1 := OutputAddDSPVolume(InputIndex1,1,1);
{$IF DEFINED(noiseremoval)}
function InputAddDSPNoiseRemoval(InputIndex: cint32): cint32;
// DSP Noise Removal
// InputIndex : InputIndex of a existing Input
// result : otherwise index of DSPIn in array
// example DSPIndex1 := InputAddDSPNoiseRemoval(InputIndex1);
procedure InputSetDSPNoiseRemoval(InputIndex: cint32; Enable: boolean);
function OutputAddDSPNoiseRemoval(OutputIndex: cint32): cint32;
// DSP Noise Removal
// InputIndex : OutputIndex of a existing Output
// result : otherwise index of DSPOut in array
// example DSPIndex1 := OutputAddDSPNoiseRemoval(OutputIndex1);
procedure OutputSetDSPNoiseRemoval(OutputIndex: cint32; Enable: boolean);
{$endif}
procedure InputSetDSPVolume(InputIndex: cint32; DSPVolIndex: cint32;
VolLeft: double; VolRight: double; Enable: boolean);
inline;
// InputIndex : InputIndex of a existing Input
// DSPIndex : DSPIndex of a existing DSP
// VolLeft : Left volume
// VolRight : Right volume
// Enable : Enabled
// example InputSetDSPVolume(InputIndex1,DSPIndex1,1,0.8,True);
procedure OutputSetDSPVolume(OutputIndex: cint32; DSPVolIndex: cint32;
VolLeft: double; VolRight: double; Enable: boolean);
inline;
// OutputIndex : OutputIndex of a existing Output
// DSPIndex : DSPIndex of a existing DSP
// VolLeft : Left volume
// VolRight : Right volume
// Enable : Enabled
// example OutputSetDSPVolume(InputIndex1,DSPIndex1,1,0.8,True);
end;
// General public procedure/function (accessible for library uos too)
function uos_GetInfoLibraries() : Pansichar ;
{$IF DEFINED(portaudio)}
procedure uos_UpdateDevice();
procedure uos_GetInfoDevice();
function uos_GetInfoDeviceStr() : Pansichar ;
{$endif}
function uos_loadlib(PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName, FaadFileName
, opusfileFileName, XMPFileName, fdkaacFilename : PChar) : cint32;
// load libraries... if libraryfilename = '' => do not load it... You may load what and when you want...
// PortAudio => needed for dealing with audio-device
// SndFile => needed for dealing with ogg, vorbis, flac and wav audio-files
// Mpg123 => needed for dealing with mp* audio-files
// Mp4ff and Faad => needed for dealing with acc, m4a audio-files
// opusfile => needed for dealing with opus audio-files
// XMP => needed for dealing with MOD audio-files
// Fdkaac => needed for webstreaming of aac files.
// If you want to load libraries from system, replace it by "'system'"
// If some libraries are not needed, replace it by "nil",
// for example : uos_loadlib('system', SndFileFileName, 'system', nil, nil, nil, OpusFileFileName, nil, nil)
function uos_loadlib(PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName, FaadFileName
, opusfileFileName, XMPFileName : PChar) : cint32;
// The same but without fdkaac. (for compatibility with previous version)
function uos_loadlib(PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName, FaadFileName
, opusfileFileName : PChar) : cint32;
// The same but without libxmp and fdkaac. (for compatibility with previous version)
procedure uos_unloadlib();
// Unload all libraries... Do not forget to call it before close application...
{$IF DEFINED(shout)}
function uos_LoadServerLib(ShoutFileName, OpusFileName : PChar) : cint32;
// Shout => needed for dealing with IceCast server
// Opus => needed for dealing with encoding opus stream
procedure uos_unloadServerLib();
// Unload server libraries... Do not forget to call it before close application...
{$endif}
procedure uos_unloadlibCust(PortAudio, SndFile, Mpg123, AAC, opus, xmp, fdkaac: boolean);
// Custom Unload libraries... if true, then unload the library. You may unload what and when you want...
function uos_loadPlugin(PluginName, PluginFilename: PChar) : cint32;
// load plugin...
{$IF DEFINED(soundtouch)}
function uos_GetBPM(TheBuffer: TDArFloat; Channels: cint32; SampleRate: CDouble) : CDouble;
inline;
// From SoundTouch plugin
{$endif}
procedure uos_unloadPlugin(PluginName: PChar);
// Unload Plugin...
procedure uos_Free();
// To call at end of application.
// If uos_flat.pas was used, it will free all the uos_player created.
function uos_GetVersion() : cint32 ;
inline;
// version of uos
function uos_File2Buffer(Filename: Pchar; SampleFormat: cint32 ; Var bufferinfos: Tuos_BufferInfos ;
frompos : cint; numbuf : cint ): TDArFloat;
// Create a memory buffer of a audio file.
// FileName : filename of audio file
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// bufferinfos : the infos of the buffer.
// frompos : from position (default : -1 = from begining, otherwise position in song)
// numbuf : number of frames to add to outmemory (default : -1 = all, otherwise number max of frames)
// result : The memory buffer
// example : buffmem := uos_File2buffer(edit5.Text,0,buffmem, buffinfos, -1, -1);
function uos_Stream2Buffer(AudioFile: TMemoryStream; SampleFormat: int32 ; Var outmemory: TDArFloat;
Var bufferinfos: Tuos_BufferInfos ; frompos : cint; numbuf : cint):
TDArFloat
;
// Create a memory buffer of a audio file.
// FileName : filename of audio file
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// Outmemory : the buffer to store data.
// bufferinfos : the infos of the buffer.
// frompos : from position (default : -1 = from begining, otherwise position in song)
// numbuf : number of buffer to add to outmemory (default : -1 = all, otherwise number max of buffers)
// result : The memory buffer
// example : buffmem := uos__Stream2Buffer(edit5.Text,0,buffmem, buffinfos, -1, -1);
procedure uos_File2File(FilenameIN: Pchar; FilenameOUT: Pchar; SampleFormat: cint32 ; typeout:
cint32 );
// Create a audio file from a audio file.
// FileNameIN : filename of audio file IN (ogg, flac, wav, mp3, opus, aac,...)
// FileNameOUT : filename of audio file OUT (wav, pcm, custom)
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// typeout : Type of out file (-1:default=wav, 0:wav, 1:pcm, 2:custom)
// example : InputIndex1 := uos_File2File(edit5.Text,0,buffmem);
procedure uos_MemStream2Wavfile(FileName: UTF8String; Data: TMemoryStream; BitsPerSample, chan:
integer;
samplerate : CDouble);
// Create a audio wav file from a TMemoryStream.
// FileName : filename of wav saved file
// data : the memorystream
// BitsPerSample : 16 or 32 (bit)
// chan : number of channels
// samplerate : sample rate
function CvInt16ToFloat32(Inbuf: TDArFloat): TDArFloat;
inline;
// convert buffer int16 into float32.
procedure uos_CustBufferInfos(Var bufferinfos: Tuos_BufferInfos; SampleRate: CDouble; SampleFormat
: cint32; Channels: cint32 ; Length: cint32);
inline;
// to initialize a custom bufferinfos: needed for AddFromMemoryBuffer() if no bufferinfos was created.
// all infos refer to the buffer used ---> length = length of the buffer div channels.
function uos_TestLoadLibrary(Filename: Pchar): boolean; inline;
// test a library to check if it can be loaded;
const
// error
noError = 0;
FilePAError = 10;
LoadPAError = 11;
FileSFError = 20;
LoadSFError = 21;
FileMPError = 30;
LoadMPError = 31;
LoadOPError = 41;
FileOPError = 50;
// uos Audio
Stereo = 2;
Mono = 1;
{$IF DEFINED(android)}
DefRate = 48000;
{$else}
DefRate = 44100;
{$endif}
// Write wav file
ReadError = 1;
HeaderError = 2;
DataError = 3;
FileCorrupt = 4;
IncorectFileFormat = 5;
HeaderWriteError = 6;
StreamError = 7;
// FFT Filters
fBandAll = 0;
fBandSelect = 1;
fBandReject = 2;
fBandPass = 3;
fLowPass = 4;
fHighPass = 5;
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
MSG_CUSTOM1 = FPGM_USER + 1;
{$endif}
var
theinc : integer = 0;
theincbpm : integer = 0;
tempload : boolean = false;
paversion : UTF8String = '';
sfversion : UTF8String = '';
mpversion : UTF8String = '';
tempSamplerate : CDouble;
tempSampleFormat, tempchan, tempratio, tempLibOpen, tempLength : cint32;
tempoutmemory: TDArFloat;
uosPlayers: array of Tuos_Player;
uosPlayersStat : array of cint32;
uosLevelArray : TDArIARFloat ;
uosDeviceInfos: array of Tuos_DeviceInfos;
uosLoadResult: Tuos_LoadResult;
uosDeviceCount: cint32 = 0;
uosDefaultDeviceIn: cint32 = -1;
uosDefaultDeviceOut: cint32 = -1;
uosInit: Tuos_Init = nil;
uosisactif : boolean = true;
{$IF DEFINED(windows)}
old8087cw: word;
{$endif}
{$IF DEFINED(Java)}
theclass : JClass;
{$endif}
implementation
function uos_TestLoadLibrary(Filename: Pchar): boolean;
// test a library to check if it can be loaded;
var
test_Handle: TLibHandle = NilHandle;
begin
result := false;
test_Handle := DynLibs.SafeLoadLibrary(Filename);
if test_Handle <> DynLibs.NilHandle then
begin
DynLibs.UnloadLibrary(test_Handle);
test_Handle := DynLibs.NilHandle;
result := true;
end;
end;
procedure TDummyThread.Execute;
begin
FreeOnTerminate := True;
Terminate;
end;
function RoundMath(aV:double): int64;
overload;
begin
if aV>=0 then
result := Trunc(aV+0.5)
else
result := Trunc(aV-0.5);
end;
function RoundMath(aV:single): int64;
overload;
begin
if aV>=0 then
result := Trunc(aV+0.5)
else
result := Trunc(aV-0.5);
end;
function FormatBuf(Inbuf: TDArFloat; format: cint32): TDArFloat;
inline;
var
x: cint32;
ps: PDArShort;
// if input is Int16 format
pl: PDArLong;
// if input is Int32 format
pf: PDArFloat;
// if input is Float32 format
begin
case format of
2:
begin
ps := @inbuf;
for x := 0 to high(inbuf) do
ps^[x] := cint16(trunc(ps^[x]));
end;
1:
begin
pl := @inbuf;
for x := 0 to high(inbuf) do
pl^[x] := cint32(trunc(pl^[x]));
end;
0:
begin
pf := @inbuf;
for x := 0 to high(inbuf) do
pf^[x] := cfloat(pf^[x]);
end;
end;
Result := Inbuf;
end;
function CvFloat32ToInt16(Inbuf: TDArFloat): TDArShort;
inline;
var
x, i: cint32;
arsh: TDArShort;
begin
SetLength(arsh, length(inbuf));
for x := 0 to high(Inbuf) do
begin
i := trunc(Inbuf[x] * 32768);
if i > 32767 then
i := 32767
else
if i < -32768 then
i := -32768;
arsh[x] := i;
end;
Result := arsh;
end;
function CvFloat32ToInt32(Inbuf: TDArFloat): TDArLong;
inline;
var
i: int64;
x : cint32;
arlo: TDArLong;
begin
SetLength(arlo, length(inbuf));
for x := 0 to high(Inbuf) do
begin
i := trunc(Inbuf[x] * 2147483647);
if i > 2147483647 then
i := 2147483647
else
if i < -2147483648 then
i := -2147483648;
arlo[x] := i;
end;
Result := arlo;
end;
function CvFloat32ToInt32fl(Inbuf: TDArFloat; nb:integer): TDArFloat;
inline;
var
x : cint32;
pl2: PDArLong;
// if input is Int32 format
pf: PDArfloat;
buffer2 : TDArFloat;
begin
pf := @Inbuf;
pl2 := @Buffer2;
setlength(buffer2,nb);
for x := 0 to nb -1 do
begin
pl2^[x] := trunc((pf^[x]) * 2147483647);
end;
Result := buffer2;
end;
function CvInt16ToFloat32(Inbuf: TDArFloat): TDArFloat;
inline;
var
x: cint32;
arfl: TDArFloat;
ps: PDArShort;
begin
setlength(arfl,length(Inbuf));
ps := @inbuf;
for x := 0 to high(Inbuf) do
arfl[x] := ps^[x] / 32768;
Result := arfl;
end;
function CvSteroToMono(Inbuf: TDArFloat; len : cint32): TDArFloat;
inline;
var
x, y: cint32;
arsh: TDArFloat;
begin
if len > 0 then
begin
setlength(arsh, len);
x := 0;
y := 0;
while x < (len * 2)-1 do
begin
// TODO -> this takes only chan1, not (chan1+chan2)/2 -> it get bad noise dont know why ???...
// arsh[y] := trunc((Inbuf[x] + Inbuf[x+1])/ 2) ;
arsh[y] := Inbuf[x+1] ;
inc(y);
x := x + 2 ;
end;
Result := arsh;
end
else Result := Inbuf;
end;
function CvInt32ToFloat32(Inbuf: TDArFloat): TDArFloat;
inline;
var
x: cint32;
arfl: TDArFloat;
pl: PDArLong;
begin
setlength(arfl,length(Inbuf));
pl := @inbuf;
for x := 0 to high(Inbuf) do
arfl[x] := pl^[x] / 2147483647;
Result := arfl;
end;
// convert a Tmemory stream into a wav file.
procedure uos_MemStream2Wavfile(FileName: UTF8String; Data: TMemoryStream; BitsPerSample, chan:
integer;
samplerate : CDouble);
var
f: TFileStream;
wFileSize: LongInt;
wChunkSize: LongInt;
ID: array[0..3] of char;
Header: Tuos_WaveHeaderChunk;
begin
f := Nil;
f := TFileStream.Create(FileName, fmCreate);
f.Seek(0, soFromBeginning);
try
ID := 'RIFF';
f.WriteBuffer(ID, 4);
wFileSize := 0;
f.WriteBuffer(wFileSize, 4);
ID := 'WAVE';
f.WriteBuffer(ID, 4);
ID := 'fmt ';
f.WriteBuffer(ID, 4);
wChunkSize := SizeOf(Header);
f.WriteBuffer(wChunkSize, 4);
Header.wFormatTag := 1;
Header.wChannels := chan;
Header.wSamplesPerSec := roundmath(samplerate);
Header.wBitsPerSample := BitsPerSample;
Header.wBlockAlign := chan * (BitsPerSample Div 8);
Header.wAvgBytesPerSec := roundmath(samplerate) * Header.wBlockAlign;
Header.wcbSize := 0;
f.WriteBuffer(Header, SizeOf(Header));
except
end;
try
ID := 'data';
f.WriteBuffer(ID, 4);
wChunkSize := Data.Size;
f.WriteBuffer(wChunkSize, 4);
except
end;
Data.Seek(0, soFromBeginning);
f.CopyFrom(Data, Data.Size);
f.Seek(SizeOf(ID), soFromBeginning);
wFileSize := f.Size - SizeOf(ID) - SizeOf(wFileSize);
f.write(wFileSize, 4);
f.Free;
end;
function WriteWaveFromMem(FileName: UTF8String; Data: Tuos_FileBuffer): word;
var
f: TFileStream;
wFileSize: LongInt;
wChunkSize: LongInt;
ID: array[0..3] of char;
Header: Tuos_WaveHeaderChunk;
begin
Result := noError;
f := Nil;
f := TFileStream.Create(FileName, fmCreate);
f.Seek(0, soFromBeginning);
if Data.FileFormat = 0 then
begin
// wav file
try
ID := 'RIFF';
f.WriteBuffer(ID, 4);
wFileSize := 0;
f.WriteBuffer(wFileSize, 4);
ID := 'WAVE';
f.WriteBuffer(ID, 4);
ID := 'fmt ';
f.WriteBuffer(ID, 4);
wChunkSize := SizeOf(Header);
f.WriteBuffer(wChunkSize, 4);
Header.wFormatTag := 1;
Header.wChannels := Data.wChannels;
Header.wSamplesPerSec := Data.wSamplesPerSec;
Header.wBlockAlign := Data.wChannels * (Data.wBitsPerSample Div 8);
Header.wAvgBytesPerSec := Data.wSamplesPerSec * Header.wBlockAlign;
Header.wBitsPerSample := Data.wBitsPerSample;
Header.wcbSize := 0;
f.WriteBuffer(Header, SizeOf(Header));
except
Result := HeaderWriteError;
end;
try
ID := 'data';
f.WriteBuffer(ID, 4);
wChunkSize := Data.DataMS.Size;
f.WriteBuffer(wChunkSize, 4);
except
Result := StreamError;
end;
end;
Data.DataMS.Seek(0, soFromBeginning);
f.CopyFrom(Data.DataMS, Data.DataMS.Size);
f.Seek(SizeOf(ID), soFromBeginning);
wFileSize := f.Size - SizeOf(ID) - SizeOf(wFileSize);
f.write(wFileSize, 4);
f.Free;
end;
procedure WriteWave(FileName: UTF8String; Data: Tuos_FileBuffer);
var
wFileSize: cint32;
ID: array[0..3] of char;
begin
Data.data.Position := 42;
//(after 'data')
Data.data.write(Data.data.Size, 4);
ID := 'RIFF';
Data.data.Seek(SizeOf(ID), soFromBeginning);
wFileSize := Data.data.Size - SizeOf(ID) - SizeOf(wFileSize);
Data.data.write(wFileSize, 4);
Data.data.Free;
end;
{$IF DEFINED(sndfile) or DEFINED(mpg123)}
function mpg_read_stream(ahandle: Pointer; AData: Pointer; ACount: Integer): Integer;
inline;
cdecl;
var
Stream: TStream absolute ahandle;
begin
Result := Stream.Read(AData^, ACount);
end;
function mpg_seek_stream(ahandle: Pointer; offset: Integer;
whence: Integer): Integer;
cdecl;
var
Stream: TStream absolute ahandle;
begin
try
case whence of
SEEK_SET : Result := Stream.Seek(offset, soFromBeginning);
SEEK_CUR : Result := Stream.Seek(offset, soFromCurrent);
SEEK_END : Result := Stream.Seek(offset, soFromEnd);
else
Result := 0;
end;
except
Result := 0;
end;
end;
procedure mpg_close_stream(ahandle: Pointer);
// not used, uos does it...
begin
TObject(ahandle).Free;
end;
{$endif}
{$IF DEFINED(webstream)}
// should use this for pipes vs memorystream ?
function mpg_seek_url(ahandle: Pointer; aoffset: Integer): Integer;
cdecl;
var
Stream: TStream absolute ahandle;
begin
// pipe streams are not seekable but memory and filestreams are
Result := 0;
try
if aoffset > 0 then
Result := Stream.Seek(aoffset, soFromCurrent);
except
Result := 0;
end;
end;
{$endif}
function Filetobuffer(Filename: Pchar; OutputIndex: cint32;
SampleFormat: cint32 ; FramesCount: cint32; Var outmemory: TDArFloat;
Var bufferinfos: Tuos_BufferInfos; frompos: cint; numbuf : cint ): TDArFloat;
// Add a input from audio file with custom parameters
// FileName : filename of audio file
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (4096)
// Outmemory : the buffer to store data.
// bufferinfos : the infos of the buffer
// frompos : from position (default : -1 = from begining, otherwise position in song)
// numbuf : number of buffer to add to outmemory (default : -1 = all, otherwise number max of buffers)
// result : Input Index in array -1 = error
// example : InputIndex1 := Filetobuffer(edit5.Text,-1,0,-1, buffmem, buffinfos, -1);
var
theplayer : Tuos_Player;
in1 : cint32;
begin
theplayer := Tuos_Player.Create();
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('begin Filetobuffer');
{$endif}
In1 := theplayer.AddFromFile( pchar(Filename), OutputIndex, SampleFormat, FramesCount) ;
if in1 > -1 then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('in1 = ' + inttostr(in1));
writeln('theplayer.InputLength(In1) = ' + inttostr(theplayer.InputLength(In1)));
{$endif}
SetLength(outmemory, 0);
tempchan := theplayer.StreamIn[in1].Data.Channels;
tempratio := theplayer.StreamIn[in1].Data.ratio;
tempSampleFormat := theplayer.StreamIn[in1].Data.SampleFormat;
tempSamplerate := theplayer.StreamIn[in1].Data.Samplerate;
templength := theplayer.StreamIn[in1].Data.Length;
bufferinfos.SampleRate := theplayer.StreamIn[in1].Data.Samplerate;
bufferinfos.SampleRateRoot := theplayer.StreamIn[in1].Data.Samplerate;
bufferinfos.SampleFormat := theplayer.StreamIn[in1].Data.SampleFormat;
bufferinfos.Channels := theplayer.StreamIn[in1].Data.Channels;
bufferinfos.Filename := theplayer.StreamIn[in1].Data.Filename;
bufferinfos.Title := theplayer.StreamIn[in1].Data.Title;
bufferinfos.Copyright := theplayer.StreamIn[in1].Data.Copyright;
bufferinfos.Software := theplayer.StreamIn[in1].Data.Software;
bufferinfos.Artist := theplayer.StreamIn[in1].Data.Artist;
bufferinfos.Comment := theplayer.StreamIn[in1].Data.Comment;
bufferinfos.Date := theplayer.StreamIn[in1].Data.Date;
bufferinfos.Tag := theplayer.StreamIn[in1].Data.Tag;
bufferinfos.Album := theplayer.StreamIn[in1].Data.Album;
bufferinfos.Genre := theplayer.StreamIn[in1].Data.Genre;
bufferinfos.Track := theplayer.StreamIn[in1].Data.Track;
bufferinfos.HDFormat := theplayer.StreamIn[in1].Data.HDFormat;
bufferinfos.Sections := theplayer.StreamIn[in1].Data.Sections;
bufferinfos.Encoding := theplayer.StreamIn[in1].Data.Encoding;
bufferinfos.bitrate := theplayer.StreamIn[in1].Data.bitrate;
bufferinfos.Length := theplayer.StreamIn[in1].Data.Length;
bufferinfos.LibOpen := 0;
bufferinfos.Ratio := 2 ;
theplayer.StreamIn[in1].Data.numbuf := numbuf;
theplayer.AddIntoMemoryBuffer( @outmemory );
theplayer.Play(0);
if frompos > 0 then theplayer.inputseek(in1,frompos);
while (theplayer.getstatus > 0) do
sleep(100);
end;
{$IF DEFINED(mse)}
theplayer.destroy;
{$endif}
result := outmemory;
end;
{$IF DEFINED(soundtouch)}
function uos_GetBPM(TheBuffer: TDArFloat; Channels: cint32; SampleRate: CDouble) : CDouble;
inline;
// From SoundTouch plugin
var
BPMhandle : THandle;
sr, ch : cint32;
begin
if SampleRate = -1 then sr := 44100
else sr := roundmath(SampleRate);
if Channels = -1 then ch := 2
else ch := Channels;
BPMhandle := bpm_createInstance(ch,sr);
bpm_putSamples(BPMhandle, pcfloat(thebuffer), length(thebuffer) div Channels);
result := bpm_getBpm(BPMhandle);
bpm_destroyInstance(BPMhandle);
end;
{$endif}
function uos_File2Buffer(Filename: Pchar; SampleFormat: cint32 ; Var bufferinfos: Tuos_BufferInfos ;
frompos : cint; numbuf : cint ): TDArFloat;
// Create a memory buffer of a audio file.
// FileName : filename of audio file
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// bufferinfos : the infos of the buffer.
// frompos : from position (default : -1 = from begining, otherwise position in song)
// numbuf : number of frames to add to outmemory (default : -1 = all, otherwise number max of frames)
// result : The memory buffer
// example : buffmem := uos_File2buffer(edit5.Text,0,buffmem, buffinfos, -1, -1);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
var
i : integer;
st : string;
{$endif}
begin
result := Filetobuffer(Filename,-1, SampleFormat, 1024, result, bufferinfos, frompos, numbuf);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('After Filetobuffer');
writeln('length(result) =' +inttostr(length(result)));
st := '';
for i := 0 to length(result) -1 do
st := st + '|' + inttostr(i) + '=' + floattostr(result[i]);
WriteLn('OUTPUT DATA into portaudio------------------------------');
WriteLn(st);
{$endif}
end;
function Streamtobuffer(AudioFile:TMemoryStream; OutputIndex: cint32;SampleFormat: cint32 ;
FramesCount: cint32;
Var outmemory: TDArFloat; Var bufferinfos: Tuos_BufferInfos; frompos: cint;
numbuf : cint): TDArFloat;
// Add a input from audio file with custom parameters
// FileName : filename of audio file
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (4096)
// Outmemory : the buffer to store data.
// bufferinfos : the infos of the buffer
// frompos : from position (default : -1 = from begining, otherwise position in song)
// numbuf : number of buffer to add to outmemory (default : -1 = all, otherwise number max of buffers)
// result : Input Index in array -1 = error
// example : InputIndex1 := streamtobuffer(edit5.Text,-1,0,-1, buffmem, buffinfos, -1);
var
theplayer : Tuos_Player;
in1 : cint32;
begin
theplayer := Tuos_Player.Create();
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('begin Filetobuffer');
{$endif}
//In1 := theplayer.AddFromFile( pchar(Filename), OutputIndex, SampleFormat, FramesCount) ;
In1 := theplayer.AddFromMemoryStream( AudioFile,-1, OutputIndex, SampleFormat, FramesCount) ;
if in1 > -1 then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('in1 = ' + inttostr(in1));
writeln('theplayer.InputLength(In1) = ' + inttostr(theplayer.InputLength(In1)));
{$endif}
SetLength(outmemory, 0);
tempchan := theplayer.StreamIn[in1].Data.Channels;
tempratio := theplayer.StreamIn[in1].Data.ratio;
tempSampleFormat := theplayer.StreamIn[in1].Data.SampleFormat;
tempSamplerate := theplayer.StreamIn[in1].Data.Samplerate;
templength := theplayer.StreamIn[in1].Data.Length;
bufferinfos.SampleRate := theplayer.StreamIn[in1].Data.Samplerate;
bufferinfos.SampleRateRoot := theplayer.StreamIn[in1].Data.Samplerate;
bufferinfos.SampleFormat := theplayer.StreamIn[in1].Data.SampleFormat;
bufferinfos.Channels := theplayer.StreamIn[in1].Data.Channels;
bufferinfos.Filename := theplayer.StreamIn[in1].Data.Filename;
bufferinfos.Title := theplayer.StreamIn[in1].Data.Title;
bufferinfos.Copyright := theplayer.StreamIn[in1].Data.Copyright;
bufferinfos.Software := theplayer.StreamIn[in1].Data.Software;
bufferinfos.Artist := theplayer.StreamIn[in1].Data.Artist;
bufferinfos.Comment := theplayer.StreamIn[in1].Data.Comment;
bufferinfos.Date := theplayer.StreamIn[in1].Data.Date;
bufferinfos.Tag := theplayer.StreamIn[in1].Data.Tag;
bufferinfos.Album := theplayer.StreamIn[in1].Data.Album;
bufferinfos.Track := theplayer.StreamIn[in1].Data.Track;
bufferinfos.Genre := theplayer.StreamIn[in1].Data.Genre;
bufferinfos.HDFormat := theplayer.StreamIn[in1].Data.HDFormat;
bufferinfos.Sections := theplayer.StreamIn[in1].Data.Sections;
bufferinfos.Encoding := theplayer.StreamIn[in1].Data.Encoding;
bufferinfos.bitrate := theplayer.StreamIn[in1].Data.bitrate;
bufferinfos.Length := theplayer.StreamIn[in1].Data.Length;
bufferinfos.LibOpen := 0;
bufferinfos.Ratio := 2 ;
theplayer.StreamIn[in1].Data.numbuf := numbuf;
theplayer.AddIntoMemoryBuffer( @outmemory );
theplayer.Play(0);
if frompos > 0 then theplayer.inputseek(in1,frompos);
while (theplayer.getstatus > 0) do
sleep(100);
end;
{$IF DEFINED(mse)}
theplayer.destroy;
{$endif}
result := outmemory;
end;
function uos_Stream2Buffer(AudioFile: TMemoryStream; SampleFormat: int32 ;
Var outmemory: TDArFloat; Var bufferinfos: Tuos_BufferInfos ; frompos:
cint; numbuf : cint): TDArFloat;
// Create a memory buffer of a audio file.
// FileName : filename of audio file
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// Outmemory : the buffer to store data.
// bufferinfos : the infos of the buffer.
// frompos : from position (default : -1 = from begining, otherwise position in song)
// numbuf : number of buffer to add to outmemory (default : -1 = all, otherwise number max of buffers)
// result : The memory buffer
// example : buffmem := uos_File2buffer(edit5.Text,0,buffmem, buffinfos, -1);
begin
result := Streamtobuffer(AudioFile,-1, SampleFormat, -1, outmemory, bufferinfos, frompos, numbuf);
end;
procedure uos_File2File(FilenameIN: Pchar; FilenameOUT: Pchar; SampleFormat: cint32 ; typeout:
cint32 );
// Create a audio file from a audio file.
// FileNameIN : filename of audio file IN (ogg, flac, wav, mp3, opus, aac,...)
// FileNameOUT : filename of audio file OUT (wav, pcm, custom)
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// typeout : Type of out file (-1:default=wav, 0:wav, 1:pcm, 2:custom)// example : InputIndex1 := uos_File2File(edit5.Text,0,buffmem);
var
theplayer : Tuos_Player;
in1 : cint32;
begin
theplayer := Tuos_Player.Create();
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('begin File2file');
{$endif}
In1 := theplayer.AddFromFile( pchar(FilenameIN), -1, SampleFormat, -1) ;
if in1 > -1 then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('in1 = ' + inttostr(in1));
writeln('theplayer.InputLength(In1) = ' + inttostr(theplayer.InputLength(In1)));
{$endif}
theplayer.AddIntoFile(FilenameOUT, theplayer.StreamIn[0].data.samplerate,
theplayer.StreamIn[0].data.channels, SampleFormat, -1 , typeout);
theplayer.Play(0);
while (theplayer.getstatus > 0) do
sleep(100);
end;
{$IF DEFINED(mse)}
theplayer.destroy;
{$endif}
end;
{$IF DEFINED(mse)}
{$else}
constructor TuosThread.Create(CreateSuspended: boolean; AParent: TObject;
Const StackSize: SizeUInt);
begin
theparent := AParent;
FreeOnTerminate := true;
inherited Create(CreateSuspended, StackSize);
Priority := tpTimeCritical;
end;
{$endif}
function Tuos_Player.GetStatus() : cint32 ;
// Get the status of the player : -1 => error or not yet played, 0 => has stopped, 1 => is running, 2 => is paused.
begin
result := -1 ;
if (isAssigned = True) then result := Status
else result := -1 ;
end;
function Tuos_Player.IsLooped: Boolean;
inline;
begin
Result := (NLooped <> 0) And
(NLooped <> 1);
end;
procedure Tuos_Player.PlayEx(no_free: Boolean; nloop: Integer; paused: boolean= false);
var
x: cint32;
begin
if (isAssigned = True) and (not IsLooped) then
begin
NLooped := nloop;
NoFree := no_free;
{$IF DEFINED(portaudio)}
for x := 0 to high(StreamOut) do
if StreamOut[x].Data.HandleSt <> nil then
Pa_StartStream(StreamOut[x].Data.HandleSt);
{$endif}
for x := 0 to high(StreamIn) do
begin
{$IF DEFINED(portaudio)}
if (StreamIn[x].Data.HandleSt <> nil) and (StreamIn[x].Data.TypePut = 1) then
Pa_StartStream(StreamIn[x].Data.HandleSt);
{$endif}
if (no_free = true) and (StreamIn[x].Data.HandleSt <> nil)
and (StreamIn[x].Data.TypePut = 4) then
StreamIn[x].Data.posmem := 0;
if (no_free = true) and (StreamIn[x].Data.HandleSt <> nil)
and ((StreamIn[x].Data.TypePut = 0) or (StreamIn[x].Data.TypePut = 4)) then
InputSeek(x, 0);
StreamIn[x].Data.status := 1 ;
end;
Status := 1;
if isGlobalPause = true then
RTLeventSetEvent(uosInit.evGlobalPause)
else
RTLeventSetEvent(evPause);
if paused = true then
begin
if isGlobalPause = true then
RTLeventReSetEvent(uosInit.evGlobalPause)
else
RTLeventResetEvent(evPause);
end;
//protect from multiple instances of thread
if thethread = nil then
begin
{$IF DEFINED(mse)}
thethread := tmsethread.create(@execute);
{$else}
thethread := tuosthread.Create(false,self);
{$endif}
end;
end;
end;
procedure Tuos_Player.PlayPaused(nloop: Integer = 0) ;
inline;
// Start play paused with loop
begin
PlayEx(False,nloop,true);
end;
procedure Tuos_Player.PlayNoFreePaused(nloop: Integer = 0) ;
inline;
// Start play paused with loop and not free player at end
begin
PlayEx(true,nloop,true);
end;
procedure Tuos_Player.Play(nloop: Integer = 0) ;
inline;
begin
PlayEx(False,nloop);
end;
procedure Tuos_Player.PlayNoFree(nloop: Integer = 0) ;
inline;
begin
PlayEx(True,nloop);
end;
procedure Tuos_Player.FreePlayer();
// Works only when PlayNoFree() was used: free the player
begin
if isAssigned then
begin
NLooped := 0;
NoFree := False;
//if it has never been put into play (= there is no thread for free)..
if thethread = nil then
Play();
Stop;
end;
end;
procedure Tuos_Player.RePlay();
// Resume Playing after Pause
begin
if (Status > 0) and (isAssigned = True) and
(not IsLooped) then
begin
Status := 1;
if isGlobalPause = true then
RTLeventSetEvent(uosInit.evGlobalPause)
else
RTLeventSetEvent(evPause);
end;
end;
procedure Tuos_Player.Stop();
begin
//writeln(inttostr(Status));
if (Status <> 0) and (isAssigned = True) then
begin
if status < 0 then playpaused;
NLooped := 0;
if isGlobalPause = true then
RTLeventSetEvent(uosInit.evGlobalPause)
else
RTLeventSetEvent(evPause);
Status := 0;
end;
end;
procedure Tuos_Player.Pause();
begin
if (Status > 0) and (isAssigned = True) then
begin
if isGlobalPause = true then
RTLeventReSetEvent(uosInit.evGlobalPause)
else
RTLeventResetEvent(evPause);
Status := 2;
end;
end;
procedure Tuos_Player.InputSeek(InputIndex:cint32; pos: Tcount_t);
// change position in samples
begin
if (isAssigned = True) then StreamIn[InputIndex].Data.Poseek := pos;
end;
procedure Tuos_Player.InputSeekSeconds(InputIndex: cint32; pos: cfloat);
// change position in seconds
begin
if (isAssigned = True) then StreamIn[InputIndex].Data.Poseek :=
trunc(pos * StreamIn[InputIndex]
.Data.SampleRate);
end;
procedure Tuos_Player.InputSeekTime(InputIndex: cint32; pos: TTime);
// change position in time format
var
ho, mi, se, ms: word;
possample : cint32;
begin
if (isAssigned = True) then
begin
sysutils.DecodeTime(pos, ho, mi, se, ms);
possample := trunc(((ho * 3600) + (mi * 60) + se + (ms / 1000)) *
StreamIn[InputIndex].Data.SampleRate);
StreamIn[InputIndex].Data.Poseek := possample;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('TTime: '+ timetostr(pos));
WriteLn('SeekTime() : Data.Poseek: '+ inttostr(possample));
{$endif}
end;
end;
procedure Tuos_Player.InputSetEnable(InputIndex: cint32; enabled: boolean);
// set enable true or false
begin
StreamIn[InputIndex].data.Enabled := enabled;
end;
function Tuos_Player.InputLength(InputIndex: cint32): cint32;
// gives length in samples
begin
result := 0;
if (isAssigned = True) then Result := StreamIn[InputIndex].Data.Length;
end;
function Tuos_Player.InputLengthSeconds(InputIndex: cint32): cfloat;
begin
result := 0;
if (isAssigned = True) then Result := StreamIn[InputIndex].Data.Length / StreamIn[InputIndex].
Data.SampleRate;
end;
function Tuos_Player.InputLengthTime(InputIndex: cint32): TTime;
var
tmp: cfloat;
h, m, s, ms: word;
begin
Result := sysutils.EncodeTime(0, 0, 0, 0);
if (isAssigned = True) then tmp := InputLengthSeconds(InputIndex);
ms := trunc(frac(tmp) * 1000);
h := trunc(tmp / 3600);
m := trunc(tmp / 60 - h * 60);
s := trunc(tmp - (h * 3600 + m * 60));
Result := sysutils.EncodeTime(h, m, s, ms);
end;
function Tuos_Player.InputPosition(InputIndex: cint32): cint32;
// gives current position
begin
Result := 0;
if (isAssigned = True) then Result := StreamIn[InputIndex].Data.Position;
end;
procedure Tuos_Player.InputSetFrameCount(InputIndex: cint32 ; framecount : cint32);
begin
if (isAssigned = True) then
case StreamIn[InputIndex].Data.LibOpen of
0:
StreamIn[InputIndex].Data.Wantframes := (framecount * StreamIn[InputIndex].Data.Channels) ;
1:
StreamIn[InputIndex].Data.Wantframes := (framecount * StreamIn[InputIndex].Data.Channels)
* 2 ;
2:
StreamIn[InputIndex].Data.Wantframes := (framecount * StreamIn[InputIndex].Data.Channels) ;
3:
StreamIn[InputIndex].Data.Wantframes := (framecount * StreamIn[InputIndex].Data.Channels) ;
4:
StreamIn[InputIndex].Data.Wantframes := (framecount * StreamIn[InputIndex].Data.Channels) ;
end;
end;
procedure Tuos_Player.InputSetLevelArrayEnable(InputIndex: cint32 ; levelcalc : cint32);
// set add level calculation in level-array (default is 0)
// 0 => no calcul
// 1 => calcul before all DSP procedures.
// 2 => calcul after all DSP procedures.
begin
if (isAssigned = True) then
begin
if index + 1 > length(uosLevelArray) then
setlength(uosLevelArray,index + 1) ;
if InputIndex + 1 > length(uosLevelArray[index]) then
setlength(uosLevelArray[index],InputIndex + 1) ;
setlength(uosLevelArray[index][InputIndex],0) ;
StreamIn[InputIndex].Data.levelArrayEnable := levelcalc;
end;
end;
procedure Tuos_Player.InputSetLevelEnable(InputIndex: cint32 ; levelcalc : cint32);
// set level calculation (default is 0)
// 0 => no calcul
// 1 => calcul before all DSP procedures.
// 2 => calcul after all DSP procedures.
// 3 => calcul before and after all DSP procedures.
begin
if (isAssigned = True) then
StreamIn[InputIndex].Data.levelEnable := levelcalc;
end;
procedure Tuos_Player.InputSetPositionEnable(InputIndex: cint32 ; poscalc : cint32);
// set position calculation (default is 0)
// 0 => no calcul
// 1 => calcul position procedures.
begin
if (isAssigned = True) then
StreamIn[InputIndex].Data.PositionEnable := poscalc;
end;
function Tuos_Player.InputGetLevelLeft(InputIndex: cint32): double;
// InputIndex : InputIndex of existing input
// result : left level(volume) from 0 to 1
begin
Result := 0;
if (isAssigned = True) then Result := StreamIn[InputIndex].Data.LevelLeft;
end;
function Tuos_Player.InputGetLevelRight(InputIndex: cint32): double;
// InputIndex : InputIndex of existing input
// result : right level(volume) from 0 to 1
begin
Result := 0;
if (isAssigned = True) then Result := StreamIn[InputIndex].Data.LevelRight;
end;
function Tuos_Player.InputFiltersGetLevelString(InputIndex: cint32): string;
// InputIndex : InputIndex of existing input
// result : list of left|right levels separed by $ character
begin
Result := '';
if (isAssigned = True) then Result := StreamIn[InputIndex].data.Levelfilters;
end;
function Tuos_Player.InputFiltersGetLevelArray(InputIndex: cint32): TDArFloat;
// InputIndex : InputIndex of existing input
// result : array of float of each filter.
//in format levelfilter0left,levelfilter0right,levelfilter1left,levelfilter2right,...
begin
if (isAssigned = True) then Result := StreamIn[InputIndex].data.Levelfiltersar;
end;
{$IF DEFINED(soundtouch)}
function Tuos_Player.InputGetBPM(InputIndex: cint32): CDouble;
// InputIndex : InputIndex of existing input
// result : Beat per minuts
begin
Result := 0;
if (isAssigned = True) then Result := StreamIn[InputIndex].Data.BPM;
end;
{$endif}
function Tuos_Player.InputPositionSeconds(InputIndex: cint32): float;
begin
Result := 0;
if (isAssigned = True) then Result := StreamIn[InputIndex].Data.Position / StreamIn[InputIndex].
Data.SampleRate;
end;
function Tuos_Player.InputPositionTime(InputIndex: cint32): TTime;
var
tmp: float = 0.0;
h: word = 0;
m: word = 0;
s: word = 0;
ms: word = 0;
begin
Result := sysutils.EncodeTime(0, 0, 0, 0);
if (isAssigned = True) then
begin
tmp := InputPositionSeconds(InputIndex);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('InputPositionTime(): InputPositionSeconds: '+ floattostr(tmp));
{$endif}
ms := trunc(frac(tmp) * 1000);
h := trunc(tmp / 3600);
m := trunc(tmp / 60 - h * 60);
s := trunc(tmp - (h * 3600 + m * 60));
Result := sysutils.EncodeTime(h, m, s, ms);
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('EncodeTime(): '+ timetostr(Result));
{$endif}
end;
// for mp3 and opus files only
function Tuos_Player.InputUpdateTag(InputIndex: cint32): boolean;
{$IF DEFINED(mpg123) or DEFINED(opus) }
var
{$endif}
{$IF DEFINED(mpg123)}
// problems with mpg123
// mpinfo: Tmpg123_frameinfo;
// mpid3v2: Tmpg123_id3v2;
BufferTag: array[1..128] of char;
F: file;
{$endif}
{$IF DEFINED(opus)}
s: UTF8String;
j: Integer;
OpusTag: POpusTags;
LComment: PPAnsiChar;
LcommentLength: PInteger;
{$endif}
begin
Result := false;
if (isAssigned = True) then
begin
{$IF DEFINED(mpg123)}
if StreamIn[InputIndex].Data.LibOpen = 1 then// mp3
begin
//mpg123_info(StreamIn[InputIndex].Data.HandleSt, MPinfo);
// custom code for reading ID3Tag ---> problems with mpg123_id3()
AssignFile(F, StreamIn[InputIndex].Data.Filename);
FileMode := fmOpenRead + fmShareDenyNone;
Reset(F, 1);
Seek(F, FileSize(F) - 128);
BlockRead(F, BufferTag, SizeOf(BufferTag));
CloseFile(F);
StreamIn[InputIndex].Data.tag := copy(BufferTag, 1, 3);
StreamIn[InputIndex].Data.title := copy(BufferTag, 4, 30);
StreamIn[InputIndex].Data.artist := copy(BufferTag, 34, 30);
StreamIn[InputIndex].Data.album := copy(BufferTag, 64, 30);
StreamIn[InputIndex].Data.date := copy(BufferTag, 94, 4);
StreamIn[InputIndex].Data.comment := copy(BufferTag, 98, 29);
StreamIn[InputIndex].Data.track := inttostr(ord(BufferTag[127]));
StreamIn[InputIndex].Data.genre := inttostr(ord(BufferTag[128]));
Result := true;
// ? freeandnil(MPinfo);
end;
{$endif}
{$IF DEFINED(opus)}
if StreamIn[InputIndex].Data.LibOpen = 4 then// opus
begin
OpusTag := op_tags(StreamIn[InputIndex].Data.HandleOP, Nil);
if OpusTag<>nil
then
begin
if OpusTag^.comments>0
then
begin
LComment := OpusTag^.user_comments;
LcommentLength := OpusTag^.comment_lengths;
for j := 0 to OpusTag^.comments - 1 do
begin
SetLength(s, LcommentLength^);
move(Pointer(LComment^)^, Pointer(s)^, LcommentLength^);
if j = 1 then StreamIn[InputIndex].Data.title := s;
if j = 2 then StreamIn[InputIndex].Data.artist := s;
if j = 3 then StreamIn[InputIndex].Data.album := s;
if j = 4 then StreamIn[InputIndex].Data.date := s;
if j = 5 then StreamIn[InputIndex].Data.comment := s;
if j = 6 then StreamIn[InputIndex].Data.tag := s;
inc(LComment);
inc(LcommentLength);
end;
result := true;
end;
end;
end;
{$endif}
end;
end;
{$IF DEFINED(webstream)}
// for mp3 files only
function Tuos_Player.InputUpdateICY(InputIndex: cint32; Var icy_data : pchar): integer;
begin
Result := -1;
if (isAssigned = True) then
begin
if StreamIn[InputIndex].Data.LibOpen = 1 then// mp3
if assigned(StreamIn[InputIndex].httpget) then
if StreamIn[InputIndex].httpget.ICYenabled = true then
begin
{$IF DEFINED(mpg123)}
Result := mpg123_icy(StreamIn[InputIndex].Data.HandleSt, icy_data);
{$endif}
end;
end;
end;
{$ENDIF}
function Tuos_Player.InputGetTagTitle(InputIndex: cint32): pchar;
begin
Result := Nil;
if (isAssigned = True) then Result := pchar(StreamIn[InputIndex].Data.title);
end;
function Tuos_Player.InputGetTagArtist(InputIndex: cint32): pchar;
begin
Result := Nil;
if (isAssigned = True) then Result := pchar(StreamIn[InputIndex].Data.Artist);
end;
function Tuos_Player.InputGetTagAlbum(InputIndex: cint32): pchar;
begin
Result := Nil;
if (isAssigned = True) then Result := pchar(StreamIn[InputIndex].Data.album);
end;
function Tuos_Player.InputGetTagComment(InputIndex: cint32): pchar;
begin
Result := Nil;
if (isAssigned = True) then Result := pchar(StreamIn[InputIndex].Data.comment);
end;
function Tuos_Player.InputGetTagTrack(InputIndex: cint32): pchar;
begin
Result := Nil;
if (isAssigned = True) then Result := pchar(StreamIn[InputIndex].Data.track);
end;
function Tuos_Player.InputGetTagGenre(InputIndex: cint32): pchar;
begin
Result := Nil;
if (isAssigned = True) then Result := pchar(StreamIn[InputIndex].Data.genre);
end;
function Tuos_Player.InputGetTagTag(InputIndex: cint32): pchar;
begin
Result := Nil;
if (isAssigned = True) then Result := pchar(StreamIn[InputIndex].Data.tag);
end;
function Tuos_Player.InputGetTagDate(InputIndex: cint32): pchar;
begin
Result := Nil;
if (isAssigned = True) then Result := pchar(StreamIn[InputIndex].Data.date);
end;
procedure Tuos_Player.InputSetDSP(InputIndex: cint32; DSPinIndex: cint32;
Enable: boolean);
begin
StreamIn[InputIndex].DSP[DSPinIndex].Enabled := Enable;
end;
procedure Tuos_Player.OutputSetDSP(OutputIndex: cint32; DSPoutIndex: cint32;
Enable: boolean);
begin
StreamOut[OutputIndex].DSP[DSPoutIndex].Enabled := Enable;
end;
function Tuos_Player.InputAddDSP(InputIndex: cint32; BeforeFunc: TFunc;
AfterFunc: TFunc; EndedFunc: TFunc; LoopProc: TProc ): cint32;
begin
SetLength(StreamIn[InputIndex].DSP, Length(StreamIn[InputIndex].DSP) + 1);
StreamIn[InputIndex].DSP[Length(StreamIn[InputIndex].DSP) - 1] := Tuos_DSP.Create();
StreamIn[InputIndex].DSP[Length(StreamIn[InputIndex].DSP) - 1].Enabled := false;
StreamIn[InputIndex].DSP[Length(StreamIn[InputIndex].DSP) - 1].BefFunc := BeforeFunc;
StreamIn[InputIndex].DSP[Length(StreamIn[InputIndex].DSP) - 1].AftFunc := AfterFunc;
StreamIn[InputIndex].DSP[Length(StreamIn[InputIndex].DSP) - 1].EndFunc := EndedFunc;
StreamIn[InputIndex].DSP[Length(StreamIn[InputIndex].DSP) - 1].LoopProc := LoopProc;
StreamIn[InputIndex].DSP[Length(StreamIn[InputIndex].DSP) - 1].Enabled := True;
Result := Length(StreamIn[InputIndex].DSP) - 1;
end;
procedure Tuos_Player.OutputSetEnable(OutputIndex: cint32; enabled: boolean);
// set enable true or false
begin
StreamOut[OutputIndex].data.Enabled := enabled;
end;
function Tuos_Player.OutputAddDSP(OutputIndex: cint32; BeforeFunc: TFunc;
AfterFunc: TFunc; EndedFunc: TFunc; LoopProc: TProc): cint32;
begin
SetLength(StreamOut[OutputIndex].DSP, Length(StreamOut[OutputIndex].DSP) + 1);
StreamOut[OutputIndex].DSP[Length(StreamOut[OutputIndex].DSP) - 1] :=
Tuos_DSP.Create;
StreamOut[OutputIndex].DSP[Length(StreamOut[OutputIndex].DSP) - 1].Enabled := false;
StreamOut[OutputIndex].DSP[Length(StreamOut[OutputIndex].DSP) - 1].BefFunc :=
BeforeFunc;
StreamOut[OutputIndex].DSP[Length(StreamOut[OutputIndex].DSP) - 1].AftFunc :=
AfterFunc;
StreamOut[OutputIndex].DSP[Length(StreamOut[OutputIndex].DSP) - 1].EndFunc :=
EndedFunc;
StreamOut[OutputIndex].DSP[Length(StreamOut[OutputIndex].DSP) - 1].LoopProc :=
LoopProc;
StreamOut[OutputIndex].DSP[Length(StreamOut[OutputIndex].DSP) - 1].Enabled := True;
Result := Length(StreamOut[OutputIndex].DSP) - 1;
end;
procedure Tuos_Player.InputSetFilter(InputIndex: cint32; FilterIndex: cint32;
TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL:
cfloat;
TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR:
cfloat;
AlsoBuf: boolean; LoopProc: TProc; Enable: boolean);
// InputIndex : InputIndex of a existing Input
// DSPInIndex : DSPInIndex of existing DSPIn
// TypeFilterL: Type of filter left:
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// LowFrequencyL : Lowest frequency left( -1 : current LowFrequency )
// HighFrequencyL : Highest frequency left( -1 : current HighFrequency )
// GainL : gain left to apply to filter
// TypeFilterR: Type of filter right (ignored if mono):
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
// HighFrequencyR : Highest frequency left( -1 : current HighFrequency )
// GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
// AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
// LoopProc : external procedure of object to synchronize after DSP done
// Enable : Filter enabled
begin
if isAssigned = true then
begin
StreamIn[InputIndex].DSP[FilterIndex].fftdata.AlsoBuf := AlsoBuf;
StreamIn[InputIndex].DSP[FilterIndex].Enabled := Enable;
if LowFrequencyL = -1 then
LowFrequencyL := StreamIn[InputIndex].DSP[FilterIndex].fftdata.LowFrequencyL;
if LowFrequencyL = -1 then
LowFrequencyL := StreamIn[InputIndex].DSP[FilterIndex].fftdata.HighFrequencyL;
if GainL <> -1 then
StreamIn[InputIndex].DSP[FilterIndex].fftdata.Gainl := cfloat(Gainl);
if LowFrequencyR = -1 then
LowFrequencyR := StreamIn[InputIndex].DSP[FilterIndex].fftdata.LowFrequencyR;
if LowFrequencyR = -1 then
LowFrequencyR := StreamIn[InputIndex].DSP[FilterIndex].fftdata.HighFrequencyR;
if GainR <> -1 then
StreamIn[InputIndex].DSP[FilterIndex].fftdata.GainR := cfloat(GainR);
if TypeFilterL <> -1 then
begin
StreamIn[InputIndex].DSP[FilterIndex].fftdata.typefilterL := TypeFilterL;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.C := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.D := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[0] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[1] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[2] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[0] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[1] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.C2 := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.D2 := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32[0] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32[1] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32[2] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22[0] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22[1] := 0.0;
case TypeFilterL of
1: // DSPFFTBandSelect := DSPFFTBandReject + DSPFFTBandPass
begin
// DSPFFTBandReject
StreamIn[InputIndex].DSP[FilterIndex].fftdata.C :=
Tan(Pi * (HighFrequencyL -
LowFrequencyl + 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.D :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyl + LowFrequencyl)
shr 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[0] :=
1 / (1 + StreamIn[InputIndex
].DSP[FilterIndex].fftdata.C
);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[1] :=
-StreamIn[InputIndex].DSP[
FilterIndex].fftdata.D *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[2] :=
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[0] :=
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[1];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[1] :=
(1 - StreamIn[InputIndex].
DSP[FilterIndex].fftdata.C)
*
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
// DSPFFTBandPass
StreamIn[InputIndex].DSP[FilterIndex].fftdata.C2 :=
1 / Tan(Pi * (HighFrequencyl -
LowFrequencyl + 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.D2 :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyl + LowFrequencyl)
shr 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32[0] :=
1 / (1 + StreamIn[
InputIndex].DSP[FilterIndex
].fftdata.C2);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32[1] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32[2] :=
-StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a32[0]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22[0] :=
-StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C2 *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.D2 *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a32[0]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22[1] :=
(StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C2 - 1
) *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a32[0]
;
//
end;
2: // DSPFFTBandReject
begin
StreamIn[InputIndex].DSP[FilterIndex].fftdata.C :=
Tan(Pi * (HighFrequencyl -
LowFrequencyl + 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.D :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyl + LowFrequencyl)
shr 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[0] :=
1 / (1 + StreamIn[InputIndex
].DSP[FilterIndex].fftdata.C
);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[1] :=
-StreamIn[InputIndex].DSP[
FilterIndex].fftdata.D *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[2] :=
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[0] :=
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[1];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[1] :=
(1 - StreamIn[InputIndex].
DSP[FilterIndex].fftdata.C)
*
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
end;
3: // DSPFFTBandPass
begin
StreamIn[InputIndex].DSP[FilterIndex].fftdata.C :=
1 / Tan(Pi * (HighFrequencyl -
LowFrequencyl + 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.D :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyl + LowFrequencyl)
shr 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[0] :=
1 / (1 + StreamIn[InputIndex
].DSP[FilterIndex].fftdata.C
);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[1] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[2] :=
-StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[0] :=
-StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.D *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[1] :=
(StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C - 1)
*
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
end;
4: // DSPFFTLowPass
begin
StreamIn[InputIndex].DSP[FilterIndex].fftdata.C :=
1 / Tan(Pi * LowFrequencyl /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[0] :=
1 / (1 + Sqrt(2) * StreamIn[
InputIndex].DSP[FilterIndex]
.fftdata.C +
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[1] :=
2 * StreamIn[InputIndex].DSP
[FilterIndex].fftdata.a3[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[2] :=
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[0] :=
2 * (1 - StreamIn[InputIndex
].DSP[FilterIndex].fftdata.C
*
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C) *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[1] :=
(1 - Sqrt(2) * StreamIn[
InputIndex].DSP[FilterIndex]
.fftdata.C +
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C) *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
end;
5: // DSPFFTHighPass
begin
StreamIn[InputIndex].DSP[FilterIndex].fftdata.C :=
Tan(Pi * HighFrequencyl /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[0] :=
1 / (1 + Sqrt(2) * StreamIn[
InputIndex].DSP[FilterIndex]
.fftdata.C +
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[1] :=
-2 * StreamIn[InputIndex].
DSP[FilterIndex].fftdata.a3[
0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3[2] :=
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[0] :=
2 * (StreamIn[InputIndex].
DSP[FilterIndex].fftdata.C *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C - 1)
*
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2[1] :=
(1 - Sqrt(2) * StreamIn[
InputIndex].DSP[FilterIndex]
.fftdata.C +
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C) *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3[0];
end;
end;
end;
if TypeFilterR <> -1 then
begin
StreamIn[InputIndex].DSP[FilterIndex].fftdata.typefilterR := TypeFilterR;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.Cr := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.Dr := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[0] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[1] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[2] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[0] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[1] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.C2r := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.D2r := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32r[0] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32r[1] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32r[2] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22r[0] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22r[1] := 0.0;
case TypeFilterR of
1: // DSPFFTBandSelect := DSPFFTBandReject + DSPFFTBandPass
begin
// DSPFFTBandReject
StreamIn[InputIndex].DSP[FilterIndex].fftdata.Cr :=
Tan(Pi * (HighFrequencyr -
LowFrequencyr + 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.Dr :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyr + LowFrequencyr)
shr 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
1 / (1 + StreamIn[
InputIndex].DSP[FilterIndex
].fftdata.Cr);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
-StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Dr *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[1]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
(1 - StreamIn[InputIndex].
DSP[FilterIndex].fftdata.Cr
) *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
// DSPFFTBandPass
StreamIn[InputIndex].DSP[FilterIndex].fftdata.C2r :=
1 / Tan(Pi * (HighFrequencyr -
LowFrequencyr + 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.D2r :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyr + LowFrequencyr
) shr 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32r[0] :=
1 / (1 + StreamIn[
InputIndex].DSP[
FilterIndex].fftdata.C2r);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32r[1] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a32r[2] :=
-StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a32r[
0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22r[0] :=
-StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C2r *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.D2r *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a32r[
0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b22r[1] :=
(StreamIn[InputIndex].DSP[
FilterIndex].fftdata.C2r -
1) *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a32r[
0];
//
end;
2: // DSPFFTBandReject
begin
StreamIn[InputIndex].DSP[FilterIndex].fftdata.Cr :=
Tan(Pi * (HighFrequencyr -
LowFrequencyr + 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.Dr :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyr + LowFrequencyr)
shr 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
1 / (1 + StreamIn[
InputIndex].DSP[FilterIndex
].fftdata.Cr);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
-StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Dr *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[1]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
(1 - StreamIn[InputIndex].
DSP[FilterIndex].fftdata.Cr
) *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
end;
3: // DSPFFTBandPass
begin
StreamIn[InputIndex].DSP[FilterIndex].fftdata.Cr :=
1 / Tan(Pi * (HighFrequencyr-
LowFrequencyr + 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.Dr :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyr + LowFrequencyr)
shr 1) /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
1 / (1 + StreamIn[
InputIndex].DSP[FilterIndex
].fftdata.Cr);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[1] := 0.0;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
-StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
-StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Cr *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Dr *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
(StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Cr - 1
) *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
end;
4: // DSPFFTLowPass
begin
StreamIn[InputIndex].DSP[FilterIndex].fftdata.Cr :=
1 / Tan(Pi * LowFrequencyr /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
1 / (1 + Sqrt(2) * StreamIn
[InputIndex].DSP[
FilterIndex].fftdata.Cr +
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Cr *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Cr);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
2 * StreamIn[InputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
2 * (1 - StreamIn[
InputIndex].DSP[FilterIndex
].fftdata.Cr *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Cr) *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
(1 - Sqrt(2) * StreamIn[
InputIndex].DSP[FilterIndex
].fftdata.Cr +
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Cr *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Cr) *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
end;
5: // DSPFFTHighPass
begin
StreamIn[InputIndex].DSP[FilterIndex].fftdata.Cr :=
Tan(Pi * HighFrequencyr /
StreamIn[InputIndex].Data.
SampleRate);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
1 / (1 + Sqrt(2) * StreamIn
[InputIndex].DSP[
FilterIndex].fftdata.Cr +
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Cr *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Cr);
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
-2 * StreamIn[InputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
StreamIn[InputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
2 * (StreamIn[InputIndex].
DSP[FilterIndex].fftdata.Cr
*
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Cr - 1
) *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
StreamIn[InputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
(1 - Sqrt(2) * StreamIn[
InputIndex].DSP[FilterIndex
].fftdata.Cr +
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Cr *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.Cr) *
StreamIn[InputIndex].DSP[
FilterIndex].fftdata.a3r[0]
;
end;
end;
end;
end;
end;
procedure Tuos_Player.OutputSetFilter(OutputIndex: cint32; FilterIndex: cint32;
TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL:
cfloat;
TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR:
cfloat;
AlsoBuf: boolean; LoopProc: TProc; Enable: boolean);
// OuputIndex : InputIndex of a existing Output
// DSPInIndex : DSPInIndex of existing DSPIn
// TypeFilterL: Type of filter left:
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// fBandPass = 3, fLowPass = 4, fHighPass = 5)
// LowFrequencyL : Lowest frequency left( -1 : current LowFrequency )
// HighFrequencyL : Highest frequency left( -1 : current HighFrequency )
// GainL : gain left to apply to filter
// TypeFilterR: Type of filter right (ignored if mono):
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
// HighFrequencyR : Highest frequency left( -1 : current HighFrequency )
// GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
// AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
// LoopProc : external procedure of object to synchronize after DSP done
// Enable : Filter enabled
begin
if isAssigned = true then
begin
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.AlsoBuf := AlsoBuf;
StreamOut[OutputIndex].DSP[FilterIndex].Enabled := Enable;
if LowFrequencyL = -1 then
LowFrequencyL := StreamOut[OutputIndex].DSP[FilterIndex].fftdata.LowFrequencyL;
if LowFrequencyL = -1 then
LowFrequencyL := StreamOut[OutputIndex].DSP[FilterIndex].fftdata.HighFrequencyL;
if GainL <> -1 then
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Gainl := cfloat(Gainl);
if LowFrequencyR = -1 then
LowFrequencyR := StreamOut[OutputIndex].DSP[FilterIndex].fftdata.LowFrequencyR;
if LowFrequencyR = -1 then
LowFrequencyR := StreamOut[OutputIndex].DSP[FilterIndex].fftdata.HighFrequencyR;
if GainR <> -1 then
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.GainR := cfloat(GainR);
if TypeFilterL <> -1 then
begin
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.typefilterL := TypeFilterL;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[0] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[1] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[2] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[0] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[1] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C2 := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D2 := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32[0] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32[1] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32[2] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22[0] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22[1] := 0.0;
case TypeFilterL of
1: // DSPFFTBandSelect := DSPFFTBandReject + DSPFFTBandPass
begin
// DSPFFTBandReject
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C :=
Tan(Pi * (HighFrequencyL -
LowFrequencyl + 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyl + LowFrequencyl
) shr 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[0] :=
1 / (1 + StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.C);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[1] :=
-StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.D
*
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[2] :=
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[0] :=
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[1
];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[1] :=
(1 - StreamOut[OutputIndex
].DSP[FilterIndex].fftdata
.C) *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
// DSPFFTBandPass
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C2 :=
1 / Tan(Pi * (HighFrequencyl
- LowFrequencyl + 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D2 :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyl +
LowFrequencyl) shr 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32[0] :=
1 / (1 + StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.C2);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32[1] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32[2] :=
-StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a32[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22[0] :=
-StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
C2 *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
D2 *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a32[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22[1] :=
(StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
C2 - 1) *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a32[0];
//
end;
2: // DSPFFTBandReject
begin
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C :=
Tan(Pi * (HighFrequencyl -
LowFrequencyl + 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyl + LowFrequencyl
) shr 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[0] :=
1 / (1 + StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.C);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[1] :=
-StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.D
*
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[2] :=
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[0] :=
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[1
];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[1] :=
(1 - StreamOut[OutputIndex
].DSP[FilterIndex].fftdata
.C) *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
end;
3: // DSPFFTBandPass
begin
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C :=
1 / Tan(Pi * (HighFrequencyl -
LowFrequencyl + 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyl + LowFrequencyl
) shr 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[0] :=
1 / (1 + StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.C);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[1] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[2] :=
-StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[0] :=
-StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.C
*
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.D *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[1] :=
(StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.C
- 1) *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
end;
4: // DSPFFTLowPass
begin
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C :=
1 / Tan(Pi * LowFrequencyl /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[0] :=
1 / (1 + Sqrt(2) *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.C +
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.C *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.C);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[1] :=
2 * StreamOut[OutputIndex]
.DSP[FilterIndex].fftdata.
a3[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[2] :=
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[0] :=
2 * (1 - StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.C *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.C) *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[1] :=
(1 - Sqrt(2) * StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.C +
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.C *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.C) *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
end;
5: // DSPFFTHighPass
begin
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C :=
Tan(Pi * HighFrequencyl /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[0] :=
1 / (1 + Sqrt(2) *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.C +
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.C *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.C);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[1] :=
-2 * StreamOut[OutputIndex
].DSP[FilterIndex].fftdata
.a3[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3[2] :=
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[0] :=
2 * (StreamOut[OutputIndex
].DSP[FilterIndex].fftdata
.C *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.C -
1) *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2[1] :=
(1 - Sqrt(2) * StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.C +
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.C *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.C) *
StreamOut[OutputIndex].DSP
[FilterIndex].fftdata.a3[0
];
end;
end;
end;
if TypeFilterR <> -1 then
begin
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.typefilterR := TypeFilterR;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Cr := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Dr := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[0] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[1] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[2] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[0] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[1] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C2r := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D2r := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32r[0] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32r[1] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32r[2] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22r[0] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22r[1] := 0.0;
case TypeFilterR of
1: // DSPFFTBandSelect := DSPFFTBandReject + DSPFFTBandPass
begin
// DSPFFTBandReject
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Cr :=
Tan(Pi * (HighFrequencyr -
LowFrequencyr + 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Dr :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyr +
LowFrequencyr) shr 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
1 / (1 + StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.Cr);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
-StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Dr *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[1];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
(1 - StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.Cr)
*
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
// DSPFFTBandPass
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.C2r :=
1 / Tan(Pi * (HighFrequencyr
- LowFrequencyr + 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.D2r :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyr +
LowFrequencyr) shr 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32r[0] :=
1 / (1 + StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.C2r
);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32r[1] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a32r[2] :=
-StreamOut[OutputIndex].
DSP[FilterIndex].fftdata
.a32r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22r[0] :=
-StreamOut[OutputIndex].
DSP[FilterIndex].fftdata
.C2r *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata
.D2r *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata
.a32r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b22r[1] :=
(StreamOut[OutputIndex].
DSP[FilterIndex].fftdata
.C2r - 1) *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata
.a32r[0];
//
end;
2: // DSPFFTBandReject
begin
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Cr :=
Tan(Pi * (HighFrequencyr -
LowFrequencyr + 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Dr :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyr +
LowFrequencyr) shr 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
1 / (1 + StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.Cr);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
-StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Dr *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[1];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
(1 - StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.Cr)
*
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
end;
3: // DSPFFTBandPass
begin
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Cr :=
1 / Tan(Pi * (HighFrequencyr-
LowFrequencyr + 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Dr :=
2 * Cos(2 * Pi * (roundmath(
HighFrequencyr +
LowFrequencyr) shr 1) /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
1 / (1 + StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.Cr);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[1] := 0.0;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
-StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
-StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Dr *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
(StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr - 1) *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
end;
4: // DSPFFTLowPass
begin
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Cr :=
1 / Tan(Pi * LowFrequencyr /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
1 / (1 + Sqrt(2) *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr +
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
2 * StreamOut[OutputIndex
].DSP[FilterIndex].
fftdata.a3r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
2 * (1 - StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.Cr *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr) *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
(1 - Sqrt(2) * StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.Cr +
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr) *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
end;
5: // DSPFFTHighPass
begin
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Cr :=
Tan(Pi * HighFrequencyr /
StreamOut[OutputIndex].Data.
SampleRate);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[0] :=
1 / (1 + Sqrt(2) *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr +
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr);
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[1] :=
-2 * StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.a3r[
0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.a3r[2] :=
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[0] :=
2 * (StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.Cr *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr - 1) *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
StreamOut[OutputIndex].DSP[FilterIndex].fftdata.b2r[1] :=
(1 - Sqrt(2) * StreamOut[
OutputIndex].DSP[
FilterIndex].fftdata.Cr +
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
Cr) *
StreamOut[OutputIndex].
DSP[FilterIndex].fftdata.
a3r[0];
end;
end;
end;
end;
end;
{$IF DEFINED(soundtouch)}
function SoundTouchPlug(bufferin: TDArFloat; plugHandle: THandle; notneeded :Tt_bs2bdp; Var
inputData: Tuos_Data;
notused1: float; notused2: float; notused3: float; notused4: float;
notused5: float; notused6: float; notused7: float; notused8: float):
TDArFloat
;
var
ratio : shortint;
numoutbuf, x1, x2: cint32;
BufferplugFLTMP: TDArFloat;
BufferplugFL: TDArFloat;
begin
case inputData.LibOpen of
0: ratio := 1;
// sndfile
1:
begin
// mpg123
case inputData.SampleFormat of
0: ratio := 2;
// float32
1: ratio := 2;
// int32
2: ratio := 1;
// int16
end;
end;
2: ratio := 1;
3: ratio := 1;
// cdrom
4: ratio := 1;
// opus
5: ratio := 1;
// xmp
end;
if inputData.LibOpen <> 4 then//not working yet for opus files
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln();
writeln('_____Begin Sound touch_____');
writeln('soundtouch_putSamples: Length(bufferin) = ' + inttostr(length(bufferin)));
writeln('outframes = ' + inttostr(inputData.outframes)+
' ratio = ' + inttostr(ratio)+' channels = ' + inttostr(inputData.Channels));
{$endif}
if inputData.outframes > 0 then
begin
soundtouch_putSamples(plugHandle, pcfloat(bufferin),
inputData.outframes div cint(inputData.Channels * ratio));
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('inputData.outframes div trunc(inputData.Channels * ratio) = '
+ inttostr(inputData.outframes Div inputData.Channels * ratio));
{$endif}
SetLength(BufferplugFL, 0);
SetLength(BufferplugFLTMP, 0);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Length(BufferplugFL) = '
+ inttostr(Length(BufferplugFL)));
writeln('Length(Bufferin) = '
+ inttostr(Length(Bufferin)));
writeln('Length(BufferplugFLTMP) = '
+ inttostr(Length(BufferplugFLTMP)));
{$endif}
SetLength(BufferplugFLTMP,(Length(Bufferin)));
{
x2 := 0 ;
while x2 < Length(BufferplugFLTMP) do
begin
BufferplugFLTMP[x2] := 0.0 ;
inc(x2);
end;
}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('2_Length(BufferplugFLTMP) = '
+ inttostr(Length(BufferplugFLTMP)));
{$endif}
numoutbuf := 1;
while numoutbuf > 0 do
begin
numoutbuf := soundtouch_receiveSamples(PlugHandle,
pcfloat(BufferplugFLTMP), inputData.outframes);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('numoutbuf = ' + inttostr(numoutbuf));
{$endif}
if numoutbuf > 0 then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('SetLength(BufferplugFL) = ' + inttostr(length(BufferplugFL) + trunc(
numoutbuf
*
inputData
.
Channels
)));
{$endif}
SetLength(BufferplugFL, length(BufferplugFL) + trunc(numoutbuf * inputData.
Channels));
// works only with 2 channels.
x2 := Length(BufferplugFL) - (numoutbuf * inputData.Channels);
for x1 := 0 to trunc(numoutbuf * inputData.Channels) -1 do
begin
BufferplugFL[x1 + x2] := BufferplugFLTMP[x1];
end;
end;
end;
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('inputData.outframes = Length(BufferplugFL) = ' + inttostr(inputData.outframes));
writeln('_____End Sound touch_____');
{$endif}
inputData.outframes := Length(BufferplugFL) Div inputData.Channels;
Result := BufferplugFL;
end
else
begin
SetLength(bufferin, inputData.outframes);
Result := bufferin;
end;
end;
function GetBPMPlug(bufferin: TDArFloat; plugHandle: THandle; notneeded :Tt_bs2bdp; Var inputData:
Tuos_Data;
numframes: float; loop: float; notused3: float; notused4: float;
notused5: float; notused6: float; notused7: float; notused8: float): TDArFloat;
var
ratio : shortint;
begin
case inputData.LibOpen of
0: ratio := 1;
// sndfile
1:
begin
// mpg123
case inputData.SampleFormat of
0: ratio := 2;
// float32
1: ratio := 2;
// int32
2: ratio := 1;
// int16
end;
end;
2: ratio := 1;
3: ratio := 1;
// cdrom
4: ratio := 1;
// opus
5: ratio := 1;
// xmp
end;
if inputData.LibOpen <> 4 then//not working yet for opus files
begin
// writeln('getBPM init ');
if (theincbpm < numframes) and (theincbpm > -1) then
begin
bpm_putSamples(plugHandle, pcfloat(bufferin), length(bufferin) div inputData.channels);
end
else
begin
if theincbpm > -1 then
begin
inputData.BPM := bpm_getBpm(plugHandle);
// writeln('inputData.BPM := ' + floattostr(inputData.BPM));
if loop = 1 then theincbpm := 0
else theincbpm := -1;
end;
end;
if theincbpm > -1 then inc(theincbpm);
SetLength(bufferin, inputData.outframes Div ratio);
Result := bufferin;
end;
end;
{$endif}
{$IF DEFINED(bs2b)}
function bs2bPlug(bufferin: TDArFloat; notneeded: THandle; Abs2bd : Tt_bs2bdp; Var inputData:
Tuos_Data;
notused1: float; notused2: float; notused3: float; notused4: float;
notused5: float; notused6: float; notused7: float; notused8: float): TDArFloat;
var
x, x2: cint32;
Bufferplug: TDArFloat;
begin
if (inputData.libopen = 0) or (inputData.libopen = 2) or (inputData.libopen = 3) or (inputData.
libopen = 4) or (inputData.libopen = 5) then
x2 := trunc(inputData.ratio * (inputData.outframes Div trunc(inputData.channels))) ;
if (inputData.libopen = 1) then
begin
if inputData.SampleFormat < 2 then
x2 := trunc((inputData.outframes Div trunc(inputData.channels)))
else x2 := trunc(inputData.ratio * (inputData.outframes Div trunc(inputData.channels))) ;
end;
SetLength(Bufferplug,x2);
x := 0;
while x < x2 do
begin
Bufferplug[x] := bufferin[x] ;
Bufferplug[x+1] := bufferin[x+1] ;
bs2b_cross_feed_f(Abs2bd,Bufferplug[x],1);
bs2b_cross_feed_f(Abs2bd,Bufferplug[x+1],2);
x := x +2;
end;
Result := Bufferplug;
end;
{$endif}
function Tuos_Player.AddPlugin(PlugName: PChar; SampleRate: CDouble;
Channels: cint32): cint32;
// SampleRate : delault : -1 (44100)
// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
// Result is PluginIndex
var
x: cint32;
chan, sr : integer;
begin
x := -1 ;
{$IF DEFINED(soundtouch)}
if lowercase(PlugName) = 'soundtouch' then
begin
//
SetLength(Plugin, Length(Plugin) + 1);
x := Length(Plugin) - 1;
Plugin[x] := Tuos_Plugin.Create();
Plugin[x].Enabled := false;
Plugin[x].Name := lowercase(PlugName);
Plugin[x].param1 := -1;
Plugin[x].param2 := -1;
Plugin[x].param3 := -1;
Plugin[x].param4 := -1;
Plugin[x].param5 := -1;
Plugin[x].param6 := -1;
Plugin[x].param7 := -1;
Plugin[x].param8 := -1;
Plugin[x].PlugHandle := soundtouch_createInstance();
if SampleRate = -1 then
soundtouch_setSampleRate(Plugin[x].PlugHandle, 44100)
else
soundtouch_setSampleRate(Plugin[x].PlugHandle, roundmath(SampleRate));
if Channels = -1 then
soundtouch_setChannels(Plugin[x].PlugHandle, 2)
else
soundtouch_setChannels(Plugin[x].PlugHandle, Channels);
soundtouch_setRate(Plugin[x].PlugHandle, 1);
soundtouch_setTempo(Plugin[x].PlugHandle, 1);
soundtouch_clear(Plugin[x].PlugHandle);
Plugin[x].PlugFunc := @soundtouchplug;
end;
if lowercase(PlugName) = 'getbpm' then
begin
//
SetLength(Plugin, Length(Plugin) + 1);
x := Length(Plugin) - 1;
Plugin[x] := Tuos_Plugin.Create();
Plugin[x].Enabled := true;
Plugin[x].Name := lowercase(PlugName);
Plugin[x].param1 := -1;
Plugin[x].param2 := -1;
Plugin[x].param3 := -1;
Plugin[x].param4 := -1;
Plugin[x].param5 := -1;
Plugin[x].param6 := -1;
Plugin[x].param7 := -1;
Plugin[x].param8 := -1;
if SampleRate = -1 then
sr := 44100
else
sr := roundmath(SampleRate);
if Channels = -1 then
chan := 2
else
chan := Channels;
Plugin[x].PlugHandle := bpm_createInstance(chan,sr);
Plugin[x].PlugFunc := @getbpmplug;
end;
{$endif}
{$IF DEFINED(bs2b)}
if lowercase(PlugName) = 'bs2b' then
begin
SetLength(Plugin, Length(Plugin) + 1);
Plugin[Length(Plugin) - 1] := Tuos_Plugin.Create();
x := Length(Plugin) - 1;
Plugin[x].Name := lowercase(PlugName);
Plugin[x].Enabled := true;
if assigned(Plugin[x].Abs2b) then bs2b_close(Plugin[x].Abs2b) ;
Plugin[x].Abs2b := bs2b_open() ;
if SampleRate = -1 then
bs2b_set_srate(Plugin[x].Abs2b, 44100)
else
bs2b_set_srate(Plugin[x].Abs2b, roundmath(SampleRate));
Plugin[x].param1 := -1;
Plugin[x].param2 := -1;
Plugin[x].param3 := -1;
Plugin[x].param4 := -1;
Plugin[x].param5 := -1;
Plugin[x].param6 := -1;
Plugin[x].param7 := -1;
Plugin[x].param8 := -1;
Plugin[x].PlugFunc := @bs2bplug;
end;
{$endif}
Plugin[x].Enabled := true;
Result := x;
end;
{$IF DEFINED(soundtouch)}
procedure Tuos_Player.SetPluginSoundTouch(PluginIndex: cint32;
Tempo: cfloat; Pitch: cfloat; Enable: boolean);
begin
soundtouch_setRate(Plugin[PluginIndex].PlugHandle, Pitch);
soundtouch_setTempo(Plugin[PluginIndex].PlugHandle, Tempo);
Plugin[PluginIndex].Enabled := Enable;
Plugin[PluginIndex].param1 := Tempo;
Plugin[PluginIndex].param2 := Pitch;
end;
procedure Tuos_Player.SetPluginGetBPM(PluginIndex: cint32; numofframes: integer; loop : boolean;
Enable: boolean);
// PluginIndex : PluginIndex Index of a existing Plugin.
// numofframes: number of frames to analyse (-1 = 512 frames)
// loop: do new detection after previous.
begin
Plugin[PluginIndex].Enabled := Enable;
Plugin[PluginIndex].param1 := numofframes;
if (loop = true) then
Plugin[PluginIndex].param2 := 1
else Plugin[PluginIndex].param2 := 0; ;
end;
{$endif}
{$IF DEFINED(bs2b)}
procedure Tuos_Player.SetPluginBs2b(PluginIndex: cint32;
level: CInt32; fcut: CInt32; feed: CInt32; Enable: boolean);
begin
Plugin[PluginIndex].Enabled := Enable;
if level > -1 then
begin
bs2b_set_level(Plugin[PluginIndex].Abs2b,level);
Plugin[PluginIndex].param1 := level;
end;
if fcut > -1 then
begin
bs2b_set_level_fcut(Plugin[PluginIndex].Abs2b,fcut);
Plugin[PluginIndex].param2 := fcut;
end;
if feed > -1 then
begin
bs2b_set_level_feed(Plugin[PluginIndex].Abs2b,feed);
Plugin[PluginIndex].param3 := feed;
end;
end;
{$endif}
function uos_InputGetLevelArray(PlayerIndex: cint32; InputIndex: cint32) : TDArFloat;
begin
result := uosLevelArray[PlayerIndex][InputIndex] ;
end;
{$IF DEFINED(noiseremoval)}
function uos_NoiseRemoval(Var Data: Tuos_Data; Var fft: Tuos_FFT): TDArFloat;
var
ratio, x: cint32;
Outfr : cint32;
tempr : PSingle;
pf: TDArFloat;
begin
case Data.LibOpen of
0: ratio := 1;
// sndfile
1: ratio := 2;
// mpg123
2: ratio := 1;
// aac
3: ratio := 1;
// cdrom
4: ratio := 1;
// opus
5: ratio := 1;
// xmp
end;
if Data.SampleFormat = 0 then// TODO for Array of integer.
begin
tempr := fft.FNoise.FilterNoise(pointer(Data.Buffer) ,
(Data.OutFrames Div ratio) , Outfr);
setlength(pf,length(Data.Buffer));
for x := 0 to length(pf) -1 do
begin
if x < Outfr then
pf[x] := tempr[x]
else pf[x] := 0.0;
end;
result := pf ;
end
else result := Data.Buffer;
// TODO for Array of integer.
end;
{$endif}
function uos_DSPVolumeIn(Var Data: Tuos_Data;Var fft: Tuos_FFT): TDArFloat;
var
x, ratio: cint32;
vleft, vright: cfloat;
// volumearray : array of double;
ps: PDArShort;
// if input is Int16 format
pl: PDArLong;
// if input is Int32 format
pf: PDArFloat;
// if input is Float32 format
begin
//setlength(volumearray,Data.channels);
vleft := Data.VLeft;
vright := Data.VRight;
case Data.SampleFormat of
2: // int16
begin
ps := @Data.Buffer;
for x := 0 to (Data.OutFrames -1) do
begin
if (Data.VLeft <> 1) or (Data.Vright <> 1) then
begin
if odd(x) then
ps^[x] := trunc(ps^[x] * vright)
else
ps^[x] := trunc(ps^[x] * vleft);
end;
// This to avoid distortion
if ps^[x] < (-32760) then ps^[x] := -32760 ;
if ps^[x] > (32760) then ps^[x] := 32760 ;
end;
end;
1: // int32
begin
pl := @Data.Buffer;
for x := 0 to (Data.OutFrames -1) do
begin
if (Data.VLeft <> 1) or (Data.Vright <> 1) then
begin
if odd(x) then
pl^[x] := trunc(pl^[x] * vright)
else
pl^[x] := trunc(pl^[x] * vleft);
end;
// This to avoid distortion
if pl^[x] < (-2147000000) then pl^[x] := -2147000000 ;
if pl^[x] > (2147000000) then pl^[x] := 2147000000 ;
end;
end;
0: // float32
begin
case Data.LibOpen of
0: ratio := 1;
// sndfile
1: ratio := 2;
// mpg123
2: ratio := 1;
// aac
3: ratio := 1;
// cdrom
4: ratio := 1;
// opus
5: ratio := 1;
// xmp
end;
pf := @Data.Buffer;
for x := 0 to (Data.OutFrames div ratio) -1 do
begin
if (Data.VLeft <> 1) or (Data.Vright <> 1) then
begin
if odd(x) then
pf^[x] := pf^[x] * vright
else
pf^[x] := pf^[x] * vleft;
end;
// This to avoid distortion
if pf^[x] < -1 then pf^[x] := -1;
if pf^[x] > 1 then pf^[x] := 1 ;
end;
end;
end;
Result := Data.Buffer;
end;
function uos_DSPVolumeOut(Var Data: Tuos_Data;Var fft: Tuos_FFT): TDArFloat;
var
x: cint32;
vleft, vright: cfloat;
ps: PDArShort;
// if output is Int16 format
pl: PDArLong;
// if output is Int32 format
pf: PDArFloat;
// if output is Float32 format
begin
vleft := Data.VLeft;
vright := Data.VRight;
case Data.SampleFormat of
2: // int16
begin
ps := @Data.Buffer;
for x := 0 to (length(Data.Buffer) -1) do
begin
if (Data.VLeft <> 1) or (Data.Vright <> 1) then
begin
if odd(x) then
ps^[x] := trunc(ps^[x] * vright)
else
ps^[x] := trunc(ps^[x] * vleft);
end;
// This to avoid distortion
if ps^[x] < (-32760) then ps^[x] := -32760 ;
if ps^[x] > (32760) then ps^[x] := 32760 ;
end;
end;
1: // int32
begin
pl := @Data.Buffer;
for x := 0 to (length(Data.Buffer) -1) do
begin
if (Data.VLeft <> 1) or (Data.Vright <> 1) then
begin
if odd(x) then
pl^[x] := trunc(pl^[x] * vright)
else
pl^[x] := trunc(pl^[x] * vleft);
end;
// This to avoid distortion
if pl^[x] < (-2147000000) then pl^[x] := -2147000000 ;
if pl^[x] > (2147000000) then pl^[x] := 2147000000 ;
end;
end;
0: // float32
begin
pf := @Data.Buffer;
for x := 0 to (length(Data.Buffer)) -1 do
begin
if (Data.VLeft <> 1) or (Data.Vright <> 1) then
begin
if odd(x) then
pf^[x] := pf^[x] * vright
else
pf^[x] := pf^[x] * vleft;
end;
// This to avoid distortion
if pf^[x] < -1 then pf^[x] := -1;
if pf^[x] > 1 then pf^[x] := 1 ;
end;
end;
end;
Result := Data.Buffer;
end;
function Tuos_Player.DSPLevel(Data: Tuos_Data): Tuos_Data;
var
x, ratio: cint32;
ps: PDArShort;
// if input is Int16 format
pl: PDArLong;
// if input is Int32 format
pf: PDArFloat;
// if input is Float32 format
mins, maxs: array[0..1] of cInt16;
// if input is Int16 format
minl, maxl: array[0..1] of cInt32;
// if input is Int32 format
minf, maxf: array[0..1] of cfloat;
// if input is Float32 format
begin
case Data.SampleFormat of
2:
begin
mins[0] := 32767;
mins[1] := 32767;
maxs[0] := -32768;
maxs[1] := -32768;
ps := @Data.Buffer;
x := 0;
while x < Data.OutFrames -1 do
begin
if ps^[x] < mins[0] then
mins[0] := ps^[x];
if ps^[x] > maxs[0] then
maxs[0] := ps^[x];
Inc(x, 1);
if ps^[x] < mins[1] then
mins[1] := ps^[x];
if ps^[x] > maxs[1] then
maxs[1] := ps^[x];
Inc(x, 1);
end;
if Abs(mins[0]) > Abs(maxs[0]) then
Data.LevelLeft := Sqrt(Abs(mins[0]) / 32768)
else
Data.LevelLeft := Sqrt(Abs(maxs[0]) / 32768);
if Abs(mins[1]) > Abs(maxs[1]) then
Data.Levelright := Sqrt(Abs(mins[1]) / 32768)
else
Data.Levelright := Sqrt(Abs(maxs[1]) / 32768);
end;
1:
begin
minl[0] := 2147483647;
minl[1] := 2147483647;
maxl[0] := -2147483648;
maxl[1] := -2147483648;
pl := @Data.Buffer;
x := 0;
while x < Data.OutFrames -1 do
begin
if pl^[x] < minl[0] then
minl[0] := pl^[x];
if pl^[x] > maxl[0] then
maxl[0] := pl^[x];
Inc(x, 1);
if pl^[x] < minl[1] then
minl[1] := pl^[x];
if pl^[x] > maxl[1] then
maxl[1] := pl^[x];
Inc(x, 1);
end;
if Abs(minl[0]) > Abs(maxl[0]) then
Data.LevelLeft := Sqrt(Abs(minl[0]) / 2147483648)
else
Data.LevelLeft := Sqrt(Abs(maxl[0]) / 2147483648);
if Abs(minl[1]) > Abs(maxl[1]) then
Data.Levelright := Sqrt(Abs(minl[1]) / 2147483648)
else
Data.Levelright := Sqrt(Abs(maxl[1]) / 2147483648);
end;
0:
begin
case Data.LibOpen of
0: ratio := 1;
// sndfile
1: ratio := 2;
// mpg123
2: ratio := 2;
// aac
3: ratio := 2;
// cdrom
4: ratio := 2;
// opus
5: ratio := 1;
// xmp
end;
minf[0] := 1;
minf[1] := 1;
maxf[0] := -1;
maxf[1] := -1;
pf := @Data.Buffer;
x := 0;
while x < (Data.OutFrames div ratio)-1 do
begin
if pf^[x] < minf[0] then
minf[0] := pf^[x];
if pf^[x] > maxf[0] then
maxf[0] := pf^[x];
Inc(x, 1);
if pf^[x] < minf[1] then
minf[1] := pf^[x];
if pf^[x] > maxf[1] then
maxf[1] := pf^[x];
Inc(x, 1);
end;
if Abs(minf[0]) > Abs(maxf[0]) then
Data.LevelLeft := Sqrt(Abs(minf[0]))
else
Data.LevelLeft := Sqrt(Abs(maxf[0]));
if Abs(minf[1]) > Abs(maxf[1]) then
Data.Levelright := Sqrt(Abs(minf[1]))
else
Data.Levelright := Sqrt(Abs(maxf[1]));
end;
end;
Result := Data;
end;
function DSPLevelString(Buffer: TDArFloat; SampleFormat, Ratio : cint32; Var resfloatleft : cfloat;
Var resfloatright : cfloat): string;
var
x, OutFrames: cint32;
ps: PDArShort;
// if input is Int16 format
pl: PDArLong;
// if input is Int32 format
pf: PDArFloat;
// if input is Float32 format
mins, maxs: array[0..1] of cInt16;
// if input is Int16 format
minl, maxl: array[0..1] of cInt32;
// if input is Int32 format
minf, maxf: array[0..1] of cfloat;
// if input is Float32 format
begin
OutFrames := length(buffer);
case SampleFormat of
2:
begin
mins[0] := 32767;
mins[1] := 32767;
maxs[0] := -32768;
maxs[1] := -32768;
ps := @Buffer;
x := 0;
while x < OutFrames -1 do
begin
if ps^[x] < mins[0] then
mins[0] := ps^[x];
if ps^[x] > maxs[0] then
maxs[0] := ps^[x];
Inc(x, 1);
if ps^[x] < mins[1] then
mins[1] := ps^[x];
if ps^[x] > maxs[1] then
maxs[1] := ps^[x];
Inc(x, 1);
end;
if Abs(mins[0]) > Abs(maxs[0]) then
resfloatLeft := Sqrt(Abs(mins[0]) / 32768)
else
resfloatLeft := Sqrt(Abs(maxs[0]) / 32768);
if Abs(mins[1]) > Abs(maxs[1]) then
resfloatright := Sqrt(Abs(mins[1]) / 32768)
else
resfloatright := Sqrt(Abs(maxs[1]) / 32768);
end;
1:
begin
minl[0] := 2147483647;
minl[1] := 2147483647;
maxl[0] := -2147483648;
maxl[1] := -2147483648;
pl := @Buffer;
x := 0;
while x < OutFrames -1 do
begin
if pl^[x] < minl[0] then
minl[0] := pl^[x];
if pl^[x] > maxl[0] then
maxl[0] := pl^[x];
Inc(x, 1);
if pl^[x] < minl[1] then
minl[1] := pl^[x];
if pl^[x] > maxl[1] then
maxl[1] := pl^[x];
Inc(x, 1);
end;
if Abs(minl[0]) > Abs(maxl[0]) then
resfloatLeft := Sqrt(Abs(minl[0]) / 2147483648)
else
resfloatLeft := Sqrt(Abs(maxl[0]) / 2147483648);
if Abs(minl[1]) > Abs(maxl[1]) then
resfloatright := Sqrt(Abs(minl[1]) / 2147483648)
else
resfloatright := Sqrt(Abs(maxl[1]) / 2147483648);
end;
0:
begin
minf[0] := 1;
minf[1] := 1;
maxf[0] := -1;
maxf[1] := -1;
pf := @Buffer;
x := 0;
while x < (OutFrames div ratio) -1 do
begin
if pf^[x] < minf[0] then
minf[0] := pf^[x];
if pf^[x] > maxf[0] then
maxf[0] := pf^[x];
Inc(x, 1);
if pf^[x] < minf[1] then
minf[1] := pf^[x];
if pf^[x] > maxf[1] then
maxf[1] := pf^[x];
Inc(x, 1);
end;
if Abs(minf[0]) > Abs(maxf[0]) then
resfloatLeft := Sqrt(Abs(minf[0]))
else
resfloatLeft := Sqrt(Abs(maxf[0]));
if Abs(minf[1]) > Abs(maxf[1]) then
resfloatright := Sqrt(Abs(minf[1]))
else
resfloatright := Sqrt(Abs(maxf[1]));
end;
end;
Result := floattostr(resfloatleft) + '|' + floattostr(resfloatright);
end;
function uos_BandFilter(Var Data: Tuos_Data; Var fft: Tuos_FFT): TDArFloat;
var
i, ratio: cint32;
ifbuf: boolean;
arg, res, res2: cfloat;
ps, ps2: PDArShort;
// if input is Int16 format
pl, pl2: PDArLong;
// if input is Int32 format
pf, pf2: PDArFloat;
// if input is Float32 format
begin
ratio := 1;
ifbuf := fft.AlsoBuf;
case Data.SampleFormat of
2:
begin
ps := @Data.Buffer;
ps2 := @fft.VirtualBuffer;
end;
1:
begin
pl := @Data.Buffer;
pl2 := @fft.VirtualBuffer;
end;
0:
begin
case Data.LibOpen of
0: ratio := 1;
// sndfile
1: ratio := 2;
// mpg123
2: ratio := 2;
// aac
3: ratio := 2;
// cdrom
4: ratio := 2;
// opus
5: ratio := 1;
// xmp
end;
pf := @Data.Buffer;
pf2 := @fft.VirtualBuffer;
end;
end;
i := 0;
while i < (Data.OutFrames div ratio) -1 do
begin
case Data.SampleFormat of
2: arg := ps^[i];
1: arg := pl^[i];
0: arg := pf^[i];
end;
res := fft.a3[0] * arg + fft.a3[1] * fft.x0[0] + fft.a3[2] *
fft.x1[0] - fft.b2[0] * fft.y0[0] - fft.b2[1] * fft.y1[0];
if fft.typefilterL = 1 then
begin
res2 := fft.a32[0] * arg + fft.a32[1] * fft.x02[0] + fft.a32[2] *
fft.x12[0] - fft.b22[0] * fft.y02[0] - fft.b22[1] * fft.y12[0];
case Data.SampleFormat of
2:
begin
if ifbuf = True then
ps^[i] := trunc((res * 1) + (res2 * fft.gainl))
else
ps2^[i] := trunc((res * 1) + (res2 * fft.gainl));
end;
1:
begin
if ifbuf = True then
pl^[i] := trunc((res * 1) + (res2 * fft.gainl))
else
pl2^[i] := trunc((res * 1) + (res2 * fft.gainl));
end;
0:
begin
if ifbuf = True then
pf^[i] := ((res * 1) + (res2 * fft.gainl))
else
pf2^[i] := ((res * 1) + (res2 * fft.gainl));
end;
end;
end
else
case Data.SampleFormat of
2:
begin
if ifbuf = True then
ps^[i] := trunc((res * fft.gainl))
else
ps2^[i] := trunc(res * fft.gainl);
end;
1:
begin
if ifbuf = True then
pl^[i] := trunc((res * fft.gainl))
else
pl2^[i] := trunc(res * fft.gainl);
end;
0:
begin
if ifbuf = True then
pf^[i] := ((res * fft.gainl))
else
pf2^[i] := ((res * fft.gainl));
end;
end;
fft.x1[0] := fft.x0[0];
fft.x0[0] := arg;
fft.y1[0] := fft.y0[0];
fft.y0[0] := res;
if fft.typefilterL = 1 then
begin
fft.x12[0] := fft.x02[0];
fft.x02[0] := arg;
fft.y12[0] := fft.y02[0];
fft.y02[0] := res2;
end;
if Data.Channels = 2 then
begin
Inc(i);
case Data.SampleFormat of
2: arg := ps^[i];
1: arg := pl^[i];
0: arg := pf^[i];
end;
res := fft.a3r[0] * arg + fft.a3r[1] * fft.x0r[1] + fft.a3r[2] *
fft.x1r[1] - fft.b2r[0] * fft.y0r[1] - fft.b2r[1] * fft.y1r[1];
if fft.typefilterR = 1 then
begin
res2 := fft.a32r[0] * arg + fft.a32r[1] * fft.x02r[1] +
fft.a32r[2] * fft.x12r[1] - fft.b22r[0] * fft.y02r[1] -
fft.b22r[1] * fft.y12r[1];
case Data.SampleFormat of
2:
begin
if ifbuf = True then
ps^[i] := trunc((res * 1) + (res2 * fft.gainr))
else
ps2^[i] := trunc((res * 1) + (res2 * fft.gainr));
end;
1:
begin
if ifbuf = True then
pl^[i] := trunc((res * 1) + (res2 * fft.gainr))
else
pl2^[i] := trunc((res * 1) + (res2 * fft.gainr));
end;
0:
begin
if ifbuf = True then
pf^[i] := ((res * 1) + (res2 * fft.gainr))
else
pf2^[i] := ((res * 1) + (res2 * fft.gainr));
end;
end;
end
else
case Data.SampleFormat of
2:
begin
if ifbuf = True then
ps^[i] := trunc((res * fft.gainr))
else
ps2^[i] := trunc((res * fft.gainr));
end;
1:
begin
if ifbuf = True then
pl^[i] := trunc((res * fft.gainr))
else
pl2^[i] := trunc((res * fft.gainr));
end;
0:
begin
if ifbuf = True then
pf^[i] := ((res * fft.gainr))
else
pf2^[i] := ((res * fft.gainr));
end;
end;
fft.x1r[1] := fft.x0r[1];
fft.x0r[1] := arg;
fft.y1r[1] := fft.y0r[1];
fft.y0r[1] := res;
if fft.typefilterR = 1 then
begin
fft.x12r[1] := fft.x02r[1];
fft.x02r[1] := arg;
fft.y12r[1] := fft.y02r[1];
fft.y02r[1] := res2;
end;
end;
Inc(i);
end;
if ifbuf = false then
begin
data.levelfilters := data.levelfilters + '%'+ DSPLevelString(fft.VirtualBuffer, Data.
SampleFormat, data.Ratio, data.levelleft, data.levelright) ;
inc(Data.incfilters);
Data.levelfiltersar[Data.incfilters-1] := data.levelleft;
inc(Data.incfilters);
Data.levelfiltersar[Data.incfilters-1] := data.levelright;
end;
Result := Data.Buffer;
end;
function uos_InputAddDSP1ChanTo2Chan(Var Data: Tuos_Data; Var fft: Tuos_FFT): TDArFloat;
// Convert mono 1 chan input into stereo 2 channels input.
// Works only if the input is mono 1 channel othewise stereo 2 chan is keeped.
// InputIndex : InputIndex of a existing Input
// result : index of DSPIn in array
// example DSPIndex1 := InputAdd1ChanTo2Chan(InputIndex1);
var
x, x2: integer ;
ps, ps2: PDArShort;
// if input is Int16 format
pl, pl2: PDArLong;
// if input is Int32 format
pf, pf2: PDArFloat;
// if input is Float32 format
buffer2 : TDArFloat;
begin
if (Data.channels = 1) then
begin
setlength(Buffer2, Data.OutFrames);
x := 0 ;
x2 := 0 ;
case Data.SampleFormat of
2:
begin
ps := @Data.Buffer;
ps2 := @Buffer2;
while x < Data.OutFrames -1 do
begin
ps2^[x2] := (ps^[x]);
ps2^[x2+1] := (ps^[x]);
x := x + 1;
x2 := x2 + 2;
end;
end;
1:
begin
pl := @Data.Buffer;
pl2 := @Buffer2;
while x < Data.OutFrames -1 do
begin
pl2^[x2] := (pl^[x]);
pl2^[x2+1] := (pl^[x]);
x := x + 1;
x2 := x2 + 2;
end;
end;
0:
begin
pf := @Data.Buffer;
pf2 := @Buffer2;
while x < Data.OutFrames -1 do
begin
pf2^[x2] := (pf^[x]);
pf2^[x2+1] := (pf^[x]);
x := x + 1;
x2 := x2 + 2;
end;
end;
end;
data.outframes := length(buffer2);
Result := Buffer2;;
end
else
begin
Result := data.Buffer;
end;
end;
function ConvertSampleFormat(Data: Tuos_Data): TDArFloat;
var
x : integer ;
ps, ps2: PDArShort;
// if input is Int16 format
pl, pl2: PDArLong;
// if input is Int32 format
buffer2 : TDArFloat;
begin
if (Data.SampleFormat > 0) then
begin
setlength(Buffer2, Data.OutFrames);
x := 0 ;
case Data.SampleFormat of
2:
begin
ps := @Data.Buffer;
ps2 := @Buffer2;
while x < Data.OutFrames do
begin
ps2^[x] := (ps^[x]);
x := x + 1;
end;
end;
1:
begin
pl := @Data.Buffer;
pl2 := @Buffer2;
while x < Data.OutFrames do
begin
pl2^[x] := (pl^[x]);
x := x + 1;
end;
end;
end;
Result := Buffer2;
end
else
begin
Result := data.Buffer;
end;
end;
{$IF DEFINED(noiseremoval)}
function Tuos_Player.InputAddDSPNoiseRemoval(InputIndex: cint32): cint32;
// DSP Noise Removal
// InputIndex : InputIndex of a existing Input
// result : otherwise index of DSPIn in array
// example DSPIndex1 := InputAddDSPNoiseRemoval(InputIndex1);
begin
Result := InputAddDSP(InputIndex, Nil, @uos_NoiseRemoval, Nil, Nil);
StreamIn[InputIndex].data.DSPNoiseIndex := Result ;
StreamIn[InputIndex].DSP[result].fftdata := Tuos_FFT.Create();
StreamIn[InputIndex].DSP[result].fftdata.FNoise :=
TuosNoiseRemoval.Create(StreamIn[InputIndex].
data.Channels,roundmath(StreamIn[InputIndex].
data.
SampleRate));
StreamIn[InputIndex].DSP[result].fftdata.FNoise.samprate :=
roundmath(StreamIn[InputIndex].data.
SampleRate);
StreamIn[InputIndex].DSP[result].fftdata.FNoise.WriteProc :=
@StreamIn[InputIndex].DSP[result].
fftdata.FNoise.WriteData;
StreamIn[InputIndex].DSP[result].fftdata.FNoise.isprofiled := false;
end;
procedure Tuos_Player.InputSetDSPNoiseRemoval(InputIndex: cint32; Enable: boolean);
begin
StreamIn[InputIndex].DSP[StreamIn[InputIndex].data.DSPNoiseIndex].enabled := Enable ;
end;
function Tuos_Player.OutputAddDSPNoiseRemoval(OutputIndex: cint32): cint32;
// DSP Noise Removal
// OutputIndex : OutputIndex of a existing Output
// result : otherwise index of DSPInOut in array
// example DSPIndex1 := OutputAddDSPNoiseRemoval(OutputIndex1);
begin
Result := OutputAddDSP(OutputIndex, Nil, @uos_NoiseRemoval, Nil, Nil);
StreamOut[OutputIndex].data.DSPNoiseIndex := Result ;
StreamOut[OutputIndex].DSP[result].fftdata := Tuos_FFT.Create();
StreamOut[OutputIndex].DSP[result].fftdata.FNoise :=
TuosNoiseRemoval.Create(StreamOut[OutputIndex
].data.Channels,roundmath(StreamOut[
OutputIndex].data.
SampleRate));
StreamOut[OutputIndex].DSP[result].fftdata.FNoise.samprate :=
roundmath(StreamOut[OutputIndex].
data.
SampleRate);
StreamOut[OutputIndex].DSP[result].fftdata.FNoise.WriteProc :=
@StreamOut[OutputIndex].DSP[result]
.fftdata.FNoise.WriteData;
StreamOut[OutputIndex].DSP[result].fftdata.FNoise.isprofiled := false;
end;
procedure Tuos_Player.OutputSetDSPNoiseRemoval(OutputIndex: cint32; Enable: boolean);
begin
StreamOut[OutputIndex].DSP[StreamOut[OutputIndex].data.DSPNoiseIndex].enabled := Enable ;
end;
{$endif}
function Tuos_Player.InputAddDSPVolume(InputIndex: cint32; VolLeft: double;
VolRight: double): cint32;
// DSP Volume changer
// InputIndex : InputIndex of a existing Input
// VolLeft : Left volume
// VolRight : Right volume
// result : index of DSPIn in array
// example DSPIndex1 := InputAddDSPVolume(InputIndex1,1,1);
begin
Result := InputAddDSP(InputIndex, Nil, @uos_DSPVolumeIn, Nil, Nil);
StreamIn[InputIndex].Data.VLeft := VolLeft;
StreamIn[InputIndex].Data.VRight := VolRight;
end;
function Tuos_Player.InputAddDSP1ChanTo2Chan(InputIndex: cint32): cint32;
// Convert mono 1 channel input to stereo 2 channels input.
// Works only if the input is mono 1 channel othewise stereo 2 chan is keeped.
// InputIndex : InputIndex of a existing Input
// result : index of DSPIn in array
// example DSPIndex1 := InputAddDSP1ChanTo2Chan(InputIndex1);
begin
Result := InputAddDSP(InputIndex, Nil, @uos_InputAddDSP1ChanTo2Chan, Nil, Nil);
end;
function Tuos_Player.OutputAddDSPVolume(OutputIndex: cint32; VolLeft: double;
VolRight: double): cint32;
// DSP Volume changer
// OutputIndex : OutputIndex of a existing Output
// VolLeft : Left volume ( 1 = max)
// VolRight : Right volume ( 1 = max)
// result : index of DSPIn in array
// example DSPIndex1 := OutputAddDSPVolume(OutputIndex1,1,1);
begin
Result := OutputAddDSP(OutputIndex, Nil, @uos_DSPVolumeOut, Nil, Nil);
StreamOut[OutputIndex].Data.VLeft := VolLeft;
StreamOut[OutputIndex].Data.VRight := VolRight;
end;
procedure Tuos_Player.InputSetDSPVolume(InputIndex: cint32; DSPVolIndex: cint32;
VolLeft: double; VolRight: double; Enable: boolean);
// InputIndex : InputIndex of a existing Input
// DSPIndex : DSPVolIndex of a existing DSPVolume
// VolLeft : Left volume ( -1 = do not change)
// VolRight : Right volume ( -1 = do not change)
// Enable : Enabled
// example InputSetDSPVolume(InputIndex1,DSPVolIndex1,1,0.8,True);
begin
if VolLeft <> -1 then
StreamIn[InputIndex].Data.VLeft := VolLeft;
if VolRight <> -1 then
StreamIn[InputIndex].Data.VRight := VolRight;
StreamIn[InputIndex].DSP[DSPVolIndex].Enabled := Enable;
end;
procedure Tuos_Player.OutputSetDSPVolume(OutputIndex: cint32;
DSPVolIndex: cint32; VolLeft: double; VolRight: double;
Enable: boolean);
// OutputIndex : OutputIndex of a existing Output
// DSPIndex : DSPIndex of a existing DSP
// VolLeft : Left volume
// VolRight : Right volume
// Enable : Enabled
// example OutputSetDSPVolume(InputIndex1,DSPIndex1,1,0.8,True);
begin
if VolLeft <> -1 then
StreamOut[OutputIndex].Data.VLeft := VolLeft;
if VolRight <> -1 then
StreamOut[OutputIndex].Data.VRight := VolRight;
StreamOut[OutputIndex].DSP[DSPVolIndex].Enabled := Enable;
end;
function Tuos_Player.InputAddFilter(InputIndex: cint32;
TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL:
cfloat;
TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR:
cfloat;
AlsoBuf: boolean; LoopProc: TProc): cint32;
// InputIndex : InputIndex of a existing Input
// TypeFilterL: Type of filter left:
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// LowFrequencyL : Lowest frequency left( -1 : current LowFrequency )
// HighFrequencyL : Highest frequency left( -1 : current HighFrequency )
// GainL : gain left to apply to filter
// TypeFilterR: Type of filter right (ignored if mono):
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
// HighFrequencyR : Highest frequency left( -1 : current HighFrequency )
// GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
// AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
// LoopProc : external procedure of object to synchronize after DSP done
// result : index of DSPIn in array
var
FilterIndex: cint32;
begin
FilterIndex := InputAddDSP(InputIndex, Nil, @uos_BandFilter, Nil, LoopProc);
if alsobuf = false then
begin
StreamIn[InputIndex].data.hasfilters := true;
inc(StreamIn[InputIndex].data.nbfilters);
end;
StreamIn[InputIndex].DSP[FilterIndex].fftdata :=
Tuos_FFT.Create();
setlength(StreamIn[InputIndex].DSP[FilterIndex].fftdata.Virtualbuffer, length(StreamIn[InputIndex]
.data.buffer));
if TypeFilterL = -1 then TypeFilterL := 1;
if TypeFilterR = -1 then TypeFilterR := 1;
InputSetFilter(InputIndex, FilterIndex, TypeFilterL, LowFrequencyL, HighFrequencyL, GainL,
TypeFilterR, LowFrequencyR, HighFrequencyR, GainR, AlsoBuf, LoopProc, True);
Result := FilterIndex;
end;
function Tuos_Player.OutputAddFilter(OutputIndex: cint32;
TypeFilterL: shortint; LowFrequencyL, HighFrequencyL, GainL:
cfloat;
TypeFilterR: shortint; LowFrequencyR, HighFrequencyR, GainR:
cfloat;
AlsoBuf: boolean; LoopProc: TProc): cint32;
// OutputIndex : InputIndex of a existing Output
// TypeFilterL: Type of filter left:
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// LowFrequencyL : Lowest frequency left( -1 : current LowFrequency )
// HighFrequencyL : Highest frequency left( -1 : current HighFrequency )
// GainL : gain left to apply to filter
// TypeFilterR: Type of filter right (ignored if mono):
// ( -1 = current filter ) (fBandAll = 0, fBandSelect = 1, fBandReject = 2
// LowFrequencyR : Lowest frequency Right (ignored if mono) ( -1 : current LowFrequency )
// HighFrequencyR : Highest frequency left( -1 : current HighFrequency )
// GainR : gain right (ignored if mono) to apply to filter ( 0 to what reasonable )
// AlsoBuf : The filter alter buffer aswell ( otherwise, only result is filled in fft.data )
// LoopProc : external procedure of object to synchronize after DSP done
// result : index of DSPIn in array
var
FilterIndex: cint32;
begin
FilterIndex := OutputAddDSP(OutputIndex, Nil, @uos_BandFilter, Nil, LoopProc);
if alsobuf = false then
begin
StreamOut[OutputIndex].data.hasfilters := true;
inc(StreamOut[OutputIndex].data.nbfilters);
end;
StreamOut[OutputIndex].DSP[FilterIndex].fftdata :=
Tuos_FFT.Create();
setlength(StreamOut[OutputIndex].DSP[FilterIndex].fftdata.Virtualbuffer,
length(StreamOut[OutputIndex].data.buffer));
if TypeFilterL = -1 then TypeFilterL := 1;
if TypeFilterR = -1 then TypeFilterR := 1;
OutputSetFilter(OutputIndex, FilterIndex, TypeFilterL, LowFrequencyL, HighFrequencyL, GainL,
TypeFilterR, LowFrequencyR, HighFrequencyR, GainR, AlsoBuf, LoopProc, True);
Result := FilterIndex;
end;
{$IF DEFINED(portaudio)}
function Tuos_Player.AddFromDevIn(Device: cint32; Latency: CDouble;
SampleRate: CDouble; OutputIndex: cint32;
SampleFormat: cint32; FramesCount : cint32; ChunkCount: cint32):
cint32
;
// Add Input from IN device with custom parameters
// Device ( -1 is default Input device )
// Latency ( -1 is latency suggested )
// SampleRate : delault : -1 (44100)
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex
// (if multi-output then OutName = name of each output separeted by ';')
// SampleFormat : -1 default : Int16 (0: Float32, 1:Int32, 2:Int16)
// FramesCount : -1 default : 4096
// ChunkCount : default : -1 (= 512)
var
x, err: cint32;
begin
result := -1 ;
if device = -1 then
err := Pa_GetDefaultInputDevice();
if err = -1 then result := -2;
if result <> -2 then
begin
x := 0;
err := -1;
SetLength(StreamIn, Length(StreamIn) + 1);
StreamIn[Length(StreamIn) - 1] := Tuos_InStream.Create();
x := Length(StreamIn) - 1;
StreamIn[x].Data.Enabled := false;
StreamIn[x].Data.levelEnable := 0;
StreamIn[x].Data.PositionEnable := 0;
StreamIn[x].Data.levelArrayEnable := 0;
StreamIn[x].PAParam.HostApiSpecificStreamInfo := Nil;
if device = -1 then
StreamIn[x].PAParam.device :=
Pa_GetDefaultInputDevice()
else
StreamIn[x].PAParam.device := cint32(device);
if SampleRate = -1 then
StreamIn[x].Data.SampleRate := DefRate
else
StreamIn[x].Data.SampleRate := SampleRate;
StreamIn[x].PAParam.SuggestedLatency := CDouble(0);
StreamIn[x].PAParam.SampleFormat := paInt16;
case SampleFormat of
0: StreamIn[x].PAParam.SampleFormat := paFloat32;
1: StreamIn[x].PAParam.SampleFormat := paInt32;
2: StreamIn[x].PAParam.SampleFormat := paInt16;
end;
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := CInt32(2)
else
StreamIn[x].Data.SampleFormat := CInt32(SampleFormat);
if ((Pa_GetDeviceInfo(StreamIn[x].PAParam.device)^.
maxInputChannels)) > 1 then
StreamIn[x].PAParam.channelCount := CInt32(2)
else
StreamIn[x].PAParam.channelCount := CInt32(1) ;
StreamIn[x].data.channels := StreamIn[x].PAParam.channelCount;
if FramesCount = -1 then StreamIn[x].Data.Wantframes := 4096
else
StreamIn[x].Data.Wantframes := (FramesCount) ;
if ChunkCount = -1 then ChunkCount := 512;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes* StreamIn[x].Data.channels);
// StreamIn[x].Data.outframes := length(StreamIn[x].Data.Buffer);
StreamIn[x].Data.outframes := 0;
StreamIn[x].Data.Status := 1;
StreamIn[x].Data.TypePut := 1;
StreamIn[x].Data.ratio := 2;
StreamIn[x].Data.Output := OutputIndex;
StreamIn[x].Data.seekable := False;
StreamIn[x].Data.LibOpen := 2;
StreamIn[x].LoopProc := Nil;
err := Pa_OpenStream(@StreamIn[x].Data.HandleSt, @StreamIn[x].PAParam,
Nil, CDouble(StreamIn[x].Data.SampleRate), CULong(ChunkCount), paClipOff, Nil, Nil);
if err <> 0 then
else
begin
StreamIn[x].Data.Enabled := True;
Result := x;
end;
end
else Result := -1;
end;
{$endif}
function Tuos_Player.InputGetBuffer(InputIndex: cint32): TDArFloat;
// Get current buffer
begin
result := StreamIn[InputIndex].data.Buffer;
end;
function Tuos_Player.AddFromEndlessMuted(Channels : cint32; FramesCount: cint32): cint32;
// Add a input from Endless Muted dummy sine wav
// FramesCountByChan = FramesCount of input-to-follow div channels of input-to-follow.
var
x, i : cint32;
begin
result := -1 ;
x := 0;
SetLength(StreamIn, Length(StreamIn) + 1);
StreamIn[Length(StreamIn) - 1] := Tuos_InStream.Create();
x := Length(StreamIn) - 1;
StreamIn[x].Data.Enabled := false;
StreamIn[x].Data.levelEnable := 0;
StreamIn[x].Data.PositionEnable := 0;
StreamIn[x].Data.levelArrayEnable := 0;
if channels = -1 then
StreamIn[x].data.channels := 2
else
StreamIn[x].data.channels := Channels;
StreamIn[x].Data.SampleRate := DefRate;
if FramesCount = -1 then StreamIn[x].Data.Wantframes := trunc(1024 * 2 Div StreamIn[x].Data.
channels)
else
StreamIn[x].Data.Wantframes := FramesCount * 2 Div channels ;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes* StreamIn[x].Data.channels);
StreamIn[x].Data.OutFrames := StreamIn[x].Data.WantFrames ;
for i := 0 to length(StreamIn[x].Data.Buffer) -1 do
StreamIn[x].Data.Buffer[i] := 0.0;
StreamIn[x].Data.SampleFormat := CInt32(0);
StreamIn[x].Data.VLeft := 0;
StreamIn[x].Data.Vright := 0;
StreamIn[x].Data.Status := 1;
StreamIn[x].Data.TypePut := 5;
StreamIn[x].Data.HandleSt := pchar('endless');
StreamIn[x].Data.ratio := 2;
StreamIn[x].Data.Output := -1;
StreamIn[x].Data.seekable := False;
StreamIn[x].Data.LibOpen := -1;
StreamIn[x].LoopProc := Nil;
StreamIn[x].Data.Enabled := True;
Result := x;
end;
{$IF DEFINED(synthesizer)}
function Tuos_Player.AddFromSynth(Channels: integer; WaveTypeL, WaveTypeR: shortint;
FrequencyL, FrequencyR: float; VolumeL, VolumeR: float;
duration : cint32; NbHarmonics: cint32; EvenHarmonics: cint32;
OutputIndex: cint32; SampleFormat: cint32 ; SampleRate: CDouble ;
FramesCount : cint32): cint32;
// Add a input from Synthesizer with custom parameters
// Channels: default: -1 (2) (1 = mono, 2 = stereo)
// WaveTypeL: default: -1 (0) (0 = sine-wave 1 = square-wave, 2 = triangle, 2= triangle, 3=sawtooth used for mono and stereo)
// WaveTypeR: default: -1 (0) (0 = sine-wave 1 = square-wave,2 = triangle, 2= triangle, 3=sawtooth used, used for stereo, ignored for mono)
// FrequencyL: default: -1 (440 htz) (Left frequency, used for mono)
// FrequencyR: default: -1 (440 htz) (Right frequency, used for stereo, ignored for mono)
// VolumeL: default: -1 (= 1) (from 0 to 1) => volume left
// VolumeR: default: -1 (= 1) (from 0 to 1) => volume rigth (ignored for mono)
// Duration: default: -1 (= 1000) => duration in msec (0 = endless)
// NbHarmonics: default: -1 (= 0) Number of Harmonies
// EvenHarmonics: default: -1 (= 0) (0 = all harmonics, 1 = Only even harmonics)
// OutputIndex: Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')
// SampleFormat: default : -1 (0: Float32) (0: Float32, 1:Int32, 2:Int16)
// SampleRate: delault : -1 (44100)
// FramesCount: -1 default : 1024
// result: Input Index in array -1 = error
var
x : cint32;
begin
result := -1 ;
x := 0;
SetLength(StreamIn, Length(StreamIn) + 1);
StreamIn[Length(StreamIn) - 1] := Tuos_InStream.Create();
x := Length(StreamIn) - 1;
StreamIn[x].Data.Enabled := false;
StreamIn[x].Data.levelEnable := 0;
StreamIn[x].Data.PositionEnable := 0;
StreamIn[x].Data.levelArrayEnable := 0;
if channels < 1 then
StreamIn[x].data.channels := 2
else
StreamIn[x].data.channels := channels;
if SampleRate = -1 then
StreamIn[x].Data.SampleRate := DefRate
else
StreamIn[x].Data.SampleRate := SampleRate;
if FramesCount = -1 then StreamIn[x].Data.Wantframes := 1024
else
StreamIn[x].Data.Wantframes := FramesCount ;
if FrequencyL = -1 then
StreamIn[x].Data.freqLsine := 440
else
StreamIn[x].Data.freqLsine := FrequencyL ;
if FrequencyR = -1 then
StreamIn[x].Data.freqRsine := 440
else
StreamIn[x].Data.freqRsine := FrequencyR ;
if WaveTypeL < 1 then
StreamIn[x].Data.typLsine := 0
else
StreamIn[x].Data.typLsine := WaveTypeL;
if WaveTypeR < 1 then
StreamIn[x].Data.typRsine := 0
else
StreamIn[x].Data.typRsine := WaveTypeR;
StreamIn[x].Data.PosInTableLeft := 0;
StreamIn[x].Data.PosInTableRight := 0;
if NbHarmonics < 1 then
StreamIn[x].data.harmonic := 0
else
StreamIn[x].data.harmonic := NbHarmonics;
if EvenHarmonics < 1 then
StreamIn[x].data.evenharm := 0
else
StreamIn[x].data.evenharm := 1;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes* StreamIn[x].Data.channels);
StreamIn[x].Data.posdursine := 0 ;
if duration = -1 then duration := 1000;
StreamIn[x].Data.dursine := trunc( StreamIn[x].Data.SampleRate * duration / 1000);
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := CInt32(0)
else
StreamIn[x].Data.SampleFormat := CInt32(SampleFormat);
if VolumeL = -1 then StreamIn[x].Data.VLeft := 1
else
StreamIn[x].Data.VLeft := VolumeL;
if VolumeR = -1 then StreamIn[x].Data.Vright := 1
else
StreamIn[x].Data.Vright := VolumeR;
StreamIn[x].Data.Status := 1;
StreamIn[x].Data.TypePut := 3;
StreamIn[x].Data.HandleSt := pchar('synth');
if (StreamIn[x].Data.SampleFormat = 2) then
StreamIn[x].Data.ratio := StreamIn[x].data.channels
else StreamIn[x].Data.ratio := 2;
StreamIn[x].Data.Output := OutputIndex;
StreamIn[x].Data.seekable := False;
StreamIn[x].Data.LibOpen := -1;
StreamIn[x].LoopProc := Nil;
StreamIn[x].Data.Enabled := True;
FillLookupTable(x, StreamIn[x].Data.typLsine, 1,StreamIn[x].data.harmonic, StreamIn[x].data.
evenharm);
FillLookupTable(x, StreamIn[x].Data.typRsine, 2,StreamIn[x].data.harmonic, StreamIn[x].data.
evenharm);
Result := x;
end;
procedure Tuos_Player.InputSetSynth(InputIndex: cint32; WaveTypeL, WaveTypeR: shortint;
FrequencyL, FrequencyR: float; VolumeL, VolumeR: float; duration
: cint32;
NbHarmonic: cint32; EvenHarmonics: cint32; Enable: boolean);
// InputIndex: one existing input index
// WaveTypeL : do not change: -1 (0 = sine-wave 1 = square-wave, 2 = triangle, 2= triangle, 3=sawtooth used for mono and stereo)
// WaveTypeR : do not change: -1 (0 = sine-wave 1 = square-wave, 2 = triangle, 2= triangle, 3=sawtooth used for stereo, ignored for mono)
// FrequencyL : do not change: -1 (Left frequency, used for mono)
// FrequencyR : do not change: -1 (440 htz) (Right frequency, used for stereo, ignored for mono)
// VolumeL : do not change: -1 (= 1) (from 0 to 1) => volume left
// VolumeR : do not change: -1 (from 0 to 1) => volume rigth (ignored for mono)
// Duration : in msec (-1 = do not change)
// NbHarmonic : Number of Harmonies (-1 not change)
// EvenHarmonics: default: -1 (= 0) (0 = all harmonics, 1 = Only even harmonics)
// Enable : true or false ;
var
newtable : boolean = false;
begin
StreamIn[InputIndex].Data.Enabled := Enable;
if NbHarmonic <> -1 then
begin
StreamIn[InputIndex].Data.harmonic := NbHarmonic;
newtable := true;
end;
if EvenHarmonics <> - 1 then
begin
if EvenHarmonics = 0 then
StreamIn[InputIndex].data.evenharm := 0
else
StreamIn[InputIndex].data.evenharm := 1;
newtable := true;
end;
if WaveTypeL <> -1 then
begin
StreamIn[InputIndex].Data.typLsine := WaveTypeL;
newtable := true;
end;
if WaveTypeR <> -1 then
begin
StreamIn[InputIndex].Data.typRsine := WaveTypeR;
newtable := true;
end;
if FrequencyL <> -1 then
begin
StreamIn[InputIndex].Data.freqLsine := FrequencyL ;
end;
if FrequencyR <> -1 then
begin
StreamIn[InputIndex].Data.freqRsine := FrequencyR ;
end;
if VolumeL <> -1 then
begin
StreamIn[InputIndex].Data.VLeft := VolumeL;
end;
if VolumeR <> -1 then
begin
StreamIn[InputIndex].Data.Vright := VolumeR;
end;
if Duration <> -1 then StreamIn[InputIndex].Data.dursine :=
trunc( StreamIn[InputIndex].Data.
SampleRate * duration / 1000);
if newtable then
begin
FillLookupTable(InputIndex,StreamIn[InputIndex].Data.typLsine, 1,
StreamIn[InputIndex].Data.harmonic, StreamIn[InputIndex].data.evenharm);
FillLookupTable(InputIndex,StreamIn[InputIndex].Data.typRsine, 2,
StreamIn[InputIndex].Data.harmonic, StreamIn[InputIndex].data.evenharm);
end;
end;
{$endif}
{$IF DEFINED(shout)}
function Tuos_Player.AddIntoIceServer(SampleRate : CDouble; Channels: cint; SampleFormat: cint;
EncodeType: cint; Port: cint; Host: pchar; User: pchar;
Password: pchar; MountFile :pchar): cint32;
// Add a Output into a IceCast server for audio-web-streaming
// SampleRate : delault : -1 (48100)
// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
// SampleFormat : -1 default : float32 : (0:float32, 1:Int16)
// EncodeType : default : -1 (0:Music) (0: Music, 1:Voice)
// Port : default : -1 (= 8000)
// Host : default : 'def' (= '127.0.0.1')
// User : default : 'def' (= 'source')
// Password : default : 'def' (= 'hackme')
// MountFile : default : 'def' (= '/example.opus')
// result : Output Index in array -1 = error
var
x, typeenc : cint32;
err : integer = -1;
begin
result := -1 ;
x := 0;
err := -1;
SetLength(StreamOut, Length(StreamOut) + 1);
StreamOut[Length(StreamOut) - 1] := Tuos_OutStream.Create();
x := Length(StreamOut) - 1;
StreamOut[x].Data.Enabled := false;
if (EncodeType = -1) or (EncodeType = 0) then typeenc := OPUS_APPLICATION_AUDIO
else
typeenc := OPUS_APPLICATION_VOIP ;
if SampleRate = -1 then StreamOut[x].Data.SampleRate := 48000
else
StreamOut[x].Data.SampleRate := SampleRate;
if Channels = -1 then StreamOut[x].Data.Channels := 2
else
StreamOut[x].Data.Channels := Channels;
if SampleFormat = -1 then StreamOut[x].Data.SampleFormat := 0
else
StreamOut[x].Data.SampleFormat := SampleFormat;
StreamOut[x].Data.TypePut := 2 ;
setlength(StreamOut[x].Data.Buffer,1024 *2);
// setlength(StreamOut[x].Data.Buffer,960);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('before opus_encoder_create ' );
{$endif}
// opus encoder
StreamOut[x].encoder := opus_encoder_create(StreamOut[x].Data.SampleRate,
StreamOut[x].Data.Channels, typeenc, err);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if (err<0)
then
begin
WriteLn(Format('failed to create an encoder: %s', [opus_strerror(err)]));
end;
{$endif}
// if (err=0) then
// err := opus_encoder_ctl(StreamOut[x].encoder , OPUS_SET_BITRATE(cBITRATE));
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if (err<0)
then
begin
WriteLn(Format('failed opus_encoder_ctl: %s', [opus_strerror(err)]));
end;
{$endif}
if err =0 then
begin
StreamOut[x].Data.HandleSt := Nil;
shout_init();
StreamOut[x].Data.HandleSt := shout_new();
if assigned(StreamOut[x].Data.HandleSt) then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('shhandle assigned');
{$endif}
err := shout_set_host( StreamOut[x].Data.HandleSt, pchar(Host));
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = SHOUTERR_SUCCESS then
WriteLn('shout_set_host ok ' + inttostr(err))
else
WriteLn('shout_set_host error: ' + pchar(shout_get_error(StreamOut[x].Data.HandleSt)));
{$endif}
err := shout_set_protocol(StreamOut[x].Data.HandleSt, SHOUT_PROTOCOL_HTTP);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = SHOUTERR_SUCCESS then
WriteLn('shout_set_protocol ' + inttostr(err))
else
WriteLn('shout_set_protocol error: ' + pchar(shout_get_error(StreamOut[x].Data.HandleSt)
));
{$endif}
err := shout_set_port(StreamOut[x].Data.HandleSt, Port);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = SHOUTERR_SUCCESS then
WriteLn('shout_set_port ok ' + inttostr(err))
else
WriteLn('shout_set_port error: ' + pchar(shout_get_error(StreamOut[x].Data.HandleSt)));
{$endif}
err := shout_set_password(StreamOut[x].Data.HandleSt, pchar(Password));
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = SHOUTERR_SUCCESS then
WriteLn('set_password ok ' + inttostr(err))
else
WriteLn('set_password error: ' + pchar(shout_get_error(StreamOut[x].Data.HandleSt)));
{$endif}
err := shout_set_mount(StreamOut[x].Data.HandleSt, pchar(MountFile));
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = SHOUTERR_SUCCESS then
WriteLn('shout_set_mount ok ' + inttostr(err))
else
WriteLn('shout_set_mount error: ' + pchar(shout_get_error(StreamOut[x].Data.HandleSt)));
{$endif}
err := shout_set_user(StreamOut[x].Data.HandleSt, pchar(user));
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = SHOUTERR_SUCCESS then
WriteLn('shout_set_user ok ' + inttostr(err))
else
WriteLn('shout_set_user error: ' + pchar(shout_get_error(StreamOut[x].Data.HandleSt)));
{$endif}
err := shout_set_format(StreamOut[x].Data.HandleSt, SHOUT_FORMAT_OGG);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = SHOUTERR_SUCCESS then
WriteLn('shout_set_format ok ' + inttostr(err))
else
WriteLn('shout_set_format error: ' + pchar(shout_get_error(StreamOut[x].Data.HandleSt)))
;
{$endif}
err := shout_open(StreamOut[x].Data.HandleSt);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = SHOUTERR_SUCCESS then
WriteLn('shout_open ok ' + inttostr(err))
else
WriteLn('shout_open error: ' + pchar(shout_get_error(StreamOut[x].Data.HandleSt)));
{$endif}
if err = SHOUTERR_SUCCESS then
begin
StreamOut[x].Data.Enabled := True;
result := x
end
else
begin
shout_free(StreamOut[x].Data.HandleSt);
StreamOut[Length(StreamOut) - 1].Destroy;
setlength(StreamOut, Length(StreamOut) - 1);
end;
end
else
begin
StreamOut[Length(StreamOut) - 1].Destroy;
setlength(StreamOut, Length(StreamOut) - 1);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('shhandle not assigned') {$endif} ;
end;
end;
end;
{$endif}
procedure uos_CustBufferInfos(Var bufferinfos: Tuos_BufferInfos; SampleRate: CDouble; SampleFormat
: cint32; Channels: cint32 ; Length: cint32);
begin
bufferinfos.SampleRate := Samplerate;
bufferinfos.SampleRateRoot := Samplerate;
bufferinfos.SampleFormat := SampleFormat;
bufferinfos.Channels := Channels;
bufferinfos.Length := Length;
bufferinfos.LibOpen := 0;
bufferinfos.Ratio := 2 ;
end;
function Tuos_Player.AddIntoFileFromMem(Filenamepath: PChar; SampleRate: CDouble;
Channels: LongInt; SampleFormat: LongInt; FramesCount:
LongInt; FileFormat: cint32): LongInt;
// Add a Output into audio wav file with Custom parameters
// FileName : filename of saved audio wav file
// SampleRate : delault : -1 (44100)
// Channels : delault : -1 (2:stereo) (1:mono, 2:stereo, ...)
// SampleFormat : -1 default : Int16 : (1:Int32, 2:Int16)
// FramesCount : -1 default : 65536 div channels
// FileFormat : default : -1 (wav) (0:wav, 1:pcm, 2:custom);
// result : Output Index in array -1 = error
// example : OutputIndex1 := AddIntoFileFromMem(edit5.Text,-1,-1,0, -1);
var
x: LongInt;
begin
result := -1 ;
x := 0;
SetLength(StreamOut, Length(StreamOut) + 1);
StreamOut[Length(StreamOut) - 1] := Tuos_OutStream.Create();
x := Length(StreamOut) - 1;
StreamOut[x].Data.Enabled := false;
StreamOut[x].FileBuffer.ERROR := 0;
StreamOut[x].Data.Filename := Filenamepath;
if (FileFormat = -1) or (FileFormat = 0) then
StreamOut[x].FileBuffer.FileFormat := 0
else StreamOut[x].FileBuffer.FileFormat := FileFormat;
StreamOut[x].Data.TypePut := 4;
FillChar(StreamOut[x].FileBuffer, sizeof(StreamOut[x].FileBuffer), 0);
StreamOut[x].FileBuffer.DataMS := TMemoryStream.Create;
result := x;
if (Channels = -1) then
StreamOut[x].FileBuffer.wChannels := 2
else
StreamOut[x].FileBuffer.wChannels := Channels;
StreamOut[x].Data.Channels := StreamOut[x].FileBuffer.wChannels;
if FramesCount = -1 then StreamOut[x].Data.Wantframes := 65536 Div StreamOut[x].Data.Channels
else
StreamOut[x].Data.Wantframes := FramesCount ;
SetLength(StreamOut[x].Data.Buffer, StreamOut[x].Data.Wantframes*StreamOut[x].Data.Channels);
if (SampleFormat = -1) or (SampleFormat = 2) then
begin
StreamOut[x].FileBuffer.wBitsPerSample := 16;
StreamOut[x].Data.SampleFormat := 2;
end;
if (SampleFormat = 1) then
begin
StreamOut[x].FileBuffer.wBitsPerSample := 32;
StreamOut[x].Data.SampleFormat := 1;
end;
if SampleRate = -1 then
StreamOut[x].FileBuffer.wSamplesPerSec := 44100
else
StreamOut[x].FileBuffer.wSamplesPerSec := roundmath(samplerate);
StreamOut[x].Data.Samplerate := StreamOut[x].FileBuffer.wSamplesPerSec;
StreamOut[x].LoopProc := Nil;
StreamOut[x].Data.Enabled := True;
end;
function Tuos_Player.AddIntoFile(Filenamepath: PChar; SampleRate: CDouble;
Channels: cint32; SampleFormat: cint32 ; FramesCount: cint32 ;
FileFormat: cint32): cint32;
// Add a Output into audio wav file with custom parameters
// FileName : filename of saved audio wav file
// SampleRate : delault : -1 (44100)
// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
// SampleFormat : default : -1 (2:Int16) ( 1:Int32, 2:Int16)
// FramesCount : default : -1 (= 4096)
// FileFormat : default : -1 (wav) (0:wav, 1:pcm, 2:custom, 3:ogg);
// result : Output Index in array -1 = error
// example : OutputIndex1 := AddIntoFile(edit5.Text,-1,-1, 0, -1, -1);
var
x: cint32;
wChunkSize: cint32;
wFileSize: cint32;
IDwav: array[0..3] of char;
Header: Tuos_WaveHeaderChunk;
{$IF DEFINED(sndfile)}
sfInfo: TSF_INFO;
{$endif}
begin
result := -1 ;
x := 0;
SetLength(StreamOut, Length(StreamOut) + 1);
StreamOut[Length(StreamOut) - 1] := Tuos_OutStream.Create();
x := Length(StreamOut) - 1;
StreamOut[x].Data.Enabled := false;
StreamOut[x].FileBuffer.ERROR := 0;
StreamOut[x].Data.Filename := filenamepath;
if (FileFormat = -1) or (FileFormat = 0) then
StreamOut[x].FileBuffer.FileFormat := 0
else StreamOut[x].FileBuffer.FileFormat := FileFormat;
FillChar(StreamOut[x].FileBuffer, sizeof(StreamOut[x].FileBuffer), 0);
result := x;
if (Channels = -1) then
StreamOut[x].FileBuffer.wChannels := 2
else
StreamOut[x].FileBuffer.wChannels := Channels;
StreamOut[x].Data.Channels := StreamOut[x].FileBuffer.wChannels;
if FramesCount = -1 then StreamOut[x].Data.Wantframes := 65536 Div StreamOut[x].Data.Channels
else
StreamOut[x].Data.Wantframes := FramesCount ;
SetLength(StreamOut[x].Data.Buffer, StreamOut[x].Data.Wantframes*StreamOut[x].Data.Channels);
if (SampleFormat = -1) or (SampleFormat = 2) then
begin
StreamOut[x].FileBuffer.wBitsPerSample := 16;
StreamOut[x].Data.SampleFormat := 2;
end;
if (SampleFormat = 1) then
begin
StreamOut[x].FileBuffer.wBitsPerSample := 32;
StreamOut[x].Data.SampleFormat := 1;
end;
if (SampleFormat = 0) then
begin
StreamOut[x].FileBuffer.wBitsPerSample := 32;
StreamOut[x].Data.SampleFormat := 0;
end;
if SampleRate = -1 then
StreamOut[x].FileBuffer.wSamplesPerSec := 44100
else
StreamOut[x].FileBuffer.wSamplesPerSec := roundmath(samplerate);
StreamOut[x].Data.Samplerate := StreamOut[x].FileBuffer.wSamplesPerSec;
StreamOut[x].LoopProc := Nil;
if fileformat = 3 then
begin
// ogg file
{$IF DEFINED(sndfile)}
StreamOut[x].FileBuffer.FileFormat := 3;
StreamOut[x].Data.TypePut := 6 ;
sfInfo.format := SF_FORMAT_OGG Or SF_FORMAT_VORBIS;
sfInfo.channels := StreamOut[x].Data.Channels;
sfInfo.frames := streamOut[x].Data.Wantframes;
SFinfo.samplerate := StreamOut[x].FileBuffer.wSamplesPerSec;
SFinfo.seekable := 0;
StreamOut[x].Data.Enabled := True;
StreamOut[x].Data.HandleSt := sf_open(pchar(FileNamepath), SFM_WRITE, sfInfo);
{$endif}
end
else
begin
// wav file
StreamOut[x].FileBuffer.Data := TFileStream.Create(filenamepath,fmCreate);
StreamOut[x].FileBuffer.Data.Seek(0, soFromBeginning);
StreamOut[x].Data.TypePut := 0 ;
IDwav := 'RIFF';
StreamOut[x].FileBuffer.Data.WriteBuffer(IDwav, 4);
wFileSize := 0;
StreamOut[x].FileBuffer.Data.WriteBuffer(wFileSize, 4);
IDwav := 'WAVE';
StreamOut[x].FileBuffer.Data.WriteBuffer(IDwav, 4);
IDwav := 'fmt ';
StreamOut[x].FileBuffer.Data.WriteBuffer(IDwav, 4);
wChunkSize := SizeOf(Header);
StreamOut[x].FileBuffer.Data.WriteBuffer(wChunkSize, 4);
Header.wFormatTag := 1;
Header.wChannels := StreamOut[x].FileBuffer.wChannels;
Header.wSamplesPerSec := StreamOut[x].FileBuffer.wSamplesPerSec;
Header.wBlockAlign := StreamOut[x].FileBuffer.wChannels * (StreamOut[x].FileBuffer.
wBitsPerSample Div 8);
Header.wAvgBytesPerSec := StreamOut[x].FileBuffer.wSamplesPerSec * Header.wBlockAlign;
Header.wBitsPerSample := StreamOut[x].FileBuffer.wBitsPerSample;
Header.wcbSize := 0;
StreamOut[x].FileBuffer.Data.WriteBuffer(Header, SizeOf(Header));
IDwav := 'data';
StreamOut[x].FileBuffer.Data.WriteBuffer(IDwav, 4);
wChunkSize := 0;
StreamOut[x].FileBuffer.Data.WriteBuffer(wChunkSize, 4);
StreamOut[x].Data.Enabled := True;
end;
end;
function Tuos_Player.AddIntoMemoryBuffer(outmemory: PDArFloat): cint32;
// Add a Output into memory-bufffer
// outmemory : buffer to use to store memory buffer
// example : OutputIndex1 := AddIntoMemoryBuffer(bufmemory);
var
x: integer;
begin
result := -1 ;
x := 0;
SetLength(StreamOut, Length(StreamOut) + 1);
StreamOut[Length(StreamOut) - 1] := Tuos_OutStream.Create();
x := Length(StreamOut) - 1;
StreamOut[x].Data.Enabled := false;
StreamOut[x].Data.TypePut := 3;
Streamout[x].Data.posmem := 0;
Streamout[x].BufferOut := outmemory;
StreamOut[x].Data.channels := 2;
StreamOut[x].Data.Wantframes := 65536 ;
StreamOut[x].Data.SampleFormat := 0;
StreamOut[x].Data.SampleRate := 44100 ;
SetLength(StreamOut[x].Data.Buffer,65536*2);
intobuf := true;
// to check, why ?
result := x;
StreamOut[x].Data.Enabled := True;
end;
function Tuos_Player.AddIntoMemoryBuffer(outmemory: PDArFloat; SampleRate: CDouble; SampleFormat:
LongInt;
Channels: LongInt; FramesCount: LongInt): LongInt;
// Add a Output into Memory Buffer with parameters.
// outmemory : pointer of buffer to use to store memory.
// SampleRate : delault : -1 (44100)
// SampleFormat : default : -1 (0:Float32) ( 1:Int32, 2:Int16)
// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
// FramesCount : default : -1 (= 65536)
var
x, ch, sr, sf, fr: integer;
begin
result := -1 ;
x := 0;
SetLength(StreamOut, Length(StreamOut) + 1);
StreamOut[Length(StreamOut) - 1] := Tuos_OutStream.Create();
x := Length(StreamOut) - 1;
StreamOut[x].Data.Enabled := false;
StreamOut[x].Data.TypePut := 3;
Streamout[x].Data.posmem := 0;
Streamout[x].BufferOut := outmemory;
if channels = -1 then ch := 2
else ch := channels;
StreamOut[x].Data.channels := ch;
if SampleFormat = -1 then sf := 0
else sf := SampleFormat;
StreamOut[x].Data.SampleFormat := sf;
if FramesCount = -1 then fr := 65536
else fr := FramesCount;
StreamOut[x].Data.Wantframes := fr ;
if SampleRate = -1 then sr := 44100
else sr := roundmath(SampleRate);
StreamOut[x].Data.SampleRate := sr ;
SetLength(StreamOut[x].Data.Buffer,fr*ch);
intobuf := true;
// to check, why ?
result := x;
StreamOut[x].Data.Enabled := True;
end;
{$IF DEFINED(portaudio)}
function Tuos_Player.AddIntoDevOut(Device: cint32; Latency: CDouble;
SampleRate: CDouble; Channels: cint32; SampleFormat: cint32 ;
FramesCount: cint32 ; ChunkCount: cint32): cint32;
// Add a Output into Device Output
// Device ( -1 is default device )
// Latency ( -1 is latency suggested )
// SampleRate : delault : -1 (44100)
// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (= 65536)
// ChunkCount : default : -1 (= 512)
// result : Output Index in array -1 = error
// example : OutputIndex1 := AddIntoDevOut(-1,-1,-1,-1,0,-1,-1);
var
x, x2, err: cint32;
begin
result := -1 ;
if device = -1 then
err := Pa_GetDefaultOutputDevice();
if err = -1 then result := -2;
if result <> -2 then
begin
x := 0;
err := -1;
SetLength(StreamOut, Length(StreamOut) + 1);
StreamOut[Length(StreamOut) - 1] := Tuos_OutStream.Create();
x := Length(StreamOut) - 1;
StreamOut[x].Data.Enabled := false;
{$IF DEFINED(portaudio)}
StreamOut[x].PAParam.hostApiSpecificStreamInfo := Nil;
if device = -1 then
StreamOut[x].PAParam.device := Pa_GetDefaultOutputDevice()
else
StreamOut[x].PAParam.device := device;
{$endif}
if SampleRate = -1 then
StreamOut[x].Data.SampleRate := DefRate
else
StreamOut[x].Data.SampleRate := SampleRate;
{$IF DEFINED(portaudio)}
if Latency = -1 then
StreamOut[x].PAParam.SuggestedLatency := CDouble((Pa_GetDeviceInfo(StreamOut[x].PAParam.
device)^. defaultHighOutputLatency)) * 1
else StreamOut[x].PAParam.SuggestedLatency := CDouble(Latency);
{$IF DEFINED(android)}
StreamOut[x].PAParam.SampleFormat := paFloat32;
{$else}
StreamOut[x].PAParam.SampleFormat := paInt16;
{$endif}
case SampleFormat of
0: StreamOut[x].PAParam.SampleFormat := paFloat32;
1: StreamOut[x].PAParam.SampleFormat := paInt32;
2: StreamOut[x].PAParam.SampleFormat := paInt16;
end;
{$endif}
if SampleFormat = -1 then
StreamOut[x].Data.SampleFormat := 2
else
StreamOut[x].Data.SampleFormat := SampleFormat;
if Channels = -1 then
begin
{$IF DEFINED(portaudio)}
StreamOut[x].PAParam.channelCount := 2 ;
{$endif}
StreamOut[x].Data.Channels := 2 ;
end
else
begin
{$IF DEFINED(portaudio)}
StreamOut[x].PAParam.channelCount := CInt32(Channels);
{$endif}
StreamOut[x].Data.Channels := CInt32(Channels);
end;
if FramesCount = -1 then StreamOut[x].Data.Wantframes :=
{$IF DEFINED(android)}
1024 * 64
else
{$else}
65536 div StreamOut[x].Data.Channels
else
{$endif}
StreamOut[x].Data.Wantframes := FramesCount ;
if ChunkCount = -1 then ChunkCount := 512;
SetLength(StreamOut[x].Data.Buffer, StreamOut[x].Data.Wantframes*StreamOut[x].Data.Channels);
x2 := 0 ;
while x2 < Length(StreamOut[x].Data.Buffer) do
begin
StreamOut[x].Data.Buffer[x2] := 0.0 ;
inc(x2);
end;
StreamOut[x].Data.TypePut := 1;
{$IF DEFINED(portaudio)}
err := Pa_OpenStream(@StreamOut[x].Data.HandleSt, Nil, @StreamOut[x].PAParam, CDouble(
StreamOut[x]
.Data.SampleRate), CULong(ChunkCount), paClipOff, Nil, Nil);
// err := Pa_OpenDefaultStream(@StreamOut[x].Data.HandleSt, 2, 2, paFloat32, DefRate, 512, nil, nil);
{$endif}
StreamOut[x].LoopProc := Nil;
if err <> 0 then Result := -1
else
begin
StreamOut[x].Data.Enabled := True;
Result := x;
end;
end
else Result := -1;
end;
{$endif}
{$IF DEFINED(webstream)}
function Tuos_Player.AddFromURL(URL: PChar; OutputIndex: cint32;
SampleFormat: cint32 ; FramesCount: cint32 ; AudioFormat: cint32 ;
ICYon : boolean): cint32;
// Add a Input from Audio URL
// URL : URL of audio file
// OutputIndex : OutputIndex of existing Output// -1: all output, -2: no output, other cint32 : existing Output
// SampleFormat : -1 default : Int16 (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (4096)
// AudioFormat : default : -1 (mp3) (0: mp3, 1: opus, 2:aac)
// ICYon : ICY data on/off
// example : InputIndex := AddFromURL('http://someserver/somesound.mp3',-1,-1,-1,-1,-1, false);
var
x, err, len, len2, i : cint32;
PipeBufferSize, totsamples : integer;
buffadd : tbytes;
samprat : cint32;
{$IF DEFINED(mpg123)}
mpinfo: Tmpg123_frameinfo;
// BufferTag: array[1..128] of char;
// F: file;
// mpid3v2: Tmpg123_id3v2;
{$endif}
{$IF DEFINED(opus)}
s: UTF8String;
j: Integer;
OpusTag: POpusTags;
LComment: PPAnsiChar;
LcommentLength: PInteger;
{$endif}
begin
result := -1 ;
x := 0;
err := -1;
SetLength(StreamIn, Length(StreamIn) + 1);
StreamIn[Length(StreamIn) - 1] := Tuos_InStream.Create;
x := Length(StreamIn) - 1;
StreamIn[x].Data.Enabled := false;
StreamIn[x].Data.LibOpen := -1;
StreamIn[x].Data.levelEnable := 0;
StreamIn[x].Data.positionEnable := 0;
StreamIn[x].Data.levelArrayEnable := 0;
{$IF DEFINED(fdkaac)}
if (AudioFormat = 2)
then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Begin fdkaac');
{$endif}
PipeBufferSize := 1024 * 4;
CreatePipeHandles(StreamIn[x].InHandle, StreamIn[x].OutHandle, PipeBufferSize);
StreamIn[x].InPipe := TInputPipeStream.Create(StreamIn[x].InHandle);
StreamIn[x].OutPipe := TOutputPipeStream.Create(StreamIn[x].OutHandle);
StreamIn[x].httpget := TThreadHttpGetter.Create(url, StreamIn[x].OutPipe);
StreamIn[x].httpget.freeonterminate := true;
StreamIn[x].httpget.ICYenabled := ICYon;
//writeln('avant httpget.Start');
StreamIn[x].httpget.Start;
// writeln('apres httpget.Start');
sleep(2000);
if StreamIn[x].httpget.IsRunning then
begin
if StreamIn[x].httpget.ICYenabled = true then
CheckSynchronize(1000);
StreamIn[x].Data.HandleSt := aacDecoder_Open(TRANSPORT_TYPE.TT_MP4_ADTS, 1);
if StreamIn[x].Data.HandleSt = nil then
begin
// writeln('NOT OK aacDecoder_Open()');
exit;
end;
// else writeln('OK aacDecoder_Open()');
if (aacDecoder_SetParam(StreamIn[x].Data.HandleSt, AAC_CONCEAL_METHOD, 1) <> AAC_DECODER_ERROR
.AAC_DEC_OK) then
begin
// writeln('Unable to set the AAC_CONCEAL_METHOD');
exit;
end;
if (aacDecoder_SetParam(StreamIn[x].Data.HandleSt, AAC_PCM_LIMITER_ENABLE, 0) <>
AAC_DECODER_ERROR.AAC_DEC_OK) then
begin
// writeln('Unable to set the AAC_PCM_LIMITER_ENABLE');
exit;
end;
// writeln('FIN INIT ------------- AACDecDecode');
StreamIn[x].Data.LibOpen := 2;
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else StreamIn[x].Data.SampleFormat := SampleFormat;
if FramesCount = -1 then
StreamIn[x].Data.Wantframes := 65536
else
StreamIn[x].Data.Wantframes := FramesCount ;
StreamIn[x].Data.Channels := 2;
StreamIn[x].Data.samplerate := 44100;
StreamIn[x].Data.ratio := 2;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes * StreamIn[x].Data.channels);
StreamIn[x].Data.Output := OutputIndex;
StreamIn[x].Data.Status := 1;
StreamIn[x].Data.Position := 0;
StreamIn[x].Data.OutFrames := 0;
StreamIn[x].Data.Poseek := 0;
StreamIn[x].Data.TypePut := 2;
StreamIn[x].Data.seekable := false;
Err := 0;
end else
begin
result := -1;
StreamIn[x].httpget.Terminate;
sleep(100);
StreamIn[x].inpipe.destroy;
StreamIn[x].outpipe.destroy;
end;
// writeln('----------- FIN add URL -------------' );
end;
{$endif}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('ac StreamIn[x].Data.LibOpen = ' + inttostr(StreamIn[x].Data.LibOpen));
{$endif}
////////////////// end aac
{$IF DEFINED(opus)}
if (AudioFormat = 1)
// or (AudioFormat = -1)
then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Begin opus test');
{$endif}
if FramesCount= -1 then
totsamples := 4096
else
totsamples := FramesCount;
PipeBufferSize := totsamples * sizeOf(Single);
// * 2
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('totsamples: ' + inttostr(totsamples));
WriteLn('PipeBufferSize: ' + inttostr(PipeBufferSize));
{$endif}
CreatePipeHandles(StreamIn[x].InHandle, StreamIn[x].OutHandle, PipeBufferSize);
StreamIn[x].InPipe := TInputPipeStream.Create(StreamIn[x].InHandle);
StreamIn[x].OutPipe := TOutputPipeStream.Create(StreamIn[x].OutHandle);
StreamIn[x].httpget := TThreadHttpGetter.Create(url, StreamIn[x].OutPipe);
StreamIn[x].httpget.freeonterminate := true;
StreamIn[x].httpget.ICYenabled := false;
// TODO
// StreamIn[x].httpget.FIsRunning := True;
StreamIn[x].httpget.Start;
// WriteLn('StreamIn[x].httpget.Start');
sleep(2000);
if StreamIn[x].httpget.IsRunning then
begin
len := 1 ;
len2 := 0 ;
setlength(buffadd, PipeBufferSize);
setlength(StreamIn[x].data.BufferTMP, PipeBufferSize);
while (len2 < PipeBufferSize) and (len > 0) do
begin
len := StreamIn[x].InPipe.Read(buffadd[0],PipeBufferSize-len2);
if len > 0 then for i := 0 to len -1 do
StreamIn[x].data.BufferTMP[i+len2] := buffadd[i] ;
len2 := len2 + len;
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('PipeBufferSize = ' + inttostr(PipeBufferSize));
WriteLn('InPipe.Read = ' + inttostr(len2));
WriteLn('----------------------------------');
//writeln(tencoding.utf8.getstring(StreamIn[x].data.BufferTMP));
{$endif}
StreamIn[x].Data.HandleSt := pchar('opusurl');
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('StreamIn[x].Data.HandleSt url assisgned');
{$endif}
StreamIn[x].Data.HandleOP :=
// op_open_callbacks(StreamIn[x].InPipe, uos_callbacks, StreamIn[x].data.BufferTMP[0], PipeBufferSize, err);
op_test_callbacks(StreamIn[x].InPipe, uos_callbacks, StreamIn[x].
data.BufferTMP[0], PipeBufferSize, err);
// op_test_memory(StreamIn[x].data.BufferTMP[0],PipeBufferSize, Err);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('error: op_test_*: ' + inttostr(err));
{$endif}
if Err=0
then
begin
Err := op_test_open(StreamIn[x].Data.HandleOP);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('error: op_test_open: ' + inttostr(err));
{$endif}
if (Err=0) and (op_link_count(StreamIn[x].Data.HandleOP)=1)
then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('OK open');
{$endif}
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else
StreamIn[x].Data.SampleFormat := SampleFormat;
//tag
OpusTag := op_tags(StreamIn[x].Data.HandleOP, Nil);
if OpusTag<>nil
then
begin
if OpusTag^.comments>0
then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn((Format('OpusTag.comments = %d', [OpusTag^.comments])));
{$endif}
LComment := OpusTag^.user_comments;
LcommentLength := OpusTag^.comment_lengths;
for j := 0 to OpusTag^.comments - 1 do
begin
SetLength(s, LcommentLength^);
move(Pointer(LComment^)^, Pointer(s)^, LcommentLength^);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn(s);
{$endif}
if j = 1 then StreamIn[x].Data.title := s;
if j = 2 then StreamIn[x].Data.artist := s;
if j = 3 then StreamIn[x].Data.album := s;
if j = 4 then StreamIn[x].Data.date := s;
if j = 5 then StreamIn[x].Data.comment := s;
if j = 6 then StreamIn[x].Data.tag := s;
if j > 6 then StreamIn[x].Data.comment := StreamIn[x].Data.comment + ' ' +
s;
inc(LComment);
inc(LcommentLength);
end;
end;
end;
StreamIn[x].Data.Length := op_pcm_total(StreamIn[x].Data.HandleOP, Nil);
StreamIn[x].Data.filename := url;
StreamIn[x].Data.channels := op_channel_count(StreamIn[x].Data.HandleOP, Nil);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn((Format('op_bitrate = %d', [op_bitrate(StreamIn[x].Data.HandleOP, Nil)])));
WriteLn('Length ' + inttostr(StreamIn[x].Data.Length));
WriteLn('Data.Channels ' + inttostr(StreamIn[x].Data.channels));
{$endif}
StreamIn[x].Data.samplerate := 48000 ;
StreamIn[x].Data.samplerateroot := StreamIn[x].Data.samplerate ;
StreamIn[x].Data.Wantframes := totsamples ;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes);
StreamIn[x].Data.LibOpen := 4;
StreamIn[x].Data.Status := 1;
StreamIn[x].Data.Position := 0;
StreamIn[x].Data.OutFrames := 0;
StreamIn[x].Data.Poseek := -1;
StreamIn[x].Data.TypePut := 2;
StreamIn[x].Data.ratio := 1;
StreamIn[x].Data.seekable := false;
StreamIn[x].LoopProc := Nil;
StreamIn[x].Data.Enabled := True;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('End opus');
{$endif}
end;
end;
end else
begin
result := -1;
StreamIn[x].httpget.Terminate;
sleep(100);
StreamIn[x].inpipe.destroy;
StreamIn[x].outpipe.destroy;
end;
end;
{$endif}
{$IF DEFINED(mpg123)}
if (StreamIn[x].Data.LibOpen = -1) and ((AudioFormat = 0) or (AudioFormat = -1)) then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Begin mpg123');
{$endif}
if FramesCount= -1 then
totsamples := $4000
else
totsamples := FramesCount;
PipeBufferSize := totsamples ;
CreatePipeHandles(StreamIn[x].InHandle, StreamIn[x].OutHandle, PipeBufferSize);
StreamIn[x].InPipe := TInputPipeStream.Create(StreamIn[x].InHandle);
StreamIn[x].OutPipe := TOutputPipeStream.Create(StreamIn[x].OutHandle);
StreamIn[x].httpget := TThreadHttpGetter.Create(url, StreamIn[x].OutPipe);
// if StreamIn[x].httpget = nil then writeln('httpget = NIL') else writeln('httpget = OK');
StreamIn[x].httpget.freeonterminate := true;
StreamIn[x].httpget.ICYenabled := ICYon;
if StreamIn[x].httpget.ICYenabled = true then
StreamIn[x].UpdateIcyMetaInterval ;
StreamIn[x].httpget.Start;
sleep(2000);
if StreamIn[x].httpget.IsRunning then
begin
if StreamIn[x].httpget.ICYenabled = true then
CheckSynchronize(1000);
StreamIn[x].Data.HandleSt := mpg123_new(Nil, Err);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = 0 then writeln('===> mpg123_new => ok.')
else writeln('===> mpg123_new NOT ok.') ;
{$endif}
if Err = 0 then
begin
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else
StreamIn[x].Data.SampleFormat := SampleFormat;
mpg123_format_none(StreamIn[x].Data.HandleSt);
case StreamIn[x].Data.SampleFormat of
0: mpg123_format(StreamIn[x].Data.HandleSt, DefRate, Stereo,
MPG123_ENC_FLOAT_32);
1: mpg123_format(StreamIn[x].Data.HandleSt, DefRate, Stereo,
MPG123_ENC_SIGNED_32);
2: mpg123_format(StreamIn[x].Data.HandleSt, DefRate, Stereo,
MPG123_ENC_SIGNED_16);
end;
// mpg123_replace_reader_handle(StreamIn[x].Data.HandleSt, @mpg_read_stream, @mpg_seek_url, @mpg_close_stream);
mpg123_replace_reader_handle(StreamIn[x].Data.HandleSt,
@mpg_read_stream, @mpg_seek_url, Nil);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = 0 then writeln('===> mpg123_replace_reader_handle => ok.') ;
{$endif}
Err := mpg123_open_handle(StreamIn[x].Data.HandleSt, Pointer(StreamIn[x].InPipe));
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = 0 then writeln('===> mpg123_open_handle => ok.')
else
writeln('===> mpg123_open_handle => NOT ok.') ;
{$endif}
sleep(10);
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = 0 then
writeln('===> mpg123_open_handle all => ok.')
else
writeln('===> mpg123_open_handle all => NOT ok.');
{$endif}
if err = 0 then
begin
StreamIn[x].Data.filename := URL ;
if FramesCount = -1 then StreamIn[x].Data.Wantframes := 1024
else
StreamIn[x].Data.Wantframes := FramesCount ;
// StreamIn[x].Data.Wantframes := totsamples;
StreamIn[x].Data.Output := OutputIndex;
StreamIn[x].Data.Status := 1;
StreamIn[x].Data.Position := 0;
StreamIn[x].Data.OutFrames := 0;
StreamIn[x].Data.Poseek := -1;
StreamIn[x].Data.TypePut := 2;
StreamIn[x].Data.seekable := false;
StreamIn[x].LoopProc := Nil;
samprat := roundmath(StreamIn[x].Data.samplerate);
Err := mpg123_getformat(StreamIn[x].Data.HandleSt,
samprat, StreamIn[x].Data.channels,
StreamIn[x].Data.encoding);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = 0 then
writeln('===> mpg123_getformat => ok.')
else
writeln('===> mpg123_getformat => NOT ok.');
{$endif}
if err <> 0 then
begin
sleep(50);
samprat := roundmath(StreamIn[x].Data.samplerate);
Err := mpg123_getformat(StreamIn[x].Data.HandleSt,
samprat, StreamIn[x].Data.channels,
StreamIn[x].Data.encoding);
end;
if err = 0 then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('===> mpg123_getformat => ok');
{$endif}
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.
Channels);
StreamIn[x].Data.LibOpen := 1;
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else
StreamIn[x].Data.SampleFormat := SampleFormat;
if StreamIn[x].Data.SampleFormat = 2 then
StreamIn[x].Data.ratio := sizeof(int16)
else
StreamIn[x].Data.ratio := sizeof(int32);
mpg123_info(StreamIn[x].Data.HandleSt, MPinfo);
// problems with mpg123
// mpg123_id3(StreamIn[x].Data.HandleSt, mpid3v1, @mpid3v2);
// mpg123_icy(StreamIn[x].Data.HandleSt, pointer(icytext));
StreamIn[x].Data.samplerateroot := StreamIn[x].Data.samplerate ;
StreamIn[x].Data.hdformat := MPinfo.layer;
StreamIn[x].Data.frames := MPinfo.framesize;
StreamIn[x].Data.Length := mpg123_length(StreamIn[x].Data.HandleSt);
if StreamIn[x].Data.SampleFormat = 0 then
mpg123_param(StreamIn[x].Data.HandleSt, StreamIn[x].Data.Channels,
MPG123_FORCE_FLOAT, 0);
StreamIn[x].Data.Enabled := True;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('===> mpg123_infos end => ok');
{$endif}
end;
end;
end else
begin
result := -1;
StreamIn[x].httpget.Terminate;
sleep(100);
StreamIn[x].inpipe.destroy;
StreamIn[x].outpipe.destroy;
end;
end;
{$endif}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before result ' + inttostr(result));
WriteLn('error ' + inttostr(err));
WriteLn('StreamIn[x].Data.LibOpen ' + inttostr(StreamIn[x].Data.LibOpen));
WriteLn('Before Length(StreamIn) ' + inttostr(Length(StreamIn)));
{$endif}
sleep(10);
if StreamIn[x].Data.LibOpen = -1 then
begin
if err <> -133 then
begin
StreamIn[Length(StreamIn) - 1].Destroy;
setlength(StreamIn, Length(StreamIn) - 1);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('After Length(StreamIn) ' + inttostr(Length(StreamIn)));
WriteLn('Result: ' + inttostr(result));
{$endif}
end;
result := -1
end
else
begin
StreamIn[x].Data.Enabled := True;
result := x ;
end;
end;
{$ENDIF}
function Tuos_Player.AddFromMemoryBuffer(Var MemoryBuffer: TDArFloat; Var Bufferinfos:
Tuos_bufferinfos;
OutputIndex: cint32; FramesCount: cint32): cint32;
// Add a input from memory buffer with custom parameters
// MemoryBuffer : the buffer
// Bufferinfos : infos of the buffer
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)// SampleRate : delault : -1 (44100)
// FramesCount : default : -1 (65536 div Channels)
// result : Input Index in array -1 = error
// example : InputIndex1 := AddFromMemoryBuffer(mybuffer, buffinfos,-1,1024);
var
x : cint32;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
st: string;
i : cint32;
{$endif}
begin
result := -1 ;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('AddFromMemoryBuffer Before all.');
writeln('length(MemoryBuffer) =' +inttostr(length(MemoryBuffer)));
st := '';
for i := 0 to length(MemoryBuffer) -1 do
st := st + '|' + inttostr(i) + '=' + floattostr(MemoryBuffer[i]);
WriteLn(st);
{$endif}
// writeln('length(MemoryBuffer) =' +inttostr(length(MemoryBuffer)));
SetLength(StreamIn, Length(StreamIn) + 1);
StreamIn[Length(StreamIn) - 1] := Tuos_InStream.Create;
x := Length(StreamIn) - 1;
StreamIn[x].Data.Enabled := false;
StreamIn[x].Data.levelEnable := 0;
StreamIn[x].Data.typeput := 4;
StreamIn[x].Data.positionEnable := 0;
StreamIn[x].Data.levelArrayEnable := 0;
{
setlength(StreamIn[x].Data.memorybuffer, length(MemoryBuffer));
writeln('length(Data.memorybuffer) =' +inttostr(length(StreamIn[x].Data.memorybuffer)));
for i := 0 to length(MemoryBuffer) -1 do
StreamIn[x].Data.memorybuffer[i] := MemoryBuffer[i];
}
StreamIn[x].Data.memorybuffer := MemoryBuffer;
sleep(50);
//TODO: it is necessary?
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('AddFromMemoryBuffer Before all.');
writeln('length(MemoryBuffer) =' +inttostr(length(MemoryBuffer)));
st := '';
for i := 0 to length(MemoryBuffer) -1 do
st := st + '|' + inttostr(i) + '=' + floattostr(StreamIn[x].Data.memorybuffer[i]);
WriteLn(st);
{$endif}
StreamIn[x].Data.Length := length(MemoryBuffer);
StreamIn[x].Data.LibOpen := 0;
StreamIn[x].Data.Channels := Bufferinfos.Channels;
if FramesCount = -1 then
StreamIn[x].Data.Wantframes := 4096
else
StreamIn[x].Data.Wantframes := FramesCount;
StreamIn[x].Data.Samplerate := bufferinfos.SampleRate;
StreamIn[x].Data.SampleRateRoot := Bufferinfos.Samplerate;
StreamIn[x].Data.SampleFormat := Bufferinfos.SampleFormat;
StreamIn[x].Data.Filename := BufferInfos.Filename;
StreamIn[x].Data.Title := BufferInfos.Title;
StreamIn[x].Data.Copyright := BufferInfos.Copyright;
StreamIn[x].Data.Software := BufferInfos.Software;
StreamIn[x].Data.Artist := BufferInfos.Artist;
StreamIn[x].Data.Comment := BufferInfos.Comment;
StreamIn[x].Data.Date := BufferInfos.Date;
StreamIn[x].Data.Tag := BufferInfos.Tag;
StreamIn[x].Data.track := BufferInfos.track;
StreamIn[x].Data.Album := BufferInfos.Album;
StreamIn[x].Data.Genre := BufferInfos.Genre;
StreamIn[x].Data.HDFormat := BufferInfos.HDFormat;
StreamIn[x].Data.Sections := BufferInfos.Sections;
StreamIn[x].Data.Encoding := BufferInfos.Encoding;
StreamIn[x].Data.bitrate := BufferInfos.bitrate;
//StreamIn[x].Data.Length := BufferInfos.Length;
StreamIn[x].Data.LibOpen := 0;
StreamIn[x].Data.ratio := StreamIn[x].Data.Channels;
StreamIn[x].Data.posmem := 0;
StreamIn[x].Data.Output := OutputIndex;
StreamIn[x].Data.Status := 1;
StreamIn[x].Data.Position := 0;
StreamIn[x].Data.OutFrames := 0;
StreamIn[x].Data.Poseek := -1;
StreamIn[x].Data.seekable := true;
StreamIn[x].LoopProc := Nil;
setlength(StreamIn[x].Data.buffer,StreamIn[x].Data.wantframes*StreamIn[x].Data.Channels);
StreamIn[x].Data.Enabled := True;
result := x;
end;
function Tuos_Player.AddFromFileIntoMemory(Filename: Pchar; OutputIndex: cint32;
SampleFormat: cint32 ; FramesCount: cint32; numbuf : cint
): cint32;
// Add a input from audio file and store it into memory with custom parameters
// FileName : filename of audio file
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (4096)
// result : Input Index in array -1 = error
// example : InputIndex1 := AddFromFileIntoMemory(edit5.Text,-1,0,-1);
var
x, i : cint32;
bufferinfos: Tuos_bufferinfos;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
st: string;
{$endif}
begin
result := -1 ;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('AddFromFileIntoMemory Before all.');
{$endif}
if fileexists(filename) then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before setlength.');
{$endif}
SetLength(StreamIn, Length(StreamIn) + 1);
StreamIn[Length(StreamIn) - 1] := Tuos_InStream.Create;
x := Length(StreamIn) - 1;
StreamIn[x].Data.Enabled := false;
StreamIn[x].Data.levelEnable := 0;
StreamIn[x].Data.typeput := 4;
StreamIn[x].Data.lastbuf := 0;
StreamIn[x].Data.positionEnable := 0;
StreamIn[x].Data.levelArrayEnable := 0;
// StreamIn[x].Data.wantframes := FramesCount;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Before Filetobuffer');
{$endif}
for i := 0 to length(tempoutmemory) -1 do
tempoutmemory[i] := 0.0;
setlength(tempoutmemory, 0);
Filetobuffer(Filename, -1, SampleFormat, FramesCount, tempoutmemory, bufferinfos, -1, numbuf);
sleep(50);
setlength(StreamIn[x].Data.memorybuffer, length(tempoutmemory));
for i := 0 to length(tempoutmemory) -1 do
StreamIn[x].Data.memorybuffer[i] := tempoutmemory [i];
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('After Filetobuffer');
writeln('length(tempoutmemory) =' +inttostr(length(tempoutmemory)));
st := '';
for i := 0 to length(tempoutmemory) -1 do
st := st + '|' + inttostr(i) + '=' + floattostr(tempoutmemory[i]);
WriteLn('OUTPUT DATA into portaudio------------------------------');
WriteLn(st);
{$endif}
StreamIn[x].Data.Length := tempLength;
StreamIn[x].Data.Samplerate := tempSamplerate;
StreamIn[x].Data.SampleFormat := tempSampleFormat;
StreamIn[x].Data.LibOpen := tempLibOpen;
StreamIn[x].Data.Channels := tempchan;
if FramesCount = -1 then StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
else
StreamIn[x].Data.Wantframes := FramesCount ;
StreamIn[x].Data.ratio := tempratio;
StreamIn[x].Data.posmem := 0;
StreamIn[x].Data.Output := OutputIndex;
StreamIn[x].Data.Status := 1;
StreamIn[x].Data.Position := 0;
StreamIn[x].Data.OutFrames := 0;
StreamIn[x].Data.Poseek := -1;
StreamIn[x].Data.seekable := true;
StreamIn[x].LoopProc := Nil;
StreamIn[x].Data.Samplerate := bufferinfos.SampleRate;
StreamIn[x].Data.SampleRateRoot := Bufferinfos.Samplerate;
StreamIn[x].Data.SampleFormat := Bufferinfos.SampleFormat;
StreamIn[x].Data.Filename := BufferInfos.Filename;
StreamIn[x].Data.Title := BufferInfos.Title;
StreamIn[x].Data.Copyright := BufferInfos.Copyright;
StreamIn[x].Data.Software := BufferInfos.Software;
StreamIn[x].Data.Artist := BufferInfos.Artist;
StreamIn[x].Data.Comment := BufferInfos.Comment;
StreamIn[x].Data.Date := BufferInfos.Date;
StreamIn[x].Data.Tag := BufferInfos.Tag;
StreamIn[x].Data.Album := BufferInfos.Album;
StreamIn[x].Data.Genre := BufferInfos.Genre;
StreamIn[x].Data.track := BufferInfos.track;
StreamIn[x].Data.HDFormat := BufferInfos.HDFormat;
StreamIn[x].Data.Sections := BufferInfos.Sections;
StreamIn[x].Data.Encoding := BufferInfos.Encoding;
StreamIn[x].Data.bitrate := BufferInfos.bitrate;
StreamIn[x].Data.Length := BufferInfos.Length;
StreamIn[x].Data.LibOpen := 0;
StreamIn[x].Data.Ratio := 2 ;
setlength(StreamIn[x].Data.buffer,StreamIn[x].Data.wantframes*StreamIn[x].Data.Channels);
StreamIn[x].Data.Enabled := True;
result := x;
end
else result := -2;
end;
{$IF DEFINED(sndfile)}
function m_get_filelen(pms: PMemoryStream): tuos_count_t;
cdecl;
begin
Result := pms^.Size;
end;
function m_seek(offset: tuos_count_t; whence: cint32; pms: PMemoryStream): tuos_count_t;
cdecl;
const
SEEK_SET = 0;
SEEK_CUR = 1;
SEEK_END = 2;
begin
Result := 0 ;
case whence of
SEEK_SET: Result := pms^.Seek(offset, soFromBeginning);
SEEK_CUR: Result := pms^.Seek(offset, soFromCurrent);
SEEK_END: Result := pms^.Seek(offset, soFromEnd);
end;
end;
function m_read(Const buf: Pointer; count: Tuos_count_t; pms: PMemoryStream): Tuos_count_t;
cdecl;
begin
Result := pms^.Read(buf^,count);
end;
function m_write(Const buf: Pointer; count: Tuos_count_t; pms: PMemoryStream): Tuos_count_t;
cdecl;
begin
Result := pms^.Write(buf^,count);
end;
function m_tell(pms: PMemoryStream): Tuos_count_t;
cdecl;
begin
Result := pms^.Position;
end;
{$endif}
function Tuos_Player.AddIntoMemoryStream(Var MemoryStream: TMemoryStream; SampleRate: CDouble;
SampleFormat: LongInt ; Channels: LongInt; FramesCount:
LongInt; AudioFormat: cint32): LongInt;
// Add a Output into TMemoryStream
// MemoryStream : the TMemoryStream to use to store memory.
// SampleRate : delault : -1 (44100)
// SampleFormat : default : -1 (2:Int16) ( 1:Int32, 2:Int16)
// Channels : delault : -1 (2:stereo) (0: no channels, 1:mono, 2:stereo, ...)
// FramesCount : default : -1 (= 4096)
// AudioFormat : default : -1 (wav) (0:wav, 1:ogg);
var
x, ch, sr, sf, fr: integer;
{$IF DEFINED(sndfile)}
sfInfo: TSF_INFO;
sfVirtual: TSF_VIRTUAL;
{$endif}
begin
result := -1 ;
x := 0;
SetLength(StreamOut, Length(StreamOut) + 1);
StreamOut[Length(StreamOut) - 1] := Tuos_OutStream.Create();
x := Length(StreamOut) - 1;
StreamOut[x].Data.Enabled := false;
if channels = -1 then ch := 2
else ch := channels;
StreamOut[x].Data.channels := ch;
if SampleFormat = -1 then sf := 2
else sf := SampleFormat;
StreamOut[x].Data.SampleFormat := sf;
if FramesCount = -1 then fr := 4096
else fr := FramesCount;
StreamOut[x].Data.Wantframes := fr ;
if SampleRate = -1 then sr := 44100
else sr := roundmath(SampleRate);
StreamOut[x].Data.SampleRate := sr ;
SetLength(StreamOut[x].Data.Buffer, StreamOut[x].Data.Wantframes*StreamOut[x].Data.Channels);
if MemoryStream = nil then
MemoryStream := Tmemorystream.create;
Streamout[x].MemorySteamOut := MemoryStream;
Streamout[x].Data.posmem := 0;
StreamOut[x].Data.TypePut := 5;
{$IF DEFINED(sndfile)}
with sfVirtual do
begin
sf_vio_get_filelen := @m_get_filelen;
seek := @m_seek;
read := @m_read;
write := @m_write;
tell := @m_tell;
end;
if (AudioFormat = 0) then
sfInfo.format := SF_FORMAT_WAV Or SF_FORMAT_PCM_16;
if (AudioFormat = 1) then
sfInfo.format := SF_FORMAT_OGG Or SF_FORMAT_VORBIS;
sfInfo.channels := StreamOut[x].Data.Channels;
sfInfo.frames := streamOut[x].Data.Wantframes;
SFinfo.samplerate := roundmath(StreamOut[x].Data.SampleRate);
SFinfo.seekable := 0;
StreamOut[x].Data.HandleSt := sf_open_virtual(@sfVirtual, SFM_WRITE, @sfInfo,
@StreamOut[x].MemorySteamOut);
{$endif}
result := x;
StreamOut[x].Data.Enabled := True;
end;
function Tuos_Player.AddFromMemoryStreamDec(Var MemoryStream: TMemoryStream; Var Bufferinfos:
Tuos_bufferinfos;
OutputIndex: cint32; FramesCount: cint32): cint32;
// MemoryStream : Memory-stream of decoded audio (like created by AddIntoMemoryStream)
// Bufferinfos : infos of the Memory-stream
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')
// FramesCount : default : -1 (4096)
// result : Input Index in array -1 = error
var
x : integer;
begin
result := -1 ;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before all.');
{$endif}
if assigned(MemoryStream) then
begin
x := 0;
MemoryStream.Position := 0;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before setlength.');
{$endif}
SetLength(StreamIn, Length(StreamIn) + 1);
StreamIn[Length(StreamIn) - 1] := Tuos_InStream.Create;
x := Length(StreamIn) - 1;
StreamIn[x].Data.LibOpen := -1;
StreamIn[x].Data.levelEnable := 0;
StreamIn[x].Data.Output := OutputIndex;
StreamIn[x].Data.Status := 1;
StreamIn[x].Data.Position := 0;
StreamIn[x].Data.lastbuf := -1;
StreamIn[x].Data.OutFrames := 0;
StreamIn[x].Data.Poseek := -1;
StreamIn[x].Data.TypePut := 6;
StreamIn[x].Data.seekable := True;
StreamIn[x].LoopProc := Nil;
StreamIn[x].Data.Channels := Bufferinfos.Channels;
if FramesCount = -1 then
StreamIn[x].Data.Wantframes := 4096
else
StreamIn[x].Data.Wantframes := FramesCount;
StreamIn[x].Data.Samplerate := bufferinfos.SampleRate;
StreamIn[x].Data.SampleRateRoot := Bufferinfos.Samplerate;
StreamIn[x].Data.SampleFormat := Bufferinfos.SampleFormat;
StreamIn[x].Data.Filename := BufferInfos.Filename;
StreamIn[x].Data.Title := BufferInfos.Title;
StreamIn[x].Data.Copyright := BufferInfos.Copyright;
StreamIn[x].Data.Software := BufferInfos.Software;
StreamIn[x].Data.Artist := BufferInfos.Artist;
StreamIn[x].Data.Comment := BufferInfos.Comment;
StreamIn[x].Data.Date := BufferInfos.Date;
StreamIn[x].Data.Tag := BufferInfos.Tag;
StreamIn[x].Data.Album := BufferInfos.Album;
StreamIn[x].Data.Track := BufferInfos.Track;
StreamIn[x].Data.Genre := BufferInfos.Genre;
StreamIn[x].Data.HDFormat := BufferInfos.HDFormat;
StreamIn[x].Data.Sections := BufferInfos.Sections;
StreamIn[x].Data.Encoding := BufferInfos.Encoding;
StreamIn[x].Data.bitrate := BufferInfos.bitrate;
//StreamIn[x].Data.Length := BufferInfos.Length;
StreamIn[x].Data.LibOpen := -1;
StreamIn[x].Data.ratio := StreamIn[x].Data.Channels;
StreamIn[x].Data.posmem := 0;
StreamIn[x].Data.Output := OutputIndex;
StreamIn[x].Data.Status := 1;
StreamIn[x].Data.Position := 0;
StreamIn[x].Data.OutFrames := 0;
StreamIn[x].Data.Poseek := -1;
StreamIn[x].Data.seekable := false;
StreamIn[x].LoopProc := Nil;
streamIn[x].Data.ratio := StreamIn[x].Data.Channels;
StreamIn[x].Data.positionEnable := 0;
StreamIn[x].Data.levelArrayEnable := 0;
StreamIn[x].MemoryStreamDec := MemoryStream;
StreamIn[x].MemoryStreamDec.Position := 0;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.Channels);
StreamIn[x].Data.Enabled := true;
result := x;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('length(StreamIn[x].MemoryStreamDec) = '+inttostr(StreamIn[x].MemoryStreamDec.size)) ;
writeln('length(MemoryStream) = '+inttostr(MemoryStream.size)) ;
WriteLn('Length(StreamIn) = '+ inttostr(x));
{$endif}
end
else result := -1;
end;
function Tuos_Player.AddFromMemoryStream(Var MemoryStream: TMemoryStream;
TypeAudio: cint32; OutputIndex: cint32; SampleFormat:
cint32 ; FramesCount: cint32): cint32;
// MemoryStream : Memory stream of encoded audio file.
// TypeAudio : default : -1 --> 0 (0: flac, ogg, wav; 1: mp3; 2:opus ; 3:decoded Tmemory-stream; 5:mod, it, xm, s3m)
// OutputIndex : Output index of used output// -1: all output, -2: no output, other cint32 refer to a existing OutputIndex (if multi-output then OutName = name of each output separeted by ';')
// SampleFormat : default : -1 (2:Int16) (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (4096)
// result : Input Index in array -1 = error
// example : InputIndex1 := AddFromMemoryStream(mymemorystream,-1,-1,0,1024);
var
x, x2, err, len, len2, i : cint32;
PipeBufferSize, totsamples : integer;
buffadd : tbytes;
samprat : cint32;
{$IF DEFINED(sndfile)}
sfInfo: TSF_INFO;
sfVirtual: TSF_VIRTUAL;
{$endif}
{$IF DEFINED(opus)}
s: UTF8String;
j: Integer;
OpusTag: POpusTags;
LComment: PPAnsiChar;
LcommentLength: PInteger;
{$endif}
{$IF DEFINED(mpg123)}
mpinfo: Tmpg123_frameinfo;
// problems with mpg123
mpid3v1: PPmpg123_id3v1;
refmpid3v1: Tmpg123_id3v1;
mpid3v2: Tmpg123_id3v2;
{$endif}
{$IF DEFINED(xmp)}
mi: xmp_module_info;
{$endif}
begin
result := -1 ;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before all.');
{$endif}
if assigned(MemoryStream) then
begin
x := 0;
MemoryStream.Position := 0;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before setlength.');
{$endif}
SetLength(StreamIn, Length(StreamIn) + 1);
StreamIn[Length(StreamIn) - 1] := Tuos_InStream.Create;
x := Length(StreamIn) - 1;
err := -1;
StreamIn[x].Data.Enabled := false;
StreamIn[x].Data.LibOpen := -1;
StreamIn[x].Data.lastbuf := -1;
StreamIn[x].Data.levelEnable := 0;
StreamIn[x].Data.positionEnable := 0;
StreamIn[x].Data.levelArrayEnable := 0;
StreamIn[x].data.MemoryStream := MemoryStream;
StreamIn[x].data.MemoryStream.Position := 0;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Length(StreamIn) = '+ inttostr(x));
{$endif}
{$IF DEFINED(sndfile)}
if ((TypeAudio = -1) or (TypeAudio = 0)) and (uosLoadResult.SFloadERROR = 0) then
begin
with sfVirtual do
begin
sf_vio_get_filelen := @m_get_filelen;
seek := @m_seek;
read := @m_read;
write := @m_write;
tell := @m_tell;
end;
try
Streamin [x] .Data.HandleSt := sf_open_virtual(@sfVirtual, SFM_READ, @sfInfo, @StreamIn[
x].Data.MemoryStream);
except
StreamIn[x].Data.HandleSt := Nil;
end;
(* try to open the file *)
if StreamIn[x].Data.HandleSt = nil then
begin
StreamIn[x].Data.LibOpen := -1;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('sf_open_virtual NOT OK');
{$endif}
end
else
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('sf_open_virtual OK');
{$endif}
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else StreamIn[x].Data.SampleFormat := SampleFormat;
StreamIn[x].Data.LibOpen := 0;
StreamIn[x].Data.channels := SFinfo.channels;
if FramesCount = -1 then
StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
else StreamIn[x].Data.Wantframes := FramesCount ;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.Channels);
StreamIn[x].Data.hdformat := SFinfo.format;
StreamIn[x].Data.frames := SFinfo.frames;
StreamIn[x].Data.samplerate := SFinfo.samplerate;
StreamIn[x].Data.samplerateroot := SFinfo.samplerate;
StreamIn[x].Data.sections := SFinfo.sections;
StreamIn[x].Data.copyright := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_COPYRIGHT);
StreamIn[x].Data.software := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_SOFTWARE);
StreamIn[x].Data.comment := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_COMMENT);
StreamIn[x].Data.artist := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_ARTIST);
StreamIn[x].Data.title := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_TITLE);
StreamIn[x].Data.date := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_DATE);
StreamIn[x].Data.track := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_TRACKNUMBER);
StreamIn[x].Data.genre := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_GENRE);
StreamIn[x].Data.album := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_ALBUM);
StreamIn[x].Data.Length := sfInfo.frames;
err := 0;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('sf_open END OK');
{$endif}
end;
end;
{$endif}
{$IF DEFINED(xmp)}
if ((StreamIn[x].Data.LibOpen = -1)) then
if ((TypeAudio = 5)) and (uosLoadResult.XMloadERROR = 0) then
begin
StreamIn[x].Data.HandleSt := xmp_create_context();
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if StreamIn[x].Data.HandleSt = nil then WriteLn(' xmp_create_context() NOT OK')
else WriteLn('xmp_create_context() OK');
{$endif}
if xmp_load_module_from_memory(StreamIn[x].Data.HandleSt,
StreamIn[x].Data.MemoryStream.Memory,
StreamIn[x].Data.MemoryStream.size) <> 0 then
begin
StreamIn[x].Data.LibOpen := -1;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('xmp_load_module_from_memory NOT OK');
{$endif}
end
else
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('xmp_load_module_from_memory OK');
{$endif}
xmp_start_player(StreamIn[x].Data.HandleSt, 44100, 0);
xmp_get_module_info(StreamIn[x].Data.HandleSt, mi);
// xmp_get_frame_info(StreamIn[x].Data.HandleSt , fi);
StreamIn[x].Data.LibOpen := 5;
StreamIn[x].Data.channels := 2;
// todo
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else
StreamIn[x].Data.SampleFormat := SampleFormat;
// Need conversion because xmp is always 16 bit
if FramesCount = -1 then StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.
Channels
else
StreamIn[x].Data.Wantframes := FramesCount ;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.
Channels);
x2 := 0 ;
while x2 < Length(Streamin[x].Data.Buffer) do
begin
Streamin[x].Data.Buffer[x2] := 0.0 ;
inc(x2);
end;
// StreamIn[x].Data.hdformat := SFinfo.format;
// StreamIn[x].Data.frames := SFinfo.frames;
StreamIn[x].Data.samplerate := 44100;
StreamIn[x].Data.samplerateroot := 44100;
// StreamIn[x].Data.sections := SFinfo.sections;
StreamIn[x].Data.title := String(mi.module^.Name);
StreamIn[x].Data.copyright := '';
StreamIn[x].Data.software := '';
StreamIn[x].Data.comment := String(mi.module^.typ);
StreamIn[x].Data.artist := String(mi.comment);
StreamIn[x].Data.date := '';
StreamIn[x].Data.track := '';
StreamIn[x].Data.genre := '';
StreamIn[x].Data.album := '';
StreamIn[x].Data.Length := 0;
err := 0;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('XMP_open END OK');
{$endif}
end;
end;
{$endif}
{$IF DEFINED(mpg123)}
// mpg123
if (((TypeAudio = 1) and (StreamIn[x].Data.LibOpen = -1)
and (uosLoadResult.MPloadERROR = 0))) then
begin
Err := -1;
StreamIn[x].Data.HandleSt := mpg123_new(Nil, Err);
if Err = 0 then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('mpg123_new OK');
{$endif}
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else StreamIn[x].Data.SampleFormat :=
SampleFormat
;
mpg123_format_none(StreamIn[x].Data.HandleSt);
case StreamIn[x].Data.SampleFormat of
0: mpg123_format(StreamIn[x].Data.HandleSt,
DefRate, Stereo,
MPG123_ENC_FLOAT_32);
1: mpg123_format(StreamIn[x].Data.HandleSt,
DefRate, Stereo,
MPG123_ENC_SIGNED_32);
2: mpg123_format(StreamIn[x].Data.HandleSt,
DefRate, Stereo,
MPG123_ENC_SIGNED_16);
end;
err := mpg123_replace_reader_handle(StreamIn[x].
Data.HandleSt, @mpg_read_stream, @
mpg_seek_stream, Nil);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = 0 then
writeln(
'===> mpg123_replace_reader_handle => ok.')
else writeln(
'===> mpg123_replace_reader_handle => NOT OK.');
{$endif}
Err := mpg123_open_handle(StreamIn[x].Data.
HandleSt, pointer(StreamIn[x].Data.
MemoryStream));
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = 0 then
writeln('===> mpg123_open_handle => ok.')
else
writeln('===> mpg123_open_handle => NOT ok.');
{$endif}
sleep(10);
end
else
begin
StreamIn[x].Data.LibOpen := -1;
end;
samprat := roundmath(StreamIn[x].Data.samplerate);
if Err = 0 then Err := mpg123_getformat(StreamIn[x].
Data.HandleSt,
samprat,
StreamIn[x].Data.channels,
StreamIn[x].Data.encoding);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = 0 then
writeln('===> mpg123_getformat => ok.')
else writeln('===> mpg123_getformat => NOT ok.') ;
{$endif}
if Err = 0 then
begin
mpg123_close(StreamIn[x].Data.HandleSt);
mpg123_delete(StreamIn[x].Data.HandleSt);
// Close handle and reload with forced resolution
StreamIn[x].Data.HandleSt := mpg123_new(Nil, Err
);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = 0 then
writeln('===> mpg123_open_handle => ok.')
else writeln(
'===> mpg123_open_handle => NOT ok.') ;
{$endif}
StreamIn[x].Data.HandleSt := Nil;
StreamIn[x].Data.HandleSt := mpg123_new(Nil, Err);
mpg123_format_none(StreamIn[x].Data.HandleSt);
samprat := roundmath(StreamIn[x].Data.samplerate);
case StreamIn[x].Data.SampleFormat of
0: mpg123_format(StreamIn[x].Data.HandleSt,
samprat,
StreamIn[x].Data.channels,
StreamIn[x].Data.encoding);
1: mpg123_format(StreamIn[x].Data.HandleSt,
samprat,
StreamIn[x].Data.channels,
StreamIn[x].Data.encoding);
2: mpg123_format(StreamIn[x].Data.HandleSt,
samprat,
StreamIn[x].Data.channels,
StreamIn[x].Data.encoding);
end;
err := mpg123_replace_reader_handle(StreamIn[x].
Data.HandleSt, @mpg_read_stream, @mpg_seek_stream, Nil);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = 0 then
writeln('===> mpg123_replace_reader_handle => ok.')
else writeln('===> mpg123_replace_reader_handle => NOT OK.');
{$endif}
Err := mpg123_open_handle(StreamIn[x].Data.
HandleSt, pointer(StreamIn[x].Data.
MemoryStream));
samprat := roundmath(StreamIn[x].Data.samplerate);
mpg123_getformat(StreamIn[x].Data.HandleSt,
samprat,
StreamIn[x].Data.channels,
StreamIn[x].Data.encoding);
if FramesCount = -1 then
StreamIn[x].Data.Wantframes := 65536 Div
StreamIn[x].
Data.Channels
else StreamIn[x].Data.Wantframes := FramesCount;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].
Data.Wantframes*StreamIn[x].Data.
Channels);
mpg123_info(StreamIn[x].Data.HandleSt, MPinfo);
// problems with mpg123 library
mpg123_id3(StreamIn[x].Data.HandleSt, @mpid3v1, @mpid3v2);
// to do : add id2v2
if (mpid3v1 <> nil) and (mpid3v1^ <> nil) then
begin
refmpid3v1 := mpid3v1^^;
StreamIn[x].Data.title := trim(refmpid3v1.title);
StreamIn[x].Data.artist := refmpid3v1.artist;
StreamIn[x].Data.album := refmpid3v1.album;
StreamIn[x].Data.date := refmpid3v1.year;
StreamIn[x].Data.comment := refmpid3v1.comment;
//StreamIn[x].Data.track := refmpid3v1.comment;
StreamIn[x].Data.tag := refmpid3v1.tag;
StreamIn[x].Data.genre := inttostr(refmpid3v1.genre);
end;
StreamIn[x].Data.samplerateroot := StreamIn[x].Data.samplerate ;
StreamIn[x].Data.hdformat := MPinfo.layer;
StreamIn[x].Data.frames := MPinfo.framesize;
if StreamIn[x].Data.SampleFormat = 0 then
mpg123_param(StreamIn[x].Data.HandleSt,
StreamIn[x].Data.Channels,
MPG123_FORCE_FLOAT, 0);
StreamIn[x].Data.LibOpen := 1;
StreamIn[x].Data.Length := mpg123_length(StreamIn[x].Data.HandleSt);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('StreamIn[x].Data.Length = ' + inttostr(
mpg123_length(StreamIn[x].Data.HandleSt));
writeln('StreamIn[x].Data.frames = ' + inttostr(
StreamIn[x].Data.frames));
writeln('END StreamIn[x].Data.samplerate = ' +
inttostr(roundmath(StreamIn[x].Data.samplerate)));
writeln('END StreamIn[x].Data.channels = ' +
inttostr(StreamIn[x].Data.channels));
{$endif}
end
else
begin
StreamIn[x].Data.LibOpen := -1;
end;
end;
{$endif}
{$IF DEFINED(opus)}
if ((TypeAudio = 2) and (StreamIn[x].Data.LibOpen = -1) and
(uosLoadResult.OPloadERROR = 0))
then
begin
Err := -1;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before Opus');
{$endif}
StreamIn[x].Data.HandleSt := pchar('opus');
if FramesCount= -1 then
totsamples := 4096
else totsamples := FramesCount;
PipeBufferSize := StreamIn[x].Data.MemoryStream.size;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('totsamples: ' + inttostr(totsamples));
WriteLn('PipeBufferSize: ' + inttostr(PipeBufferSize));
{$endif}
len := 1 ;
len2 := 0 ;
setlength(buffadd, PipeBufferSize);
setlength(StreamIn[x].data.BufferTMP, PipeBufferSize);
while (len2 < PipeBufferSize) and (len > 0) do
begin
len := StreamIn[x].Data.MemoryStream.Read(buffadd[0],PipeBufferSize-len2);
if len > 0 then
for i := 0 to len -1 do
StreamIn[x].data.BufferTMP[i+len2] := buffadd[i] ;
len2 := len2 + len;
end;
// memory stream not needed anymore ---> converted into buffer
freeandnil(StreamIn[x].Data.MemoryStream);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('PipeBufferSize = ' + inttostr(PipeBufferSize));
WriteLn('Data.MemoryStream.Read = ' + inttostr(len2));
WriteLn('----------------------------------');
//writeln(tencoding.utf8.getstring(StreamIn[x].data.BufferTMP));
{$endif}
StreamIn[x].Data.HandleSt := pchar('opusstream');
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('StreamIn[x].Data.HandleSt assisgned');
{$endif}
// Can not make work...
// StreamIn[x].Data.HandleOP := op_test_callbacks(StreamIn[x].data.MemoryStream, uos_callbacksms, StreamIn[x].data.BufferTMP[0], PipeBufferSize, err);
// this is a memorystream converted into a buffer, it works...
StreamIn[x].Data.HandleOP := op_test_memory(StreamIn[x].data.BufferTMP[0],PipeBufferSize, Err);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('op_test_file error = '+ inttostr(Err));
{$endif}
if Err=0 then
begin
Err := op_test_open(StreamIn[x].Data.HandleOP);
if (Err=0) and (op_link_count(StreamIn[x].Data.HandleOP)=1) then
begin
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else StreamIn[x].Data.SampleFormat := SampleFormat;
//tag
OpusTag := op_tags(StreamIn[x].Data.HandleOP, Nil);
if OpusTag<>nil then
begin
if OpusTag^.comments>0 then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn((Format('OpusTag.comments = %d', [OpusTag^.comments])));
{$endif}
LComment := OpusTag^.user_comments;
LcommentLength := OpusTag^.comment_lengths;
for j := 0 to OpusTag^.comments - 1 do
begin
SetLength(s, LcommentLength^);
move(Pointer(LComment^)^, Pointer(s)^, LcommentLength^);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
// WriteLn(s);
{$endif}
if j = 1 then StreamIn[x].Data.title := s;
if j = 2 then StreamIn[x].Data.artist := s;
if j = 3 then StreamIn[x].Data.album := s;
if j = 4 then StreamIn[x].Data.date := s;
if j = 5 then StreamIn[x].Data.comment := s;
if j = 6 then StreamIn[x].Data.tag := s;
inc(LComment);
inc(LcommentLength);
end;
end;
end;
// WriteLn((Format('op_bitrate = %d', [op_bitrate(StreamIn[x].Data.HandleOP, nil)])));
StreamIn[x].Data.Length := op_pcm_total(StreamIn[x].Data.HandleOP, Nil);
StreamIn[x].Data.channels := op_channel_count(StreamIn[x].Data.HandleOP, Nil);
StreamIn[x].Data.bitrate := op_bitrate(StreamIn[x].Data.HandleOP, Nil);
// opus use constant sample rate 48k
StreamIn[x].Data.samplerate := 48000 ;
StreamIn[x].Data.samplerateroot := StreamIn[x].Data.samplerate ;
StreamIn[x].Data.Seekable := true;
if FramesCount = -1 then
StreamIn[x].Data.Wantframes := 4096 * StreamIn[x].Data.Channels
else StreamIn[x].Data.Wantframes := FramesCount ;
SetLength(StreamIn[x].Data.Buffer,
StreamIn[x].Data.Wantframes*StreamIn[x].Data.Channels);
StreamIn[x].Data.LibOpen := 4;
end
else
begin
StreamIn[x].Data.LibOpen := -1;
end;
end;
end;
{$endif}
{$IF DEFINED(neaac)}
if (StreamIn[x].Data.LibOpen = -1) and (uosLoadResult.AAloadERROR = 0) then
begin
Err := -1;
StreamIn[x].AACI := TAACInfo.Create();
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('TAACInfo.Create() = ok');
{$endif}
{
Case SampleFormat of
0 : StreamIn[x].AACI:= MP4OpenFile(FileName, FAAD_FMT_FLOAT);
1 : StreamIn[x].AACI:= MP4OpenFile(FileName, FAAD_FMT_32BIT);
2 : StreamIn[x].AACI:= MP4OpenFile(FileName, FAAD_FMT_16BIT);
End;
}
if StreamIn[x].AACI <> nil then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('MP4OpenFile() = ok');
{$endif}
case StreamIn[x].AACI.outputFormat of
FAAD_FMT_16BIT : StreamIn[x].Data.SampleFormat := 2;
//FAAD_FMT_24BIT : ;
FAAD_FMT_32BIT : StreamIn[x].Data.SampleFormat := 1;
FAAD_FMT_FLOAT : StreamIn[x].Data.SampleFormat := 0;
//FAAD_FMT_DOUBLE: ;
end;
// StreamIn[x].Data.filename := FileName;
StreamIn[x].Data.HandleSt := StreamIn[x].AACI.hMP4;
StreamIn[x].Data.samplerate := StreamIn[x].AACI.SampleRate;
StreamIn[x].Data.channels := StreamIn[x].AACI.Channels;
case StreamIn[x].AACI.outputFormat of
FAAD_FMT_16BIT : StreamIn[x].Data.encoding := MPG123_ENC_SIGNED_16;
//FAAD_FMT_24BIT : ;
FAAD_FMT_32BIT : StreamIn[x].Data.encoding := MPG123_ENC_SIGNED_32;
FAAD_FMT_FLOAT : StreamIn[x].Data.encoding := MPG123_ENC_FLOAT_32;
//FAAD_FMT_DOUBLE: ;
end;
if FramesCount = -1 then
StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
else StreamIn[x].Data.Wantframes := FramesCount ;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes * StreamIn[x].Data.Channels
);
StreamIn[x].Data.title := StreamIn[x].AACI.Title;
StreamIn[x].Data.artist := StreamIn[x].AACI.Artist;
StreamIn[x].Data.album := StreamIn[x].AACI.Album;
StreamIn[x].Data.date := StreamIn[x].AACI.Date;
StreamIn[x].Data.comment := StreamIn[x].AACI.Comment;
StreamIn[x].Data.tag[0] := #0;
StreamIn[x].Data.tag[1] := #0;
StreamIn[x].Data.tag[2] := #0;
StreamIn[x].Data.genre := StreamIn[x].AACI.Genre;
StreamIn[x].Data.samplerateroot := StreamIn[x].AACI.SampleRate;
StreamIn[x].Data.hdformat := 0;
StreamIn[x].Data.frames := 0;
StreamIn[x].Data.Length := StreamIn[x].AACI.TotalSamples;
StreamIn[x].Data.Seekable := StreamIn[x].AACI.Size > 0;
StreamIn[x].Data.LibOpen := 2 ;
Err := 0;
end
else
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('MP4OpenFile() NOT ok');
{$endif}
end;
end;
{$endif}
{$IF DEFINED(cdrom)}
if (StreamIn[x].Data.LibOpen = -1) then
begin
Err := -1;
StreamIn[x].pCD := Nil;
case SampleFormat of
2 : StreamIn[x].pCD := CDROM_OpenFile(StreamIn[x].Data.FileName);
end;
if StreamIn[x].pCD <> nil then
begin
case StreamIn[x].pCD^.BitsPerSample of
16 : StreamIn[x].Data.SampleFormat := 2;
end;
StreamIn[x].Data.HandleSt := @StreamIn[x].pCD;
// Uos requires an assigned pointer....
StreamIn[x].Data.samplerate := StreamIn[x].pCD^.SampleRate;
StreamIn[x].Data.channels := StreamIn[x].pCD^.Channels;
case StreamIn[x].pCD^.BitsPerSample of
16 : StreamIn[x].Data.encoding := MPG123_ENC_SIGNED_16;
end;
if FramesCount = -1 then
StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
else StreamIn[x].Data.Wantframes := FramesCount;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes * StreamIn[x].Data.Channels
);
StreamIn[x].Data.title := '';
StreamIn[x].Data.artist := '';
StreamIn[x].Data.album := '';
StreamIn[x].Data.date := '';
StreamIn[x].Data.comment := '';
StreamIn[x].Data.tag[0] := #0;
StreamIn[x].Data.tag[1] := #0;
StreamIn[x].Data.tag[2] := #0;
StreamIn[x].Data.genre := 0;
StreamIn[x].Data.samplerateroot := StreamIn[x].pCD^.SampleRate;
StreamIn[x].Data.hdformat := 0;
StreamIn[x].Data.frames := 0;
StreamIn[x].Data.Length := StreamIn[x].pCD^.TotalSamples;
StreamIn[x].Data.LibOpen := 3;
Err := 0;
end;
end;
{$endif}
if err <> 0 then
begin
result := -1 ;
StreamIn[Length(StreamIn) - 1].Destroy;
setlength(StreamIn, Length(StreamIn) - 1);
end
else
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('addfrom memorystream OK');
{$endif}
Result := x;
StreamIn[x].Data.Output := OutputIndex;
StreamIn[x].Data.Status := 1;
StreamIn[x].Data.Position := 0;
StreamIn[x].Data.OutFrames := 0;
StreamIn[x].Data.Poseek := -1;
StreamIn[x].Data.TypePut := 0;
StreamIn[x].Data.seekable := True;
StreamIn[x].LoopProc := Nil;
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else StreamIn[x].Data.SampleFormat := SampleFormat;
case StreamIn[x].Data.LibOpen of
-1: ;
{$IF DEFINED(sndfile)}
0: StreamIn[x].Data.ratio := StreamIn[x].Data.Channels;
{$endif}
{$IF DEFINED(mpg123)}
1:
begin
if StreamIn[x].Data.SampleFormat = 2 then
StreamIn[x].Data.ratio := streamIn[x].Data.Channels
else StreamIn[x].Data.ratio := 2 * streamIn[x].Data.Channels;
if StreamIn[x].Data.SampleFormat = 0 then
mpg123_param(StreamIn[x].Data.HandleSt, StreamIn[x].Data.Channels, MPG123_FORCE_FLOAT
, 0);
end;
{$endif}
{$IF DEFINED(neaac)}
2 : StreamIn[x].Data.ratio := streamIn[x].AACI.Channels;
{$endif}
{$IF DEFINED(cdrom)}
3 : StreamIn[x].Data.ratio := streamIn[x].pCD^.Channels;
{$endif}
{$IF DEFINED(opus)}
4 : StreamIn[x].Data.ratio := streamIn[x].Data.Channels;
{$endif}
{$IF DEFINED(xmp)}
5 : StreamIn[x].Data.ratio := streamIn[x].Data.Channels;
{$endif}
end;
StreamIn[x].Data.Enabled := True;
end;
end;
end;
function Tuos_Player.AddFromFile(Filename: PChar; OutputIndex: cint32;
SampleFormat: cint32 ; FramesCount: cint32 ): cint32;
// Add a Input from Audio file with Custom parameters
// FileName : filename of audio file
// OutputIndex : OutputIndex of existing Output// -1: all output, -2: no output, other cint32 : existing Output
// SampleFormat : -1 default : Int16 (0: Float32, 1:Int32, 2:Int16)
// FramesCount : default : -1 (65536 div channels)
// example : InputIndex := AddFromFile('/usr/home/test.ogg',-1,-1,-1);
var
x, x2, err: cint32;
samprat : integer;
{$IF DEFINED(sndfile)}
sfInfo: TSF_INFO;
{$endif}
{$IF DEFINED(opus)}
s: UTF8String;
j: Integer;
OpusTag: POpusTags;
LComment: PPAnsiChar;
LcommentLength: PInteger;
{$endif}
{$IF DEFINED(xmp)}
mi: xmp_module_info;
{$endif}
{$IF DEFINED(mpg123)}
mpinfo: Tmpg123_frameinfo;
BufferTag: array[1..128] of char;
F: file;
// problems with mpg123
// mpid3v2: Tmpg123_id3v2;
{$endif}
begin
result := -1 ;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before all.');
{$endif}
if fileexists(filename) then
begin
x := 0;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before setlength.');
{$endif}
SetLength(StreamIn, Length(StreamIn) + 1);
StreamIn[Length(StreamIn) - 1] := Tuos_InStream.Create;
x := Length(StreamIn) - 1;
err := -1;
StreamIn[x].Data.Enabled := false;
StreamIn[x].Data.LibOpen := -1;
StreamIn[x].Data.levelEnable := 0;
StreamIn[x].Data.positionEnable := 0;
StreamIn[x].Data.levelArrayEnable := 0;
StreamIn[x].Data.lastbuf := 0;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Length(StreamIn) = '+ inttostr(x));
{$endif}
{$IF DEFINED(sndfile)}
if (uosLoadResult.SFloadERROR = 0) then
begin
StreamIn[x].Data.HandleSt := sf_open(FileName, SFM_READ, sfInfo);
(* try to open the file *)
if StreamIn[x].Data.HandleSt = nil then
begin
StreamIn[x].Data.LibOpen := -1;
err := -1;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('sf_open NOT OK');
{$endif}
end
else
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('sf_open OK');
{$endif}
StreamIn[x].Data.LibOpen := 0;
StreamIn[x].Data.filename := FileName;
StreamIn[x].Data.channels := SFinfo.channels;
if FramesCount = -1 then StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.
Channels
else
StreamIn[x].Data.Wantframes := FramesCount ;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.
Channels);
x2 := 0 ;
while x2 < Length(Streamin[x].Data.Buffer) do
begin
Streamin[x].Data.Buffer[x2] := 0.0 ;
inc(x2);
end;
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else
StreamIn[x].Data.SampleFormat := SampleFormat;
StreamIn[x].Data.hdformat := SFinfo.format;
StreamIn[x].Data.frames := SFinfo.frames;
StreamIn[x].Data.samplerate := SFinfo.samplerate;
StreamIn[x].Data.samplerateroot := SFinfo.samplerate;
StreamIn[x].Data.sections := SFinfo.sections;
StreamIn[x].Data.title :=
sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_TITLE);
StreamIn[x].Data.copyright :=
sf_get_string(StreamIn[x].Data.HandleSt,
SF_STR_COPYRIGHT);
StreamIn[x].Data.software :=
sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_SOFTWARE)
;
StreamIn[x].Data.comment :=
sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_COMMENT);
StreamIn[x].Data.artist :=
sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_ARTIST);
StreamIn[x].Data.date := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_DATE);
StreamIn[x].Data.track := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_TRACKNUMBER);
StreamIn[x].Data.genre := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_GENRE);
StreamIn[x].Data.album := sf_get_string(StreamIn[x].Data.HandleSt, SF_STR_ALBUM);
StreamIn[x].Data.Length := sfInfo.frames;
err := 0;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('sf_open END OK');
{$endif}
end;
end;
{$endif}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('sf StreamIn[x].Data.LibOpen = ' + inttostr(StreamIn[x].Data.LibOpen));
WriteLn('sf err = ' + inttostr(err));
{$endif}
// XMP
{$IF DEFINED(xmp)}
if (StreamIn[x].Data.LibOpen = -1) and (uosLoadResult.XMloadERROR = 0) then
begin
Err := -1;
StreamIn[x].Data.HandleSt := xmp_create_context();
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if StreamIn[x].Data.HandleSt = nil then WriteLn(' xmp_create_context() NOT OK')
else WriteLn(' xmp_create_context() OK');
{$endif}
if xmp_load_module(StreamIn[x].Data.HandleSt, PChar(FileName)) <> 0 then
begin
StreamIn[x].Data.LibOpen := -1;
err := -1;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('xmp_load_module NOT OK');
{$endif}
end
else
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('xmp_load_module() = ok');
{$endif}
xmp_start_player(StreamIn[x].Data.HandleSt, 44100, 0);
xmp_get_module_info(StreamIn[x].Data.HandleSt, mi);
// xmp_get_frame_info(StreamIn[x].Data.HandleSt , fi);
StreamIn[x].Data.LibOpen := 5;
StreamIn[x].Data.filename := FileName;
StreamIn[x].Data.channels := 2;
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else
StreamIn[x].Data.SampleFormat := SampleFormat;
// Need conversion because xmp is always 16 bit
if FramesCount = -1 then StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.
Channels
else
StreamIn[x].Data.Wantframes := FramesCount ;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.
Channels);
x2 := 0 ;
while x2 < Length(Streamin[x].Data.Buffer) do
begin
Streamin[x].Data.Buffer[x2] := 0.0 ;
inc(x2);
end;
StreamIn[x].Data.hdformat := 0;
StreamIn[x].Data.frames := 0;
StreamIn[x].Data.samplerate := 44100;
StreamIn[x].Data.samplerateroot := 44100;
// StreamIn[x].Data.sections := SFinfo.sections;
StreamIn[x].Data.title := String(mi.module^.Name);
StreamIn[x].Data.copyright := '';
StreamIn[x].Data.software := '';
StreamIn[x].Data.comment := String(mi.module^.typ);
StreamIn[x].Data.artist := String(mi.comment);
StreamIn[x].Data.date := '';
StreamIn[x].Data.track := '';
StreamIn[x].Data.genre := '';
StreamIn[x].Data.album := '';
StreamIn[x].Data.Length := 0;
err := 0;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('XMP_open END OK');
{$endif}
end;
end;
{$endif}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('XMP StreamIn[x].Data.LibOpen = ' + inttostr(StreamIn[x].Data.LibOpen));
WriteLn('XMP err = ' + inttostr(err));
{$endif}
{$IF DEFINED(mpg123)}
if ((StreamIn[x].Data.LibOpen = -1)) and (uosLoadResult.MPloadERROR = 0) then
begin
Err := -1;
StreamIn[x].Data.HandleSt := mpg123_new(Nil, Err);
if Err = 0 then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('mpg123_new OK');
{$endif}
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else
StreamIn[x].Data.SampleFormat := SampleFormat;
mpg123_format_none(StreamIn[x].Data.HandleSt);
case StreamIn[x].Data.SampleFormat of
0: mpg123_format(StreamIn[x].Data.HandleSt, DefRate, Stereo,
MPG123_ENC_FLOAT_32);
1: mpg123_format(StreamIn[x].Data.HandleSt, DefRate, Stereo,
MPG123_ENC_SIGNED_32);
2: mpg123_format(StreamIn[x].Data.HandleSt, DefRate, Stereo,
MPG123_ENC_SIGNED_16);
end;
Err := mpg123_open(StreamIn[x].Data.HandleSt, PChar(FileName));
end
else
begin
StreamIn[x].Data.LibOpen := -1;
end;
samprat := roundmath(StreamIn[x].Data.samplerate);
if Err = 0 then
Err := mpg123_getformat(StreamIn[x].Data.HandleSt,
samprat, StreamIn[x].Data.channels,
StreamIn[x].Data.encoding);
if Err = 0 then
begin
// Close handle and reload with forced resolution
mpg123_close(StreamIn[x].Data.HandleSt);
mpg123_delete(StreamIn[x].Data.HandleSt);
StreamIn[x].Data.HandleSt := mpg123_new(Nil, Err);
mpg123_format_none(StreamIn[x].Data.HandleSt);
case StreamIn[x].Data.SampleFormat of
0: mpg123_format(StreamIn[x].Data.HandleSt, samprat,
StreamIn[x].Data.channels, StreamIn[x].Data.encoding);
1: mpg123_format(StreamIn[x].Data.HandleSt, samprat,
StreamIn[x].Data.channels, StreamIn[x].Data.encoding);
2: mpg123_format(StreamIn[x].Data.HandleSt, samprat,
StreamIn[x].Data.channels, StreamIn[x].Data.encoding);
end;
mpg123_open(StreamIn[x].Data.HandleSt, (PChar(FileName)));
mpg123_getformat(StreamIn[x].Data.HandleSt,
samprat, StreamIn[x].Data.channels,
StreamIn[x].Data.encoding);
StreamIn[x].Data.filename := filename;
if FramesCount = -1 then StreamIn[x].Data.Wantframes :=
65536 Div StreamIn[x].Data.
Channels
else
StreamIn[x].Data.Wantframes := FramesCount ;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.
Channels);
mpg123_info(StreamIn[x].Data.HandleSt, MPinfo);
// custom code for reading ID3Tag ---> problems with mpg123_id3()
AssignFile(F, Filename);
FileMode := fmOpenRead + fmShareDenyNone;
Reset(F, 1);
Seek(F, FileSize(F) - 128);
BlockRead(F, BufferTag, SizeOf(BufferTag));
CloseFile(F);
StreamIn[x].Data.tag := copy(BufferTag, 1, 3);
StreamIn[x].Data.title := copy(BufferTag, 4, 30);
StreamIn[x].Data.artist := copy(BufferTag, 34, 30);
StreamIn[x].Data.album := copy(BufferTag, 64, 30);
StreamIn[x].Data.date := copy(BufferTag, 94, 4);
StreamIn[x].Data.comment := copy(BufferTag, 98, 30);
StreamIn[x].Data.track := inttostr(ord(BufferTag[127]));
StreamIn[x].Data.genre := inttostr(ord(BufferTag[128]));
StreamIn[x].Data.samplerateroot := StreamIn[x].Data.samplerate ;
StreamIn[x].Data.hdformat := MPinfo.layer;
StreamIn[x].Data.frames := MPinfo.framesize;
StreamIn[x].Data.Length := mpg123_length(StreamIn[x].Data.HandleSt);
StreamIn[x].Data.LibOpen := 1;
end
else
begin
StreamIn[x].Data.LibOpen := -1;
end;
end;
{$endif}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('mp StreamIn[x].Data.LibOpen = ' + inttostr(StreamIn[x].Data.LibOpen));
WriteLn('mp err = ' + inttostr(err));
{$endif}
{$IF DEFINED(opus)}
if (StreamIn[x].Data.LibOpen = -1) and (uosLoadResult.OPloadERROR = 0) then
begin
Err := -1;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before Opus');
{$endif}
StreamIn[x].Data.HandleSt := pchar('opus');
StreamIn[x].Data.HandleOP := op_test_file(PChar(FileName), Err);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('op_test_file error = '+ inttostr(Err));
{$endif}
if Err=0
then
begin
Err := op_test_open(StreamIn[x].Data.HandleOP);
if (Err=0) and (op_link_count(StreamIn[x].Data.HandleOP)=1)
then
begin
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else
StreamIn[x].Data.SampleFormat := SampleFormat;
//tag
OpusTag := op_tags(StreamIn[x].Data.HandleOP, Nil);
if OpusTag<>nil
then
begin
if OpusTag^.comments>0
then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn((Format('OpusTag.comments = %d', [OpusTag^.comments])));
{$endif}
LComment := OpusTag^.user_comments;
LcommentLength := OpusTag^.comment_lengths;
for j := 0 to OpusTag^.comments - 1 do
begin
SetLength(s, LcommentLength^);
move(Pointer(LComment^)^, Pointer(s)^, LcommentLength^);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
// WriteLn(s);
{$endif}
if j = 1 then StreamIn[x].Data.title := s;
if j = 2 then StreamIn[x].Data.artist := s;
if j = 3 then StreamIn[x].Data.album := s;
if j = 4 then StreamIn[x].Data.date := s;
if j = 5 then StreamIn[x].Data.comment := s;
if j = 6 then StreamIn[x].Data.tag := s;
inc(LComment);
inc(LcommentLength);
end;
end;
end;
// WriteLn((Format('op_bitrate = %d', [op_bitrate(StreamIn[x].Data.HandleOP, nil)])));
StreamIn[x].Data.Length := op_pcm_total(StreamIn[x].Data.HandleOP, Nil);
StreamIn[x].Data.filename := FileName;
StreamIn[x].Data.channels := op_channel_count(StreamIn[x].Data.HandleOP, Nil);
// opus use constant sample rate 48k
StreamIn[x].Data.samplerate := 48000 ;
StreamIn[x].Data.samplerateroot := StreamIn[x].Data.samplerate ;
StreamIn[x].Data.Seekable := true;
if FramesCount = -1 then StreamIn[x].Data.Wantframes := 4096 * StreamIn[x].Data.
Channels
else
StreamIn[x].Data.Wantframes := FramesCount ;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes*StreamIn[x].Data.
Channels);
StreamIn[x].Data.LibOpen := 4;
end
else
begin
StreamIn[x].Data.LibOpen := -1;
end;
end;
end;
{$endif}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('op StreamIn[x].Data.LibOpen = ' + inttostr(StreamIn[x].Data.LibOpen));
WriteLn('op err = ' + inttostr(err));
{$endif}
{$IF DEFINED(neaac)}
if (StreamIn[x].Data.LibOpen = -1) and (uosLoadResult.AAloadERROR = 0) then
begin
Err := -1;
StreamIn[x].AACI := TAACInfo.Create();
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('TAACInfo.Create() = ok');
{$endif}
case SampleFormat of
0 : StreamIn[x].AACI := MP4OpenFile(FileName, FAAD_FMT_FLOAT);
1 : StreamIn[x].AACI := MP4OpenFile(FileName, FAAD_FMT_32BIT);
2 : StreamIn[x].AACI := MP4OpenFile(FileName, FAAD_FMT_16BIT);
end;
if StreamIn[x].AACI <> nil then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('MP4OpenFile() = ok');
{$endif}
case StreamIn[x].AACI.outputFormat of
FAAD_FMT_16BIT : StreamIn[x].Data.SampleFormat := 2;
//FAAD_FMT_24BIT : ;
FAAD_FMT_32BIT : StreamIn[x].Data.SampleFormat := 1;
FAAD_FMT_FLOAT : StreamIn[x].Data.SampleFormat := 0;
//FAAD_FMT_DOUBLE: ;
end;
StreamIn[x].Data.filename := FileName;
StreamIn[x].Data.HandleSt := StreamIn[x].AACI.hMP4;
StreamIn[x].Data.samplerate := StreamIn[x].AACI.SampleRate;
StreamIn[x].Data.channels := StreamIn[x].AACI.Channels;
case StreamIn[x].AACI.outputFormat of
FAAD_FMT_16BIT : StreamIn[x].Data.encoding := MPG123_ENC_SIGNED_16;
//FAAD_FMT_24BIT : ;
FAAD_FMT_32BIT : StreamIn[x].Data.encoding := MPG123_ENC_SIGNED_32;
FAAD_FMT_FLOAT : StreamIn[x].Data.encoding := MPG123_ENC_FLOAT_32;
//FAAD_FMT_DOUBLE: ;
end;
if FramesCount = -1 then
StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
else
StreamIn[x].Data.Wantframes := FramesCount ;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes * StreamIn[x].Data.
Channels);
StreamIn[x].Data.title := StreamIn[x].AACI.Title;
StreamIn[x].Data.artist := StreamIn[x].AACI.Artist;
StreamIn[x].Data.album := StreamIn[x].AACI.Album;
StreamIn[x].Data.date := StreamIn[x].AACI.Date;
StreamIn[x].Data.comment := StreamIn[x].AACI.Comment;
StreamIn[x].Data.tag[0] := #0;
StreamIn[x].Data.tag[1] := #0;
StreamIn[x].Data.tag[2] := #0;
StreamIn[x].Data.genre := StreamIn[x].AACI.Genre;
StreamIn[x].Data.samplerateroot := StreamIn[x].AACI.SampleRate;
StreamIn[x].Data.hdformat := 0;
StreamIn[x].Data.frames := 0;
StreamIn[x].Data.Length := StreamIn[x].AACI.TotalSamples;
StreamIn[x].Data.Seekable := StreamIn[x].AACI.Size > 0;
StreamIn[x].Data.LibOpen := 2 ;
Err := 0;
end
else
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('MP4OpenFile() NOT ok');
{$endif}
end;
end;
{$endif}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('ac StreamIn[x].Data.LibOpen = ' + inttostr(StreamIn[x].Data.LibOpen));
WriteLn('ac err = ' + inttostr(err));
{$endif}
{$IF DEFINED(cdrom)}
if (StreamIn[x].Data.LibOpen = -1) then
begin
Err := -1;
StreamIn[x].pCD := Nil;
case SampleFormat of
2 : StreamIn[x].pCD := CDROM_OpenFile(FileName);
end;
if StreamIn[x].pCD <> nil then
begin
case StreamIn[x].pCD^.BitsPerSample of
16 : StreamIn[x].Data.SampleFormat := 2;
end;
StreamIn[x].Data.filename := FileName;
StreamIn[x].Data.HandleSt := @StreamIn[x].pCD;
// Uos requires an assigned pointer....
StreamIn[x].Data.samplerate := StreamIn[x].pCD^.SampleRate;
StreamIn[x].Data.channels := StreamIn[x].pCD^.Channels;
case StreamIn[x].pCD^.BitsPerSample of
16 : StreamIn[x].Data.encoding := MPG123_ENC_SIGNED_16;
end;
if FramesCount = -1 then
StreamIn[x].Data.Wantframes := 65536 Div StreamIn[x].Data.Channels
else
StreamIn[x].Data.Wantframes := FramesCount;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.Wantframes * StreamIn[x].Data.
Channels);
StreamIn[x].Data.title := '';
StreamIn[x].Data.artist := '';
StreamIn[x].Data.album := '';
StreamIn[x].Data.date := '';
StreamIn[x].Data.comment := '';
StreamIn[x].Data.tag[0] := #0;
StreamIn[x].Data.tag[1] := #0;
StreamIn[x].Data.tag[2] := #0;
StreamIn[x].Data.genre := '0';
StreamIn[x].Data.samplerateroot := StreamIn[x].pCD^.SampleRate;
StreamIn[x].Data.hdformat := 0;
StreamIn[x].Data.frames := 0;
StreamIn[x].Data.Length := StreamIn[x].pCD^.TotalSamples;
StreamIn[x].Data.LibOpen := 3;
Err := 0;
end;
end;
{$endif}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('cd StreamIn[x].Data.LibOpen = ' + inttostr(StreamIn[x].Data.LibOpen));
WriteLn('cd err = ' + inttostr(err));
{$endif}
if (err <> 0) or (StreamIn[x].Data.LibOpen = -1) then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('not ok StreamIn[x].Data.LibOpen = -1');
WriteLn('not ok cd err = ' + inttostr(err));
{$endif}
result := -1 ;
StreamIn[Length(StreamIn) - 1].Destroy;
setlength(StreamIn, Length(StreamIn) - 1);
end
else
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('addfromfile OK');
{$endif}
Result := x;
StreamIn[x].Data.Output := OutputIndex;
StreamIn[x].Data.Status := 1;
StreamIn[x].Data.Position := 0;
StreamIn[x].Data.OutFrames := 0;
StreamIn[x].Data.Poseek := -1;
StreamIn[x].Data.TypePut := 0;
StreamIn[x].Data.seekable := True;
StreamIn[x].LoopProc := Nil;
if SampleFormat = -1 then
StreamIn[x].Data.SampleFormat := 2
else
StreamIn[x].Data.SampleFormat := SampleFormat;
case StreamIn[x].Data.LibOpen of
0: StreamIn[x].Data.ratio := StreamIn[x].Data.Channels;
{$IF DEFINED(mpg123)}
1:
begin
if StreamIn[x].Data.SampleFormat = 2 then
StreamIn[x].Data.ratio := streamIn[x].Data.Channels
else
StreamIn[x].Data.ratio := 2 * streamIn[x].Data.Channels;
if StreamIn[x].Data.SampleFormat = 0 then
mpg123_param(StreamIn[x].Data.HandleSt, StreamIn[x].Data.Channels,
MPG123_FORCE_FLOAT, 0);
end;
{$endif}
{$IF DEFINED(neaac)}
2 : StreamIn[x].Data.ratio := streamIn[x].AACI.Channels;
{$endif}
{$IF DEFINED(cdrom)}
3 : StreamIn[x].Data.ratio := streamIn[x].pCD^.Channels;
{$endif}
{$IF DEFINED(opus)}
4 : StreamIn[x].Data.ratio := streamIn[x].Data.Channels;
{$endif}
{$IF DEFINED(xmp)}
5 : StreamIn[x].Data.ratio := streamIn[x].Data.Channels;
{$endif}
end;
StreamIn[x].Data.Enabled := True;
end;
end
else result := -2;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('result = ' + inttostr(result));
WriteLn('cd err = ' + inttostr(err));
{$endif}
end;
procedure Tuos_Player.ReadEndless(x : integer);
begin
{
Nothing to do: all is done with AddFromEndlessMuted.
}
end;
{$IF DEFINED(synthesizer)}
procedure Tuos_Player.FillLookupTable(x, typewave, channel, AHarmonics: Integer;
EvenHarmonics : shortint);
var
i, j, l: Integer;
nPI_l, attenuation: Double;
thesample: single;
begin
l := 1024;
nPI_l := 2*PI/l;
for i:=0 to l-1 do
begin
if typewave = 0 then // sine
begin
thesample := sin(i * nPI_l);
if thesample > 1 then
thesample := 1;
if thesample < -1 then
thesample := -1;
if Channel = 1 then
StreamIn[x].Data.LookupTableLeft[i] := thesample;
// writeln( floattostr((LookupTableLeft[i])) + ' left ');
if Channel = 2 then
StreamIn[x].Data.LookupTableRight[i] := thesample;
// writeln( 'right ' + floattostr((LookupTableRight[i])));
end;
if typewave = 1 then // square
begin
if sin(i * nPI_l) >= 0 then
thesample := 1
else
thesample := -1;
if Channel = 1 then
StreamIn[x].Data.LookupTableLeft[i] := thesample;
if Channel = 2 then
StreamIn[x].Data.LookupTableRight[i] := thesample;
end;
if typewave = 2 then // triangle
begin
if Channel = 1 then
begin
if i < (l div 2) + 1 then
thesample := (((l - (i * 2)) / (l / 2))) - 1
else
thesample := StreamIn[x].Data.LookupTableLeft[l - i];
if thesample > 1 then
thesample := 1;
if thesample < -1 then
thesample := -1;
StreamIn[x].Data.LookupTableLeft[i] := thesample;
//writeln( floattostr((LookupTableLeft[i])) + ' left ');
end;
if Channel = 2 then
begin
if i < (l div 2) + 1 then
thesample := (((l - (i * 2)) / (l / 2))) - 1
else
thesample := StreamIn[x].Data.LookupTableRight[l - i];
if thesample > 1 then
thesample := 1;
if thesample < -1 then
thesample := -1;
StreamIn[x].Data.LookupTableRight[i] := thesample;
// writeln( floattostr((LookupTableright[i])) + ' right ');
end;
end;
if typewave = 3 then // Sawtooth
begin
thesample := ((l - i) / (l / 2)) - 1;
if thesample > 1 then
thesample := 1;
if thesample < -1 then
thesample := -1;
if Channel = 1 then
StreamIn[x].Data.LookupTableLeft[i] := thesample;
if Channel = 2 then
StreamIn[x].Data.LookupTableRight[i] := thesample;
end;
end;
if AHarmonics > 0 then
for j:=1 to AHarmonics do
begin
if ((((j mod 2) =1) and (EvenHarmonics=1)) or (EvenHarmonics=0)) then
begin
attenuation := power(j+1, 4);
nPI_l := 2*j*pi/l;
for i:=0 to l-1 do
begin
if typewave = 0 then
begin
if channel = 1 then
StreamIn[x].Data.LookupTableLeft[i] :=
StreamIn[x].Data.LookupTableLeft[i]+sin
(i*nPI_l)/attenuation;
if channel = 2 then
StreamIn[x].Data.LookupTableRight[i] :=
StreamIn[x].Data.LookupTableRight[i]+
sin(i*nPI_l)/attenuation;
end;
if typewave = 1 then
begin
if channel = 1 then
begin
if sin(i*nPI_l) >= 0 then
StreamIn[x].Data.LookupTableLeft[i] :=
StreamIn[x].Data.LookupTableLeft[i]
+(1/attenuation)
else
StreamIn[x].Data.LookupTableLeft[i] :=
StreamIn[x].Data.LookupTableLeft[i]
+(-1/attenuation);
end ;
if channel = 2 then
begin
if sin(i*nPI_l) >= 0 then
StreamIn[x].Data.LookupTableRight[i] :=
StreamIn[x].Data.LookupTableRight[
i]+(1/attenuation)
else
StreamIn[x].Data.LookupTableRight[i] :=
StreamIn[x].Data.LookupTableRight[
i]+(-1/attenuation);
end ;
end;
end;
end;
end;
end;
procedure Tuos_Player.ReadSynth(x :integer);
var
x2 : integer;
sf1, sf2 : cfloat;
ps: PDArShort;
// if input is Int16 format
pl: PDArLong;
// if input is Int32 format
pf: PDArFloat;
// if input is Float32 format
i: culong;
chan : integer;
aFreqL, aFreqR, aPosL, aPosR, aStepL, aStepR: cfloat;
begin
//for x2 := 0 to length(StreamIn[x].Data.Buffer)
// do StreamIn[x].Data.Buffer[x2] := 0;
if StreamIn[x].Data.SampleFormat = 2 then ps := @StreamIn[x].Data.Buffer
else
if StreamIn[x].Data.SampleFormat = 1 then pl := @StreamIn[x].Data.Buffer
else
if StreamIn[x].Data.SampleFormat = 0 then pf := @StreamIn[x].Data.Buffer;
chan := StreamIn[x].Data.channels;
aPosL := StreamIn[x].Data.PosInTableLeft;
aPosR := StreamIn[x].Data.PosInTableRight;
aFreqL := StreamIn[x].Data.freqLsine;
aFreqR := StreamIn[x].Data.freqRsine;
aStepL := (aFreqL*1024/StreamIn[x].Data.samplerate);
aStepR := (aFreqR*1024/StreamIn[x].Data.samplerate);;
StreamIn[x].Data.posdursine :=
StreamIn[x].Data.posdursine + (StreamIn[x].Data.WantFrames Div chan
);
x2 := 0 ;
if (StreamIn[x].Data.posdursine <= StreamIn[x].Data.dursine) or (StreamIn[x].Data.dursine = 0)
then
begin
while x2 < (length(StreamIn[x].Data.Buffer) div chan) do
begin
sf2 := 0;
sf1 := 0;
sf1 := StreamIn[x].Data.VLeft*StreamIn[x].Data.LookupTableLeft[trunc(aPosL) And (1023)];
aPosL := aPosL+aStepL;
if chan = 2 then
begin
sf2 := StreamIn[x].Data.VRight*StreamIn[x].Data.LookupTableRight[trunc(aPosR) And (
1023)];
aPosR := aPosR+aStepR;
end;
case StreamIn[x].Data.SampleFormat of
2: // int16
begin
ps^[x2] := trunc(sf1 * 32768);
if chan = 2 then ps^[x2+1] := trunc(sf2 * 32768);
end;
1: // int32
begin
pl^[x2] := trunc(sf1 * 2147483648);
if chan = 2 then pl^[x2+1] := trunc(sf2 * 2147483648);
end;
0: // float32
begin
pf^[x2] := sf1;
if chan = 2 then pf^[x2+1] := sf2 ;
end;
end;
inc(x2, chan);
end;
i := trunc(aPosL) Div 1024;
StreamIn[x].Data.PosInTableLeft := aPosL-(i*1024);
i := trunc(aPosR) Div 1024;
StreamIn[x].Data.PosInTableRight := aPosR-(i*1024);
StreamIn[x].Data.OutFrames := StreamIn[x].Data.WantFrames;
end
else StreamIn[x].Data.OutFrames := 0 ;
end;
{$endif}
procedure Tuos_Player.ReadMem(X : integer);
var
x2, wantframestemp : integer;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
i : integer;
st : string;
{$endif}
begin
if length(StreamIn[x].Data.memorybuffer) - StreamIn[x].Data.posmem - (StreamIn[x].Data.WantFrames
* StreamIn[x].Data.Channels) >= 0 then wantframestemp := (StreamIn[x].Data.WantFrames
* StreamIn[x].Data.Channels)
else
wantframestemp := length(StreamIn[x].Data.memorybuffer) - StreamIn[x].Data.posmem;
// wantframestemp := StreamIn[x].Data.wantframes;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('length(StreamIn[x].Data.MemoryBuffer) = '+inttostr(length(StreamIn[x].Data.MemoryBuffer))
) ;
writeln('StreamIn[x].Data.posmem = '+inttostr(StreamIn[x].Data.posmem)) ;
writeln('wantframestemp = '+inttostr(wantframestemp)) ;
{$endif}
for x2 := 0 to wantframestemp -1 do
StreamIn[x].Data.Buffer[x2] := (StreamIn[x].Data.memorybuffer[StreamIn[x].Data.posmem + x2]);
StreamIn[x].Data.posmem := StreamIn[x].Data.posmem + wantframestemp;
StreamIn[x].Data.OutFrames := wantframestemp;
if StreamIn[x].Data.SampleFormat > 0 then
StreamIn[x].Data.Buffer := ConvertSampleFormat(StreamIn[x].Data);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('StreamIn[x].Data.posmem after = '+inttostr(StreamIn[x].Data.posmem)) ;
writeln('StreamIn[x].Data.OutFrames = '+ inttostr(wantframestemp)) ;
st := '';
for i := 0 to length(StreamIn[x].data.Buffer) -1 do
st := st + '|' + inttostr(i) + '=' + floattostr(StreamIn[x].data.Buffer[i]);
WriteLn('OUTPUT DATA AFTER Input from memory ------------------------------');
WriteLn(st);
{$endif}
end;
procedure Tuos_Player.ReadMemDec(X : integer);
var
wantframestemp : integer;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
i : integer;
st : string;
{$endif}
begin
{
if length(StreamIn[x].Data.MemoryStream) - StreamIn[x].Data.posmem - (StreamIn[x].Data.WantFrames
* StreamIn[x].Data.Channels) >= 0 then wantframestemp := (StreamIn[x].Data.WantFrames
* StreamIn[x].Data.Channels) else
wantframestemp := length(StreamIn[x].Data.MemoryStream) - StreamIn[x].Data.posmem;
}
wantframestemp := (StreamIn[x].Data.WantFrames * StreamIn[x].Data.channels);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('length(StreamIn[x].MemoryStreamDec) = '+inttostr(StreamIn[x].MemoryStreamDec.size)) ;
writeln('StreamIn[x].Data.posmem = '+inttostr(StreamIn[x].Data.posmem)) ;
writeln('wantframestemp = '+inttostr(wantframestemp)) ;
{$endif}
StreamIn[x].Data.OutFrames := StreamIn[x].MemoryStreamDec.Read(StreamIn[x].Data.Buffer[0] ,
wantframestemp);
StreamIn[x].Data.OutFrames := StreamIn[x].Data.OutFrames Div StreamIn[x].Data.channels;
StreamIn[x].Data.posmem := StreamIn[x].Data.posmem + wantframestemp;
// StreamIn[x].Data.OutFrames := wantframestemp;
if StreamIn[x].Data.SampleFormat > 0 then
StreamIn[x].Data.Buffer := ConvertSampleFormat(StreamIn[x].Data);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('StreamIn[x].Data.posmem after = '+inttostr(StreamIn[x].Data.posmem)) ;
writeln('StreamIn[x].Data.OutFrames = '+ inttostr(wantframestemp)) ;
st := '';
for i := 0 to length(StreamIn[x].data.Buffer) -1 do
st := st + '|' + inttostr(i) + '=' + floattostr(StreamIn[x].data.Buffer[i]);
WriteLn('OUTPUT DATA AFTER Input from memory ------------------------------');
WriteLn(st);
{$endif}
end;
procedure Tuos_Player.DoSeek( x : integer);
begin
if StreamIn[x].Data.TypePut = 4 then
StreamIn[x].Data.posmem := 0
else
case StreamIn[x].Data.LibOpen of
-1: ;
{$IF DEFINED(sndfile)}
0: sf_seek(StreamIn[x].Data.HandleSt, StreamIn[x].Data.Poseek, 0);
{$endif}
{$IF DEFINED(mpg123)}
1: mpg123_seek(StreamIn[x].Data.HandleSt, StreamIn[x].Data.Poseek, 0);
{$endif}
{$IF DEFINED(neaac)}
2 : MP4Seek(StreamIn[x].AACI, StreamIn[x].Data.Poseek);
{$endif}
{$IF DEFINED(cdrom)}
3 : ;
{$endif}
{$IF DEFINED(opus)}
4 : op_pcm_seek(StreamIn[x].Data.HandleOP, StreamIn[x].Data.Poseek);
{$endif}
end;
end;
procedure Tuos_Player.DoDSPOutAfterBufProc(x: integer);
var
x3 : integer;
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
msg: TfpgMessageParams;
// for fpgui
{$endif}
begin
for x3 := 0 to high(StreamOut[x].DSP) do
if (StreamOut[x].DSP[x3].Enabled = True) then
begin
if (StreamOut[x].DSP[x3].AftFunc <> nil) then
StreamOut[x].Data.Buffer :=
StreamOut[x].DSP[x3].AftFunc(StreamOut[x].Data,
StreamOut[x].DSP[x3].fftdata);
{$IF DEFINED(mse)}
if (StreamOut[x].DSP[x3].LoopProc <> nil) then
begin
application.queueasynccall(StreamOut[x].DSP[x3].LoopProc);
end;
{$else}
{$IF not DEFINED(Library)}
if (StreamOut[x].DSP[x3].LoopProc <> nil) then
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,StreamOut[x].
DSP[x3].LoopProc);
{$else}
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
begin
msg.user.Param1 := x3 ;
// the index of the dsp
msg.user.Param2 := 1;
// it is a OUT DSP
fpgPostMessage(self, refer, MSG_CUSTOM1, msg);
end;
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,StreamOut[x].DSP[
x3].LoopProc);
{$endif}
{$endif}
{$elseif not DEFINED(java)}
if (StreamOut[x].DSP[x3].LoopProc <> nil) then
StreamOut[x].DSP[x3].LoopProc;
{$else}
if (StreamOut[x].DSP[x3].LoopProc <> nil) then
{$IF FPC_FULLVERSION >= 20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@StreamOut[x].
DSP[x3].LoopProcjava);
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@StreamOut[x].DSP
[x3].LoopProcjava);
{$endif}
{$endif}
{$endif}
end;
end;
procedure Tuos_Player.DoArrayLevel(x: integer);
begin
setlength(uosLevelArray[index][x],length(uosLevelArray[index][x]) +1);
uosLevelArray[index][x][length(uosLevelArray[index][x]) -1 ] := StreamIn[x].Data.LevelLeft;
setlength(uosLevelArray[index][x],length(uosLevelArray[index][x]) +1);
uosLevelArray[index][x][length(uosLevelArray[index][x]) -1 ] := StreamIn[x].Data.LevelRight;
// writeln('array length = ' + inttostr(length(uosLevelArray[index][x])));
end;
{$IF DEFINED(portaudio)}
procedure Tuos_Player.ReadDevice(x : integer);
var
x2 : integer;
begin
for x2 := 0 to StreamIn[x].Data.WantFrames -1 do
StreamIn[x].Data.Buffer[x2] := cfloat(0.0);
// clear input
Pa_ReadStream(StreamIn[x].Data.HandleSt,
@StreamIn[x].Data.Buffer[0], StreamIn[x].Data.WantFrames);
// err :=// if you want clean buffer
StreamIn[x].Data.OutFrames :=
StreamIn[x].Data.WantFrames * StreamIn[x].Data.Channels;
// if err = 0 then StreamIn[x].Data.Status := 1 else StreamIn[x].Data.Status := 0;// if you want clean buffer
end;
{$endif}
procedure Tuos_Player.DoDSPinBeforeBufProc(x: integer);
var
x2 : integer;
begin
for x2 := 0 to high(StreamIn[x].DSP) do
if (StreamIn[x].DSP[x2].Enabled = True) and
(StreamIn[x].DSP[x2].BefFunc <> nil) then
StreamIn[x].DSP[x2].BefFunc(StreamIn[x].Data, StreamIn[x].DSP[x2].fftdata);
end;
procedure Tuos_Player.DoDSPinAfterBufProc(x: integer);
var
x2 : integer;
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
msg: TfpgMessageParams;
// for fpgui
{$endif}
begin
for x2 := 0 to high(StreamIn[x].DSP) do
if (StreamIn[x].DSP[x2].Enabled = True) then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('DSPin AfterBuffProc 1.');
{$endif}
if (StreamIn[x].DSP[x2].AftFunc <> nil) then
StreamIn[x].Data.Buffer :=
StreamIn[x].DSP[x2].AftFunc(StreamIn[x].Data,
StreamIn[x].DSP[x2].fftdata);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('DSPin AfterBuffProc 2.');
{$endif}
{$IF DEFINED(mse)}
if (StreamIn[x].DSP[x2].LoopProc <> nil) then
begin
application.queueasynccall(StreamIn[x].DSP[x2].LoopProc) ;
end;
{$else}
{$IF not DEFINED(Library)}
if (StreamIn[x].DSP[x2].LoopProc <> nil) then
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,StreamIn[x].DSP
[x2].LoopProc);
{$else}
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
begin
msg.user.Param1 := x2 ;
// the index of the dsp
msg.user.Param2 := 0;
// it is a In DSP
fpgPostMessage(self, refer, MSG_CUSTOM1, msg);
end;
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,StreamIn[x].DSP[
x2].LoopProc);
{$endif}
{$endif}
{$elseif not DEFINED(java)}
if (StreamIn[x].DSP[x2].LoopProc <> nil) then
StreamIn[x].DSP[x2].LoopProc;
{$else}
if (StreamIn[x].DSP[x2].LoopProc <> nil) then
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@Streamin[x].
DSP[x2].LoopProcjava);
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@Streamin[x].DSP[
x2].LoopProcjava);
{$endif}
{$endif}
{$endif}
end;
end;
procedure Tuos_Player.SeekIfTerminated;
var
x, statustemp : integer;
begin
statustemp := 0 ;
for x := 0 to high(StreamIn) do
begin
if (StreamIn[x].Data.enabled = true)
then
begin
if (StreamIn[x].Data.TypePut <> 1)
then
begin
if StreamIn[x].Data.Status = 1 then
statustemp := StreamIn[x].Data.Status;
if (StreamIn[x].Data.Status = 2) and (statustemp = 0) then
statustemp := StreamIn[x].Data.Status;
end
else
if
(StreamIn[x].Data.TypePut = 1) then statustemp := status ;
end ;
end;
if statustemp <> status then status := statustemp;
if (status = 0) and IsLooped then
begin
for x:= 0 to high(StreamIn) do
begin
InputSeek(x, 0);
if StreamIn[x].Data.TypePut = 4 then
StreamIn[x].Data.posmem := 0;
StreamIn[x].Data.status := 1;
end;
Status := 1;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Loop (NLooped: '+IntToStr(NLooped)+')----');
{$endif}
if NLooped > 0 then
Dec(NLooped);
end;
end;
procedure Tuos_Player.DoLoopEndMethods;
begin
{$IF DEFINED(mse)}
if LoopEndProc <> nil then
begin
application.queueasynccall(LoopEndProc);
end;
{$else}
{$IF not DEFINED(Library)}
if LoopEndProc <> nil then
// Execute LoopEndProc procedure
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,LoopEndProc);
{$else}
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
begin
msg.user.Param1 := -2 ;
// it is the first proc
fpgPostMessage(self, refer, MSG_CUSTOM1, msg);
end;
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,LoopEndProc);
{$endif}
{$endif}
{$elseif not DEFINED(java)}
if LoopEndProc <> nil then
LoopEndProc;
{$else}
if LoopEndProc <> nil then
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@endprocjava);
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@endprocjava);
// Execute EndProc procedure
{$endif}
{$endif}
{$endif}
end;
procedure Tuos_Player.DoEndProc;
begin
{$IF DEFINED(mse)}
if EndProc <> nil then
application.queueasynccall(EndProc);
{$else}
{$IF not DEFINED(Library)}
if EndProc <> nil then
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,EndProc);
// Execute EndProc procedure
//thethread.queue(thethread,EndProc);// Execute EndProc procedure
{$elseif not DEFINED(java)}
if (EndProc <> nil) then
EndProc;
{$else}
if (EndProc <> nil) then
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@endprocjava);
// Execute EndProc procedure
{$endif}
{$endif}
end;
procedure Tuos_Player.DoTerminateNoFreePlayer;
var
x, x2 : integer;
begin
for x := 0 to high(StreamIn) do
begin
if (length(StreamIn[x].DSP) > 0) then
for x2 := 0 to high(StreamIn[x].DSP) do
if (StreamIn[x].DSP[x2].EndFunc <> nil) then
StreamIn[x].DSP[x2].EndFunc(StreamIn[x].Data, StreamIn[x].DSP[x2].fftdata);
end;
for x := 0 to high(StreamOut) do
begin
if (length(StreamOut[x].DSP) > 0) then
for x2 := 0 to high(StreamOut[x].DSP) do
if (StreamOut[x].DSP[x2].EndFunc <> nil) then
StreamOut[x].DSP[x2].EndFunc(StreamOut[x].Data, StreamOut[x].DSP[x2].fftdata);
end;
if (StreamOut[x].Data.TypePut = 0) then
begin
WriteWave(StreamOut[x].Data.Filename, StreamOut[x].FileBuffer);
// StreamOut[x].FileBuffer.Data.Free;
end;
if (StreamOut[x].Data.TypePut = 4) then
begin
WriteWaveFromMem(StreamOut[x].Data.Filename, StreamOut[x].FileBuffer);
// StreamOut[x].FileBuffer.Data.Free;
end;
{$IF DEFINED(sndfile)}
if (StreamOut[x].Data.TypePut = 6) then
begin
sf_write_sync(StreamOut[x].Data.HandleSt);
sf_close(StreamOut[x].Data.HandleSt);
end;
if (StreamOut[x].Data.TypePut = 5) then
begin
sf_write_sync(StreamOut[x].Data.HandleSt);
sf_close(StreamOut[x].Data.HandleSt);
end;
{$endif}
{$IF DEFINED(mse)}
if EndProc <> nil then
begin
application.queueasynccall(EndProc);
end;
{$else}
{$IF not DEFINED(Library)}
if EndProc <> nil then
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,EndProc);
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,EndProc);
// Execute EndProc procedure
{$endif}
{$elseif not DEFINED(java)}
if (EndProc <> nil) then
EndProc;
{$else}
if (EndProc <> nil) then
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@endprocjava);
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@endprocjava);
// Execute EndProc procedure
{$endif}
{$endif}
{$endif}
{$IF DEFINED(portaudio)}
for x := 0 to high(StreamOut) do
if (StreamOut[x].Data.HandleSt <> nil) and
(StreamOut[x].Data.TypePut = 1) then
Pa_StopStream(StreamOut[x].Data.HandleSt);
{$ENDIF}
if EndProcOnly <> nil then EndProcOnly;
StreamIn[x].Data.Poseek := 0;
// set to begin
doseek(x);
Status := 2;
if isGlobalPause = true then
begin
RTLeventReSetEvent(uosInit.evGlobalPause)
end
else
begin
RTLeventReSetEvent(evPause);
end;
end;
procedure Tuos_Player.DoTerminatePlayer;
var
x, x2 : integer;
begin
if length(PlugIn) > 0 then
begin
for x := 0 to high(PlugIn) do
begin
{$IF DEFINED(soundtouch)}
if Plugin[x].Name = 'soundtouch' then
begin
soundtouch_clear(Plugin[x].PlugHandle);
soundtouch_destroyInstance(Plugin[x].PlugHandle);
end;
if Plugin[x].Name = 'getbpm' then
begin
bpm_destroyInstance(Plugin[x].PlugHandle);
end;
{$endif}
{$IF DEFINED(bs2b)}
if Plugin[x].Name = 'bs2b' then
begin
bs2b_close(Plugin[x].Abs2b);
end;
{$endif}
end;
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Destroy DSP In');
{$endif}
for x := 0 to high(StreamIn) do
begin
if (length(StreamIn[x].DSP) > 0) then
for x2 := 0 to high(StreamIn[x].DSP) do
if (StreamIn[x].DSP[x2].EndFunc <> nil) then
StreamIn[x].DSP[x2].EndFunc(StreamIn[x].Data, StreamIn[x].DSP[x2].fftdata);
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Destroy DSP Out');
{$endif}
for x := 0 to high(StreamOut) do
begin
if (assigned(StreamOut[x].DSP)) and (assigned(StreamOut[x])) then if (length(StreamOut[x].
DSP) > 0) then
for x2 := 0 to high(
StreamOut[x].DSP) do
if (StreamOut[x].DSP[
x2].EndFunc <> nil)
then
StreamOut[x].DSP[x2]
.EndFunc(StreamOut[x
].Data,
StreamOut[x
].DSP[x2].
fftdata);
end;
for x := 0 to high(StreamIn) do
if assigned(StreamIn[x].Data.HandleSt) then if (StreamIn[x].Data.HandleSt <> nil) then
case StreamIn[x].Data.TypePut of
0: case StreamIn[x].Data.LibOpen of
{$IF DEFINED(sndfile)}
0: sf_close(StreamIn[x].Data.HandleSt);
{$endif}
{$IF DEFINED(mpg123)}
1:
begin
mpg123_close(StreamIn[x].Data.HandleSt
);
mpg123_delete(StreamIn[x].Data.
HandleSt);
end;
{$ENDIF}
{$IF DEFINED(neaac)}
2 :
begin
MP4CloseFile(StreamIn[x].AACI);
end;
{$endif}
{$IF DEFINED(cdrom)}
3:
begin
CDROM_Close(StreamIn[x].pCD);
end;
{$endif}
{$IF DEFINED(opus)}
4:
begin
op_free(StreamIn[x].Data.HandleOP);
sleep(50);
// needed ?
end;
{$ENDIF}
{$IF DEFINED(xmp)}
5:
begin
xmp_end_player(StreamIn[x].Data.
HandleSt);
xmp_release_module(StreamIn[x].Data.
HandleSt);
xmp_free_context(StreamIn[x].Data.
HandleSt);
end;
{$ENDIF}
99: // if nothing was defined
end;
{$IF DEFINED(portaudio)}
1:
begin
Pa_StopStream(StreamIn[x].Data.HandleSt);
Pa_CloseStream(StreamIn[x].Data.HandleSt);
end;
{$endif}
{$IF DEFINED(webstream)}
2:
begin
StreamIn[x].httpget.Terminate;
sleep(100);
StreamIn[x].inpipe.destroy;
StreamIn[x].outpipe.destroy;
case StreamIn[x].Data.LibOpen of
{$IF DEFINED(mpg123)}
1:
begin
mpg123_close(StreamIn[x].Data.
HandleSt);
mpg123_delete(StreamIn[x].Data.
HandleSt);
end;
{$ENDIF}
{$IF DEFINED(opus)}
4:
begin
op_free(StreamIn[x].Data.HandleOP);
sleep(50);
// needed ?
end;
{$ENDIF}
{$IF DEFINED(fdkaac)}
2 :
begin
aacDecoder_Close(StreamIn[x].Data.
HandleSt);
end;
{$ENDIF}
end;
end;
{$ENDIF}
end;
for x := 0 to high(StreamOut) do
begin
{$IF DEFINED(portaudio)}
if (StreamOut[x].Data.HandleSt <> nil) and
(StreamOut[x].Data.TypePut = 1) then
begin
Pa_StopStream(StreamOut[x].Data.HandleSt);
Pa_CloseStream(StreamOut[x].Data.HandleSt);
end;
{$ENDIF}
{$IF DEFINED(shout)}
if (StreamOut[x].Data.TypePut = 2) then
begin
// freeandnil(StreamOut[x].encoder) ;
shout_free(StreamOut[x].Data.HandleSt);
end;
{$endif}
if (StreamOut[x].Data.TypePut = 0) then
begin
WriteWave(StreamOut[x].Data.Filename, StreamOut[x].FileBuffer);
// StreamOut[x].FileBuffer.Data.Free;
end;
if (StreamOut[x].Data.TypePut = 4) then
begin
WriteWaveFromMem(StreamOut[x].Data.Filename, StreamOut[x].FileBuffer);
StreamOut[x].FileBuffer.Data.Free;
end;
{$IF DEFINED(sndfile)}
if (StreamOut[x].Data.TypePut = 6) then
begin
sf_close( StreamOut[x].Data.HandleSt);
end;
if (StreamOut[x].Data.TypePut = 7) then
begin
sf_close( StreamOut[x].Data.HandleSt);
end;
{$endif}
end;
end;
procedure Tuos_Player.DoMainLoopProc(x: integer);
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
var
msg: TfpgMessageParams;
// for fpgui
{$endif}
begin
{$IF DEFINED(mse)}
if StreamIn[x].LoopProc <> nil then
begin
application.queueasynccall(StreamIn[x].LoopProc);
end;
{$else}
// The synchro main loop procedure
{$IF not DEFINED(Library)}
if StreamIn[x].LoopProc <> nil then
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,StreamIn[x].LoopProc)
;
{$else}
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
begin
msg.user.Param1 := -1 ;
// it is the main loop procedure
msg.user.Param2 := 0 ;
// it is a INput procedure
fpgPostMessage(self, refer, MSG_CUSTOM1, msg);
end;
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,StreamIn[x].LoopProc);
{$endif}
{$endif}
{$elseif not DEFINED(java)}
if (StreamIn[x].LoopProc <> nil) then
StreamIn[x].LoopProc;
{$else}
if (StreamIn[x].LoopProc <> nil) then
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@Streamin[x].
LoopProcjava);
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@Streamin[x].
LoopProcjava);
{$endif}
{$endif}
{$endif}
end;
procedure Tuos_Player.DoBeginMethods;
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
var
msg: TfpgMessageParams;
// for fpgui
{$endif}
begin
{$IF DEFINED(mse)}
if BeginProc <> nil then
begin
application.queueasynccall(BeginProc);
end;
{$else}
{$IF not DEFINED(Library)}
if BeginProc <> nil then
// Execute BeginProc procedure
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,BeginProc);
{$else}
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
begin
msg.user.Param1 := -2 ;
// it is the first proc
fpgPostMessage(self, refer, MSG_CUSTOM1, msg);
end;
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,BeginProc);
{$endif}
{$endif}
{$elseif not DEFINED(java)}
if BeginProc <> nil then
BeginProc;
{$else}
if BeginProc <> nil then
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@BeginProcjava);
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@BeginProcjava);
{$endif}
{$endif}
{$endif}
end;
procedure Tuos_Player.DoLoopBeginMethods;
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
var
msg: TfpgMessageParams;
// for fpgui
{$endif}
begin
{$IF DEFINED(mse)}
if LoopBeginProc <> nil then
begin
application.queueasynccall(LoopBeginProc);
end;
{$else}
{$IF not DEFINED(Library)}
if LoopBeginProc <> nil then
// Execute BeginProc procedure
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,LoopBeginProc);
{$else}
{$IF (FPC_FULLVERSION < 20701) and DEFINED(fpgui)}
begin
msg.user.Param1 := -2 ;
// it is the first proc
fpgPostMessage(self, refer, MSG_CUSTOM1, msg);
end;
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,LoopBeginProc);
{$endif}
{$endif}
{$elseif not DEFINED(java)}
if loopBeginProc <> nil then
loopBeginProc;
{$else}
if loopBeginProc <> nil then
{$IF FPC_FULLVERSION>=20701}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@loopBeginProcjava);
{$else}
thethread.{$IF DEFINED(usequeue)}Queue{$else}Synchronize{$endif}(thethread,@loopBeginProcjava);
{$endif}
{$endif}
{$endif}
end;
procedure Tuos_Player.WriteOut(x:integer; x2 : integer);
var
err, rat, wantframestemp: integer;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
st : string;
i : integer;
{$endif}
Bufferst2mo: TDArFloat;
begin
// Convert Input format into Output format if needed:
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Convert Input format into Output');
{$endif}
case StreamOut[x].Data.SampleFormat of
0: case StreamIn[x2].Data.SampleFormat of
1: StreamOut[x].Data.Buffer :=
CvInt32toFloat32(StreamOut[x].Data.Buffer);
2: StreamOut[x].Data.Buffer :=
CvInt16toFloat32(StreamOut[x].Data.Buffer);
end;
end;
// End convert.
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Finally give buffer to output');
{$endif}
// writeln(inttostr(StreamOut[x].Data.TypePut));
// Finally give buffer to output
case StreamOut[x].Data.TypePut of
{$IF DEFINED(portaudio)}
1: // Give to output device using portaudio
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Give to output device');
writeln('length(StreamOut[x].Data.Buffer) =' + inttostr(length(StreamOut[x].Data.Buffer)));
{$endif}
if (StreamIn[x2].Data.TypePut <> 1) or
((StreamIn[x2].Data.TypePut = 1) and (StreamIn[x2].Data.Channels > 1)) then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
st := '';
for i := 0 to length(StreamOut[x].Data.Buffer) -1 do
st := st + '|' + inttostr(i) + '=' + floattostr(StreamOut[x].Data.Buffer[i]);
WriteLn('OUTPUT DATA into portaudio------------------------------');
//WriteLn(st);
{$endif}
// err :=// if you want clean buffer
if assigned(StreamOut[x].Data.HandleSt) then
Pa_WriteStream(StreamOut[x].Data.HandleSt,
@StreamOut[x].Data.Buffer[0], StreamIn[x2].Data.outframes Div StreamIn
[x2].Data.ratio);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('give to output device 1');
{$endif}
end
else
begin
// err :=// if you want clean buffer
Pa_WriteStream(StreamOut[x].Data.HandleSt,
@StreamOut[x].Data.Buffer[0], StreamIn[x2].Data.outframes);
end;
// if err <> 0 then status := 0;// if you want clean buffer ...
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('End give to output device 2');
{$endif}
end;
{$endif}
{$IF DEFINED(shout)}
2: // Give to IceCast server
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Give to output IceCast server');
{$endif}
case StreamOut[x].Data.SampleFormat of
0:
begin
err := opus_encode_float(StreamOut[x].encoder, @StreamOut[x].Data.Buffer[0],
cFRAME_SIZE*3, StreamOut[x].cbits, cMAX_PACKET_SIZE);
end;
1:
begin
err := opus_encode(StreamOut[x].encoder, @StreamOut[x].Data.Buffer[0], cFRAME_SIZE*
3, StreamOut[x].cbits, cMAX_PACKET_SIZE);
end;
2:
begin
err := opus_encode(StreamOut[x].encoder, @StreamOut[x].Data.Buffer[0], cFRAME_SIZE*3
, StreamOut[x].cbits, cMAX_PACKET_SIZE);
end;
end;
StreamOut[x].data.outframes := err;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('opus_encode outframes =' + inttostr(err));
WriteLn('----------------------------------');
// writeln(tencoding.utf8.getstring(StreamOut[x].cbits));
{$endif}
if err > 0 then
err := shout_send_raw(StreamOut[x].Data.HandleSt, StreamOut[x].cbits, StreamOut[x].data.
outframes);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = SHOUTERR_SUCCESS then
WriteLn('shout_send ok ' + inttostr(err))
else
WriteLn('shout_send error: '+ inttostr(err) + ' ' + pchar(shout_get_error(StreamOut[x].
Data.HandleSt)));
writeln('End give output to IceCast server');
{$endif}
shout_sync(StreamOut[x].Data.HandleSt);
end;
{$endif}
3:
begin
// Give to memory buffer
wantframestemp := StreamIn[x2].Data.outframes ;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before Give to memory ------------------------------');
st := '';
for i := 0 to wantframestemp -1 do
st := st + '|' + inttostr(i) + '=' + floattostr(StreamOut[x].Data.Buffer[i]);
WriteLn(st);
WriteLn('OUTPUT DATA AFTER5 ------------------------------');
writeln('Streamout[x].Data.posmem before = '+inttostr( Streamout[x].Data.posmem)) ;
writeln('StreamIn[x2].Data.outframes * StreamIn[x2].Data.channels = '+inttostr( StreamIn[x2
].Data.outframes * StreamIn[x2].Data.channels)) ;
writeln('length(tempoutmemory) = '+ inttostr(length(tempoutmemory)));
writeln('Begin Give to memory buffer');
writeln('(StreamIn[x2].Data.outframes ) -1 = ' +
inttostr((StreamIn[x2].Data.outframes) -1));
{$endif}
if StreamIn[x2].Data.numbuf > -1 then
begin
// writeln('theinc = ' + inttostr(theinc));
inc(theinc);
if theinc > StreamIn[x2].Data.numbuf then status := 0 ;
end;
SetLength(Streamout[x].BufferOut^,length(Streamout[x].BufferOut^) + wantframestemp );
Streamout[x].Data.posmem := length(Streamout[x].BufferOut^) - wantframestemp;
for x2 := 0 to (wantframestemp) -1 do
begin
Streamout[x].BufferOut^[Streamout[x].Data.posmem + x2] := StreamOut[x].Data.Buffer[x2];
end;
Streamout[x].Data.posmem := Streamout[x].Data.posmem + (wantframestemp);
// if Streamout[x].Data.SampleFormat > 0 then
//StreamOut[x].Data.Buffer := ConvertSampleFormat(StreamOut[x].Data);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Streamout[x].Data.posmem after = '+inttostr( Streamout[x].Data.posmem)) ;
st := '';
for i := 0 to length(tempoutmemory) -1 do
st := st + '|' + inttostr(i) + '=' + floattostr(tempoutmemory[i]);
WriteLn('OUTPUT DATA AFTER5 ------------------------------');
//WriteLn(st);
{$endif}
end;
4: // Give to wav file from TMemoryStream
begin
case StreamOut[x].Data.SampleFormat of
0: rat := 2 ;
1: rat := 2 ;
2: rat := 1 ;
end;
if (StreamOut[x].FileBuffer.wChannels = 1) and (StreamIn[x2].Data.Channels = 2) then
begin
Bufferst2mo := CvSteroToMono(StreamOut[x].Data.Buffer, StreamIn[x2].Data.outframes);
StreamOut[x].FileBuffer.DataMS.WriteBuffer(
Bufferst2mo[0],
StreamIn[x2].Data.outframes * rat);
end
else
if (StreamOut[x].FileBuffer.wChannels = 1) and (StreamIn[x2].Data.Channels = 1) then
begin
StreamOut[x].FileBuffer.DataMS.WriteBuffer(
StreamOut[x].Data.Buffer[0], StreamIn[x2]
.Data.outframes * StreamIn[x2].Data.ratio
* rat * 2);
end
else
StreamOut[x].FileBuffer.DataMS.WriteBuffer(
StreamOut[x].Data.Buffer[0], StreamIn[x2].
Data.outframes * StreamIn[x2].Data.Channels *
rat);
end;
{$IF DEFINED(sndfile)}
5: // Give to MemoryStream
begin
if StreamIn[x2].Data.TypePut = 1 then rat := StreamIn[x2].Data.Channels
else rat := 1;
// writeln('MemoryStream');
if assigned(StreamOut[x].MemorySteamOut) then
case StreamOut[x].Data.SampleFormat of
0: StreamOut[x].Data.OutFrames :=
sf_write_float(StreamOut[x].Data.HandleSt,
@StreamOut[x].Data.Buffer[0], StreamOut[x].Data.
Wantframes *rat );
1: StreamOut[x].Data.OutFrames :=
sf_write_int(StreamOut[x].Data.HandleSt,
@StreamOut[x].Data.Buffer[0], StreamOut[x].Data.
Wantframes *rat );
2: StreamOut[x].Data.OutFrames :=
sf_write_short(StreamOut[x].Data.HandleSt,
@StreamOut[x].Data.Buffer[0], StreamOut[x].Data.
Wantframes *rat);
end;
end;
6: // give to ogg file from Tfilestream
begin
//writeln('ok ogg');
// if StreamIn[x2].Data.outframes = StreamOut[x].Data.Wantframes * StreamOut[x].Data.channels then
case StreamOut[x].Data.SampleFormat of
0: StreamOut[x].Data.OutFrames :=
sf_write_float(StreamOut[x].Data.HandleSt,
@StreamOut[x].Data.Buffer[0], StreamOut[x].Data.
Wantframes * StreamOut[x].Data.channels);
1: StreamOut[x].Data.OutFrames :=
sf_write_int(StreamOut[x].Data.HandleSt,
@StreamOut[x].Data.Buffer[0], StreamOut[x].Data.
Wantframes * StreamOut[x].Data.channels);
2: StreamOut[x].Data.OutFrames :=
sf_write_short(StreamOut[x].Data.HandleSt,
@StreamOut[x].Data.Buffer[0], StreamOut[x].Data.
Wantframes * StreamOut[x].Data.channels);
end;
sf_write_sync(StreamOut[x].Data.HandleSt);
// writeln(inttostr(StreamOut[x].Data.OutFrames));
end;
{$endif}
0: // Give to wav file from TFileStream
begin
case StreamOut[x].Data.SampleFormat of
0: rat := 2 ;
1: rat := 2 ;
2: rat := 1 ;
end;
if (StreamOut[x].FileBuffer.wChannels = 1) and (StreamIn[x2].Data.Channels = 2) then
begin
Bufferst2mo := CvSteroToMono(StreamOut[x].Data.Buffer, StreamIn[x2].Data.outframes);
StreamOut[x].FileBuffer.Data.WriteBuffer(
Bufferst2mo[0],
StreamIn[x2].Data.outframes * rat);
end
else
if (StreamOut[x].FileBuffer.wChannels = 1) and (StreamIn[x2].Data.Channels = 1) then
begin
StreamOut[x].FileBuffer.Data.WriteBuffer(
StreamOut[x].Data.Buffer[0], StreamIn[x2].
Data.outframes * StreamIn[x2].Data.ratio *
rat * 2);
end
else
StreamOut[x].FileBuffer.Data.WriteBuffer(
StreamOut[x].Data.Buffer[0], StreamIn[x2].Data.
outframes * StreamIn[x2].Data.Channels * rat);
end;
end;
end;
procedure Tuos_Player.WriteOutPlug(x:integer; x2 : integer);
var
x3, x4, err, wantframestemp: integer;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
st : string;
i : integer;
{$endif}
BufferplugINFLTMP: TDArFloat;
BufferplugFL: TDArFloat;
BufferplugSH: TDArShort;
BufferplugLO: TDArLong;
Bufferst2mo: TDArFloat;
begin
// convert buffer if needed
case StreamOut[x].Data.SampleFormat of
1: StreamOut[x].Data.Buffer :=
CvInt32toFloat32(StreamOut[x].Data.Buffer);
2: StreamOut[x].Data.Buffer :=
CvInt16toFloat32(StreamOut[x].Data.Buffer);
end;
// transfer buffer out to temp
SetLength(BufferplugINFLTMP, (StreamIn[x2].Data.outframes) *
StreamIn[x2].Data.Channels);
if length(BufferplugINFLTMP) > 2 then
for x3 := 0 to (length(BufferplugINFLTMP) div 2) - 1 do
BufferplugINFLTMP[x3] := cfloat(StreamOut[x].Data.Buffer[x3]);
// dealing with input plugin
for x3 := 0 to high(PlugIn) do
begin
if PlugIn[x3].Enabled = True then
begin
{$IF DEFINED(bs2b) or DEFINED(soundtouch) or DEFINED(noiseremoval)}
BufferplugFL := Plugin[x3].PlugFunc(BufferplugINFLTMP,
Plugin[x3].PlugHandle, Plugin[x3].Abs2b, StreamIn[x2].Data,
Plugin[x3].param1, Plugin[x3].param2, Plugin[x3].param3, Plugin[x3].param4
,
Plugin[x3].param5, Plugin[x3].param6, Plugin[x3].param7, Plugin[x3].param8
);
{$endif}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('PlugFunc: Length(BufferplugINFLTMP,BufferplugFL) = ' +
inttostr(Length(BufferplugINFLTMP)) + ' , ' + inttostr(Length(BufferplugFL)));
{$endif}
if (length(PlugIn) > 1) then
begin
// TO CHECK : works only if SoundTouch is last or only plugin
for x4 := 0 to length(BufferplugFL) - 1 do
BufferplugINFLTMP[x4] := cfloat(BufferplugFL[x4]);
end;
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('2-PlugFunc: Length(BufferplugINFLTMP,BufferplugFL) = ' +
inttostr(Length(BufferplugINFLTMP)) + ' , ' + inttostr(Length(BufferplugFL)));
{$endif}
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Give the processed input to output.');
writeln('Length(BufferplugFL) = ' + inttostr(Length(BufferplugFL)));
{$endif}
if Length(BufferplugFL) > 0 then
begin
case StreamOut[x].Data.SampleFormat of
1:
begin
SetLength(BufferplugLO, length(BufferplugFL));
BufferplugLO := CvFloat32ToInt32(BufferplugFL);
end;
2:
begin
SetLength(BufferplugSH, length(BufferplugFL));
BufferplugSH := CvFloat32ToInt16(BufferplugFL);
end;
end;
case StreamOut[x].Data.TypePut of
{$IF DEFINED(portaudio)}
1: // Give to output device
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Before Pa_WriteStream: Length(BufferplugFL) = ' + inttostr(Length(BufferplugFL
)));
{$endif}
case StreamOut[x].Data.SampleFormat of
0:
begin
err :=
Pa_WriteStream(StreamOut[x].Data.HandleSt,
@BufferplugFL[0], Length(BufferplugFL) Div
StreamIn[x2].Data.Channels);
end;
1:
begin
BufferplugLO := CvFloat32ToInt32(BufferplugFL);
err :=
Pa_WriteStream(StreamOut[x].Data.HandleSt,
@BufferplugLO[0], Length(BufferplugLO) Div
StreamIn[x2].Data.Channels);
end;
2:
begin
BufferplugSH := CvFloat32ToInt16(BufferplugFL);
err :=
Pa_WriteStream(StreamOut[x].Data.HandleSt,
@BufferplugSH[0], Length(BufferplugSH) Div
StreamIn[x2].Data.Channels);
end;
end;
// if err <> 0 then status := 0;// if you want clean buffer ...
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Pa_WriteStream error = '+ inttostr(err));
{$endif}
end;
{$endif}
{$IF DEFINED(shout)}
2: // Give to IceCast server
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Give to output IceCast server');
{$endif}
case StreamOut[x].Data.SampleFormat of
0:
begin
err := opus_encode_float(StreamOut[x].encoder, @BufferplugFL[0], cFRAME_SIZE,
StreamOut[x].cbits, cMAX_PACKET_SIZE);
end;
1:
begin
err := opus_encode(StreamOut[x].encoder, @BufferplugLO[0], cFRAME_SIZE,
StreamOut[x].cbits, cMAX_PACKET_SIZE);
end;
2:
begin
err := opus_encode(StreamOut[x].encoder, @BufferplugSH[0], cFRAME_SIZE,
StreamOut[x].cbits, cMAX_PACKET_SIZE);
end;
end;
StreamOut[x].data.outframes := err ;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('opus_encode outframes =' + inttostr(err));
WriteLn('----------------------------------');
// writeln(tencoding.utf8.getstring(StreamOut[x].cbits));
{$endif}
if err > 0 then
err := shout_send(StreamOut[x].Data.HandleSt, StreamOut[x].cbits, StreamOut[x].data.
outframes);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
if err = SHOUTERR_SUCCESS then
WriteLn('shout_send ok ' + inttostr(err))
else
WriteLn('shout_send error: '+ inttostr(err) + ' ' + pchar(shout_get_error(StreamOut[x
].Data.HandleSt)));
writeln('End give output to IceCast server');
{$endif}
shout_sync(StreamOut[x].Data.HandleSt);
// ?
end;
{$endif}
0:
begin
// Give to wav file from TFileStream
if (StreamOut[x].FileBuffer.wChannels = 1) and (StreamIn[x2].Data.Channels = 2) then
begin
Bufferst2mo := CvSteroToMono(BufferplugFL, Length(BufferplugFL) Div 2);
BufferplugSH := CvFloat32ToInt16(Bufferst2mo);
end
else
begin
BufferplugSH := CvFloat32ToInt16(BufferplugFL);
end;
StreamOut[x].FileBuffer.Data.WriteBuffer(BufferplugSH[0],
Length(BufferplugSH));
end;
4:
begin
// Give to wav file from TMemoryStream
if (StreamOut[x].FileBuffer.wChannels = 1) and (StreamIn[x2].Data.Channels = 2) then
begin
Bufferst2mo := CvSteroToMono(BufferplugFL, Length(BufferplugFL) Div 2);
BufferplugSH := CvFloat32ToInt16(Bufferst2mo);
end
else
begin
BufferplugSH := CvFloat32ToInt16(BufferplugFL);
end;
StreamOut[x].FileBuffer.DataMS.WriteBuffer(BufferplugSH[0],
Length(BufferplugSH));
end;
5: // Give to MemoryStream
begin
case StreamOut[x].Data.SampleFormat of
0: StreamOut[x].MemorySteamOut.WriteBuffer(BufferplugFL[0],
Length(BufferplugFL));
1: StreamOut[x].MemorySteamOut.WriteBuffer(BufferplugLO[0],
Length(BufferplugLO));
2: StreamOut[x].MemorySteamOut.WriteBuffer(BufferplugSH[0],
Length(BufferplugSH));
end;
end;
3:
begin
// Give to memory buffer
wantframestemp := Length(BufferplugFL) ;
SetLength(Streamout[x].BufferOut^,length(Streamout[x].BufferOut^) + wantframestemp );
for x2 := 0 to wantframestemp -1 do
Streamout[x].BufferOut^[Streamout[x].Data.posmem + x2] := BufferplugFL[x2];
Streamout[x].Data.posmem := Streamout[x].Data.posmem + wantframestemp;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Streamout[x].Data.posmem = '+inttostr( Streamout[x].Data.posmem)) ;
st := '';
for i := 0 to length(tempoutmemory) -1 do
st := st + '|' + inttostr(i) + '|' + floattostr(tempoutmemory[i]);
WriteLn('OUTPUT DATA AFTER4 ------------------------------');
WriteLn(st);
{$endif}
end;
end;
end;
end;
{$IF DEFINED(webstream)}
procedure Tuos_Player.ReadUrl(x : integer);
var
err : integer;
{$IF DEFINED(fdkaac)}
FErrorCode : AAC_DECODER_ERROR;
FByteFilled, FBytesRead : longword;
FOutputBuff : array of cfloat;
FCStreamInfo : PCStreamInfo;
len, len2, len3: integer;
rawAACBuffer: PByte;
{$endif}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
i : integer;
st : string;
{$endif}
begin
case StreamIn[x].Data.LibOpen of
1 :
begin
{$IF DEFINED(mpg123)}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('===> Before mpg123_read') ;
{$endif}
err :=
mpg123_read(StreamIn[x].Data.HandleSt, @StreamIn[x].Data.Buffer[0],
StreamIn[x].Data.wantframes, StreamIn[x].Data.outframes);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('===> mpg123_read error => ' + inttostr(err)) ;
{$endif}
StreamIn[x].Data.outframes :=
StreamIn[x].Data.outframes Div StreamIn[x].Data.Channels;
{$ENDIF}
end;
2:
begin
{$IF DEFINED(fdkaac)}
setlength(FOutputBuff, StreamIn[x].Data.wantframes);
GetMem(rawAACBuffer,StreamIn[x].Data.wantframes);
// writeln('avant bytesRead');
FBytesRead := StreamIn[x].InPipe.Read(rawAACBuffer[0],1024);
// writeln('StreamIn[x].Data.bytesRead ' + inttostr(StreamIn[x].Data.bytesRead));
FByteFilled := FBytesRead;
FErrorCode := aacDecoder_Fill(StreamIn[x].Data.HandleSt,@rawAACBuffer, FBytesRead,
FByteFilled);
// writeLn('FByteFilled ' + inttostr(FByteFilled));
len2 := 0;
len3 := 0;
while true do
begin
FErrorCode := aacDecoder_DecodeFrame(StreamIn[x].Data.HandleSt, PSmallInt(FOutputBuff),
StreamIn[x].Data.wantframes, 0);
if (FErrorCode <> AAC_DECODER_ERROR.AAC_DEC_OK) then
begin
if FErrorCode = AAC_DECODER_ERROR.AAC_DEC_NOT_ENOUGH_BITS then
break;
// writeln(Format('Decode failed: %x', [Integer(FErrorCode)]));
end;
// else writeln('Decode ok ');
FCStreamInfo := aacDecoder_GetStreamInfo(StreamIn[x].Data.HandleSt);
if ((not assigned(FCStreamInfo)) or (FCStreamInfo^.sampleRate <= 0)) then
raise Exception.Create('No stream info');
for len := 0 to (FCStreamInfo^.frameSize) -1 do
begin
// writeln(round(FOutputBuff[len]));
StreamIn[x].Data.Buffer[len + len2] := FOutputBuff[len];
// writeln((StreamIn[x].Data.Buffer[len + len2]));
inc(len3);
end;
len2 := len2 + FCStreamInfo^.frameSize;
end;
// StreamIn[x].Data.outframes := len3 * StreamIn[x].Data.Channels;
StreamIn[x].Data.outframes := len3 * 2;
if StreamIn[x].Data.SampleFormat < 2 then
begin
StreamIn[x].Data.Buffer := CvInt16ToFloat32(StreamIn[x].Data.Buffer);
if StreamIn[x].Data.SampleFormat = 1 then
StreamIn[x].Data.Buffer := CvFloat32toInt32fl(StreamIn[x].Data.Buffer, length(
StreamIn[x].Data.Buffer));
end;
freemem(rawAACBuffer);
// writeln('---------- FIN read url ok ');
{$ENDIF}
end;
4 :
begin
{$IF DEFINED(opus)}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('===> Before op_read_x.') ;
{$endif}
case StreamIn[x].Data.SampleFormat of
0:
begin
StreamIn[x].Data.outframes := cint(op_read_float(StreamIn[x].Data.HandleOP,
@StreamIn[x].Data.Buffer[0], cint(StreamIn[x].Data.
Wantframes
Div StreamIn[x].Data.channels) , Nil));
end;
1:
begin
StreamIn[x].Data.outframes := cint(op_read_float(StreamIn[x].Data.HandleOP,
@StreamIn[x].Data.Buffer[0], cint(StreamIn[x].Data.
Wantframes
Div StreamIn[x].Data.channels), Nil));
// no int32 format with opus => need a conversion from float32 to int32.
StreamIn[x].Data.Buffer := Cvfloat32ToInt32fl( StreamIn[x].Data.Buffer,
StreamIn[x].Data.outframes * StreamIn[x].Data.Channels )
;
end;
2:
begin
StreamIn[x].Data.outframes := cint( op_read(StreamIn[x].Data.HandleOP,
@StreamIn[x].Data.Buffer[0], cint(StreamIn[x].Data.
Wantframes
Div StreamIn[x].Data.channels), Nil));
end;
end;
setlength(StreamIn[x].data.Buffer, StreamIn[x].Data.outframes * StreamIn[x].Data.Channels)
;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Seek outframes = '+inttostr(StreamIn[x].Data.outframes)) ;
st := '';
for i := 0 to length(StreamIn[x].data.Buffer) -1 do
st := st + '|' + inttostr(i) + '|' + floattostr(StreamIn[x].data.Buffer[i]);
WriteLn('OUTPUT DATA AFTER1 ------------------------------');
// WriteLn(st);
writeln(' StreamIn[x].Data.outframes = '+inttostr(StreamIn[x].Data.outframes * StreamIn[x]
.Data.Channels)) ;
{$endif}
if StreamIn[x].Data.outframes < 0 then StreamIn[x].Data.outframes := 0 ;
{$ENDIF}
end;
end;
if (StreamIn[x].Data.TypePut = 2) and ((StreamIn[x].Data.LibOpen = 1 ) or (StreamIn[x].Data.
LibOpen = 4 )) then
begin
if StreamIn[x].httpget.IsRunning = false then StreamIn[x].Data.status := 0;
// no more data then close the stream
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Check if internet is stopped.');
{$endif}
end;
end;
{$endif}
procedure Tuos_Player.ReadFile(x : integer);
{$IF DEFINED(neaac) or DEFINED(uos_debug)}
var
{$endif}
{$IF DEFINED(neaac)}
outBytes: longword;
{$endif}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
i : integer;
st : string;
{$endif}
begin
if length(StreamIn[x].Data.Buffer) <> StreamIn[x].Data.Wantframes then
setlength(StreamIn[x].Data.Buffer,StreamIn[x].Data.Wantframes);
case StreamIn[x].Data.LibOpen of
// Here we are, reading the data and store it in buffer
{$IF DEFINED(sndfile)}
0:
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before sf_read ' + inttostr(StreamIn[x].Data.Wantframes) +
' length(StreamIn[x].Data.Buffer ' +
inttostr(length(StreamIn[x].Data.Buffer)));
{$endif}
case StreamIn[x].Data.SampleFormat of
0: StreamIn[x].Data.OutFrames :=
sf_read_float(StreamIn[x].Data.HandleSt,
@StreamIn[x].Data.Buffer[0], StreamIn[x].Data.Wantframes
);
1: StreamIn[x].Data.OutFrames :=
sf_read_int(StreamIn[x].Data.HandleSt,
@StreamIn[x].Data.Buffer[0], StreamIn[x].Data.Wantframes
);
2: StreamIn[x].Data.OutFrames :=
sf_read_short(StreamIn[x].Data.HandleSt,
@StreamIn[x].Data.Buffer[0], StreamIn[x].Data.Wantframes
);
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln(inttostr(StreamIn[x].Data.lastbuf));
WriteLn('after sf_read');
{$endif}
if StreamIn[x].Data.outframes < 0 then StreamIn[x].Data.outframes := 0 ;
if (StreamIn[x].Data.lastbuf < 0) and (StreamIn[x].Data.outframes < StreamIn[x].Data.
wantframes) then
begin
StreamIn[x].Data.outframes := StreamIn[x].Data.wantframes;
StreamIn[x].Data.lastbuf := StreamIn[x].Data.lastbuf -1;
if StreamIn[x].Data.lastbuf = -9 then StreamIn[x].Data.lastbuf := 0;
end;
setlength(StreamIn[x].data.Buffer,StreamIn[x].Data.outframes);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
st := '';
for i := 0 to length(StreamIn[x].data.Buffer) -1 do
case StreamIn[x].Data.SampleFormat of
0: st := st + '|' + inttostr(i) + '=' + floattostr(StreamIn[x].data.Buffer[i]);
1: st := st + '|' + inttostr(i) + '=' + inttostr(cint32(StreamIn[x].data.Buffer[i]));
2: st := st + '|' + inttostr(i) + '=' + inttostr(cint16(cint32(StreamIn[x].data.Buffer[
i])));
end;
WriteLn('OUTPUT DATA sf_read_() ---------------------------');
WriteLn('StreamIn[x].Data.outframes = ' + inttostr(StreamIn[x].Data.outframes));
WriteLn(st);
{$endif}
end;
{$endif}
{$IF DEFINED(mpg123)}
1:
begin
mpg123_read(StreamIn[x].Data.HandleSt, @StreamIn[x].Data.Buffer[0],
StreamIn[x].Data.wantframes, StreamIn[x].Data.outframes);
if StreamIn[x].Data.outframes < 0 then StreamIn[x].Data.outframes := 0 ;
setlength(StreamIn[x].data.Buffer,StreamIn[x].Data.outframes Div
(StreamIn[x].Data.channels) );
{$IF DEFINED(uos_debug) and DEFINED(unix)}
st := '';
for i := 0 to length(StreamIn[x].data.Buffer) -1 do
case StreamIn[x].Data.SampleFormat of
0: st := st + '|' + floattostr(StreamIn[x].data.Buffer[i]);
1: st := st + '|' + inttostr(cint32(StreamIn[x].data.Buffer[i]));
2: st := st + '|' + inttostr(cint16(cint32(StreamIn[x].data.Buffer[i])));
end;
WriteLn('OUTPUT DATA mpg123_read_() ---------------------------');
// WriteLn(st);
{$endif}
StreamIn[x].Data.outframes :=
StreamIn[x].Data.outframes Div StreamIn[x].Data.Channels;
end;
{$endif}
{$IF DEFINED(neaac)}
2 :
begin
StreamIn[x].AACI.lwDataLen := 0;
case StreamIn[x].AACI.outputFormat of
FAAD_FMT_16BIT, FAAD_FMT_32BIT, FAAD_FMT_FLOAT :
begin
outBytes := StreamIn[x].Data.
Wantframes;
MP4GetData(StreamIn[x].AACI, StreamIn
[x].AACI.pData, outBytes);
Move(StreamIn[x].AACI.pData^,
StreamIn[x].Data.Buffer[0],
outBytes);
StreamIn[x].AACI.lwDataLen :=
outBytes
;
end;
end;
if StreamIn[x].AACI.lwDataLen > (StreamIn[x].AACI.BitsPerSample div 8) then
StreamIn[x].Data.outframes := trunc(StreamIn[x].AACI.lwDataLen Div (StreamIn[x].AACI.
BitsPerSample Div 8))
else
StreamIn[x].Data.outframes := 0;
if StreamIn[x].Data.outframes < 0 then StreamIn[x].Data.outframes := 0 ;
// setlength(StreamIn[x].data.Buffer,StreamIn[x].Data.outframes * StreamIn[x].Data.channels );
{$IF DEFINED(uos_debug) and DEFINED(unix)}
st := '';
for i := 0 to length(StreamIn[x].data.Buffer) -1 do
case StreamIn[x].Data.SampleFormat of
0: st := st + '|' + floattostr(StreamIn[x].data.Buffer[i]);
1: st := st + '|' + inttostr(cint32(StreamIn[x].data.Buffer[i]));
2: st := st + '|' + inttostr(cint16(cint32(StreamIn[x].data.Buffer[i])));
end;
WriteLn('OUTPUT DATA MP4GetData() ---------------------------');
// WriteLn(st);
{$endif}
end;
{$endif}
{$IF DEFINED(cdrom)}
3:
begin
StreamIn[x].pCD^.pDataLen := 0;
case StreamIn[x].pCD^.BitsPerSample of
16 :
begin
outBytes := StreamIn[x].Data.Wantframes;
CDROM_GetData(StreamIn[x].pCD, StreamIn[x].pCD^.pData, outBytes);
Move(StreamIn[x].pCD^.pData^, StreamIn[x].Data.Buffer[0], outBytes);
StreamIn[x].pCD^.pDataLen := outBytes;
end;
end;
if StreamIn[x].pCD^.pDataLen > (StreamIn[x].pCD^.BitsPerSample div 8) then
StreamIn[x].Data.outframes := StreamIn[x].pCD^.pDataLen Div (StreamIn[x].pCD^.
BitsPerSample Div 8)
else
StreamIn[x].Data.outframes := 0;
end;
{$endif}
{$IF DEFINED(opus)}
4:
begin
case StreamIn[x].Data.SampleFormat of
0: StreamIn[x].Data.outframes := op_read_float(StreamIn[x].Data.HandleOP,
@StreamIn[x].Data.Buffer[0], cint(StreamIn[x].Data.
Wantframes Div StreamIn[x].Data.channels), Nil);
1:
begin
StreamIn[x].Data.outframes := op_read_float(StreamIn[x].Data.HandleOP,
@StreamIn[x].Data.Buffer[0],cint(StreamIn[x].Data.
Wantframes Div StreamIn[x].Data.channels), Nil);
// no int32 format with opus => needs a conversion from float32 to int32.
StreamIn[x].Data.Buffer := Cvfloat32ToInt32fl( StreamIn[x].Data.Buffer,
StreamIn[x].Data.outframes * StreamIn[x].Data.Channels );
end;
2:
begin
StreamIn[x].Data.outframes := op_read(StreamIn[x].Data.HandleOP,
@StreamIn[x].Data.Buffer[0], cint(StreamIn[x].Data.
Wantframes), Nil);
end;
end;
setlength(StreamIn[x].data.Buffer,int32(StreamIn[x].Data.outframes * StreamIn[x].Data.
Channels));
{$IF DEFINED(uos_debug) and DEFINED(unix)}
st := '';
for i := 0 to length(StreamIn[x].data.Buffer) -1 do
case StreamIn[x].Data.SampleFormat of
0: st := st + '|' + floattostr(StreamIn[x].data.Buffer[i]);
1: st := st + '|' + inttostr(cint32(StreamIn[x].data.Buffer[i]));
2: st := st + '|' + inttostr(cint16(cint32(StreamIn[x].data.Buffer[i])));
end;
WriteLn('OUTPUT DATA op_read_ ---------------------------');
// WriteLn(st);
{$endif}
if StreamIn[x].Data.outframes < 0 then StreamIn[x].Data.outframes := 0 ;
StreamIn[x].Data.outframes := StreamIn[x].Data.outframes * StreamIn[x].Data.Channels ;
end;
{$endif}
{$IF DEFINED(xmp)}
5:
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before xmp_play_buffer ' + inttostr(StreamIn[x].Data.Wantframes) +
' length(StreamIn[x].Data.Buffer ' +
inttostr(length(StreamIn[x].Data.Buffer)));
{$endif}
if xmp_play_buffer(StreamIn[x].Data.HandleSt,
@StreamIn[x].Data.Buffer[0], StreamIn[x].Data.Wantframes * StreamIn[x].Data.channels , 0
) < 0 then
StreamIn[x].Data.outframes := 0
else
begin
StreamIn[x].Data.outframes := StreamIn[x].Data.Wantframes;
if StreamIn[x].Data.SampleFormat < 2 then
begin
StreamIn[x].Data.Buffer := CvInt16ToFloat32(StreamIn[x].Data.Buffer);
if StreamIn[x].Data.SampleFormat = 1 then
StreamIn[x].Data.Buffer := CvFloat32toInt32fl(StreamIn[x].Data.Buffer, length(
StreamIn[x].Data.Buffer));
end;
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln(inttostr(StreamIn[x].Data.lastbuf));
WriteLn('after xmp_play_buffer');
{$endif}
setlength(StreamIn[x].data.Buffer,StreamIn[x].Data.outframes);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
st := '';
for i := 0 to length(StreamIn[x].data.Buffer) -1 do
begin
st := st + '|' + inttostr(i) + '=' + inttostr(cint16(cint32(StreamIn[x].data.Buffer[
i])));
end;
WriteLn('OUTPUT DATA xmp_read_ ---------------------------');
WriteLn('StreamIn[x].Data.outframes = ' + inttostr(StreamIn[x].Data.outframes));
// WriteLn(st);
{$endif}
end;
{$endif}
99: // if nothing was defined
end;
SetLength(StreamIn[x].Data.Buffer, StreamIn[x].Data.outframes);
end;
procedure Tuos_Player.CheckIfPaused ;
begin
if isGlobalPause = true then
begin
RTLeventWaitFor(uosInit.evGlobalPause);
RTLeventSetEvent(uosInit.evGlobalPause);
end
else
begin
RTLeventWaitFor(evPause);
// is there a pause waiting ?
RTLeventSetEvent(evPause);
end;
end;
{$IF DEFINED(mse)}
function Tuos_Player.execute(thread: tmsethread): integer;
// The Main Loop Procedure
{$else}
procedure TuosThread.Execute;
// The Main Loop Procedure
{$endif}
var
x, x2, x3 : cint32;
plugenabled: boolean;
curpos: cint64 = 0;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
st : string;
i : integer;
{$endif}
begin
theinc := 0;
{$IF DEFINED(mse)}
{$else}
with Tuos_Player(theparent) do
begin
{$endif}
CheckIfPaused ;
// is there a pause waiting ?
DoBeginMethods();
CheckIfPaused ;
// is there a pause waiting ?
repeat
if uosisactif then DoLoopBeginMethods
else nofree := false;
CheckIfPaused ;
// is there a pause waiting ?
// Dealing with input
for x := 0 to high(StreamIn) do
begin
if (StreamIn[x].data.hasfilters) and uosisactif then
begin
setlength(StreamIn[x].Data.levelfiltersar,StreamIn[x].Data.nbfilters * StreamIn[x].
Data.channels );
StreamIn[x].Data.incfilters := 0;
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before for x := 0 to high(StreamIn)');
{$endif}
CheckIfPaused ;
// is there a pause waiting ?
if (StreamIn[x].Data.Status > 0) and
(StreamIn[x].Data.Enabled = True) then
begin
StreamIn[x].Data.levelfilters := '';
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before StreamIn[x].Data.Seekable = True');
{$endif}
if (StreamIn[x].Data.Poseek > -1) and (StreamIn[x].Data.Seekable = True) and
uosisactif then
begin
// there is a seek waiting
DoSeek(x);
curpos := StreamIn[x].Data.Poseek;
StreamIn[x].Data.Poseek := -1;
end;
if (StreamIn[x].Data.positionEnable = 1) and (StreamIn[x].Data.Seekable = True)
then
StreamIn[x].Data.position := curpos;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('DSPin BeforeBufProc 1');
{$endif}
if (StreamIn[x].Data.Status = 1) and (length(StreamIn[x].DSP) > 0) then
DoDSPinBeforeBufProc(x);
// Procedure in DSP to execute before fill buffer.
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('DSPin BeforeBufProc 2');
{$endif}
if uosisactif then
begin
CheckIfPaused ;
// is there a pause waiting ?
case StreamIn[x].Data.TypePut of
0: // It is a input from audio file.
ReadFile(x);
{$IF DEFINED(portaudio)}
1: // for Input from device
ReadDevice(x);
{$endif}
{$IF DEFINED(webstream)}
2: // for Input from Internet audio stream.
ReadUrl(x);
{$ENDIF}
{$IF DEFINED(synthesizer)}
3: // for Input from Synthesizer
ReadSynth(x);
{$endif}
4: // for Input from memory
ReadMem(x);
5: // for Input from endless muted
ReadEndless(x);
6: // for Input from decoded memory-stream
ReadMemDec(x);
end;
//case StreamIn[x].Data.TypePut of
end
else StreamIn[x].Data.OutFrames := 0;
if StreamIn[x].Data.OutFrames = 0 then StreamIn[x].Data.status := 0;
if (StreamIn[x].Data.Seekable = True) then if StreamIn[x].Data.OutFrames < 100 then
StreamIn[x].Data.status := 0;
// no more data then close the stream
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('StreamIn[x].Data.status = ' + inttostr(StreamIn[x].Data.status));
{$endif}
if StreamIn[x].Data.status > 0 then// still working
begin
if (StreamIn[x].Data.positionEnable = 1) then
begin
if (StreamIn[x].Data.LibOpen = 1) and (StreamIn[x].Data.SampleFormat < 2)
then
curpos := curpos + (StreamIn[x].Data.OutFrames Div
(StreamIn[x].Data.Channels * 2))
// strange outframes float 32 with Mpg123 ?
else
curpos := curpos + (StreamIn[x].Data.OutFrames Div
(StreamIn[x].Data.Channels));
StreamIn[x].Data.position := curpos;
// new position
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Getting the level before DSP procedure');
{$endif}
if (StreamIn[x].Data.levelEnable = 1) or (StreamIn[x].Data.levelEnable = 3) then
StreamIn[x].Data := DSPLevel(StreamIn[x].Data);
// Adding level in array-level// ideal for pre-wave form
if (StreamIn[x].Data.levelArrayEnable = 1) then
begin
if (StreamIn[x].Data.levelEnable = 0) or (StreamIn[x].Data.levelEnable = 3)
then
StreamIn[x].Data := DSPLevel(StreamIn[x].Data);
DoArrayLevel(x);
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('DSPin AfterBuffProcBefore');
{$endif}
if (StreamIn[x].Data.Status = 1) and (length(StreamIn[x].DSP) > 0) then
DoDSPinAfterBufProc(x) ;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('DSPin AfterBuffProcAfter');
{$endif}
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('The synchro main loop procedurebefore');
{$endif}
DoMainLoopProc(x);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Getting the level after DSP procedure');
{$endif}
// Getting the level after DSP procedure
if ((StreamIn[x].Data.levelEnable = 2) or (StreamIn[x].Data.levelEnable = 3))
then StreamIn[x].Data := DSPLevel(StreamIn[x].Data);
// Adding level in array-level
if (StreamIn[x].Data.levelArrayEnable = 2) then
begin
if (StreamIn[x].Data.levelEnable = 0) or (StreamIn[x].Data.levelEnable = 1)
then
StreamIn[x].Data := DSPLevel(StreamIn[x].Data);
DoArrayLevel(x);
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('End level after DSP procedure');
{$endif}
end;
//if StreamIn[x].Data.status > 0 then
end;
//if (StreamIn[x].Data.Status > 0) and (StreamIn[x].Data.Enabled = True) then
end;
// end for low(StreamIn[x]) to high(StreamIn[x])
// Seeking if StreamIn is terminated
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Seeking if StreamIn is terminated');
{$endif}
if status <> 0 then SeekIfTerminated;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('status = ' +inttostr(status));
{$endif}
CheckIfPaused ;
// is there a pause waiting ?
// Give Buffer to Output
if status = 1 then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Give Buffer to Output');
{$endif}
if uosisactif then for x := 0 to high(StreamOut) do
if (StreamOut[x].Data.Enabled = True)
then
begin
if StreamOut[x].data.hasfilters then
begin
setlength(StreamOut[x].Data.levelfiltersar,StreamOut[x].
Data.nbfilters * StreamOut[x].Data.channels );
StreamOut[x].Data.incfilters := 0;
end;
for x2 := 0 to high(StreamOut[x].Data.Buffer) do
StreamOut[x].Data.Buffer[x2] := cfloat(0.0);
// clear output
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Buffer[x2] := cfloat(0.0)');
{$endif}
for x2 := 0 to high(StreamIn) do
if (StreamIn[x2].Data.status > 0) and
(StreamIn[x2].Data.Enabled = True)
and ((StreamIn[x2].Data.Output = x) or (StreamIn[x2].Data
.Output = -1))
then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('length(StreamIn[x2].Data.Buffer) = ' +inttostr(
length(StreamIn[x2].Data.Buffer)));
writeln('length(StreamOut[x].Data.Buffer) = ' +inttostr(
length(StreamOut[x].Data.Buffer)));
writeln(
'for x3 := 0 to high(StreamIn[x2].Data.Buffer) do'
);
writeln('high(StreamIn[x2].Data.Buffer) = '+ inttostr(
high(StreamIn[x2].Data.Buffer)));
{$endif}
for x3 := 0 to high(StreamIn[x2].Data.Buffer) do
begin
if x3 < high(StreamOut[x].Data.Buffer) + 1 then
StreamOut[x].Data.Buffer[x3] :=
cfloat(StreamOut[x]
.Data.Buffer[x3]) +
cfloat(StreamIn[x2]
.Data.Buffer[x3]);
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn(
'StreamOut[x].Data.Buffer ------------------------------'
);
st := '';
for i := 0 to length(StreamOut[0].Data.Buffer) -1 do
st := st + '|' + inttostr(i) + '=' + floattostr(
Streamout[0].Data.Buffer[i]);
// WriteLn(st);
writeln(
'for x3 := 0 to high(StreamIn[x2].Data.Buffer) done'
);
{$endif}
case StreamIn[x2].Data.LibOpen of
0: StreamOut[x].Data.outframes := StreamIn[x2].Data.
outframes ;
// sndfile
1: StreamOut[x].Data.outframes := StreamIn[x2].Data.
outframes Div
StreamIn[x2].Data.
Channels;
// mpg123
2: StreamOut[x].Data.outframes := StreamIn[x2].Data.
outframes ;
// aac
3: StreamOut[x].Data.outframes := StreamIn[x2].Data.
outframes ;
// CDRom
4: StreamOut[x].Data.outframes := StreamIn[x2].Data.
outframes ;
// opus
end;
end;
// copy buffer-in into buffer-out
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('copy buffer-in into buffer-out');
{$endif}
// DSPOut AfterBuffProc
if (length(StreamOut[x].DSP) > 0) and uosisactif then
DoDSPOutAfterBufProc(x) ;
// apply plugin (ex: SoundTouch Library)
plugenabled := False;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln(' if (length(Plugin) > 0) then');
{$endif}
if (length(Plugin) > 0) then
begin
for x3 := 0 to high(PlugIn) do
if Plugin[x3].Enabled = True then
plugenabled := True;
end;
//
if uosisactif then
begin
if plugenabled = True then
WriteOutPlug(x, x2)
else// No plugin
WriteOut(x, x2);
end;
end;
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before LoopEndProc ------------------------------');
{$endif}
if uosisactif then DoLoopEndMethods;
if length(StreamIn) > 1 then// clear buffer for multi-input
for x2 := 0 to high(StreamIn) do
for x3 := 0 to high(StreamIn[x2].Data.Buffer) do
StreamIn[x2].Data.Buffer[x3] := cfloat(0.0);
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before if (nofree = true) and (status = 0)-----');
{$endif}
if (nofree = true) and (status = 0) then
DoTerminateNoFreePlayer ;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before until status = 0;----');
{$endif}
until status = 0;
// End of Loop ---
{$IF DEFINED(uos_debug) and DEFINED(unix)}
WriteLn('Before Terminate Thread---');
{$endif}
// Terminate Thread
if status = 0 then
begin
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('Status = 0');
{$endif}
DoTerminatePlayer;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('EndProc---');
{$endif}
if uosisactif then DoEndProc;
if uosisactif then if EndProcOnly <> nil then EndProcOnly;
isAssigned := false ;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('EndProc All');
{$endif}
end;
{$IF DEFINED(uos_debug) and DEFINED(unix)}
writeln('This is the end...');
{$endif}
{$IF DEFINED(mse)}
{$else}
// FreeOnTerminate:=True;
// terminate();
end;
{$endif}
end;
procedure Tuos_Init.unloadPlugin(PluginName: Pchar);
// Unload Plugin...
begin
{$IF DEFINED(soundtouch)}
if lowercase(PluginName) = 'soundtouch' then st_Unload();
{$endif}
{$IF DEFINED(bs2b)}
if lowercase(PluginName) = 'bs2b' then bs_Unload();
{$endif}
end;
procedure Tuos_Init.unloadlib;
begin
{$IF DEFINED(sndfile)}
Sf_Unload();
{$endif}
{$IF DEFINED(mpg123)}
Mp_Unload();
{$endif}
{$IF DEFINED(xmp)}
xmp_Unload();
{$endif}
{$IF DEFINED(portaudio)}
Pa_Unload();
{$endif}
{$IF DEFINED(neaac)}
Aa_Unload;
{$endif}
{$IF DEFINED(fdkaac)}
ad_Unload;
{$endif}
{$IF DEFINED(opus)}
//op_Unload;
of_Unload;
{$endif}
{$IF DEFINED(windows)}
Set8087CW(old8087cw);
{$endif}
end;
function Tuos_Init.InitLib(): cint32;
begin
Result := -1;
{$IF DEFINED(mpg123)}
if (uosLoadResult.MPloadERROR = 0) then
if mpg123_init() = MPG123_OK then
begin
mpversion := UTF8Decode(mpg123_decoders()^);
uosLoadResult.MPinitError := 0;
Result := 0;
end
else
begin
Result := -2;
uosLoadResult.MPinitError := 1;
end;
{$endif}
{$IF DEFINED(portaudio)}
if (uosLoadResult.PAloadERROR = 0) then
begin
uosLoadResult.PAinitError := Pa_Initialize();
paversion := UTF8Decode(Pa_GetVersionText());
if uosLoadResult.PAinitError = 0 then
begin
Result := 0;
DefDevInInfo := Nil ;
DefDevOutInfo := Nil ;
DefDevOut := Pa_GetDefaultOutputDevice();
if DefDevOut >= 0 then
DefDevOutInfo := Pa_GetDeviceInfo(DefDevOut);
if DefDevOutInfo <> nil then
DefDevOutAPIInfo := Pa_GetHostApiInfo(DefDevOutInfo^.hostApi);
DefDevIn := Pa_GetDefaultInputDevice();
if DefDevIn >= 0 then
DefDevInInfo := Pa_GetDeviceInfo(DefDevIn);
if DefDevInInfo <> nil then
DefDevInAPIInfo := Pa_GetHostApiInfo(DefDevInInfo^.hostApi);
end;
end;
{$endif}
{$IF DEFINED(sndfile)}
if (Result = -1) and (uosLoadResult.SFloadERROR = 0) then
begin
sfversion := UTF8Decode(sf_version_string());
Result := 0;
end;
{$endif}
{$IF DEFINED(xmp)}
if (Result = -1) and (uosLoadResult.XMloadERROR = 0) then
begin
Result := 0;
end;
{$endif}
end;
function Tuos_Init.loadlib(): cint32;
begin
Result := -1;
uosLoadResult.PAloadERROR := -1;
uosLoadResult.SFloadERROR := -1;
uosLoadResult.MPloadERROR := -1;
uosLoadResult.AAloadError := -1;
uosLoadResult.OPloadERROR := -1;
uosLoadResult.STloadERROR := -1;
uosLoadResult.BSloadERROR := -1;
uosLoadResult.XMloadERROR := -1;
uosLoadResult.FAloadERROR := -1;
{$IF DEFINED(portaudio)}
if (PA_FileName <> nil) and (PA_FileName <> '') then
begin
if PA_FileName = 'system' then PA_FileName := '' ;
if Pa_Load(PA_FileName) then
begin
// {
Result := 0;
uosLoadResult.PAloadERROR := 0;
uosDefaultDeviceOut := Pa_GetDefaultOutPutDevice();
uosDefaultDeviceIn := Pa_GetDefaultInPutDevice();
uosDeviceCount := Pa_GetDeviceCount();
// }
end
else
uosLoadResult.PAloadERROR := 2;
end
else
uosLoadResult.PAloadERROR := -1;
{$endif}
{$IF DEFINED(sndfile)}
if (SF_FileName <> nil) and (SF_FileName <> '') then
begin
if Sf_FileName = 'system' then sf_FileName := '' ;
if Sf_Load(SF_FileName) then
begin
uosLoadResult.SFloadERROR := 0;
if uosLoadResult.PAloadERROR = -1 then
Result := 0;
end
else
begin
uosLoadResult.SFloadERROR := 2;
Result := -1;
end;
end
else
uosLoadResult.SFloadERROR := -1;
{$endif}
{$IF DEFINED(mpg123)}
if (MP_FileName <> nil) and (MP_FileName <> '') then
begin
if mp_FileName = 'system' then mp_FileName := '' ;
if mp_Load(Mp_FileName) then
begin
uosLoadResult.MPloadERROR := 0;
if (uosLoadResult.PAloadERROR = -1) and (uosLoadResult.SFloadERROR = -1) then
Result := 0;
end
else
begin
uosLoadResult.MPloadERROR := 2;
Result := -1;
end;
end
else
uosLoadResult.MPloadERROR := -1;
{$endif}
{$IF DEFINED(neaac)}
if (AA_FileName <> nil) and (AA_FileName <> '') and (M4_FileName <> nil) and (M4_FileName <> '')
then
begin
if m4_FileName = 'system' then m4_FileName := '' ;
if aa_FileName = 'system' then aa_FileName := '' ;
if aa_load(UTF8String(M4_FileName), UTF8String(AA_FileName)) then
begin
uosLoadResult.AAloadERROR := 0;
if (uosLoadResult.MPloadERROR = -1) and (uosLoadResult.PAloadERROR = -1) and
(uosLoadResult.SFloadERROR = -1) then
Result := 0;
end
else
begin
uosLoadResult.AAloadERROR := 2;
Result := -1;
end;
end
else
uosLoadResult.AAloadERROR := -1;
{$endif}
{$IF DEFINED(opus)}
if (OF_FileName <> nil) and (OF_FileName <> '') then
begin
if of_FileName = 'system' then of_FileName := '' ;
if (of_load(UTF8String(OF_FileName))) then
begin
uosLoadResult.OPloadERROR := 0;
if (uosLoadResult.MPloadERROR = -1) and (uosLoadResult.PAloadERROR = -1) and
(uosLoadResult.SFloadERROR = -1) and (uosLoadResult.AAloadERROR = -1)
then
Result := 0;
end
else
begin
uosLoadResult.OPloadERROR := 2;
Result := -1;
end;
end
else
uosLoadResult.OPloadERROR := -1;
{$endif}
{$IF DEFINED(xmp)}
if (XM_FileName <> nil) and (XM_FileName <> '') then
begin
if XM_FileName = 'system' then XM_FileName := '' ;
if (xmp_Load(UTF8String(XM_FileName))) then
begin
uosLoadResult.XMloadERROR := 0;
if (uosLoadResult.MPloadERROR = -1) and (uosLoadResult.PAloadERROR = -1) and
(uosLoadResult.SFloadERROR = -1) and (uosLoadResult.AAloadERROR = -1) and
(uosLoadResult.OPloadERROR = -1)
then
Result := 0;
end
else
begin
uosLoadResult.XMloadERROR := 2;
Result := -1;
end;
end
else
uosLoadResult.XMloadERROR := -1;
{$endif}
{$IF DEFINED(fdkaac)}
if (FA_FileName <> nil) and (FA_FileName <> '') then
begin
if FA_FileName = 'system' then FA_FileName := '' ;
if (ad_Load(UTF8String(FA_FileName))) then
begin
uosLoadResult.FAloadERROR := 0;
if (uosLoadResult.MPloadERROR = -1) and (uosLoadResult.PAloadERROR = -1) and
(uosLoadResult.SFloadERROR = -1) and (uosLoadResult.AAloadERROR = -1) and
(uosLoadResult.OPloadERROR = -1) and (uosLoadResult.XMloadERROR = -1)
then
Result := 0;
end
else
begin
uosLoadResult.FAloadERROR := 2;
Result := -1;
end;
end
else
uosLoadResult.FAloadERROR := -1;
{$endif}
if Result = 0 then Result := InitLib();
end;
function uos_loadPlugin(PluginName, PluginFilename: PChar) : cint32;
begin
Result := -1;
{$IF DEFINED(soundtouch)}
if ((lowercase(PluginName) = 'soundtouch') or (lowercase(PluginName) = 'getbpm')) and (
PluginFileName <> nil) and (PluginFileName <> '') then
begin
if PluginFileName = 'system' then PluginFileName := '' ;
if ST_Load(PluginFileName) then
begin
Result := 0;
uosLoadResult.STloadERROR := 0;
uosInit.Plug_ST_FileName := PluginFileName;
end
else
begin
uosLoadResult.STloadERROR := 2;
Result := -1;
end;
end;
{$endif}
{$IF DEFINED(bs2b)}
if (lowercase(PluginName) = 'bs2b') and (PluginFileName <> nil) and (PluginFileName <> '') then
begin
if PluginFileName = 'system' then PluginFileName := '' ;
if BS_Load(PluginFileName) then
begin
Result := 0;
uosLoadResult.BSloadERROR := 0;
uosInit.Plug_BS_FileName := PluginFileName;
end
else
begin
uosLoadResult.BSloadERROR := 2;
Result := -1;
end;
end;
{$endif}
end;
{$IF DEFINED(shout)}
function uos_LoadServerLib(ShoutFileName, OpusFileName : PChar) : cint32;
// Shout => needed for dealing with IceCast server
// Opus => needed for dealing with encoding opus stream
begin
Result := -1;
if not fileexists(ShoutFileName) then
else
if sh_Load(UTF8String(ShoutFileName)) then
Result := 0;
if result = 0 then
if not fileexists(OpusFileName) then
Result := -2
else
if op_Load(UTF8String(OpusFileName)) then
Result := 0
else Result := -1 ;
end;
procedure uos_unloadServerLib();
// Unload server libraries... Do not forget to call it before close application...
begin
shout_shutdown;
sh_unload;
op_unload;
end;
{$endif}
function uos_loadlib(PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName, FaadFileName
, opusfileFileName, XMPFileName, fdkaacFilename : PChar) : cint32;
begin
result := -1 ;
if not assigned(uosInit) then
begin
{$IF DEFINED(windows)}
old8087cw := Get8087CW;
Set8087CW($133f);
{$endif}
uosInit := TUOS_Init.Create;
// Create Libraries Loader-Init
end;
uosInit.PA_FileName := PortAudioFileName;
uosInit.SF_FileName := SndFileFileName;
uosInit.MP_FileName := Mpg123FileName;
uosInit.AA_FileName := FaadFileName;
uosInit.M4_FileName := Mp4ffFileName;
uosInit.OF_FileName := opusfileFileName;
uosInit.XM_FileName := XMPFileName;
uosInit.FA_FileName := fdkaacFilename;
result := uosInit.loadlib ;
end;
function uos_loadlib(PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName, FaadFileName
, opusfileFileName, XMPFileName : PChar) : cint32;
begin
result := uos_loadlib(PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName,
FaadFileName
, opusfileFileName, XMPFileName, nil);
end;
function uos_loadlib(PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName, FaadFileName
, opusfileFileName: PChar) : cint32;
begin
result := uos_loadlib(PortAudioFileName, SndFileFileName, Mpg123FileName, Mp4ffFileName,
FaadFileName
, opusfileFileName, Nil, nil);
end;
function uos_GetVersion() : cint32 ;
begin
result := uos_version ;
end;
function Tuos_Player.SetGlobalEvent(isenabled : boolean) : boolean;
// Set the RTL Events Global (will pause/start/replay all the players synchro with same rtl event))
// result : true if set ok.
begin
result := false;
if (isAssigned = True) then
begin
isGlobalPause := isenabled;
result := true;
end;
end;
procedure uos_unloadlib() ;
begin
if assigned(uosInit) then
begin
uosInit.unloadlib ;
end;
end;
procedure uos_unloadlibCust(PortAudio, SndFile, Mpg123, AAC, opus, xmp, fdkaac: boolean);
// Custom Unload libraries... if true, then unload the library. You may unload what and when you want...
begin
uosInit.unloadlibcust(PortAudio, SndFile, Mpg123, AAC, opus, xmp, fdkaac) ;
end;
procedure uos_UnloadPlugin(PluginName: PChar);
// load plugin...
begin
uosInit.unloadplugin(PluginName);
end;
function uos_GetInfoLibraries() : PansiChar ;
begin
result := pchar(paversion + ' | Sndfile: ' + sfversion + ' | Mpg123: ' + mpversion);
end;
{$IF DEFINED(portaudio)}
procedure uos_UpdateDevice();
begin
Pa_Terminate();
Pa_Initialize();
end;
procedure uos_GetInfoDevice();
var
x: cint32;
devinf: PPaDeviceInfo;
apiinf: PPaHostApiInfo;
begin
x := 0;
uosDeviceCount := 0;
SetLength(uosDeviceInfos, 0);
uos_UpdateDevice();
if Pa_GetDeviceCount() > 0 then
begin
uosDeviceCount := Pa_GetDeviceCount();
SetLength(uosDeviceInfos, uosDeviceCount);
uosDefaultDeviceOut := Pa_GetDefaultOutPutDevice();
uosDefaultDeviceIn := Pa_GetDefaultInPutDevice();
while x < uosDeviceCount do
begin
uosDeviceInfos[x].DeviceNum := x;
devinf := Pa_GetDeviceInfo(x);
apiinf := Pa_GetHostApiInfo(devinf^.hostApi);
uosDeviceInfos[x].DeviceName := UTF8Decode(devinf^._name);
uosDeviceInfos[x].HostAPIName := UTF8Decode(apiinf^._name);
if x = uosDefaultDeviceIn then
uosDeviceInfos[x].DefaultDevIn := True
else
uosDeviceInfos[x].DefaultDevIn := False;
if x = uosDefaultDeviceOut then
uosDeviceInfos[x].DefaultDevOut := True
else
uosDeviceInfos[x].DefaultDevOut := False;
uosDeviceInfos[x].ChannelsIn := devinf^.maxInputChannels;
uosDeviceInfos[x].ChannelsOut := devinf^.maxOutPutChannels;
uosDeviceInfos[x].SampleRate := devinf^.defaultSampleRate;
uosDeviceInfos[x].LatencyHighIn := devinf^.defaultHighInputLatency;
uosDeviceInfos[x].LatencyLowIn := devinf^.defaultLowInputLatency;
uosDeviceInfos[x].LatencyHighOut := devinf^.defaultHighOutputLatency;
uosDeviceInfos[x].LatencyLowOut := devinf^.defaultLowOutputLatency;
if uosDeviceInfos[x].ChannelsIn = 0 then
begin
if uosDeviceInfos[x].ChannelsOut = 0 then
uosDeviceInfos[x].DeviceType := 'None'
else uosDeviceInfos[x].DeviceType := 'Out' ;
end
else
begin
if uosDeviceInfos[x].ChannelsOut = 0 then
uosDeviceInfos[x].DeviceType := 'In'
else uosDeviceInfos[x].DeviceType := 'In/Out' ;
end ;
Inc(x);
end;
end;
end;
function uos_GetInfoDeviceStr() : PansiChar ;
var
x : cint32 ;
devtmp , bool1, bool2 : UTF8String;
begin
uos_GetInfoDevice() ;
x := 0;
devtmp := '';
while x < length(uosDeviceInfos) do
begin
if uosDeviceInfos[x].DefaultDevIn then bool1 := 'Yes'
else bool1 := 'No';
if uosDeviceInfos[x].DefaultDevOut then bool2 := 'Yes'
else bool2 := 'No';
devtmp := devtmp +
'DeviceNum: ' + inttostr(uosDeviceInfos[x].DeviceNum) + ' |' +
' Name: ' + uosDeviceInfos[x].DeviceName + ' |' +
' Type: ' + uosDeviceInfos[x].DeviceType + ' |' +
' DefIn: ' + bool1 + ' |' +
' DefOut: ' + bool2 + ' |' +
' ChanIn: ' + IntToStr(uosDeviceInfos[x ].ChannelsIn)+ ' |' +
' ChanOut: ' + IntToStr(uosDeviceInfos[x].ChannelsOut) + ' |' +
' SampleRate: ' + floattostrf(uosDeviceInfos[x].SampleRate, ffFixed, 15, 0) + ' |'
+
' LatencyHighIn: ' + floattostrf(uosDeviceInfos[x].LatencyHighIn, ffFixed, 15, 8) +
' |' +
' LatencyHighOut: ' + floattostrf(uosDeviceInfos[x].LatencyHighOut, ffFixed, 15, 8)+
' |' +
' LatencyLowIn: ' + floattostrf(uosDeviceInfos[x].LatencyLowIn, ffFixed, 15, 8)+
' |' +
' LatencyLowOut: ' + floattostrf(uosDeviceInfos[x].LatencyLowOut, ffFixed, 15, 8)+
' |' +
' HostAPI: ' + uosDeviceInfos[x].HostAPIName ;
if x < length(uosDeviceInfos)-1 then devtmp := devtmp + #13#10 ;
Inc(x);
end;
result := pansichar( devtmp + ' ' );
// }
end;
{$endif}
{$IF DEFINED(Java)}
procedure Tuos_Player.beginprocjava();
begin
(PEnv^^).CallVoidMethod(PEnv,Obj,BeginProc) ;
end;
procedure Tuos_Player.endprocjava();
begin
(PEnv^^).CallVoidMethod(PEnv,Obj,EndProc) ;
end;
procedure Tuos_Player.LoopBeginProcjava();
begin
(PEnv^^).CallVoidMethod(PEnv,Obj,LoopBeginProc) ;
end;
procedure Tuos_Player.LoopEndProcjava();
begin
(PEnv^^).CallVoidMethod(PEnv,Obj,LoopEndProc) ;
end;
procedure Tuos_DSP.LoopProcjava();
begin
// todo
end;
procedure Tuos_InStream.LoopProcjava();
begin
// todo
end;
procedure Tuos_OutStream.LoopProcjava();
begin
// todo
end;
{$endif}
{$IF DEFINED(webstream)}
procedure Tuos_InStream.UpdateIcyMetaInterval;
begin
if Data.HandleSt<>nil then
mpg123_param(Data.HandleSt, MPG123_ICY_INTERVAL, httpget.IcyMetaInt, 0);
end;
{$endif}
function AssignDefaultForUOSData: Tuos_Data;
var
i: Integer;
begin
with Result do
begin
Enabled := False;
TypePut := -1;
//nothing
Seekable := False;
Status := 0;
// no data
SetLength(Buffer,0);
SetLength(MemoryBuffer,0);
MemoryStream := Nil;
posmem := 0;
{$IF DEFINED(opus)}
SetLength(BufferTMP,0);
{$endif}
DSPVolumeIndex := -1;
DSPNoiseIndex := -1;
VLeft := 0;
VRight := 0;
hasfilters := false;
nbfilters := 0;
incfilters := 0;
PositionEnable := 0;
LevelEnable := 0;
LevelLeft := 0;
LevelRight := 0;
levelArrayEnable := 0;
//----------------------------//
SampleRate := 44100;
{$IF DEFINED(synthesizer)}
freqLsine := 440;
freqRsine := freqLsine;
dursine := 0;
posdursine := 0;
harmonic := 0;
{$endif}
SamplerateRoot := SampleRate;
//----------------------------//
Wantframes := 0;
OutFrames := 0;
SampleFormat := -1;
// default
Channels := -1;
// default
HandleSt := Nil;
{$IF DEFINED(opus)}
HandleOP := Nil;
{$endif}
Filename := '';
Title := '';
Copyright := '';
Software := '';
Artist := '';
Comment := '';
Date := '';
for i:= 0 to High(Tag) do
Tag[i] := #0;
Album := '';
Genre := '';
HDFormat := 0;
Frames := 0;
Sections := 0;
Encoding := -1;
// unknow
bitrate := -1;
// unknow
Length := 0;
LibOpen := -1;
// nothing open
Ratio := 0;
BPM := 0;
numbuf := -1;
//default
Output := -1;
//error
Position := 0;
Poseek := 0;
end;
end;
constructor Tuos_FFT.Create;
var
i: Integer;
begin
inherited;
AlsoBuf := False;
TypeFilterL := 0;
LowFrequencyL := 0;
HighFrequencyL := 0;
GainL := 0;
for i:= 0 to High(a3) do
a3[i] := 0;
for i:= 0 to High(a32) do
a32[i] := 0;
for i:= 0 to High(TArray01) do
begin
b2[i] := 0;
x0[i] := 0;
x1[i] := 0;
y0[i] := 0;
y1[i] := 0;
b22[i] := 0;
x02[i] := 0;
x12[i] := 0;
y02[i] := 0;
y12[i] := 0;
end;
C := 0;
D := 0;
C2 := 0;
D2 := 0;
TypeFilterR := 0;
LowFrequencyR := 0;
HighFrequencyR := 0;
GainR := 0;
for i:= 0 to High(a3r) do
a3r[i] := 0;
for i:= 0 to High(a32r) do
a32r[i] := 0;
for i:= 0 to High(TArray01) do
begin
b2r[i] := 0;
x0r[i] := 0;
x1r[i] := 0;
y0r[i] := 0;
y1r[i] := 0;
b22r[i] := 0;
x02r[i] := 0;
x12r[i] := 0;
y02r[i] := 0;
y12r[i] := 0;
end;
Cr := 0;
Dr := 0;
C2r := 0;
D2r := 0;
levelstring := '';
{$IF DEFINED(noiseremoval)}
FNoise := Nil;
{$endif}
end;
constructor Tuos_DSP.Create;
begin
inherited;
Enabled := False;
BefFunc := Nil;
AftFunc := Nil;
EndFunc := Nil;
LoopProc := Nil;
fftdata := Nil;
end;
constructor Tuos_InStream.Create;
begin
inherited;
Data := AssignDefaultForUOSData;
SetLength(DSP,0);
{$IF DEFINED(neaac)}
AACI := Nil;
{$endif}
{$IF DEFINED(cdrom)}
pCD := Nil;
{$endif}
{$IF DEFINED(webstream)}
httpget := Nil;
InHandle := 0;
OutHandle := 0;
InPipe := Nil;
OutPipe := Nil;
{$ENDIF}
{$IF DEFINED(portaudio)}
with PAParam do
begin
device := 0;
channelCount := 0;
sampleFormat := Nil;
suggestedLatency := 0;
hostApiSpecificStreamInfo := Nil;
end;
{$endif}
LoopProc := Nil;
end;
constructor Tuos_OutStream.Create;
{$IF DEFINED(shout)}
var
i: integer;
{$endif}
begin
inherited;
Data := AssignDefaultForUOSData;
BufferOut := Nil;
SetLength(DSP,0);
{$IF DEFINED(portaudio)}
with PAParam do
begin
//TODO: check if the default settings are ok
device := 0;
channelCount := 0;
sampleFormat := Nil;
suggestedLatency := 0;
hostApiSpecificStreamInfo := Nil;
end;
{$endif}
{$IF DEFINED(shout)}
encoder := Nil;
for i:= 0 to High(cbits) do
cbits[i] := 0;
//byte
{$endif}
with FileBuffer do
begin
ERROR := 0;
wSamplesPerSec := 44100;
wBitsPerSample := 32;
wChannels := 2;
FileFormat := -1;
Data := Nil;
DataMS := Nil;
end;
LoopProc := Nil;
MemorySteamOut := Nil;
{$IF DEFINED(Java)}
// procedure LoopProcjava;
{$endif}
end;
constructor Tuos_Plugin.Create;
begin
inherited;
Enabled := False;
Name := '';
{$IF DEFINED(windows)}
PlugHandle := 0;
{$else}
PlugHandle := Nil;
{$endif}
{$IF DEFINED(bs2b) or DEFINED(soundtouch)}
Abs2b := Nil;
PlugFunc := Nil;
{$endif}
param1 := -1;
param2 := -1;
param3 := -1;
param4 := -1;
param5 := -1;
param6 := -1;
param7 := -1;
param8 := -1;
SetLength(Buffer,0);
end;
constructor Tuos_Init.Create;
begin
{$IF DEFINED(portaudio)}
DefDevOut := -1;
DefDevOutInfo := Nil;
DefDevOutAPIInfo := Nil;
DefDevIn := -1;
DefDevInInfo := Nil;
DefDevInAPIInfo := Nil;
{$endif}
TDummyThread.Create(false);
evGlobalPause := RTLEventCreate;
SetExceptionMask(GetExceptionMask + [exZeroDivide] + [exInvalidOp] +
[exDenormalized] + [exOverflow] + [exUnderflow] + [exPrecision]);
uosLoadResult.PAloadERROR := -1;
uosLoadResult.PCloadERROR := -1;
uosLoadResult.SFloadERROR := -1;
uosLoadResult.BSloadERROR := -1;
uosLoadResult.STloadERROR := -1;
uosLoadResult.MPloadERROR := -1;
uosLoadResult.AAloadERROR := -1;
uosLoadResult.OPloadERROR := -1;
uosLoadResult.XMloadERROR := -1;
uosLoadResult.PAinitError := -1;
uosLoadResult.MPinitError := -1;
PA_FileName := Nil;
// PortAudio
SF_FileName := Nil;
// SndFile
MP_FileName := Nil;
// Mpg123
AA_FileName := Nil;
// Faad
M4_FileName := Nil;
// Mp4ff
OF_FileName := Nil;
// opusfile
XM_FileName := Nil;
// XMP
Plug_ST_FileName := Nil;
// Plugin SoundTouch
Plug_BS_FileName := Nil;
// Plugin bs2b
end;
constructor Tuos_Player.create();
begin
evPause := RTLEventCreate;
Index := -1;
//default for independent instance
isAssigned := true;
isGlobalPause := false;
intobuf := false;
NLooped := 0;
NoFree := False;
status := -1;
BeginProc := Nil;
EndProc := Nil;
EndProcOnly := Nil;
loopBeginProc := Nil;
loopEndProc := Nil;
thethread := Nil;
SetLength(StreamIn,0);
SetLength(StreamOut,0);
SetLength(PlugIn,0);
{$IF DEFINED(Java)}
PEnv := Nil;
Obj := Nil;
{$endif}
end;
{$IF DEFINED(mse)}
{$else}
procedure TuosThread.DoTerminate;
begin
{$IF FPC_FULLVERSION>=20701}
//Terminate the thread the calls places into the queuelist will be removed
RemoveQueuedEvents(Self);
{$ENDIF}
//notice that is no longer valid (for safe destroy event of theparent)
Tuos_Player(theparent).thethread := Nil;
//execute player destroy
FreeAndNil(theparent);
end;
{$endif}
destructor Tuos_Player.Destroy;
var
x: cint32;
begin
if thethread <> nil then
begin
{$ifdef mse}
thethread.terminate();
application.waitforthread(thethread);
//calls unlockall()/relockall in order to avoid possible deadlock
thethread.destroy();
{$endif}
end;
if assigned(evPause) then RTLeventdestroy(evPause);
if length(StreamOut) > 0 then
for x := 0 to high(StreamOut) do
freeandnil(StreamOut[x]);
if length(StreamIn) > 0 then
for x := 0 to high(StreamIn) do
freeandnil(StreamIn[x]);
if length(Plugin) > 0 then
for x := 0 to high(Plugin) do
freeandnil(Plugin[x]);
//Note: if Index = -1 is a independent instance
if Index <> -1 then
begin
//now notice that player is really free
uosPlayersStat[Index] := -1 ;
uosPlayers[Index] := Nil;
end;
inherited Destroy;
end;
destructor Tuos_DSP.Destroy;
begin
if assigned(fftdata) then
begin
{$IF DEFINED(noiseremoval)}
if assigned(fftdata.FNoise) then FreeAndNil(fftdata.FNoise);
{$endif}
FreeandNil(fftdata);
end;
inherited Destroy;
end;
destructor Tuos_InStream.Destroy;
var
x: cint32;
begin
{$IF DEFINED(neaac)}
if assigned(AACI) then
begin
if assigned(AACI.fsStream) then
begin
freeandnil(AACI.fsStream);
sleep(100);
end;
freeandnil(AACI);
sleep(100);
end;
{$endif}
if assigned(Data.MemoryStream) then
freeandnil(Data.MemoryStream);
if length(DSP) > 0 then
for x := 0 to high(DSP) do
freeandnil(DSP[x]);
inherited Destroy;
end;
destructor Tuos_OutStream.Destroy;
var
x: cint32;
begin
if length(DSP) > 0 then
for x := 0 to high(DSP) do
freeandnil(DSP[x]);
inherited Destroy;
end;
procedure Tuos_Init.unloadlibCust(PortAudio, SndFile, Mpg123, AAC, opus, xmp, fdkaac: boolean);
// Custom Unload libraries... if true, then unload the library. You may unload what and when you want...
begin
{$IF DEFINED(portaudio)}
if PortAudio = true then Pa_Unload();
{$endif}
{$IF DEFINED(sndfile)}
if SndFile = true then sf_Unload();
{$endif}
{$IF DEFINED(mpg123)}
if Mpg123 = true then mp_Unload();
{$endif}
{$IF DEFINED(xmp)}
if xmp = true then xmp_Unload();
{$endif}
{$IF DEFINED(fdkaac)}
if fdkaac = true then ad_Unload();
{$endif}
{$IF DEFINED(neaac)}
if AAC = True then aa_Unload();
{$endif}
{$IF DEFINED(opus)}
if opus = True then
begin
of_Unload();
// op_Unload();
end;
{$endif}
end;
procedure uos_Free();
begin
uos_unloadlib() ;
if assigned(uosInit) then
begin
if assigned(uosInit.evGlobalPause) then
RTLeventdestroy(uosInit.evGlobalPause);
freeandnil(uosInit);
end;
end;
initialization
SetLength(tempoutmemory,0);
SetLength(uosPlayers,0);
SetLength(uosPlayersStat,0);
SetLength(uosLevelArray,0);
SetLength(uosDeviceInfos,0);
uosInit := Nil;
end.