You've already forked lazarus-ccr
fpsound: Starts adjusting the openal code
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2261 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -6,6 +6,7 @@ object Form1: TForm1
|
||||
Caption = 'Form1'
|
||||
ClientHeight = 240
|
||||
ClientWidth = 320
|
||||
OnCreate = FormCreate
|
||||
LCLVersion = '0.9.31'
|
||||
object btnOpenPlayAndClose: TButton
|
||||
Left = 12
|
||||
@ -18,7 +19,7 @@ object Form1: TForm1
|
||||
end
|
||||
object pathEdit: TFileNameEdit
|
||||
Left = 12
|
||||
Height = 25
|
||||
Height = 21
|
||||
Top = 13
|
||||
Width = 268
|
||||
FileName = '/home/felipe/Programas/lazarus-ccr/components/fpsound/testsounds/test.wav'
|
||||
|
@ -16,6 +16,7 @@ type
|
||||
btnOpenPlayAndClose: TButton;
|
||||
pathEdit: TFileNameEdit;
|
||||
procedure btnOpenPlayAndCloseClick(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
private
|
||||
{ private declarations }
|
||||
public
|
||||
@ -39,7 +40,16 @@ var
|
||||
begin
|
||||
lSoundDoc := TSoundDocument.Create;
|
||||
lSoundDoc.LoadFromFile(pathEdit.FileName);
|
||||
lSoundDoc.Free;
|
||||
lSoundDoc.SetSoundPlayer(spOpenAL);
|
||||
lSoundDoc.Play;
|
||||
end;
|
||||
|
||||
procedure TForm1.FormCreate(Sender: TObject);
|
||||
begin
|
||||
{$ifdef Windows}
|
||||
pathEdit.FileName := ExtractFilePath(Application.ExeName) + '..\testsounds\test.wav';
|
||||
pathEdit.FileName := SysUtils.ExpandFileName(pathEdit.FileName);
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -68,9 +68,6 @@
|
||||
</Options>
|
||||
</Linking>
|
||||
<Other>
|
||||
<CompilerMessages>
|
||||
<MsgFileName Value=""/>
|
||||
</CompilerMessages>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
|
@ -35,7 +35,11 @@ type
|
||||
TSoundPlayer = class
|
||||
public
|
||||
constructor Create; virtual;
|
||||
procedure Initialize; virtual; abstract;
|
||||
procedure Finalize; virtual; abstract;
|
||||
procedure Play(ASound: TSoundDocument); virtual; abstract;
|
||||
procedure Pause(ASound: TSoundDocument); virtual; abstract;
|
||||
procedure Stop(ASound: TSoundDocument); virtual; abstract;
|
||||
end;
|
||||
|
||||
// Sound data representation
|
||||
@ -46,12 +50,22 @@ type
|
||||
// A Key element sets the basic information of the music for the following samples,
|
||||
// such as sample rate. It has no sample data in itself
|
||||
TSoundKeyElement = class(TSoundElement)
|
||||
public
|
||||
SampleRate: Cardinal; // example values: 8000, 44100, etc.
|
||||
BitsPerSample: Byte; // Tipical values: 8 and 16
|
||||
Channels: Byte; // Number of channels
|
||||
end;
|
||||
|
||||
TSoundSample = class(TSoundElement)
|
||||
ChannelValues: array of Integer;
|
||||
public
|
||||
ChannelValues: array of SmallInt;
|
||||
end;
|
||||
|
||||
{ TSoundThread }
|
||||
|
||||
TSoundThread = class(TThread)
|
||||
protected
|
||||
procedure Execute; override;
|
||||
end;
|
||||
|
||||
{ TSoundDocument }
|
||||
@ -60,6 +74,7 @@ type
|
||||
private
|
||||
AStream: TStream;
|
||||
FPlayer: TSoundPlayer;
|
||||
FCurElementIndex: Integer;
|
||||
FSoundData: TFPList; // of TSoundElement
|
||||
public
|
||||
constructor Create; virtual;
|
||||
@ -71,9 +86,14 @@ type
|
||||
// Document edition methods
|
||||
procedure Clear;
|
||||
procedure AddSoundElement(const AElement: TSoundElement);
|
||||
function GetSoundElement(const AIndex: Integer): TSoundElement;
|
||||
function GetSoundElementCount: Integer;
|
||||
function GetFirstSoundElement: TSoundKeyElement;
|
||||
function GetNextSoundElement: TSoundElement;
|
||||
// Document playing methods
|
||||
procedure Play;
|
||||
procedure Pause;
|
||||
procedure Stop;
|
||||
procedure Seek(ANewPos: Double);
|
||||
procedure SetSoundPlayer(AKind: TSoundPlayerKind);
|
||||
end;
|
||||
@ -110,6 +130,13 @@ begin
|
||||
Result := GSoundReaders[AFormat];
|
||||
end;
|
||||
|
||||
{ TSoundThread }
|
||||
|
||||
procedure TSoundThread.Execute;
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
{ TSoundPlayer }
|
||||
|
||||
constructor TSoundPlayer.Create;
|
||||
@ -187,24 +214,61 @@ begin
|
||||
FSoundData.Add(AElement);
|
||||
end;
|
||||
|
||||
function TSoundDocument.GetSoundElement(const AIndex: Integer): TSoundElement;
|
||||
begin
|
||||
Result := TSoundElement(FSoundData.Items[AIndex]);
|
||||
end;
|
||||
|
||||
function TSoundDocument.GetSoundElementCount: Integer;
|
||||
begin
|
||||
Result := FSoundData.Count;
|
||||
end;
|
||||
|
||||
function TSoundDocument.GetFirstSoundElement: TSoundKeyElement;
|
||||
begin
|
||||
if GetSoundElementCount() = 0 then
|
||||
Result := nil
|
||||
else
|
||||
Result := GetSoundElement(0) as TSoundKeyElement;
|
||||
FCurElementIndex := 1;
|
||||
end;
|
||||
|
||||
function TSoundDocument.GetNextSoundElement: TSoundElement;
|
||||
begin
|
||||
if GetSoundElementCount() >= FCurElementIndex then Exit(nil);
|
||||
Result := GetSoundElement(FCurElementIndex);
|
||||
Inc(FCurElementIndex);
|
||||
end;
|
||||
|
||||
procedure TSoundDocument.Play;
|
||||
begin
|
||||
|
||||
if FPlayer = nil then Exit;
|
||||
FPlayer.Play(Self);
|
||||
end;
|
||||
|
||||
procedure TSoundDocument.Pause;
|
||||
begin
|
||||
if FPlayer = nil then Exit;
|
||||
FPlayer.Pause(Self);
|
||||
end;
|
||||
|
||||
procedure TSoundDocument.Stop;
|
||||
begin
|
||||
if FPlayer = nil then Exit;
|
||||
FPlayer.Stop(Self);
|
||||
FPlayer.Finalize;
|
||||
end;
|
||||
|
||||
procedure TSoundDocument.Seek(ANewPos: Double);
|
||||
begin
|
||||
if FPlayer = nil then Exit;
|
||||
|
||||
end;
|
||||
|
||||
procedure TSoundDocument.SetSoundPlayer(AKind: TSoundPlayerKind);
|
||||
begin
|
||||
|
||||
Stop;
|
||||
FPlayer := GSoundPlayers[AKind];
|
||||
end;
|
||||
|
||||
var
|
||||
|
@ -20,6 +20,9 @@ var
|
||||
al_context : PALCcontext;
|
||||
|
||||
type
|
||||
|
||||
{ TOpenALPlayer }
|
||||
|
||||
TOpenALPlayer = class(TSoundPlayer)
|
||||
private
|
||||
{ buffer : Cardinal;
|
||||
@ -43,13 +46,14 @@ type
|
||||
al_rate : Longword;
|
||||
wave : TWaveReader;
|
||||
public
|
||||
procedure Initialize; override;
|
||||
procedure Finalize; override;
|
||||
procedure Play(ASound: TSoundDocument); override;
|
||||
procedure AdjustToKeyElement(AElement: TSoundKeyElement);
|
||||
//procedure OPCSoundPlayStreamEx(AStream: TStream);
|
||||
procedure OPCSoundOpenALPlay();
|
||||
procedure OPCSoundOpenALLoadWavFromStream(AStream: TStream);
|
||||
procedure OPCSoundOpenALInitialize();
|
||||
procedure OPCSoundOpenALFinalize();
|
||||
procedure alStop;
|
||||
function alProcess: Boolean;
|
||||
procedure alFillBuffer(ASound: TSoundDocument; AKeyElement: TSoundKeyElement);
|
||||
end;
|
||||
|
||||
|
||||
@ -314,22 +318,71 @@ begin
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
procedure TOpenALPlayer.OPCSoundOpenALPlay();
|
||||
procedure TOpenALPlayer.alFillBuffer(ASound: TSoundDocument; AKeyElement: TSoundKeyElement);
|
||||
var
|
||||
lCurSample: TSoundSample;
|
||||
lReadCount: Integer = 0;
|
||||
begin
|
||||
while lReadCount < al_bufsize do
|
||||
begin
|
||||
lCurSample := ASound.GetNextSoundElement() as TSoundSample;
|
||||
if lCurSample = nil then Exit;
|
||||
|
||||
lReadCount := lReadCount + AKeyElement.BitsPerSample div 8;
|
||||
|
||||
if AKeyElement.BitsPerSample = 8 then
|
||||
PByte(al_readbuf)[lReadCount] := Lo(lCurSample.ChannelValues[0])
|
||||
else
|
||||
PWord(al_readbuf)[lReadCount div 2] := Word(lCurSample.ChannelValues[0])
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TOpenALPlayer.Initialize;
|
||||
begin
|
||||
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
|
||||
alGenSources(1, @al_source);
|
||||
alGenBuffers(al_bufcount, @al_buffers);
|
||||
|
||||
GetMem(al_readbuf, al_bufsize);
|
||||
end;
|
||||
|
||||
procedure TOpenALPlayer.Finalize;
|
||||
begin
|
||||
// finalize openal
|
||||
alDeleteSources(1, @al_source);
|
||||
alDeleteBuffers(al_bufcount, @al_buffers);
|
||||
FreeMem(al_readbuf);
|
||||
|
||||
// wave.fStream := nil;
|
||||
// source := nil;
|
||||
|
||||
// finalize codec
|
||||
wave.Free;
|
||||
|
||||
// close file
|
||||
// source.Free;
|
||||
end;
|
||||
|
||||
procedure TOpenALPlayer.Play(ASound: TSoundDocument);
|
||||
var
|
||||
i: Integer;
|
||||
queued : Integer;
|
||||
done : Boolean;
|
||||
lKeyElement: TSoundKeyElement;
|
||||
begin
|
||||
if not OPCSoundStreamIsLoaded then Exit;
|
||||
// First adjust to the first key element
|
||||
lKeyElement := ASound.GetFirstSoundElement();
|
||||
AdjustToKeyElement(lKeyElement);
|
||||
|
||||
// Now clean up the source
|
||||
alSourceStop(al_source);
|
||||
alSourceRewind(al_source);
|
||||
alSourcei(al_source, AL_BUFFER, 0);
|
||||
|
||||
for i := 0 to al_bufcount - 1 do
|
||||
begin
|
||||
//f/ if wave.ReadBuf(al_readbuf^, al_bufsize) = 0 then
|
||||
Break;
|
||||
// Fill the buffer
|
||||
AlFillBuffer(ASound, lKeyElement);
|
||||
|
||||
alBufferData(al_buffers[i], al_format, al_readbuf, al_bufsize, al_rate);
|
||||
alSourceQueueBuffers(al_source, 1, @al_buffers[i]);
|
||||
@ -350,45 +403,26 @@ begin
|
||||
until done;
|
||||
end;
|
||||
|
||||
procedure TOpenALPlayer.OPCSoundOpenALLoadWavFromStream(AStream: TStream);
|
||||
var
|
||||
Filename: String;
|
||||
queued : Integer;
|
||||
done : Boolean;
|
||||
procedure TOpenALPlayer.AdjustToKeyElement(AElement: TSoundKeyElement);
|
||||
begin
|
||||
if AStream = nil then
|
||||
begin
|
||||
OPCSoundStreamIsLoaded := False;
|
||||
Exit;
|
||||
end
|
||||
else
|
||||
OPCSoundStreamIsLoaded := True;
|
||||
|
||||
FreeAndNil(source);
|
||||
// define codec
|
||||
source := AStream;
|
||||
//source := AStream;
|
||||
|
||||
// inittialize codec
|
||||
wave:=TWaveReader.Create;
|
||||
//f/ if not wave.LoadFromStream(source) then
|
||||
raise Exception.Create('[OPCSoundLoadWavFromStream] unable to read WAVE format');
|
||||
|
||||
if wave.fmt.Format<>1 then
|
||||
raise Exception.Create('[OPCSoundLoadWavFromStream] WAVE files with compression aren''t supported');
|
||||
|
||||
if wave.fmt.Channels=2 then begin
|
||||
if wave.fmt.BitsPerSample=8 then al_format:=AL_FORMAT_STEREO8
|
||||
else al_format:=AL_FORMAT_STEREO16
|
||||
end else begin
|
||||
if wave.fmt.BitsPerSample=8 then al_format:=AL_FORMAT_MONO8
|
||||
if AElement.Channels = 1 then
|
||||
begin
|
||||
if AElement.BitsPerSample=8 then al_format:=AL_FORMAT_MONO8
|
||||
else al_format:=AL_FORMAT_MONO16
|
||||
end
|
||||
else
|
||||
begin
|
||||
if AElement.BitsPerSample=8 then al_format := AL_FORMAT_STEREO8
|
||||
else al_format:=AL_FORMAT_STEREO16
|
||||
end;
|
||||
|
||||
codec_bs:=2*wave.fmt.Channels;
|
||||
|
||||
//al_bufsize := 20000 - (20000 mod codec_bs);
|
||||
codec_bs:=2*AElement.Channels;
|
||||
al_bufsize := 20000 - (20000 mod codec_bs);
|
||||
al_rate:=wave.fmt.SampleRate;
|
||||
al_rate:=AElement.SampleRate;
|
||||
// WriteLn('Blocksize : ', codec_bs);
|
||||
// WriteLn('Rate : ', wave.fmt.SampleRate);
|
||||
// WriteLn('Channels : ', wave.fmt.Channels);
|
||||
@ -398,35 +432,5 @@ begin
|
||||
alProcess();
|
||||
end;
|
||||
|
||||
procedure TOpenALPlayer.OPCSoundOpenALInitialize();
|
||||
begin
|
||||
OPCSoundWasInitialized := True;
|
||||
|
||||
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
|
||||
alGenSources(1, @al_source);
|
||||
alGenBuffers(al_bufcount, @al_buffers);
|
||||
|
||||
GetMem(al_readbuf, al_bufsize);
|
||||
end;
|
||||
|
||||
procedure TOpenALPlayer.OPCSoundOpenALFinalize();
|
||||
begin
|
||||
// finalize openal
|
||||
alDeleteSources(1, @al_source);
|
||||
alDeleteBuffers(al_bufcount, @al_buffers);
|
||||
FreeMem(al_readbuf);
|
||||
|
||||
// wave.fStream := nil;
|
||||
// source := nil;
|
||||
|
||||
// finalize codec
|
||||
wave.Free;
|
||||
|
||||
// close file
|
||||
// source.Free;
|
||||
end;
|
||||
|
||||
finalization
|
||||
//if OPCSoundWasInitialized then OPCSoundOpenALFinalize();
|
||||
end.
|
||||
|
||||
|
@ -118,6 +118,7 @@ begin
|
||||
// Store the data in the document
|
||||
lKeyElement := TSoundKeyElement.Create;
|
||||
lKeyElement.SampleRate := fmt.SampleRate;
|
||||
lKeyElement.BitsPerSample := fmt.BitsPerSample;
|
||||
lKeyElement.Channels := fmt.Channels;
|
||||
ADest.AddSoundElement(lKeyElement);
|
||||
end;
|
||||
|
Reference in New Issue
Block a user