code_glitch
21-11-2010, 04:08 PM
In my quest for Prometheus_Audio I came across a small nuisance in how OpenAl works... Or rather common sense: I have to update buffers at least once every second at least.
Prometheus is aimed at beginners, and I must say I'm not sure I want to tell them that if they want audio you have to call the update procedure at least once a second, depending on the bit rate of you audio file.
My solution was to have Prometheus make a thread that would only run that loop. 8)
However, I did poke around for multi-threading and drew one major conclusion: headache. Anyways, always the optimist I thought it was easier than it looked and gave it a go. And guess what: I gots a headache too now...
My question is: does anyone have a snippet that launches a thread that simply steps through a loop non-stop and how to get it working? ???
Any help would be much appreciated; I'm totally confused d now...
cheers,
code_glitch
code_glitch
21-11-2010, 05:07 PM
Just another thing: I just finished this new version of Prometheus_Audio in OpenAl but no matter what I try I only get segmentation faults, exit codes and no sound:
unit Prometheus_Audio;
{$Mode ObjFpc}
interface
uses
sysutils,
Classes,
OpenAl;
const
ID_RIFF = 'RIFF';
ID_WAVE = 'WAVE';
ID_fmt = 'fmt ';
ID_data = 'data';
al_bufcount = 100;
al_polltime = 1000;
BufferSize = 8192;
MAX_AUDIOSTREAMS: Int64 = 600;
type
TAlData = record
Al_Device: PALCdevice;
Al_Context: PALCcontext;
Al_Source: ALuint;
Al_Format: Integer;
Al_Buffers: array[0..al_bufcount-1] of ALuint;
Al_Bufsize: Longword;
Al_Readbuf: Pointer;
Al_Rate: Longword;
Codec_bs: Longword;
Queued: Integer;
end;
TRiffHeader = record
ID: array [0..3] of char;
Size: Longword;
Format: array [0..3] of char;
end;
TDataChunk = record
Id: array [0..3] of char;
Size: Longword;
end;
TWaveFormat = record
Id: array [0..3] of char;
Size: Longword;
Format: Word;
Channels: Word;
SampleRate: Longword;
ByteRate: Longword;
BlockAlign: Word;
BitsPerSample: Word;
end;
Audio = object
Initialized: Boolean;
Loaded: Boolean;
ChunkData: TDataChunk;
ChunkPos: Int64;
Pos: Int64;
EOF: Boolean;
fStream: TStream;
Result: Boolean;
Fmt: TWaveFormat;
AlData: TAlData;
function ReadBuf(var Buffer; BufferSize: Integer): Integer;
procedure Initialize();
end;
pAudio = ^Audio;
PrometheusAudioRec = record
AudioStream: array [1..600] of pAudio;
ActiveStream: array [1..600] of Boolean;
TotalStreams: Int64;
end;
var
PrometheusAudio: PrometheusAudioRec;
procedure LoadAudio(Src: String; Audio: pAudio);
procedure PlayAudio(Audio: pAudio);
procedure AudioProcess();
implementation
function AudioExists(Audio: pAudio): Boolean;
var
i: Int64;
begin
i := 0;
repeat
i := i + 1;
until (i >= MAX_AUDIOSTREAMS) or (@PrometheusAudio.AudioStream[i] = @Audio);
if (i >= MAX_AUDIOSTREAMS) and (@PrometheusAudio.AudioStream[i] <> @Audio) then
AudioExists := False
else
AudioExists := True;
end;
function Min(a,b: Integer): Integer;
begin
if a<b then Result:=a
else Result:=b;
end;
procedure Audio.Initialize();
begin
AlData.Al_Bufsize := BufferSize;
AlData.Al_Format := AL_FORMAT_STEREO16;
AlData.Codec_bs := 2;
AlData.Al_Device := alcOpenDevice(nil);
AlData.Al_Context := alcCreateContext(AlData.Al_Device, nil);
alcMakeContextCurrent(AlData.Al_Context);
AlData.Al_Rate := 44100;
AlDistanceModel( Al_Inverse_Distance_Clamped);
AlGenSources(1, @AlData.Al_Source);
AlGenBuffers(al_bufcount, @AlData.Al_Buffers);
GetMem(AlData.Al_Readbuf, AlData.Al_Bufsize);
Initialized := True;
end;
function Audio.ReadBuf(var Buffer; BufferSize: Integer): Integer;
var
Sz: Integer;
P: PByteArray;
I: Integer;
begin
if Initialized = False then
Initialize();
FillChar(Buffer, BufferSize, 0);
Result := 0;
if eof then Exit;
p := @Buffer;
I := 0;
while (not EOF) and (i < BufferSize) do
begin
if ChunkPos >= ChunkData.Size then
begin
if Pos < 0 then
fStream.Position := SizeOf(TRiffHeader) + Int64(Fmt.Size) + SizeOf(TDataChunk)
else
fStream.Position := Pos + ChunkData.Size + SizeOf(ChunkData);
EOF := pos >= fStream.Size;
if not EOF then
begin
Pos := fStream.Position;
Sz := fStream.Read(ChunkData, SizeOf(ChunkData));
ChunkData.Size := LEtoN(ChunkData.Size);
if (Sz <> SizeOf(ChunkData)) or (ChunkData.Id <> ID_data) then
ChunkPos := ChunkData.Size
else
ChunkPos := 0;
end;
end
else
begin
Sz := Min(BufferSize, ChunkData.Size - ChunkPos);
fStream.Position := Pos + SizeOf(ChunkData) + ChunkPos;
Sz := fStream.Read(P[I], Sz);
if Sz < 0 then
exit;
inc(ChunkPos, Sz);
inc(I, Sz);
end;
end;
end;
procedure LoadAudio(Src: String; Audio: pAudio);
var
Riff: TRiffHeader;
begin
if Audio^.Initialized = False then
Audio^.Initialize;
Audio^.fStream := TFileStream.Create(Src, fmOpenRead);
Audio^.Loaded := True;
try
Audio^.Result := Audio^.fStream.Read(Riff, SizeOf(Riff)) = SizeOf(Riff);
Riff.Size := LEtoN(Riff.Size);
Audio^.Result := Audio^.Result and (Riff.ID = ID_RIFF) and (Riff.Format = ID_WAVE);
if not Audio^.Result then
Exit;
Audio^.Result := Audio^.fStream.Read(Audio^.Fmt, SizeOf(Audio^.Fmt)) = SizeOf(Audio^.Fmt);
Audio^.Fmt.Size := LEtoN(Audio^.Fmt.Size);
Audio^.Fmt.Format := LEtoN(Audio^.Fmt.Format);
Audio^.Fmt.Channels := LEtoN(Audio^.Fmt.Channels);
Audio^.Fmt.SampleRate := LEtoN(Audio^.Fmt.SampleRate);
Audio^.Fmt.ByteRate := LEtoN(Audio^.Fmt.ByteRate);
Audio^.Fmt.BlockAlign := LEtoN(Audio^.Fmt.BlockAlign);
Audio^.Fmt.BitsPerSample := LEtoN(Audio^.Fmt.BitsPerSample);
Audio^.Result := Audio^.Fmt.ID = ID_FMT;
Audio^.Pos := -1;
except
Audio^.Result := False;
Exit;
end;
if AudioExists(Audio) = False then
begin
PrometheusAudio.ActiveStream[PrometheusAudio.TotalStreams + 1] := True;
PrometheusAudio.AudioStream[PrometheusAudio.TotalStreams + 1] := Audio;
PrometheusAudio.TotalStreams := PrometheusAudio.TotalStreams + 1;
end;
end;
procedure PlayAudio(Audio: pAudio);
var
i: Int64;
begin
alSourceStop(Audio^.AlData.Al_Source);
alSourceRewind(Audio^.AlData.Al_Source);
alSourcei(Audio^.AlData.Al_Source, Al_Buffer, 0);
for i := 0 to al_bufcount - 1 do
begin
if Audio^.ReadBuf(Audio^.AlData.Al_Readbuf^, Audio^.AlData.Al_Bufsize) = 0 then
break;
alBufferData(Audio^.AlData.Al_Buffers[i], Audio^.AlData.Al_Format, Audio^.AlData.Al_Readbuf, Audio^.AlData.Al_BufSize, Audio^.AlData.Al_Rate);
alSourceQueueBuffers(Audio^.AlData.Al_Source, 1, @Audio^.AlData.Al_Buffers[i]);
end;
alSourcei(Audio^.AlData.Al_Source, Al_Looping, AL_False);
alSourcePlay(Audio^.AlData.Al_Source);
end;
function AlSubProcess(Audio: pAudio): Boolean;
var
Processed: ALint;
Buffer: ALuint;
Sz: Integer;
begin
alGetSourcei(Audio^.AlData.Al_Source, Al_Buffers_Processed, Processed);
while (processed > 0) and (processed <= al_bufcount) do
begin
alSourceUnqueueBuffers(Audio^.AlData.Al_Source, 1, @Buffer);
Sz := Audio^.ReadBuf(Audio^.AlData.Al_Readbuf, Audio^.AlData.Al_Bufsize);
if Sz <= 0 then
begin
Exit(False);
end;
alBufferData(Buffer, Audio^.AlData.Al_Format, Audio^.AlData.Al_Readbuf, Sz, Audio^.AlData.Al_Rate);
alSourceQueueBuffers(Audio^.AlData.Al_Source, 1, @Buffer);
Dec(Processed);
end;
Result := True;
end;
procedure AudioProcess();
var
i: Int64;
begin
i := 0;
repeat
i := i + 1;
if PrometheusAudio.ActiveStream[i] = True then
alSubProcess(PrometheusAudio.AudioStream[i]);
until i >= MAX_AUDIOSTREAMS;
end;
end.
can any of you OpenAl savvy people see what's gone wrong in this? I suspect PlayAudio, LoadAudio and Audio.Initialize but cant see any errors... Sorry for the long code, but I trimmed it down as much as I could. Cheers for any help.
JSoftware
21-11-2010, 06:34 PM
Sure. Here's a snippet using TThread
type
TSomeThreadClass = class(TThread)
protected
procedure Execute; override;
end;
procedure TSomeThreadClass.Execute;
begin
//Initialize Stuff
while not Terminated do
begin
//Do something
//You may want to put a sleep(10) or something depending on how long time the task takes
end;
//Clean up stuff
end;
...
var SoundThread: TSomeThreadClass;
begin
SoundThread := TSomeThreadClass.Create(false); //Create the thread, s
...
SoundThread.Terminate; //Tell thread to stop
SoundThread.WaitFor; //Wait until thread exits
SoundThread.Free;
end;
code_glitch
21-11-2010, 07:02 PM
cheers for that. Will start experimenting ASAP.
arthurprs
22-11-2010, 02:45 PM
I had similar problems when I was coding http://www.1clickmusic.net on the past, but with DirectSound. Your solution is the right one :)
code_glitch
22-11-2010, 05:40 PM
Any thoughts on whats causing the audio screwup I posted about earlier? I posted it in this thread to avoid clutter since they were a bit related...
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions Inc. All rights reserved.