summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c7a5223)
raw | patch | inline | side by side (parent: c7a5223)
author | fgsfds <pvt.fgsfds@gmail.com> | |
Tue, 10 Mar 2020 20:29:50 +0000 (23:29 +0300) | ||
committer | fgsfds <pvt.fgsfds@gmail.com> | |
Tue, 10 Mar 2020 20:29:50 +0000 (23:29 +0300) |
index 53ee47e63a9e351ffefbf73209d094305eddfdd3..838e15863608563cbfad4d6f76eab805a1344ad2 100644 (file)
alGetSourcei(S, AL_SOURCE_STATE, Result);
end;
+function LoadEntireSound(var Snd: TSoundRec; Loader: TSoundLoader): Boolean;
+var
+ Frame: Pointer;
+ Data: Pointer;
+ Rx: LongWord;
+ DataLen, OldLen: LongWord;
+const
+ CHUNK_SIZE = 65536 * 2 * 2;
+begin
+ Result := False;
+
+ Frame := GetMem(CHUNK_SIZE);
+ if Frame = nil then exit;
+
+ Data := nil;
+ DataLen := 0;
+
+ repeat
+ Rx := Loader.FillBuffer(Frame, CHUNK_SIZE);
+ if Rx = 0 then break;
+
+ OldLen := DataLen;
+ DataLen := DataLen + Rx;
+ Data := ReAllocMem(Data, DataLen);
+ if Data = nil then begin FreeMem(Frame); exit; end;
+
+ Move(Frame^, (Data + OldLen)^, Rx);
+ until Loader.Finished();
+
+ FreeMem(Frame);
+
+ alGenBuffers(1, Addr(Snd.alBuffer));
+ if CheckALError() then
+ begin
+ e_LogWritefln('AL: Could not create AL buffer: %s', [GetALError()]);
+ FreeMem(Data);
+ exit;
+ end;
+
+ alBufferData(
+ Snd.alBuffer,
+ GetALSoundFormat(Loader.Format),
+ Data,
+ DataLen,
+ Loader.Format.SampleRate
+ );
+
+ FreeMem(Data);
+
+ if CheckALError() then
+ begin
+ e_LogWriteln('AL: Could not fill AL buffer: ' + GetALError());
+ alDeleteBuffers(1, Addr(Snd.alBuffer));
+ Snd.alBuffer := 0;
+ exit;
+ end;
+
+ Result := True;
+end;
+
function e_LoadSound(FileName: String; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
var
find_id: DWORD;
Loader: TSoundLoader;
- OutData: Pointer;
- OutLen: LongWord;
begin
ID := NO_SOUND_ID;
Result := False;
exit;
end;
- Loader.Looping := e_SoundsArray[find_id].Loops;
-
- if not Loader.Load(FileName, e_SoundsArray[find_id].isMusic) then
+ if not Loader.Load(FileName, e_SoundsArray[find_id].Loops) then
begin
e_LogWritefln('Could not load sound `%s`', [FileName]);
exit;
alGetError(); // reset error state, god damn it
- if not Loader.Streaming then
+ if not isMusic then
begin
- alGenBuffers(1, Addr(e_SoundsArray[find_id].alBuffer));
- if CheckALError() then
- begin
- e_LogWritefln('Could not create AL buffer for `%s`: %s', [FileName, GetALError()]);
- Loader.Free();
- exit;
- end;
-
- OutLen := Loader.GetAll(OutData);
- alBufferData(
- e_SoundsArray[find_id].alBuffer,
- GetALSoundFormat(Loader.Format),
- OutData,
- OutLen,
- Loader.Format.SampleRate
- );
-
+ if not LoadEntireSound(e_SoundsArray[find_id], Loader) then
+ e_LogWritefln('AL: Could not buffer sound effect `%s`', [FileName]);
// don't need this anymore
Loader.Free();
Loader := nil;
-
- if CheckALError() then
- begin
- e_LogWriteln('AL: what the fuck: ' + GetALError());
- alDeleteBuffers(1, Addr(e_SoundsArray[find_id].alBuffer));
- e_SoundsArray[find_id].alBuffer := 0;
- exit;
- end;
end
else
begin
@@ -344,8 +377,6 @@ function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic:
var
find_id: DWORD;
Loader: TSoundLoader;
- OutData: Pointer;
- OutLen: LongWord;
begin
ID := NO_SOUND_ID;
Result := False;
exit;
end;
- Loader.Looping := e_SoundsArray[find_id].Loops;
-
- if not Loader.Load(pData, LongWord(Length), e_SoundsArray[find_id].isMusic) then
+ if not Loader.Load(pData, LongWord(Length), e_SoundsArray[find_id].Loops) then
begin
e_LogWritefln('Could not load sound `%p`', [pData]);
exit;
alGetError(); // reset error state, god damn it
- if not Loader.Streaming then
+ if not isMusic then
begin
- alGenBuffers(1, Addr(e_SoundsArray[find_id].alBuffer));
- if CheckALError() then
- begin
- e_LogWritefln('Could not create AL buffer for `%p`: %s', [pData, GetALError()]);
- Loader.Free();
- exit;
- end;
-
- OutLen := Loader.GetAll(OutData);
- alBufferData(
- e_SoundsArray[find_id].alBuffer,
- GetALSoundFormat(Loader.Format),
- OutData,
- OutLen,
- Loader.Format.SampleRate
- );
-
+ if not LoadEntireSound(e_SoundsArray[find_id], Loader) then
+ e_LogWritefln('AL: Could not buffer sound effect `%p`', [pData]);
// don't need this anymore
Loader.Free();
Loader := nil;
-
- if CheckALError() then
- begin
- e_LogWriteln('AL: what the fuck: ' + GetALError());
- alDeleteBuffers(1, Addr(e_SoundsArray[find_id].alBuffer));
- e_SoundsArray[find_id].alBuffer := 0;
- exit;
- end;
end
else
begin
begin
// this is a stream
// reset position
- e_SoundsArray[ID].Loader.SetPosition(0);
+ e_SoundsArray[ID].Loader.Restart();
if CurStream <> ID then // changing streams
begin
alSourceStop(Src); // this should mark all buffers as processed
index 4ba5cd6ac0b40eeaaa6cd2948655a03df2373b89..c508593235bc070b10a2d348efcc7942131e4885 100644 (file)
protected
FFormat: TSoundFormat;
FStreaming: Boolean;
- FLooping: Boolean;
public
- function Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean; virtual; abstract; overload;
- function Load(FName: string; SStreaming: Boolean): Boolean; virtual; abstract; overload;
+ function Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean; virtual; abstract; overload;
+ function Load(FName: string; Loop: Boolean): Boolean; virtual; abstract; overload;
- function SetPosition(Pos: LongWord): Boolean; virtual; abstract;
+ function Finished(): Boolean; virtual; abstract;
+ function Restart(): Boolean; virtual; abstract;
function FillBuffer(Buf: Pointer; Len: LongWord): LongWord; virtual; abstract;
- function GetAll(var OutPtr: Pointer): LongWord; virtual; abstract;
-
procedure Free(); virtual; abstract;
property Format: TSoundFormat read FFormat;
property Streaming: Boolean read FStreaming;
- property Looping: Boolean read FLooping write FLooping;
end;
TSoundLoaderFactory = class
index 5235f2c0097a7040f297b350e984b45bdda46fd7..fba2726d408d211e3fd32b453cf70dce4ab62513 100644 (file)
TFluidLoader = class (TSoundLoader)
public
- function Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean; override; overload;
- function Load(FName: string; SStreaming: Boolean): Boolean; override; overload;
- function SetPosition(Pos: LongWord): Boolean; override;
+ function Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean; override; overload;
+ function Load(FName: string; Loop: Boolean): Boolean; override; overload;
+ function Finished(): Boolean; override;
+ function Restart(): Boolean; override;
function FillBuffer(Buf: Pointer; Len: LongWord): LongWord; override;
- function GetAll(var OutPtr: Pointer): LongWord; override;
procedure Free(); override;
private
(* TFluidLoader *)
-function TFluidLoader.Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean;
+function TFluidLoader.Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean;
var
Ret: cint;
begin
end;
end;
- if FLooping then
+ if Loop then
fluid_player_set_loop(FPlayer, -1);
+
FFormat.SampleRate := 44100;
FFormat.SampleBits := 16;
FFormat.Channels := 2;
Result := True;
end;
-function TFluidLoader.Load(FName: string; SStreaming: Boolean): Boolean;
+function TFluidLoader.Load(FName: string; Loop: Boolean): Boolean;
var
Ret: cint;
begin
end;
end;
- if FLooping then
+ if Loop then
fluid_player_set_loop(FPlayer, -1);
+
FFormat.SampleRate := 44100;
FFormat.SampleBits := 16;
FFormat.Channels := 2;
Result := True;
end;
-function TFluidLoader.SetPosition(Pos: LongWord): Boolean;
+function TFluidLoader.Finished(): Boolean;
begin
- Result := False; // unsupported?
+ Result := fluid_player_get_status(FPlayer) = FLUID_PLAYER_DONE;
+end;
+
+function TFluidLoader.Restart(): Boolean;
+begin
+ Result := False;
+ // fluid_player_seek() is only supported in full 2.x.x, and I ain't compiling that shit
+ // if (FSynth <> nil) and (FPlayer <> nil) then
+ // begin
+ // fluid_synth_system_reset(FSynth);
+ // fluid_player_seek(FPlayer, 0);
+ // fluid_player_play(FPlayer);
+ // Result := True;
+ // end;
end;
function TFluidLoader.FillBuffer(Buf: Pointer; Len: LongWord): LongWord;
if Ret = FLUID_OK then Result := Len;
end;
-function TFluidLoader.GetAll(var OutPtr: Pointer): LongWord;
-begin
- Result := 0; // midis are always streaming, so this don't make sense
-end;
-
procedure TFluidLoader.Free();
begin
if FPlayer <> nil then
index 0a2c280c656d0a111e50cae9e1b231b2b503bd9a..600512b06e9cb05d805cb8d36e527f9b1b570fe4 100644 (file)
TModPlugLoader = class (TSoundLoader)
public
- function Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean; override; overload;
- function Load(FName: string; SStreaming: Boolean): Boolean; override; overload;
- function SetPosition(Pos: LongWord): Boolean; override;
+ function Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean; override; overload;
+ function Load(FName: string; Loop: Boolean): Boolean; override; overload;
+ function Finished(): Boolean; override;
+ function Restart(): Boolean; override;
function FillBuffer(Buf: Pointer; Len: LongWord): LongWord; override;
- function GetAll(var OutPtr: Pointer): LongWord; override;
procedure Free(); override;
private
FFile: PModPlugFile;
+ FFinished: Boolean;
+ FLooping: Boolean;
end;
TModPlugLoaderFactory = class (TSoundLoaderFactory)
(* TModPlugLoader *)
-function TModPlugLoader.Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean;
+function TModPlugLoader.Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean;
begin
Result := False;
FFormat.SampleBits := 16;
FFormat.Channels := 2;
FStreaming := True; // modules are always streaming
+ FFinished := False;
+ FLooping := Loop;
Result := True;
end;
-function TModPlugLoader.Load(FName: string; SStreaming: Boolean): Boolean;
+function TModPlugLoader.Load(FName: string; Loop: Boolean): Boolean;
var
S: TStream = nil;
Data: Pointer;
Len := S.Read(Data^, S.Size);
if Len < 0 then
raise Exception.Create('what the fuck');
- Result := Load(Data, Len, SStreaming)
+ Result := Load(Data, Len, Loop);
except
on E: Exception do
e_LogWritefln('ModPlug: ERROR: could not read file `%s`: %s', [FName, E.Message]);
if S <> nil then S.Free();
end;
-function TModPlugLoader.SetPosition(Pos: LongWord): Boolean;
+function TModPlugLoader.Finished(): Boolean;
+begin
+ Result := FFinished;
+end;
+
+function TModPlugLoader.Restart(): Boolean;
begin
Result := False;
if FFile = nil then Exit;
- ModPlug_Seek(FFile, Pos);
+ ModPlug_Seek(FFile, 0);
+ FFinished := False;
Result := True;
end;
Cnt := ModPlug_Read(FFile, Buf, Len);
if Cnt < 0 then Exit;
- if FLooping and (Cnt < Len) then
- begin
- // assume it just ended and restart, because modplug only loops if the
- // module tells it to
- ModPlug_Seek(FFile, 0);
- // this used to be Result := Cnt + Read(FFile, Buf + Cnt, Len - Cnt)
- // but the difference appears to be negligible
- Result := ModPlug_Read(FFile, Buf, Len);
- end
- else
- Result := Len;
-end;
+ Result := Cnt;
-function TModPlugLoader.GetAll(var OutPtr: Pointer): LongWord;
-begin
- Result := 0; // modules are always streaming, so this don't make sense
+ if Cnt < Len then
+ begin
+ if FLooping then
+ begin
+ // assume it just ended and restart, because modplug only loops if the
+ // module tells it to
+ ModPlug_Seek(FFile, 0);
+ // this used to be Result := Cnt + Read(FFile, Buf + Cnt, Len - Cnt)
+ // but the difference appears to be negligible
+ Result := ModPlug_Read(FFile, Buf, Len);
+ end
+ else
+ FFinished := True;
+ end;
end;
procedure TModPlugLoader.Free();
begin
ModPlug_Unload(FFile);
FFile := nil;
+ FFinished := False;
+ FLooping := False;
end;
end;
index 65b47e60e68e6176a2c8a97ef00904219184bdb3..c49f376b574c01abe207f062ee934890884333c4 100644 (file)
TMP3Loader = class (TSoundLoader)
public
- function Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean; override; overload;
- function Load(FName: string; SStreaming: Boolean): Boolean; override; overload;
- function SetPosition(Pos: LongWord): Boolean; override;
+ function Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean; override; overload;
+ function Load(FName: string; Loop: Boolean): Boolean; override; overload;
+ function Finished(): Boolean; override;
+ function Restart(): Boolean; override;
function FillBuffer(Buf: Pointer; Len: LongWord): LongWord; override;
- function GetAll(var OutPtr: Pointer): LongWord; override;
procedure Free(); override;
private
FMPG: pmpg123_handle;
FData: TStream;
FBuf: Pointer;
- FAllSamples: Pointer;
FOpen: Boolean;
+ FFinished: Boolean;
+ FLooping: Boolean;
- function LoadStream(Stream: TStream; SStreaming: Boolean): Boolean;
+ function LoadStream(Stream: TStream): Boolean;
end;
TMP3LoaderFactory = class (TSoundLoaderFactory)
(* TMP3Loader *)
-function TMP3Loader.LoadStream(Stream: TStream; SStreaming: Boolean): Boolean;
+function TMP3Loader.LoadStream(Stream: TStream): Boolean;
var
SRate: clong;
SEnc, SChans: LongInt;
FFormat.SampleRate := SRate;
FFormat.SampleBits := 16;
FFormat.Channels := SChans;
- FStreaming := SStreaming;
+ FStreaming := True;
+ FFinished := False;
Result := True;
end;
-function TMP3Loader.Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean;
+function TMP3Loader.Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean;
var
S: TStream;
begin
Move(Data^, FBuf^, Len);
S := TSFSMemoryStreamRO.Create(FBuf, Len{, True});
- Result := LoadStream(S, SStreaming);
+ Result := LoadStream(S);
+ FLooping := Loop;
if not Result and (S <> nil) then
begin
end;
end;
-function TMP3Loader.Load(FName: string; SStreaming: Boolean): Boolean;
+function TMP3Loader.Load(FName: string; Loop: Boolean): Boolean;
var
S: TStream = nil;
begin
try
S := openDiskFileRO(FName);
- Result := LoadStream(S, SStreaming);
+ Result := LoadStream(S);
+ FLooping := Loop;
except
on E: Exception do
e_LogWritefln('MPG123: ERROR: could not read file `%s`: %s', [FName, E.Message]);
S.Destroy();
end;
-function TMP3Loader.SetPosition(Pos: LongWord): Boolean;
+function TMP3Loader.Finished(): Boolean;
+begin
+ Result := FFinished;
+end;
+
+function TMP3Loader.Restart(): Boolean;
begin
Result := False;
if FMPG = nil then Exit;
- Result := mpg123_seek(FMPG, Pos, 0) = MPG123_OK;
+ FFinished := False;
+ Result := mpg123_seek(FMPG, 0, 0) = MPG123_OK;
end;
function TMP3Loader.FillBuffer(Buf: Pointer; Len: LongWord): LongWord;
Result := 0;
Got := 0;
if FMPG = nil then Exit;
+
Ret := mpg123_read(FMPG, Buf, Len, @Got);
- if FLooping and ((Ret = MPG123_DONE) or (Got = 0)) then
- Ret := mpg123_seek(FMPG, 0, 0); // loop
- if Ret = MPG123_OK then
- Result := Got;
-end;
-function TMP3Loader.GetAll(var OutPtr: Pointer): LongWord;
-begin
- Result := 0;
- if FMPG = nil then Exit;
- if FStreaming then Exit;
- // TODO
+ if (Ret = MPG123_DONE) or (Got = 0) then
+ begin
+ if FLooping then
+ Ret := mpg123_seek(FMPG, 0, 0) // loop
+ else
+ FFinished := True;
+ end;
+
+ if (Ret = MPG123_OK) or FFinished then
+ Result := Got;
end;
procedure TMP3Loader.Free();
if FMPG <> nil then mpg123_delete(FMPG);
if FData <> nil then FData.Destroy();
if FBuf <> nil then FreeMem(FBuf);
- if FAllSamples <> nil then FreeMem(FAllSamples);
FOpen := False;
+ FFinished := False;
+ FLooping := False;
FMPG := nil;
FData := nil;
FBuf := nil;
- FAllSamples := nil;
end;
initialization
index ab799510d62777515048b071d79121e671cd84e7..e0b41e392fd078be32895fd36cc3d709bf891dce 100644 (file)
TOpusLoader = class (TSoundLoader)
public
- function Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean; override; overload;
- function Load(FName: string; SStreaming: Boolean): Boolean; override; overload;
- function SetPosition(Pos: LongWord): Boolean; override;
+ function Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean; override; overload;
+ function Load(FName: string; Loop: Boolean): Boolean; override; overload;
+ function Finished(): Boolean; override;
+ function Restart(): Boolean; override;
function FillBuffer(Buf: Pointer; Len: LongWord): LongWord; override;
- function GetAll(var OutPtr: Pointer): LongWord; override;
procedure Free(); override;
private
FOpus: POggOpusFile;
FBuf: Pointer;
+ FFinished: Boolean;
+ FLooping: Boolean;
end;
TOpusLoaderFactory = class (TSoundLoaderFactory)
(* TOpusLoader *)
-function TOpusLoader.Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean;
+function TOpusLoader.Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean;
begin
Result := False;
FFormat.SampleBits := 16;
FFormat.SampleRate := 48000; // is this even correct?
FStreaming := True; // opus is always streaming
+ FFinished := False;
+ FLooping := Loop;
Result := True;
end;
-function TOpusLoader.Load(FName: string; SStreaming: Boolean): Boolean;
+function TOpusLoader.Load(FName: string; Loop: Boolean): Boolean;
begin
Result := False;
FFormat.SampleBits := 16;
FFormat.SampleRate := 48000; // is this even correct?
FStreaming := True; // opus is always streaming
+ FFinished := False;
+ FLooping := Loop;
Result := True;
end;
-function TOpusLoader.SetPosition(Pos: LongWord): Boolean;
+function TOpusLoader.Finished(): Boolean;
+begin
+ Result := FFinished;
+end;
+
+function TOpusLoader.Restart(): Boolean;
begin
Result := False;
if (FOpus = nil) or (op_seekable(FOpus) = 0) then Exit;
- Result := op_pcm_seek(FOpus, Pos) = 0;
+ Result := op_pcm_seek(FOpus, 0) = 0;
+ FFinished := False;
end;
function TOpusLoader.FillBuffer(Buf: Pointer; Len: LongWord): LongWord;
Ret := op_read_stereo(FOpus, Buf + Rx, (Len - Rx) div 2);
if Ret = OP_HOLE then continue;
if Ret < 0 then break;
- if FLooping and (Ret = 0) then op_pcm_seek(FOpus, 0); // loop
+ if Ret = 0 then
+ begin
+ if FLooping then
+ op_pcm_seek(FOpus, 0)
+ else
+ begin
+ FFinished := True;
+ break;
+ end;
+ end;
Rx := Rx + Ret * 4;
end;
Result := Rx;
end;
-function TOpusLoader.GetAll(var OutPtr: Pointer): LongWord;
-begin
- Result := 0; // always streaming
-end;
-
procedure TOpusLoader.Free();
begin
if FOpus <> nil then
FOpus := nil;
FBuf := nil;
FStreaming := False;
+ FFinished := False;
+ FLooping := False;
end;
initialization
index d003fb697b728a16065af8e245af5bbf9c6d6571..d2d364bf53e6854ff2d78856c03abe885afc11b7 100644 (file)
TVorbisLoader = class (TSoundLoader)
public
- function Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean; override; overload;
- function Load(FName: string; SStreaming: Boolean): Boolean; override; overload;
- function SetPosition(Pos: LongWord): Boolean; override;
+ function Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean; override; overload;
+ function Load(FName: string; Loop: Boolean): Boolean; override; overload;
+ function Finished(): Boolean; override;
+ function Restart(): Boolean; override;
function FillBuffer(Buf: Pointer; Len: LongWord): LongWord; override;
- function GetAll(var OutPtr: Pointer): LongWord; override;
procedure Free(); override;
private
FOgg: OggVorbis_File;
FData: TStream;
FBuf: Pointer;
- FTotal: LongWord;
FOpen: Boolean;
+ FFinished: Boolean;
+ FLooping: Boolean;
- function LoadStream(Stream: TStream; SStreaming: Boolean): Boolean;
- function LoadEntireStream(): Pointer;
+ function LoadStream(Stream: TStream): Boolean;
end;
TVorbisLoaderFactory = class (TSoundLoaderFactory)
(* TVorbisLoader *)
-function TVorbisLoader.LoadEntireStream(): Pointer;
-var
- Samples: ogg_int64_t;
- Ret: clong;
-begin
- Result := nil;
-
- Samples := ov_pcm_total(FOgg, -1);
- if Samples < 0 then Exit;
-
- FTotal := Samples * 2 * FFormat.Channels;
- Result := GetMem(FTotal);
- if Result = nil then Exit;
-
- Ret := ov_read_ext(FOgg, Result, FTotal, False, 2, True);
- if Ret < 0 then
- begin
- FreeMem(Result);
- Result := nil;
- end
- else
- FTotal := Ret;
-end;
-
-function TVorbisLoader.LoadStream(Stream: TStream; SStreaming: Boolean): Boolean;
+function TVorbisLoader.LoadStream(Stream: TStream): Boolean;
var
Ret: clong;
Info: pvorbis_info;
- FullBuf: Pointer;
begin
Result := False;
FFormat.SampleRate := Info^.rate;
FFormat.Channels := Info^.channels;
FFormat.SampleBits := 16;
+ FOpen := True;
+ FData := Stream;
- if not SStreaming then
- begin
- FullBuf := LoadEntireStream();
-
- if FullBuf = nil then
- begin
- e_LogWriteln('OGG: Load(Data) failed: couldn''t allocate for non-streaming chunk');
- ov_clear(FOgg);
- FTotal := 0;
- Exit;
- end;
-
- ov_clear(FOgg);
- Stream.Free();
-
- FreeMem(FBuf);
- FBuf := FullBuf;
- end
- else
- begin
- FTotal := 0;
- FOpen := True;
- FData := Stream;
- end;
-
- FStreaming := SStreaming;
+ FStreaming := True;
+ FFinished := False;
Result := True;
end;
-function TVorbisLoader.Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean;
+function TVorbisLoader.Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean;
var
S: TStream;
begin
Move(Data^, FBuf^, Len);
S := TSFSMemoryStreamRO.Create(FBuf, Len{, True});
- Result := LoadStream(S, SStreaming);
+ Result := LoadStream(S);
+ FLooping := Loop;
if not Result and (S <> nil) then
begin
end;
end;
-function TVorbisLoader.Load(FName: string; SStreaming: Boolean): Boolean;
+function TVorbisLoader.Load(FName: string; Loop: Boolean): Boolean;
var
S: TStream = nil;
begin
try
S := openDiskFileRO(FName);
- Result := LoadStream(S, SStreaming);
+ Result := LoadStream(S);
+ FLooping := Loop;
except
on E: Exception do
e_LogWritefln('OGG: ERROR: could not read file `%s`: %s', [FName, E.Message]);
S.Free();
end;
-function TVorbisLoader.SetPosition(Pos: LongWord): Boolean;
+function TVorbisLoader.Finished(): Boolean;
+begin
+ Result := FFinished;
+end;
+
+function TVorbisLoader.Restart(): Boolean;
begin
Result := False;
if not FOpen or (ov_seekable(FOgg) = 0) then Exit;
- Result := ov_pcm_seek(FOgg, Pos) = 0;
+ FFinished := False;
+ Result := ov_pcm_seek(FOgg, 0) = 0;
end;
function TVorbisLoader.FillBuffer(Buf: Pointer; Len: LongWord): LongWord;
Ret: clong;
begin
Result := 0;
- if not FOpen or not FStreaming then Exit;
+ if not FOpen then Exit;
Ret := ov_read_ext(FOgg, Buf, Len, False, 2, True);
if Ret < 0 then Exit;
- if FLooping and (Ret = 0) then
- ov_pcm_seek(FOgg, 0);
+ if Ret = 0 then
+ begin
+ if FLooping then
+ ov_pcm_seek(FOgg, 0)
+ else
+ FFinished := True;
+ end;
Result := Ret;
end;
-function TVorbisLoader.GetAll(var OutPtr: Pointer): LongWord;
-begin
- Result := 0;
- if FStreaming or (FTotal = 0) then Exit;
- Result := FTotal;
- OutPtr := FBuf;
-end;
-
procedure TVorbisLoader.Free();
begin
if FOpen then
ov_clear(FOgg);
if FData <> nil then
FData.Free();
- if FBuf <> nil then
- FreeMem(FBuf);
FData := nil;
- FBuf := nil;
FOpen := False;
- FTotal := 0;
FStreaming := False;
+ FFinished := False;
end;
initialization
index fe9a8a26f9c10ded420e82f183cee4c6167f3c77..84ea42df4c5c12068309086e75f61ff2941c2593 100644 (file)
TWAVLoader = class (TSoundLoader)
public
- function Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean; override; overload;
- function Load(FName: string; SStreaming: Boolean): Boolean; override; overload;
- function SetPosition(Pos: LongWord): Boolean; override;
+ function Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean; override; overload;
+ function Load(FName: string; Loop: Boolean): Boolean; override; overload;
+ function Finished(): Boolean; override;
+ function Restart(): Boolean; override;
function FillBuffer(Buf: Pointer; Len: LongWord): LongWord; override;
- function GetAll(var OutPtr: Pointer): LongWord; override;
procedure Free(); override;
private
FData: Pointer;
FDataLen: LongWord;
+ FDataPos: LongWord;
+ FLooping: Boolean;
end;
TWAVLoaderFactory = class (TSoundLoaderFactory)
FFormat.SampleBits := Spec.format and $FF;
{$ENDIF}
FFormat.Channels := Spec.channels;
- FStreaming := False; // never stream wavs
+ FDataPos := 0;
FDataLen := Len;
FData := Buf;
end
end
end;
-function TWAVLoader.Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean;
+function TWAVLoader.Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean;
var
RW: PSDL_RWops;
begin
if Result = False then
e_LogWriteln('Could not load WAV: ' + SDL_GetError());
SDL_RWclose(RW);
+ FStreaming := False;
+ FLooping := Loop;
end;
-function TWAVLoader.Load(FName: string; SStreaming: Boolean): Boolean;
+function TWAVLoader.Load(FName: string; Loop: Boolean): Boolean;
var
RW: PSDL_RWops;
begin
Result := False
end;
SDL_RWclose(RW);
+ FStreaming := False;
+ FLooping := Loop;
end;
-function TWAVLoader.SetPosition(Pos: LongWord): Boolean;
+function TWAVLoader.Finished(): Boolean;
begin
- Result := False; // makes no sense when not streaming
+ Result := FDataPos >= FDataLen;
end;
-function TWAVLoader.FillBuffer(Buf: Pointer; Len: LongWord): LongWord;
+function TWAVLoader.Restart(): Boolean;
begin
- if FDataLen < Len then
- Len := FDataLen;
- if FData <> nil then
- begin
- Move(FData^, Buf^, Len);
- Result := Len;
- end
- else
- Result := 0;
+ Result := True;
+ FDataPos := 0;
end;
-function TWAVLoader.GetAll(var OutPtr: Pointer): LongWord;
+function TWAVLoader.FillBuffer(Buf: Pointer; Len: LongWord): LongWord;
+var
+ OutPos: LongWord;
+ Tx: LongWord;
begin
- OutPtr := FData;
- Result := FDataLen;
+ OutPos := 0;
+ Result := 0;
+
+ while (FDataPos < FDataLen) and (OutPos < Len) do
+ begin
+ Tx := nmin(FDataLen - FDataPos, Len - OutPos);
+ Move((FData + FDataPos)^, (Buf + OutPos)^, Tx);
+
+ FDataPos := FDataPos + Tx;
+ OutPos := OutPos + Tx;
+ Result := Result + Tx;
+
+ if (FDataPos >= FDataLen) and FLooping then
+ FDataPos := 0;
+ end;
end;
procedure TWAVLoader.Free();
begin
if FData <> nil then
SDL_FreeWAV(FData); // SDL allocates inside the DLL, so we need this
+ FDataPos := 0;
+ FData := nil;
+ FDataLen := 0;
end;
initialization
index b4c406ce139d3ade999c6697c5b0aa4c55ceba27..3d2ef087b957a08a1fcd69e22c17ef48b5569ea3 100644 (file)
TXMPLoader = class (TSoundLoader)
public
- function Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean; override; overload;
- function Load(FName: string; SStreaming: Boolean): Boolean; override; overload;
- function SetPosition(Pos: LongWord): Boolean; override;
+ function Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean; override; overload;
+ function Load(FName: string; Loop: Boolean): Boolean; override; overload;
+ function Finished(): Boolean; override;
+ function Restart(): Boolean; override;
function FillBuffer(Buf: Pointer; Len: LongWord): LongWord; override;
- function GetAll(var OutPtr: Pointer): LongWord; override;
procedure Free(); override;
private
FXMP: xmp_context;
FLoaded: Boolean;
+ FLooping: Boolean;
+ FFinished: Boolean;
end;
TXMPLoaderFactory = class (TSoundLoaderFactory)
implementation
-uses sysutils, utils, e_sound, e_log;
+uses sysutils, utils, math, e_sound, e_log;
(* TXMPLoaderFactory *)
(* TXMPLoader *)
-function TXMPLoader.Load(Data: Pointer; Len: LongWord; SStreaming: Boolean): Boolean;
+function TXMPLoader.Load(Data: Pointer; Len: LongWord; Loop: Boolean): Boolean;
var
Err: LongInt;
Interp: LongInt;
FStreaming := True; // modules are always streaming
FLoaded := True;
+ FLooping := Loop;
+ FFinished := False;
Result := True;
except
on E: Exception do
end;
end;
-function TXMPLoader.Load(FName: string; SStreaming: Boolean): Boolean;
+function TXMPLoader.Load(FName: string; Loop: Boolean): Boolean;
var
Err: LongInt;
Interp: LongInt;
FFormat.Channels := 2;
FStreaming := True; // modules are always streaming
+ FLooping := Loop;
FLoaded := True;
+ FFinished := False;
Result := True;
except
on E: Exception do
end;
end;
-function TXMPLoader.SetPosition(Pos: LongWord): Boolean;
+function TXMPLoader.Finished(): Boolean;
+begin
+ Result := FFinished;
+end;
+
+function TXMPLoader.Restart(): Boolean;
begin
Result := False;
if FXMP = nil then Exit;
- Result := xmp_set_position(FXMP, Pos) = 0;
+ Result := True;
+ FFinished := False;
+ xmp_restart_module(FXMP);
end;
function TXMPLoader.FillBuffer(Buf: Pointer; Len: LongWord): LongWord;
var
- LoopN: LongInt;
+ Ret: LongInt;
begin
Result := 0;
if FXMP = nil then Exit;
- if FLooping then
- LoopN := 0
- else
- LoopN := 1;
- if xmp_play_buffer(FXMP, Buf, Len, LoopN) = 0 then
- Result := Len;
-end;
-function TXMPLoader.GetAll(var OutPtr: Pointer): LongWord;
-begin
- Result := 0; // modules are always streaming, so this don't make sense
+ Ret := xmp_play_buffer(FXMP, Buf, Len, IfThen(FLooping, 0, 1));
+
+ if Ret = 0 then
+ Result := Len
+ else if (Ret = -XMP_END) and not FLooping then
+ FFinished := True;
end;
procedure TXMPLoader.Free();
FXMP := nil;
end;
FLoaded := False;
+ FLooping := False;
+ FFinished := False;
end;
initialization
index 6a8c34f3fff4ee44b2a005c00c3862fd9d1d95e3..de042062d862fd800ab108374457738931a52d9d 100644 (file)
const
FLUID_OK = 0;
FLUID_FAILED = -1;
+ FLUID_PLAYER_DONE = 2;
type
pfluid_settings_t = pointer;
function delete_fluid_synth(synth: pfluid_synth_t): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
function fluid_synth_get_settings(synth: pfluid_synth_t): pfluid_settings_t; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
function fluid_synth_sfload(synth: pfluid_synth_t; fname: pchar; reset: cint): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
+function fluid_synth_system_reset(synth: pfluid_synth_t): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};
function fluid_synth_write_s16(synth: pfluid_synth_t; len: cint; lout: pointer; loff, linc: cint; rout: pointer; roff, rinc: cint): cint; cdecl; external {$IFDEF FS_DYNAMIC}fluidlib{$ENDIF};