index 340aa920725f1cd69dca7054f4f70acd3c152eb2..153cad427f4f1b58c94f60977644c9dedeb882ec 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)
uses
{$IFDEF USE_SDL}
- SDL,
+ SDL, cmem,
{$ELSE}
SDL2,
{$ENDIF}
end;
(* TWAVLoader *)
-function FixSoundEndian (Buf: PUInt8; Len: UInt32; format: UInt16; rate: cint; chan: UInt8): Boolean;
- const
- {$IFDEF FPC_LITTLE_ENDIAN}
- TARGET_AUDIO_S16 = AUDIO_S16LSB;
- TARGET_AUDIO_U16 = AUDIO_U16LSB;
- {$ELSE}
- TARGET_AUDIO_S16 = AUDIO_S16MSB;
- TARGET_AUDIO_U16 = AUDIO_U16MSB;
- {$ENDIF}
+function ConvertSound (var buf: PUInt8; var len: UInt32; var format: UInt16; rate: cint; chan: UInt8): Boolean;
var cvt: TSDL_AudioCVT; tformat: UInt16;
begin
+ result := true;
case format of
- AUDIO_U16LSB, AUDIO_U16MSB: tformat := TARGET_AUDIO_U16;
- AUDIO_S16LSB, AUDIO_S16MSB: tformat := TARGET_AUDIO_S16;
- else tformat := format
+ AUDIO_U8, AUDIO_S8 : tformat := AUDIO_U8; (* yes, unsigned *)
+ AUDIO_U16LSB, AUDIO_U16MSB: tformat := AUDIO_S16SYS; (* and yes, signed *)
+ AUDIO_S16LSB, AUDIO_S16MSB: tformat := AUDIO_S16SYS;
+ {$IFDEF USE_SDL2}
+ AUDIO_S32LSB, AUDIO_S32MSB: tformat := AUDIO_S16SYS; (* 32bit not supported in al core *)
+ AUDIO_F32LSB, AUDIO_F32MSB: tformat := AUDIO_S16SYS; (* float not supported in al core *)
+ {$ENDIF}
+ else result := false (* unsupported format *)
end;
- Result := True;
- if format <> tformat then
+ if (result = true) and (format <> tformat) then
begin
Result := False;
if SDL_BuildAudioCVT(@cvt, format, chan, rate, tformat, chan, rate) <> -1 then
begin
- cvt.buf := Buf;
- cvt.len := Len;
- assert(cvt.len_mult = 1);
- Result := SDL_ConvertAudio(@cvt) = 0;
- assert(cvt.len_ratio = 1);
- assert(cvt.len = Len)
+ {$IFDEF USE_SDL2}
+ buf := SDL_realloc(buf, len * cvt.len_mult);
+ {$ELSE}
+ buf := realloc(buf, len * cvt.len_mult);
+ {$ENDIF}
+ cvt.len := len;
+ cvt.buf := buf;
+ result := SDL_ConvertAudio(@cvt) = 0;
+ len := cvt.len_cvt;
+ format := tformat
end
end
end;
if SDL_LoadWAV_RW(RW, 0, @Spec, PUInt8(@Buf), @Len) <> nil then
{$ENDIF}
begin
- Result := FixSoundEndian(Buf, Len, Spec.format, Spec.freq, Spec.channels);
+ Result := ConvertSound(Buf, Len, Spec.format, Spec.freq, Spec.channels);
if Result = True then
begin
with Loader do
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