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:
sekelsenmat
2012-01-23 10:43:32 +00:00
parent ba32690bfa
commit 95a37b7c82
6 changed files with 154 additions and 77 deletions

View File

@ -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'

View File

@ -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.

View File

@ -68,9 +68,6 @@
</Options>
</Linking>
<Other>
<CompilerMessages>
<MsgFileName Value=""/>
</CompilerMessages>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>

View File

@ -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

View File

@ -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.

View File

@ -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;