DEADSOFTWARE

Sound: Initial OpenAL driver impl
authorfgsfds <pvt.fgsfds@gmail.com>
Sat, 31 Aug 2019 01:29:57 +0000 (04:29 +0300)
committerfgsfds <pvt.fgsfds@gmail.com>
Sat, 31 Aug 2019 01:30:04 +0000 (04:30 +0300)
src/engine/e_sound.pas
src/engine/e_sound_al.inc [new file with mode: 0644]
src/engine/e_soundfile.pas [new file with mode: 0644]
src/engine/e_soundfile_wav.pas [new file with mode: 0644]
src/game/Doom2DF.lpr
src/lib/openal/al.inc [new file with mode: 0644]
src/lib/openal/al.pas [new file with mode: 0644]
src/lib/openal/alc.inc [new file with mode: 0644]
src/lib/openal/alext.inc [new file with mode: 0644]
src/lib/openal/efx.inc [new file with mode: 0644]

index ebec200a21330dcd488ad3c0e985274ae47af94f..d689dfeca5e66feae9dd7e9755760aa1693e24c8 100644 (file)
@@ -19,5 +19,9 @@ unit e_sound;
 {$IFDEF USE_SDLMIXER}
   {$I e_sound_sdl.inc}
 {$ELSE}
-  {$I e_sound_fmod.inc}
+  {$IFDEF USE_OPENAL}
+    {$I e_sound_al.inc}
+  {$ELSE}
+    {$I e_sound_fmod.inc}
+  {$ENDIF}
 {$ENDIF}
diff --git a/src/engine/e_sound_al.inc b/src/engine/e_sound_al.inc
new file mode 100644 (file)
index 0000000..d570129
--- /dev/null
@@ -0,0 +1,758 @@
+(* Copyright (C)  Doom 2D: Forever Developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *)
+interface
+
+uses
+  AL,
+  {$IFDEF USE_MEMPOOL}mempool,{$ENDIF}
+  e_soundfile,
+  e_log,
+  SysUtils;
+
+type
+  TSoundRec = record
+    Fmt: TSoundFormat;
+    Data: Pointer;
+    DataLen: Integer;
+    alBuffer: ALuint;
+    isMusic: Boolean;
+    Loops: Boolean;
+    nRefs: Integer;
+  end;
+
+  TBasicSound = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
+  private
+    FSource: Integer;
+    FOldGain: ALfloat;
+    FMuted: Boolean;
+
+    function InvalidSource(): Boolean; inline;
+
+  protected
+    FID: DWORD;
+    FMusic: Boolean;
+    FPosition: DWORD;
+
+    function RawPlay(Pan: Single; Volume: Single; aPos: DWORD): Boolean;
+
+  public
+    constructor Create();
+    destructor Destroy(); override;
+    procedure SetID(ID: DWORD);
+    procedure FreeSound();
+    function IsPlaying(): Boolean;
+    procedure Stop();
+    function IsPaused(): Boolean;
+    procedure Pause(Enable: Boolean);
+    function GetVolume(): Single;
+    procedure SetVolume(Volume: Single);
+    function GetPan(): Single;
+    procedure SetPan(Pan: Single);
+    function IsMuted(): Boolean;
+    procedure Mute(Enable: Boolean);
+    function GetPosition(): DWORD;
+    procedure SetPosition(aPos: DWORD);
+    procedure SetPriority(priority: Integer);
+  end;
+
+const
+  NO_SOUND_ID = DWORD(-1);
+
+function e_InitSoundSystem(NoOutput: Boolean = False): Boolean;
+
+function e_LoadSound(FileName: string; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
+function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
+
+function e_PlaySound(ID: DWORD): Integer;
+function e_PlaySoundPan(ID: DWORD; Pan: Single): Integer;
+function e_PlaySoundVolume(ID: DWORD; Volume: Single): Integer;
+function e_PlaySoundPanVolume(ID: DWORD; Pan, Volume: Single): Integer;
+
+procedure e_ModifyChannelsVolumes(SoundMod: Single; setMode: Boolean);
+procedure e_MuteChannels(Enable: Boolean);
+procedure e_StopChannels();
+
+procedure e_DeleteSound(ID: DWORD);
+procedure e_RemoveAllSounds();
+procedure e_ReleaseSoundSystem();
+procedure e_SoundUpdate();
+
+var
+  e_SoundsArray: array of TSoundRec = nil;
+  e_ZeroPosition: array [0..2] of ALfloat;
+  e_ALError: ALenum = 0;
+
+implementation
+
+uses
+  g_window, g_options, utils;
+
+const
+  NUM_SOURCES = 250;
+  MUSIC_SOURCE = 0;
+
+var
+  alDevice: PALCdevice = nil;
+  alContext: PALCcontext = nil;
+  // sources for one-shot sounds
+  // TBasicSounds have a built in source that lives and dies with them
+  alSources: array of ALuint;
+  alOwners: array of TBasicSound;
+  SoundMuted: Boolean = False;
+
+function CheckALError(): Boolean;
+begin
+  e_ALError := alGetError();
+  Result := e_ALError <> AL_NO_ERROR;
+end;
+
+function GetALError(): string;
+begin
+  Result := '';
+  case e_ALError of
+    AL_NO_ERROR:          Result := '';
+    AL_INVALID_NAME:      Result := 'AL_INVALID_NAME';
+    AL_INVALID_ENUM:      Result := 'AL_INVALID_ENUM';
+    AL_INVALID_VALUE:     Result := 'AL_INVALID_VALUE';
+    AL_INVALID_OPERATION: Result := 'AL_INVALID_OPERATION';
+    AL_OUT_OF_MEMORY:     Result := 'AL_OUT_OF_MEMORY';
+    else                  Result := Format('unknown error %x', [e_ALError]);
+  end;
+end;
+
+function e_InitSoundSystem(NoOutput: Boolean = False): Boolean;
+var
+  alExt, alRend, alVendor, alVer: string;
+  DevName: string = '';
+  alAttrs: array [0..4] of ALCint = (
+    ALC_STEREO_SOURCES, 1,
+    ALC_MONO_SOURCES, NUM_SOURCES,
+    0
+  );
+begin
+  Result := False;
+
+  DevName := alcGetString(nil, ALC_DEVICE_SPECIFIER);
+  e_LogWritefln('AL: available devices: %s', [DevName]);
+
+  // TODO: open a dummy device when NoOutput is true or something
+  DevName := alcGetString(nil, ALC_DEFAULT_DEVICE_SPECIFIER);
+  e_LogWritefln('AL: trying to open device %s', [DevName]);
+
+  alDevice := alcOpenDevice(PChar(DevName));
+  if alDevice = nil then
+  begin
+    e_LogWritefln('AL: ERROR: could not open device %s: %s', [DevName, GetALError()]);
+    exit;
+  end;
+
+  alContext := alcCreateContext(alDevice, alAttrs);
+  if alContext = nil then
+  begin
+    e_LogWritefln('AL: ERROR: could not create context: %s', [GetALError()]);
+    alcCloseDevice(alDevice);
+    alDevice := nil;
+    exit;
+  end;
+
+  alcMakeContextCurrent(alContext);
+
+  alVendor := alGetString(AL_VENDOR);
+  alRend := alGetString(AL_RENDERER);
+  alVer := alGetString(AL_VERSION);
+  alExt := alGetString(AL_EXTENSIONS);
+
+  e_LogWriteln('AL INFO:');
+  e_LogWriteln('  Version:  ' + alVer);
+  e_LogWriteln('  Vendor:   ' + alVendor);
+  e_LogWriteln('  Renderer: ' + alRend);
+  e_LogWriteln('  Device:   ' + DevName);
+  e_LogWriteln('  Extensions:');
+  e_LogWriteln('    ' + alExt);
+
+  SetLength(alSources, NUM_SOURCES + 1); // 0 is the music source
+  SetLength(alOwners, NUM_SOURCES + 1);  // to avoid destructive operations on sources
+  ZeroMemory(@alSources[0], sizeof(alSources[0]) * Length(alSources));
+  ZeroMemory(@alOwners[0], sizeof(alOwners[0]) * Length(alOwners));
+
+  alGetError(); // reset the goddamn error state
+  alGenSources(1, @alSources[0]); // generate the music source
+  if CheckALError() then
+    e_LogWriteln('AL: ERROR: alGenSources() for music failed: ' + GetALError());
+
+  Result := True;
+end;
+
+function FindESound(): DWORD;
+var
+  i: Integer;
+
+begin
+  if e_SoundsArray <> nil then
+    for i := 0 to High(e_SoundsArray) do
+      if e_SoundsArray[i].alBuffer = 0 then
+      begin
+        Result := i;
+        Exit;
+      end;
+
+  if e_SoundsArray = nil then
+    begin
+      SetLength(e_SoundsArray, 16);
+      Result := 0;
+    end
+  else
+    begin
+      Result := High(e_SoundsArray) + 1;
+      SetLength(e_SoundsArray, Length(e_SoundsArray) + 16);
+    end;
+end;
+
+function GetALSoundFormat(Fmt: TSoundFormat): ALenum; inline;
+begin
+  if Fmt.Channels = 2 then
+  begin
+    if Fmt.SampleBits = 16 then
+      Result := AL_FORMAT_STEREO16
+    else
+      Result := AL_FORMAT_STEREO8;
+  end
+  else
+  begin
+    if Fmt.SampleBits = 16 then
+      Result := AL_FORMAT_MONO16
+    else
+      Result := AL_FORMAT_MONO8;
+  end;
+end;
+
+function GetALSourceState(S: ALuint): ALint; inline;
+begin
+  alGetSourcei(S, AL_SOURCE_STATE, Result);
+end;
+
+function e_LoadSound(FileName: String; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
+var
+  find_id: DWORD;
+  Loader: TSoundLoader;
+begin
+  ID := NO_SOUND_ID;
+  Result := False;
+
+  find_id := FindESound();
+
+  e_SoundsArray[find_id].Data := nil;
+  e_SoundsArray[find_id].DataLen := 0;
+  e_SoundsArray[find_id].isMusic := isMusic;
+  e_SoundsArray[find_id].Loops := isMusic and not ForceNoLoop;
+  e_SoundsArray[find_id].nRefs := 0;
+
+  Loader := e_GetSoundLoader(FileName);
+  if Loader = nil then
+  begin
+    e_LogWritefln('Could not find loader for sound `%s`', [FileName]);
+    exit;
+  end;
+
+  e_SoundsArray[find_id].Data := Loader.Load(FileName, e_SoundsArray[find_id].DataLen, e_SoundsArray[find_id].Fmt);
+  if e_SoundsArray[find_id].Data = nil then
+  begin
+    e_LogWritefln('Could not load sound `%s`', [FileName]);
+    exit;
+  end;
+
+  alGetError(); // reset error state, god damn it
+
+  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(e_SoundsArray[find_id].Data);
+    exit;
+  end;
+
+  alBufferData(
+    e_SoundsArray[find_id].alBuffer,
+    GetALSoundFormat(e_SoundsArray[find_id].Fmt),
+    e_SoundsArray[find_id].Data,
+    e_SoundsArray[find_id].DataLen,
+    e_SoundsArray[find_id].Fmt.SampleRate
+  );
+
+  // don't need this anymore
+  Loader.Free(e_SoundsArray[find_id].Data);
+  e_SoundsArray[find_id].Data := nil;
+  e_SoundsArray[find_id].DataLen := 0;
+
+  if CheckALError() then
+  begin
+    e_LogWriteln('AL: what the fuck: ' + GetALError());
+    alDeleteBuffers(1, Addr(e_SoundsArray[find_id].alBuffer));
+    exit;
+  end;
+
+  ID := find_id;
+  Result := True;
+end;
+
+function e_LoadSoundMem(pData: Pointer; Length: Integer; var ID: DWORD; isMusic: Boolean; ForceNoLoop: Boolean = False): Boolean;
+var
+  find_id: DWORD;
+  Loader: TSoundLoader;
+begin
+  ID := NO_SOUND_ID;
+  Result := False;
+
+  find_id := FindESound();
+
+  e_SoundsArray[find_id].Data := nil;
+  e_SoundsArray[find_id].DataLen := 0;
+  e_SoundsArray[find_id].isMusic := isMusic;
+  e_SoundsArray[find_id].Loops := isMusic and not ForceNoLoop;
+  e_SoundsArray[find_id].nRefs := 0;
+
+  Loader := e_GetSoundLoader(pData, Length);
+  if Loader = nil then
+  begin
+    e_LogWritefln('Could not find loader for sound `%p`', [pData]);
+    exit;
+  end;
+
+  e_SoundsArray[find_id].Data := Loader.Load(pData, Length, e_SoundsArray[find_id].DataLen, e_SoundsArray[find_id].Fmt);
+  if e_SoundsArray[find_id].Data = nil then
+  begin
+    e_LogWritefln('Could not load sound `%p`', [pData]);
+    exit;
+  end;
+
+  alGetError(); // reset error state, god damn it
+
+  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(e_SoundsArray[find_id].Data);
+    exit;
+  end;
+
+  alBufferData(
+    e_SoundsArray[find_id].alBuffer,
+    GetALSoundFormat(e_SoundsArray[find_id].Fmt),
+    e_SoundsArray[find_id].Data,
+    e_SoundsArray[find_id].DataLen,
+    e_SoundsArray[find_id].Fmt.SampleRate
+  );
+
+  // don't need this anymore
+  Loader.Free(e_SoundsArray[find_id].Data);
+  e_SoundsArray[find_id].Data := nil;
+  e_SoundsArray[find_id].DataLen := 0;
+
+  if CheckALError() then
+  begin
+    e_LogWriteln('AL: what the fuck: ' + GetALError());
+    alDeleteBuffers(1, Addr(e_SoundsArray[find_id].alBuffer));
+    exit;
+  end;
+
+  ID := find_id;
+  Result := True;
+end;
+
+function FindSourceForSound(ID: DWORD): Integer;
+var
+  S: Integer;
+begin
+  Result := -1;
+  if ID > High(e_SoundsArray) then
+    exit;
+
+  if e_SoundsArray[ID].isMusic then
+  begin
+    // last source is for music
+    Result := MUSIC_SOURCE;
+    exit;
+  end;
+
+  for S := 1 to High(alSources) do
+    if alSources[S] = 0 then
+    begin
+      alOwners[S] := nil; // TBasicSounds will set this if needed
+      Result := S;
+      break;
+    end;
+
+  if Result = -1 then Exit; // no voices left
+
+  alGetError(); // reset error state
+  alGenSources(1, @alSources[Result]);
+  if CheckALError() then
+  begin
+    e_LogWriteln('AL: FindSourceForSound(): alGenSources() failed: ' + GetALError());
+    Result := -1;
+  end;
+end;
+
+procedure AssignSound(ID: DWORD; Src: ALuint); inline;
+begin
+  alGetError(); // reset error state
+  alSourcei(Src, AL_BUFFER, e_SoundsArray[ID].alBuffer);
+  alSourcei(Src, AL_SOURCE_RELATIVE, AL_TRUE);
+  if (e_SoundsArray[ID].Loops) then
+    alSourcei(Src, AL_LOOPING, AL_TRUE)
+  else
+    alSourcei(Src, AL_LOOPING, AL_FALSE);
+end;
+
+function e_PlaySound(ID: DWORD): Integer;
+begin
+  Result := FindSourceForSound(ID);
+  if Result >= 0 then
+  begin 
+    AssignSound(ID, alSources[Result]);
+    alSourcef(alSources[Result], AL_GAIN, 1);
+    alSourcefv(alSources[Result], AL_POSITION, e_ZeroPosition);
+    alSourcePlay(alSources[Result]);
+  end;
+end;
+
+function e_PlaySoundPan(ID: DWORD; Pan: Single): Integer;
+var
+  Pos: array [0..2] of ALfloat;
+begin
+  Result := FindSourceForSound(ID);
+  if Result >= 0 then
+  begin
+    Pos[0] := Pan;
+    AssignSound(ID, alSources[Result]);
+    alSourcef(alSources[Result], AL_GAIN, 1);
+    alSourcefv(alSources[Result], AL_POSITION, Pos);
+    alSourcePlay(alSources[Result]);
+  end;
+end;
+
+function e_PlaySoundVolume(ID: DWORD; Volume: Single): Integer;
+begin
+  Result := FindSourceForSound(ID);
+  if Result >= 0 then
+  begin
+    AssignSound(ID, alSources[Result]);
+    alSourcef(alSources[Result], AL_GAIN, Volume);
+    alSourcefv(alSources[Result], AL_POSITION, e_ZeroPosition);
+    alSourcePlay(alSources[Result]);
+  end;
+end;
+
+function e_PlaySoundPanVolume(ID: DWORD; Pan, Volume: Single): Integer;
+var
+  Pos: array [0..2] of ALfloat;
+begin
+  Result := FindSourceForSound(ID);
+  if Result >= 0 then
+  begin
+    Pos[0] := Pan;
+    AssignSound(ID, alSources[Result]);
+    alSourcefv(alSources[Result], AL_POSITION, Pos);
+    alSourcef(alSources[Result], AL_GAIN, Volume);
+    alSourcePlay(alSources[Result]);
+  end;
+end;
+
+procedure e_DeleteSound(ID: DWORD);
+begin
+  if ID > High(e_SoundsArray) then
+    exit;
+  if (e_SoundsArray[ID].alBuffer <> 0) then
+  begin
+    alDeleteBuffers(1, Addr(e_SoundsArray[ID].alBuffer));
+    e_SoundsArray[ID].alBuffer := 0;
+  end;
+  if (e_SoundsArray[ID].Data <> nil) then
+  begin
+    e_SoundsArray[ID].Fmt.Loader.Free(e_SoundsArray[ID].Data);
+    e_SoundsArray[ID].Data := nil;
+    e_SoundsArray[ID].DataLen := 0;
+  end;
+end;
+
+procedure e_ModifyChannelsVolumes(SoundMod: Single; setMode: Boolean);
+var
+  S: Integer;
+  V: ALfloat;
+begin
+  // TODO: replace manual volume calculations everywhere with
+  //       alListenerf(AL_GAIN) or something
+  if setMode then
+  begin
+    for S := 1 to High(alSources) do
+      if alSources[S] <> 0 then
+        alSourcef(alSources[S], AL_GAIN, SoundMod)
+  end
+  else
+  begin
+    for S := 1 to High(alSources) do
+      if alSources[S] <> 0 then
+      begin
+        alGetSourcef(alSources[S], AL_GAIN, V);
+        alSourcef(alSources[S], AL_GAIN, V * SoundMod);
+      end;
+  end;
+end;
+
+procedure e_MuteChannels(Enable: Boolean);
+begin
+  if Enable = SoundMuted then
+    Exit;
+
+  SoundMuted := Enable;
+end;
+
+procedure e_StopChannels();
+var
+  S: Integer;
+begin
+  alGetError(); // reset error state
+  for S := Low(alSources) to High(alSources) do
+    if (alSources[S] <> 0) and (GetALSourceState(alSources[S]) = AL_PLAYING) then
+    begin
+      alSourceStop(alSources[S]);
+      alDeleteSources(1, @alSources[S]);
+      alSources[S] := 0;
+    end;
+end;
+
+procedure e_RemoveAllSounds();
+var
+  i: Integer;
+begin
+  for i := 0 to High(e_SoundsArray) do
+    if e_SoundsArray[i].alBuffer <> 0 then
+      e_DeleteSound(i);
+  SetLength(e_SoundsArray, 0);
+  e_SoundsArray := nil;
+end;
+
+procedure e_ReleaseSoundSystem();
+begin
+  e_RemoveAllSounds();
+
+  alcMakeContextCurrent(nil);
+  alcDestroyContext(alContext);
+  alcCloseDevice(alDevice);
+
+  alDevice := nil;
+  alContext := nil;
+end;
+
+procedure e_SoundUpdate();
+var
+  S: Integer;
+begin
+  alGetError(); // reset error state
+  // clear out all stopped sources
+  for S := 1 to High(alSources) do
+    if (alSources[S] <> 0) and (GetALSourceState(alSources[S]) = AL_STOPPED) then
+    begin
+      alDeleteSources(1, @alSources[S]);
+      alSources[S] := 0;
+      alOwners[S] := nil;
+    end;
+end;
+
+{ TBasicSound: }
+
+constructor TBasicSound.Create();
+begin
+  FID := NO_SOUND_ID;
+  FMusic := False;
+  FSource := -1;
+  FPosition := 0;
+  FMuted := False;
+  FOldGain := 1;
+end;
+
+destructor TBasicSound.Destroy();
+begin
+  FreeSound();
+  inherited;
+end;
+
+function TBasicSound.InvalidSource(): Boolean; inline;
+begin
+  Result := (FSource < 0) or (alSources[FSource] = 0) or (alOwners[FSource] <> self);
+end;
+
+procedure TBasicSound.FreeSound();
+begin
+  if FID = NO_SOUND_ID then
+    Exit;
+
+  Stop();
+  FID := NO_SOUND_ID;
+  FMusic := False;
+  FPosition := 0;
+end;
+
+function TBasicSound.RawPlay(Pan: Single; Volume: Single; aPos: DWORD): Boolean;
+begin
+  Result := False;
+  if FID = NO_SOUND_ID then Exit;
+
+  if e_SoundsArray[FID].nRefs >= gMaxSimSounds then
+  begin
+    Result := True;
+    Exit;
+  end;
+
+  FSource := e_PlaySoundPanVolume(FID, Pan, Volume);
+  if FSource >= 0 then
+  begin
+    alOwners[FSource] := self;
+    Result := True;
+  end;
+end;
+
+procedure TBasicSound.SetID(ID: DWORD);
+begin
+  FreeSound();
+
+  if ID > High(e_SoundsArray) then
+    exit;
+
+  FID := ID;
+  FMusic := e_SoundsArray[ID].isMusic;
+end;
+
+function TBasicSound.IsPlaying(): Boolean;
+begin
+  Result := False;
+  if InvalidSource() then
+    Exit;
+  Result := GetALSourceState(alSources[FSource]) = AL_PLAYING;
+end;
+
+procedure TBasicSound.Stop();
+begin
+  if InvalidSource() then
+    Exit;
+  GetPosition();
+  alSourceStop(alSources[FSource]);
+end;
+
+function TBasicSound.IsPaused(): Boolean;
+begin
+  Result := False;
+  if InvalidSource() then
+    Exit;
+  Result := GetALSourceState(alSources[FSource]) = AL_PAUSED;
+end;
+
+procedure TBasicSound.Pause(Enable: Boolean);
+begin
+  if InvalidSource() then
+    Exit;
+  if Enable then
+    alSourcePause(alSources[FSource])
+  else
+    alSourcePlay(alSources[FSource]);
+end;
+
+function TBasicSound.GetVolume(): Single;
+begin
+  Result := 0.0;
+  if InvalidSource() then
+    Exit;
+  alGetSourcef(alSources[FSource], AL_GAIN, Result);
+end;
+
+procedure TBasicSound.SetVolume(Volume: Single);
+begin
+  if InvalidSource() then
+    Exit;
+  alSourcef(alSources[FSource], AL_GAIN, Volume);
+end;
+
+function TBasicSound.GetPan(): Single;
+var
+  Pos: array [0..2] of ALfloat;
+begin
+  Result := 0.0;
+  if InvalidSource() then
+    Exit;
+  alGetSourcefv(alSources[FSource], AL_POSITION, Pos);
+  Result := Pos[0];
+end;
+
+procedure TBasicSound.SetPan(Pan: Single);
+var
+  Pos: array [0..2] of ALfloat;
+begin
+  if InvalidSource() then
+    Exit;
+  Pos[0] := Pan;
+  alSourcefv(alSources[FSource], AL_POSITION, Pos);
+end;
+
+function TBasicSound.IsMuted(): Boolean;
+begin
+  if InvalidSource() then
+    Result := False
+  else
+    Result := FMuted;
+end;
+
+procedure TBasicSound.Mute(Enable: Boolean);
+begin
+  if InvalidSource() then
+    Exit;
+   if Enable then
+   begin
+     FOldGain := GetVolume();
+     FMuted := True;
+     SetVolume(0);
+   end
+   else if FMuted then
+   begin
+     FMuted := False;
+     SetVolume(FOldGain);
+   end;
+end;
+
+function TBasicSound.GetPosition(): DWORD;
+var
+  Bytes: ALint;
+begin
+  Result := 0;
+  if InvalidSource() then
+    Exit;
+  alGetSourcei(alSources[FSource], AL_BYTE_OFFSET, Bytes);
+  FPosition := Bytes;
+  Result := FPosition;
+end;
+
+procedure TBasicSound.SetPosition(aPos: DWORD);
+begin
+  FPosition := aPos;
+  if InvalidSource() then
+    Exit;
+  alSourcei(alSources[FSource], AL_BYTE_OFFSET, aPos);
+end;
+
+procedure TBasicSound.SetPriority(priority: Integer);
+begin
+end;
+
+end.
diff --git a/src/engine/e_soundfile.pas b/src/engine/e_soundfile.pas
new file mode 100644 (file)
index 0000000..df4aa45
--- /dev/null
@@ -0,0 +1,90 @@
+(* Copyright (C)  Doom 2D: Forever Developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *)
+{$INCLUDE ../shared/a_modes.inc}
+unit e_soundfile;
+
+interface
+
+type
+  TSoundLoader = class;
+
+  TSoundFormat = record
+    Loader: TSoundLoader;
+    SampleBits: Integer;
+    SampleRate: Integer;
+    Channels: Integer;
+  end;
+
+  // each sound file format has its own loader 
+  // TODO: maybe make TBasicSound contain an instance of its loader
+  //       and add a FetchSamples method or something, for streaming shit
+  TSoundLoader = class
+  public
+    // can this loader load the sound file in Data?
+    function CanLoad(Data: Pointer; Len: Integer): Boolean; virtual; abstract; overload;
+    // can this loader load the sound file at FName?
+    function CanLoad(FName: string): Boolean; virtual; abstract; overload;
+    // load from memory
+    function Load(Data: Pointer; Len: Integer; var OutLen: Integer; var OutFmt: TSoundFormat): Pointer; virtual; abstract; overload;
+    // load from file
+    function Load(FName: string; var OutLen: Integer; var OutFmt: TSoundFormat): Pointer; virtual; abstract; overload;
+    // needed in case memory is allocated in a lib or something
+    procedure Free(Data: Pointer); virtual; abstract;
+  end;
+
+function e_GetSoundLoader(Data: Pointer; Len: Integer): TSoundLoader; overload;
+function e_GetSoundLoader(FName: string): TSoundLoader; overload;
+
+procedure e_AddSoundLoader(Loader: TSoundLoader);
+
+implementation
+
+var
+  e_SoundLoaders: array of TSoundLoader;
+
+function e_GetSoundLoader(FName: string): TSoundLoader; overload;
+var
+  I: Integer;
+begin
+  Result := nil;
+  for I := Low(e_SoundLoaders) to High(e_SoundLoaders) do
+    if e_SoundLoaders[I].CanLoad(FName) then
+    begin
+      Result := e_SoundLoaders[I];
+      break;
+    end;
+end;
+
+function e_GetSoundLoader(Data: Pointer; Len: Integer): TSoundLoader; overload;
+var
+  I: Integer;
+begin
+  Result := nil;
+  for I := Low(e_SoundLoaders) to High(e_SoundLoaders) do
+    if e_SoundLoaders[I].CanLoad(Data, Len) then
+    begin
+      Result := e_SoundLoaders[I];
+      break;
+    end;
+end;
+
+procedure e_AddSoundLoader(Loader: TSoundLoader);
+begin
+  SetLength(e_SoundLoaders, Length(e_SoundLoaders) + 1);
+  e_SoundLoaders[High(e_SoundLoaders)] := Loader;
+end;
+
+end.
diff --git a/src/engine/e_soundfile_wav.pas b/src/engine/e_soundfile_wav.pas
new file mode 100644 (file)
index 0000000..b88dd5a
--- /dev/null
@@ -0,0 +1,127 @@
+(* Copyright (C)  Doom 2D: Forever Developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *)
+{$INCLUDE ../shared/a_modes.inc}
+unit e_soundfile_wav;
+
+interface
+
+uses e_soundfile;
+
+type
+  // a WAV loader that just uses SDL_LoadWAV
+  TWAVLoader = class (TSoundLoader)
+  public
+    function CanLoad(Data: Pointer; Len: Integer): Boolean; override; overload;
+    function CanLoad(FName: string): Boolean; override; overload;
+    function Load(Data: Pointer; Len: Integer; var OutLen: Integer; var OutFmt: TSoundFormat): Pointer; override; overload;
+    function Load(FName: string; var OutLen: Integer; var OutFmt: TSoundFormat): Pointer; override; overload;
+    procedure Free(Data: Pointer); override;
+  end;
+
+implementation
+
+uses sdl2, utils, e_log;
+
+function TWAVLoader.CanLoad(Data: Pointer; Len: Integer): Boolean;
+var
+  P: PByte;
+begin
+  if Len < 5 then
+  begin
+    Result := False;
+    exit;
+  end;
+  P := PByte(Data);
+  Result := ((P+0)^ = Ord('R')) and ((P+1)^ = Ord('I')) and ((P+2)^ = Ord('F')) and ((P+3)^ = Ord('F'));
+end;
+
+function TWAVLoader.CanLoad(FName: string): Boolean;
+begin
+  // TODO: actually check for RIFF header
+  Result := GetFilenameExt(FName) = '.wav';
+end;
+
+function TWAVLoader.Load(Data: Pointer; Len: Integer; var OutLen: Integer; var OutFmt: TSoundFormat): Pointer;
+var
+  Spec: TSDL_AudioSpec;
+  RW: PSDL_RWops;
+  TmpLen: UInt32;
+  TmpBuf: PUInt8;
+begin
+  Result := nil;
+
+  RW := SDL_RWFromConstMem(Data, Len);
+
+  if SDL_LoadWAV_RW(RW, 0, @Spec, @TmpBuf, @TmpLen) = nil then
+  begin
+    e_LogWriteln('Could not load WAV: ' + SDL_GetError());
+  end
+  else
+  begin
+    OutFmt.Loader := self;
+    OutFmt.SampleRate := Spec.freq;
+    OutFmt.SampleBits := SDL_AUDIO_BITSIZE(Spec.format);
+    OutFmt.Channels := Spec.channels;
+    OutLen := TmpLen;
+    Result := TmpBuf;
+  end;
+
+  SDL_RWclose(RW);
+end;
+
+function TWAVLoader.Load(FName: string; var OutLen: Integer; var OutFmt: TSoundFormat): Pointer;
+var
+  Spec: TSDL_AudioSpec;
+  RW: PSDL_RWops;
+  TmpLen: UInt32;
+  TmpBuf: PUInt8;
+begin
+  Result := nil;
+
+  RW := SDL_RWFromFile(PChar(FName), 'rb');
+
+  if RW = nil then
+  begin
+    e_LogWritefln('Could not open WAV file `%s`: %s', [FName, SDL_GetError()]);
+    exit;
+  end;
+
+  if SDL_LoadWAV_RW(RW, 0, @Spec, @TmpBuf, @TmpLen) = nil then
+  begin
+    e_LogWritefln('Could not load WAV file `%s`: %s', [FName, SDL_GetError()]);
+    Result := nil;
+  end
+  else
+  begin
+    OutFmt.Loader := self;
+    OutFmt.SampleRate := Spec.freq;
+    OutFmt.SampleBits := SDL_AUDIO_BITSIZE(Spec.format);
+    OutFmt.Channels := Spec.channels;
+    OutLen := TmpLen;
+    Result := TmpBuf;
+  end;
+
+  SDL_RWclose(RW);
+end;
+
+procedure TWAVLoader.Free(Data: Pointer);
+begin
+  SDL_FreeWAV(Data); // SDL allocates inside the DLL, so we need this
+end;
+
+initialization
+  e_AddSoundLoader(TWAVLoader.Create());
+end.
index f8d946e730c74329686fae4c3cfccf10654b61ec..546cabf9f423cee29481327d8b4f4fca3b5a6190 100644 (file)
@@ -51,6 +51,11 @@ uses
   SDL2 in '../lib/sdl2/sdl2.pas',
 {$IFDEF USE_SDLMIXER}
   SDL2_mixer in '../lib/sdl2/SDL2_mixer.pas',
+{$ENDIF}
+{$IFDEF USE_OPENAL}
+  AL in '../lib/openal/al.pas',
+  e_soundfile in '../engine/e_soundfile.pas',
+  e_soundfile_wav in '../engine/e_soundfile_wav.pas',
 {$ENDIF}
   ENet in '../lib/enet/enet.pp',
   e_graphics in '../engine/e_graphics.pas',
diff --git a/src/lib/openal/al.inc b/src/lib/openal/al.inc
new file mode 100644 (file)
index 0000000..d7db89a
--- /dev/null
@@ -0,0 +1,722 @@
+(**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2000 by authors.
+ * This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the
+ *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ *)
+
+
+(*
+ * The OPENAL, ALAPI, ALAPIENTRY, AL_INVALID, AL_ILLEGAL_ENUM, and
+ * AL_ILLEGAL_COMMAND macros are deprecated, but are included for
+ * applications porting code from AL 1.0
+ *)
+
+{ OPENAL
+  ALAPI AL_API
+  ALAPIENTRY AL_APIENTRY
+  AL_INVALID                        = (-1);
+  AL_ILLEGAL_ENUM                   = AL_INVALID_ENUM;
+  AL_ILLEGAL_COMMAND                = AL_INVALID_OPERATION;
+
+  AL_VERSION_1_0
+  AL_VERSION_1_1}
+
+
+type
+
+(** 8-bit boolean *)
+  ALboolean                         = cbool;
+  PALboolean                        = pcbool;
+
+(** character *)
+  ALchar                            = char;
+  PALchar                           = pchar;
+
+(** signed 8-bit 2's complement integer *)
+  ALbyte                            = cint8;
+  PALbyte                           = pcint8;
+
+(** unsigned 8-bit integer *)
+  ALubyte                           = cuint8;
+  PALubyte                          = pcuint8;
+
+(** signed 16-bit 2's complement integer *)
+  ALshort                           = cint16;
+  PALshort                          = pcint16;
+
+(** unsigned 16-bit integer *)
+  ALushort                          = cuint16;
+  PALushort                         = pcuint16;
+
+(** signed 32-bit 2's complement integer *)
+  ALint                             = cint32;
+  PALint                            = pcint32;
+
+(** unsigned 32-bit integer *)
+  ALuint                            = cuint32;
+  PALuint                           = pcuint32;
+
+(** non-negative 32-bit binary integer size *)
+  ALsizei                           = cint32;
+  PALsizei                          = pcint32;
+
+(** enumerated 32-bit value *)
+  ALenum                            = cint32;
+  PALenum                           = pcint32;
+
+(** 32-bit IEEE754 floating-point *)
+  ALfloat                           = cfloat;
+  PALfloat                          = pcfloat;
+
+(** 64-bit IEEE754 floating-point *)
+  ALdouble                          = cdouble;
+  PALdouble                         = pcdouble;
+
+(** void type (for opaque pointers only) *)
+  PALvoid                           = pointer;
+
+
+(* Enumerant values begin at column 50. No tabs. *)
+
+const
+(* "no distance model" or "no buffer" *)
+  AL_NONE                           = 0;
+
+(* Boolean False. *)
+  AL_FALSE                          = 0;
+
+(** Boolean True. *)
+  AL_TRUE                           = 1;
+
+(** Indicate Source has relative coordinates. *)
+  AL_SOURCE_RELATIVE                = $202;
+
+
+
+(**
+ * Directional source, inner cone angle, in degrees.
+ * Range:    [0-360] 
+ * Default:  360
+ *)
+  AL_CONE_INNER_ANGLE               = $1001;
+
+(**
+ * Directional source, outer cone angle, in degrees.
+ * Range:    [0-360] 
+ * Default:  360
+ *)
+  AL_CONE_OUTER_ANGLE               = $1002;
+
+(**
+ * Specify the pitch to be applied, either at source,
+ *  or on mixer results, at listener.
+ * Range:   [0.5-2.0]
+ * Default: 1.0
+ *)
+  AL_PITCH                          = $1003;
+  
+(** 
+ * Specify the current location in three dimensional space.
+ * OpenAL, like OpenGL, uses a right handed coordinate system,
+ *  where in a frontal default view X (thumb) points right, 
+ *  Y points up (index finger), and Z points towards the
+ *  viewer/camera (middle finger). 
+ * To switch from a left handed coordinate system, flip the
+ *  sign on the Z coordinate.
+ * Listener position is always in the world coordinate system.
+ *) 
+  AL_POSITION                       = $1004;
+  
+(** Specify the current direction. *)
+  AL_DIRECTION                      = $1005;
+  
+(** Specify the current velocity in three dimensional space. *)
+  AL_VELOCITY                       = $1006;
+
+(**
+ * Indicate whether source is looping.
+ * Type: ALboolean?
+ * Range:   [AL_TRUE, AL_FALSE]
+ * Default: FALSE.
+ *)
+  AL_LOOPING                        = $1007;
+
+(**
+ * Indicate the buffer to provide sound samples. 
+ * Type: ALuint.
+ * Range: any valid Buffer id.
+ *)
+  AL_BUFFER                         = $1009;
+  
+(**
+ * Indicate the gain (volume amplification) applied. 
+ * Type:  ALfloat.
+ * Range:  ]0.0-  ]
+ * A value of 1.0 means un-attenuated/unchanged.
+ * Each division by 2 equals an attenuation of -6dB.
+ * Each multiplicaton with 2 equals an amplification of +6dB.
+ * A value of 0.0 is meaningless with respect to a logarithmic
+ *  scale; it is interpreted as zero volume - the channel
+ *  is effectively disabled.
+ *)
+  AL_GAIN                           = $100A;
+
+(*
+ * Indicate minimum source attenuation
+ * Type: ALfloat
+ * Range:  [0.0 - 1.0]
+ *
+ * Logarthmic
+ *)
+  AL_MIN_GAIN                       = $100D;
+
+(**
+ * Indicate maximum source attenuation
+ * Type: ALfloat
+ * Range:  [0.0 - 1.0]
+ *
+ * Logarthmic
+ *)
+  AL_MAX_GAIN                       = $100E;
+
+(**
+ * Indicate listener orientation.
+ *
+ * at/up 
+ *)
+  AL_ORIENTATION                    = $100F;
+
+(**
+ * Source state information.
+ *)
+  AL_SOURCE_STATE                   = $1010;
+  AL_INITIAL                        = $1011;
+  AL_PLAYING                        = $1012;
+  AL_PAUSED                         = $1013;
+  AL_STOPPED                        = $1014;
+
+(**
+ * Buffer Queue params
+ *)
+  AL_BUFFERS_QUEUED                 = $1015;
+  AL_BUFFERS_PROCESSED              = $1016;
+
+(**
+ * Source buffer position information
+ *)
+  AL_SEC_OFFSET                     = $1024;
+  AL_SAMPLE_OFFSET                  = $1025;
+  AL_BYTE_OFFSET                    = $1026;
+
+(*
+ * Source type (Static, Streaming or undetermined)
+ * Source is Static if a Buffer has been attached using AL_BUFFER
+ * Source is Streaming if one or more Buffers have been attached using alSourceQueueBuffers
+ * Source is undetermined when it has the NULL buffer attached
+ *)
+  AL_SOURCE_TYPE                    = $1027;
+  AL_STATIC                         = $1028;
+  AL_STREAMING                      = $1029;
+  AL_UNDETERMINED                   = $1030;
+
+(** Sound samples: format specifier. *)
+  AL_FORMAT_MONO8                   = $1100;
+  AL_FORMAT_MONO16                  = $1101;
+  AL_FORMAT_STEREO8                 = $1102;
+  AL_FORMAT_STEREO16                = $1103;
+
+(**
+ * source specific reference distance
+ * Type: ALfloat
+ * Range:  0.0 - +inf
+ *
+ * At 0.0, no distance attenuation occurs.  Default is
+ * 1.0.
+ *)
+  AL_REFERENCE_DISTANCE             = $1020;
+
+(**
+ * source specific rolloff factor
+ * Type: ALfloat
+ * Range:  0.0 - +inf
+ *
+ *)
+  AL_ROLLOFF_FACTOR                 = $1021;
+
+(**
+ * Directional source, outer cone gain.
+ *
+ * Default:  0.0
+ * Range:    [0.0 - 1.0]
+ * Logarithmic
+ *)
+  AL_CONE_OUTER_GAIN                = $1022;
+
+(**
+ * Indicate distance above which sources are not
+ * attenuated using the inverse clamped distance model.
+ *
+ * Default: +inf
+ * Type: ALfloat
+ * Range:  0.0 - +inf
+ *)
+  AL_MAX_DISTANCE                   = $1023;
+
+(** 
+ * Sound samples: frequency, in units of Hertz [Hz].
+ * This is the number of samples per second. Half of the
+ *  sample frequency marks the maximum significant
+ *  frequency component.
+ *)
+  AL_FREQUENCY                      = $2001;
+  AL_BITS                           = $2002;
+  AL_CHANNELS                       = $2003;
+  AL_SIZE                           = $2004;
+
+(**
+ * Buffer state.
+ *
+ * Not supported for public use (yet).
+ *)
+  AL_UNUSED                         = $2010;
+  AL_PENDING                        = $2011;
+  AL_PROCESSED                      = $2012;
+
+
+(** Errors: No Error. *)
+  AL_NO_ERROR                       = AL_FALSE;
+
+(** 
+ * Invalid Name paramater passed to AL call.
+ *)
+  AL_INVALID_NAME                   = $A001;
+
+(** 
+ * Invalid parameter passed to AL call.
+ *)
+  AL_INVALID_ENUM                   = $A002;
+
+(** 
+ * Invalid enum parameter value.
+ *)
+  AL_INVALID_VALUE                  = $A003;
+
+(** 
+ * Illegal call.
+ *)
+  AL_INVALID_OPERATION              = $A004;
+
+  
+(**
+ * No mojo.
+ *)
+  AL_OUT_OF_MEMORY                  = $A005;
+
+
+(** Context strings: Vendor Name. *)
+  AL_VENDOR                         = $B001;
+  AL_VERSION                        = $B002;
+  AL_RENDERER                       = $B003;
+  AL_EXTENSIONS                     = $B004;
+
+(** Global tweakage. *)
+
+(**
+ * Doppler scale.  Default 1.0
+ *)
+  AL_DOPPLER_FACTOR                 = $C000;
+
+(**
+ * Tweaks speed of propagation.
+ *)
+  AL_DOPPLER_VELOCITY               = $C001;
+
+(**
+ * Speed of Sound in units per second
+ *)
+  AL_SPEED_OF_SOUND                 = $C003;
+
+(**
+ * Distance models
+ *
+ * used in conjunction with DistanceModel
+ *
+ * implicit: NONE, which disances distance attenuation.
+ *)
+  AL_DISTANCE_MODEL                 = $D000;
+  AL_INVERSE_DISTANCE               = $D001;
+  AL_INVERSE_DISTANCE_CLAMPED       = $D002;
+  AL_LINEAR_DISTANCE                = $D003;
+  AL_LINEAR_DISTANCE_CLAMPED        = $D004;
+  AL_EXPONENT_DISTANCE              = $D005;
+  AL_EXPONENT_DISTANCE_CLAMPED      = $D006;
+
+(*
+ * Renderer State management
+ *)
+procedure alEnable(capability: ALenum); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alDisable(capability: ALenum); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alIsEnabled(capability: ALenum): ALboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(*
+ * State retrieval
+ *)
+function alGetString(param: ALenum): PALchar; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetBooleanv(param: ALenum; data: PALboolean); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetIntegerv(param: ALenum; data: PALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetFloatv(param: ALenum; data: PALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetDoublev(param: ALenum; data: PALdouble); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alGetBoolean(param: ALenum): ALboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alGetInteger(param: ALenum): ALint; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alGetFloat(param: ALenum): ALfloat; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alGetDouble(param: ALenum): ALdouble; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(*
+ * Error support.
+ * Obtain the most recent error generated in the AL state machine.
+ *)
+function alGetError: ALenum; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(* 
+ * Extension support.
+ * Query for the presence of an extension, and obtain any appropriate
+ * function pointers and enum values.
+ *)
+function alIsExtensionPresent(const extname: PALChar): ALboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alGetProcAddress(const fname: PALChar): pointer; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alGetEnumValue(const ename: PALChar): ALenum; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(*
+ * LISTENER
+ * Listener represents the location and orientation of the
+ * 'user' in 3D-space.
+ *
+ * Properties include: -
+ *
+ * Gain        AL_GAIN        ALfloat
+ * Position    AL_POSITION    ALfloat[3]
+ * Velocity    AL_VELOCITY    ALfloat[3]
+ * Orientation  AL_ORIENTATION  ALfloat[6] (Forward then Up vectors)
+*)
+
+(*
+ * Set Listener parameters
+ *)
+procedure alListenerf(param: ALenum; value: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alListener3f(param: ALenum; value1, value2, value3: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alListenerfv(param: ALenum; const values: PALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alListeneri(param: ALenum; value: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alListener3i(param: ALenum; value1, value2, value3: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alListeneriv(param: ALenum; const values: PALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(*
+ * Get Listener parameters
+ *)
+procedure alGetListenerf(param: ALenum; var value: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetListener3f(param: ALenum; var value1, value2, value3: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetListenerfv(param: ALenum; values: PALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetListeneri(param: ALenum; var value: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetListener3i(param: ALenum; var value1, value2, value3: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetListeneriv(param: ALenum; values: PALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(**
+ * SOURCE
+ * Sources represent individual sound objects in 3D-space.
+ * Sources take the PCM data provided in the specified Buffer,
+ * apply Source-specific modifications, and then
+ * submit them to be mixed according to spatial arrangement etc.
+ * 
+ * Properties include: -
+ *
+ * Gain                             AL_GAIN                ALfloat
+ * Min Gain                         AL_MIN_GAIN            ALfloat
+ * Max Gain                         AL_MAX_GAIN            ALfloat
+ * Position                         AL_POSITION            ALfloat[3]
+ * Velocity                         AL_VELOCITY            ALfloat[3]
+ * Direction                        AL_DIRECTION           ALfloat[3]
+ * Head Relative Mode               AL_SOURCE_RELATIVE     ALint (AL_TRUE or AL_FALSE)
+ * Reference Distance               AL_REFERENCE_DISTANCE  ALfloat
+ * Max Distance                     AL_MAX_DISTANCE        ALfloat
+ * RollOff Factor                   AL_ROLLOFF_FACTOR      ALfloat
+ * Inner Angle                      AL_CONE_INNER_ANGLE    ALint or ALfloat
+ * Outer Angle                      AL_CONE_OUTER_ANGLE    ALint or ALfloat
+ * Cone Outer Gain                  AL_CONE_OUTER_GAIN     ALint or ALfloat
+ * Pitch                            AL_PITCH               ALfloat
+ * Looping                          AL_LOOPING             ALint (AL_TRUE or AL_FALSE)
+ * MS Offset                        AL_MSEC_OFFSET         ALint or ALfloat
+ * Byte Offset                      AL_BYTE_OFFSET         ALint or ALfloat
+ * Sample Offset                    AL_SAMPLE_OFFSET       ALint or ALfloat
+ * Attached Buffer                  AL_BUFFER              ALint
+ * State (Query only)               AL_SOURCE_STATE        ALint
+ * Buffers Queued (Query only)      AL_BUFFERS_QUEUED      ALint
+ * Buffers Processed (Query only)   AL_BUFFERS_PROCESSED   ALint
+ *)
+
+(* Create Source objects *)
+procedure alGenSources(n: ALsizei; sources: PALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* Delete Source objects *)
+procedure alDeleteSources(n: ALsizei; const sources: PALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* Verify a handle is a valid Source *) 
+function alIsSource(sid: ALuint): ALboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(*
+ * Set Source parameters
+ *)
+procedure alSourcef(sid: ALuint; param: ALenum; value: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alSource3f(sid: ALuint; param: ALenum; value1, value2, value3: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alSourcefv(sid: ALuint; param: ALenum; const values: PALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alSourcei(sid: ALuint; param: ALenum; value: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alSource3i(sid: ALuint; param: ALenum; value1, value2, value3: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alSourceiv(sid: ALuint; param: ALenum; const values: PALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(*
+ * Get Source parameters
+ *)
+procedure alGetSourcef(sid: ALuint; param: ALenum; var value: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetSource3f(sid: ALuint; param: ALenum; var value1, value2, value3: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetSourcefv(sid: ALuint; param: ALenum; values: PALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetSourcei(sid: ALuint; param: ALenum; var value: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetSource3i(sid: ALuint; param: ALenum; var value1, value2, value3: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetSourceiv(sid: ALuint; param: ALenum; values: PALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(*
+ * Source vector based playback calls
+ *)
+
+(* Play, replay, or resume (if paused) a list of Sources *)
+procedure alSourcePlayv(ns: ALsizei; const sids: PALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* Stop a list of Sources *)
+procedure alSourceStopv(ns: ALsizei; const sids: PALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* Rewind a list of Sources *)
+procedure alSourceRewindv(ns: ALsizei; const sids: PALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* Pause a list of Sources *)
+procedure alSourcePausev(ns: ALsizei; const sids: PALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(*
+ * Source based playback calls
+ *)
+
+(* Play, replay, or resume a Source *)
+procedure alSourcePlay(sid: ALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* Stop a Source *)
+procedure alSourceStop(sid: ALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* Rewind a Source (set playback postiton to beginning) *)
+procedure alSourceRewind(sid: ALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* Pause a Source *)
+procedure alSourcePause(sid: ALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(*
+ * Source Queuing 
+ *)
+procedure alSourceQueueBuffers(sid: ALuint; numEntries: ALsizei; const bids: PALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alSourceUnqueueBuffers(sid: ALuint; numEntries: ALsizei; bids: PALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(**
+ * BUFFER
+ * Buffer objects are storage space for sample data.
+ * Buffers are referred to by Sources. One Buffer can be used
+ * by multiple Sources.
+ *
+ * Properties include: -
+ *
+ * Frequency (Query only)   AL_FREQUENCY     ALint
+ * Size (Query only)        AL_SIZE          ALint
+ * Bits (Query only)        AL_BITS          ALint
+ * Channels (Query only)    AL_CHANNELS      ALint
+ *)
+
+(* Create Buffer objects *)
+procedure alGenBuffers(n: ALsizei; buffers: PALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* Delete Buffer objects *)
+procedure alDeleteBuffers(n: ALsizei; const buffers: PALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* Verify a handle is a valid Buffer *)
+function alIsBuffer(bid: ALuint): ALboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* Specify the data to be copied into a buffer *)
+procedure alBufferData(bid: ALuint; format: ALenum; data: PALvoid; size: ALsizei; freq: ALsizei); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(*
+ * Set Buffer parameters
+ *)
+procedure alBufferf(bid: ALuint; param: ALenum; value: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alBuffer3f(bid: ALuint; param: ALenum; value1, value2, value3: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alBufferfv(bid: ALuint; param: ALenum; const values: PALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alBufferi(bid: ALuint; param: ALenum; value: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alBuffer3i(bid: ALuint; param: ALenum; value1, value2, value3: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alBufferiv(bid: ALuint; param: ALenum; const values: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(*
+ * Get Buffer parameters
+ *)
+procedure alGetBufferf(bid: ALuint; param: ALenum; var value: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetBuffer3f(bid: ALuint; param: ALenum; var value1, value2, value3: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetBufferfv(bid: ALuint; param: ALenum; values: PALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetBufferi(bid: ALuint; param: ALenum; var value: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetBuffer3i(bid: ALuint; param: ALenum; var value1, value2, value3: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetBufferiv(bid: ALuint; param: ALenum; values: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(*
+ * Global Parameters
+ *)
+procedure alDopplerFactor(value: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alDopplerVelocity(value: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alSpeedOfSound(value: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alDistanceModel(distanceModel: ALenum); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(*
+ * Pointer-to-function types, useful for dynamically getting AL entry points.
+ *)
+{
+type
+  LPALENABLE                        = procedure( ALenum capability ); cdecl;
+  LPALDISABLE                       = procedure( ALenum capability ); cdecl;
+  LPALISENABLED                     = function( ALenum capability ): ALboolean; cdecl;
+  LPALGETSTRING                     = function( ALenum param ): PALchar; cdecl;
+  LPALGETBOOLEANV                   = procedure( ALenum param, ALboolean* data ); cdecl;
+  LPALGETINTEGERV                   = procedure( ALenum param, ALint* data ); cdecl;
+  LPALGETFLOATV                     = procedure( ALenum param, ALfloat* data ); cdecl;
+  LPALGETDOUBLEV                    = procedure( ALenum param, ALdouble* data ); cdecl;
+  LPALGETBOOLEAN                    = function( ALenum param ): ALboolean; cdecl;
+  LPALGETINTEGER                    = function( ALenum param ): ALint; cdecl;
+  LPALGETFLOAT                      = function( ALenum param ): ALfloat; cdecl;
+  LPALGETDOUBLE                     = function( ALenum param ): ALdouble; cdecl;
+  LPALGETERROR                      = function( void ): ALenum; cdecl;
+  LPALISEXTENSIONPRESENT            = function(const ALchar* extname ): ALboolean; cdecl;
+  LPALGETPROCADDRESS                = function( const ALchar* fname ): pointer; cdecl;
+  LPALGETENUMVALUE                  = function( const ALchar* ename ): ALenum; cdecl;
+  LPALLISTENERF                     = procedure( ALenum param, ALfloat value ); cdecl;
+  LPALLISTENER3F                    = procedure( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); cdecl;
+  LPALLISTENERFV                    = procedure( ALenum param, const ALfloat* values ); cdecl;
+  LPALLISTENERI                     = procedure( ALenum param, ALint value ); cdecl;
+  LPALLISTENER3I                    = procedure( ALenum param, ALint value1, ALint value2, ALint value3 ); cdecl;
+  LPALLISTENERIV                    = procedure( ALenum param, const ALint* values ); cdecl;
+  LPALGETLISTENERF                  = procedure( ALenum param, ALfloat* value ); cdecl;
+  LPALGETLISTENER3F                 = procedure( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 ); cdecl;
+  LPALGETLISTENERFV                 = procedure( ALenum param, ALfloat* values ); cdecl;
+  LPALGETLISTENERI                  = procedure( ALenum param, ALint* value ); cdecl;
+  LPALGETLISTENER3I                 = procedure( ALenum param, ALint *value1, ALint *value2, ALint *value3 ); cdecl;
+  LPALGETLISTENERIV                 = procedure( ALenum param, ALint* values ); cdecl;
+  LPALGENSOURCES                    = procedure( ALsizei n, ALuint* sources ); cdecl;
+  LPALDELETESOURCES                 = procedure( ALsizei n, const ALuint* sources ); cdecl;
+  LPALISSOURCE                      = function( ALuint sid ): ALboolean; cdecl;
+  LPALSOURCEF                       = procedure( ALuint sid, ALenum param, ALfloat value); cdecl;
+  LPALSOURCE3F                      = procedure( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); cdecl;
+  LPALSOURCEFV                      = procedure( ALuint sid, ALenum param, const ALfloat* values ); cdecl;
+  LPALSOURCEI                       = procedure( ALuint sid, ALenum param, ALint value); cdecl;
+  LPALSOURCE3I                      = procedure( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 ); cdecl;
+  LPALSOURCEIV                      = procedure( ALuint sid, ALenum param, const ALint* values ); cdecl;
+  LPALGETSOURCEF                    = procedure( ALuint sid, ALenum param, ALfloat* value ); cdecl;
+  LPALGETSOURCE3F                   = procedure( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); cdecl;
+  LPALGETSOURCEFV                   = procedure( ALuint sid, ALenum param, ALfloat* values ); cdecl;
+  LPALGETSOURCEI                    = procedure( ALuint sid, ALenum param, ALint* value ); cdecl;
+  LPALGETSOURCE3I                   = procedure( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3); cdecl;
+  LPALGETSOURCEIV                   = procedure( ALuint sid, ALenum param, ALint* values ); cdecl;
+  LPALSOURCEPLAYV                   = procedure( ALsizei ns, const ALuint *sids ); cdecl;
+  LPALSOURCESTOPV                   = procedure( ALsizei ns, const ALuint *sids ); cdecl;
+  LPALSOURCEREWINDV                 = procedure( ALsizei ns, const ALuint *sids ); cdecl;
+  LPALSOURCEPAUSEV                  = procedure( ALsizei ns, const ALuint *sids ); cdecl;
+  LPALSOURCEPLAY                    = procedure( ALuint sid ); cdecl;
+  LPALSOURCESTOP                    = procedure( ALuint sid ); cdecl;
+  LPALSOURCEREWIND                  = procedure( ALuint sid ); cdecl;
+  LPALSOURCEPAUSE                   = procedure( ALuint sid ); cdecl;
+  LPALSOURCEQUEUEBUFFERS            = procedure(ALuint sid, ALsizei numEntries, const ALuint *bids ); cdecl;
+  LPALSOURCEUNQUEUEBUFFERS          = procedure(ALuint sid, ALsizei numEntries, ALuint *bids ); cdecl;
+  LPALGENBUFFERS                    = procedure( ALsizei n, ALuint* buffers ); cdecl;
+  LPALDELETEBUFFERS                 = procedure( ALsizei n, const ALuint* buffers ); cdecl;
+  LPALISBUFFER                      = function( ALuint bid ): ALboolean; cdecl;
+  LPALBUFFERDATA                    = procedure( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq ); cdecl;
+  LPALBUFFERF                       = procedure( ALuint bid, ALenum param, ALfloat value); cdecl;
+  LPALBUFFER3F                      = procedure( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); cdecl;
+  LPALBUFFERFV                      = procedure( ALuint bid, ALenum param, const ALfloat* values ); cdecl;
+  LPALBUFFERI                       = procedure( ALuint bid, ALenum param, ALint value); cdecl;
+  LPALBUFFER3I                      = procedure( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 ); cdecl;
+  LPALBUFFERIV                      = procedure( ALuint bid, ALenum param, const ALint* values ); cdecl;
+  LPALGETBUFFERF                    = procedure( ALuint bid, ALenum param, ALfloat* value ); cdecl;
+  LPALGETBUFFER3F                   = procedure( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); cdecl;
+  LPALGETBUFFERFV                   = procedure( ALuint bid, ALenum param, ALfloat* values ); cdecl;
+  LPALGETBUFFERI                    = procedure( ALuint bid, ALenum param, ALint* value ); cdecl;
+  LPALGETBUFFER3I                   = procedure( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3); cdecl;
+  LPALGETBUFFERIV                   = procedure( ALuint bid, ALenum param, ALint* values ); cdecl;
+  LPALDOPPLERFACTOR                 = procedure( ALfloat value ); cdecl;
+  LPALDOPPLERVELOCITY               = procedure( ALfloat value ); cdecl;
+  LPALSPEEDOFSOUND                  = procedure( ALfloat value ); cdecl;
+  LPALDISTANCEMODEL                 = procedure( ALenum distanceModel ); cdecl;
+}
diff --git a/src/lib/openal/al.pas b/src/lib/openal/al.pas
new file mode 100644 (file)
index 0000000..0d6afba
--- /dev/null
@@ -0,0 +1,42 @@
+{
+  Translation of the OpenAL headers for FreePascal
+  Copyright (C) 2006 by Ivo Steinmann
+  Copyright (C) 2019 by fgsfds
+}
+
+unit AL;
+
+{$mode objfpc}
+
+interface
+
+uses
+  ctypes;
+
+{$IFDEF WINDOWS}
+  {$DEFINE AL_DYNAMIC}
+{$ENDIF}
+
+{$IF DEFINED(AL_DYNAMIC)}
+const
+{$IF DEFINED(WINDOWS)}
+  openallib = 'openal32.dll';
+{$ELSEIF DEFINED(UNIX)}
+  openallib = 'libopenal.so';
+{$ELSE}
+  {$MESSAGE ERROR 'AL_DYNAMIC not supported'}
+{$IFEND}
+{$ELSEIF DEFINED(Darwin)}
+{$LINKFRAMEWORK OpenAL}
+{$ELSE}
+  {$LINKLIB openal}
+{$ENDIF}
+
+{$include al.inc}
+{$include alc.inc}
+{$include alext.inc}
+{$include efx.inc}
+
+implementation
+
+end.
diff --git a/src/lib/openal/alc.inc b/src/lib/openal/alc.inc
new file mode 100644 (file)
index 0000000..6ad5860
--- /dev/null
@@ -0,0 +1,256 @@
+(*
+ * The ALCAPI, ALCAPIENTRY, and ALC_INVALID macros are deprecated, but are
+ * included for applications porting code from AL 1.0
+ *)
+
+{ ALCAPI ALC_API
+  ALCAPIENTRY ALC_APIENTRY
+  ALC_INVALID                       = 0;
+
+
+  ALC_VERSION_0_1                   = 1;}
+
+type
+  PALCdevice                        = ^ALCdevice;
+  ALCdevice                         = record
+  end;
+
+  PALCcontext                       = ^ALCcontext;
+  ALCcontext                        = record
+  end;
+
+
+(** 8-bit boolean *)
+  ALCboolean                        = cbool;
+  PALCboolean                       = pcbool;
+
+(** character *)
+  ALCchar                           = char;
+  PALCchar                          = pchar;
+
+(** signed 8-bit 2's complement integer *)
+  ALCbyte                           = cint8;
+  PALCbyte                          = pcint8;
+
+(** unsigned 8-bit integer *)
+  ALCubyte                          = cuint8;
+  PALCubyte                         = pcuint8;
+
+(** signed 16-bit 2's complement integer *)
+  ALCshort                          = cint16;
+  PALCshort                         = pcint16;
+
+(** unsigned 16-bit integer *)
+  ALCushort                         = cuint16;
+  PALCushort                        = pcuint16;
+
+(** signed 32-bit 2's complement integer *)
+  ALCint                            = cint32;
+  PALCint                           = pcint32;
+
+(** unsigned 32-bit integer *)
+  ALCuint                           = cuint32;
+  PALCuint                          = pcuint32;
+
+(** non-negative 32-bit binary integer size *)
+  ALCsizei                          = cint32;
+  PALCsizei                         = pcint32;
+
+(** enumerated 32-bit value *)
+  ALCenum                           = cint32;
+  PALCenum                          = pcint32;
+
+(** 32-bit IEEE754 floating-point *)
+  ALCfloat                          = cfloat;
+  PALCfloat                         = pcfloat;
+
+(** 64-bit IEEE754 floating-point *)
+  ALCdouble                         = cdouble;
+  PALCdouble                        = pcdouble;
+
+(** void type (for opaque pointers only) *)
+  PALCvoid                          = pointer;
+
+
+(* Enumerant values begin at column 50. No tabs. *)
+const
+
+(* Boolean False. *)
+  ALC_FALSE                         = 0;
+
+(* Boolean True. *)
+  ALC_TRUE                          = 1;
+
+(**
+ * followed by <int> Hz
+ *)
+  ALC_FREQUENCY                     = $1007;
+
+(**
+ * followed by <int> Hz
+ *)
+  ALC_REFRESH                       = $1008;
+
+(**
+ * followed by AL_TRUE, AL_FALSE
+ *)
+  ALC_SYNC                          = $1009;
+
+(**
+ * followed by <int> Num of requested Mono (3D) Sources
+ *)
+  ALC_MONO_SOURCES                  = $1010;
+
+(**
+ * followed by <int> Num of requested Stereo Sources
+ *)
+  ALC_STEREO_SOURCES                = $1011;
+
+(**
+ * errors
+ *)
+
+(**
+ * No error
+ *)
+  ALC_NO_ERROR                      = ALC_FALSE;
+
+(**
+ * No device
+ *)
+  ALC_INVALID_DEVICE                = $A001;
+
+(**
+ * invalid context ID
+ *)
+  ALC_INVALID_CONTEXT               = $A002;
+
+(**
+ * bad enum
+ *)
+  ALC_INVALID_ENUM                  = $A003;
+
+(**
+ * bad value
+ *)
+  ALC_INVALID_VALUE                 = $A004;
+
+(**
+ * Out of memory.
+ *)
+  ALC_OUT_OF_MEMORY                 = $A005;
+
+
+(**
+ * The Specifier string for default device
+ *)
+  ALC_DEFAULT_DEVICE_SPECIFIER      = $1004;
+  ALC_DEVICE_SPECIFIER              = $1005;
+  ALC_EXTENSIONS                    = $1006;
+
+  ALC_MAJOR_VERSION                 = $1000;
+  ALC_MINOR_VERSION                 = $1001;
+
+  ALC_ATTRIBUTES_SIZE               = $1002;
+  ALC_ALL_ATTRIBUTES                = $1003;
+
+(**
+ * Capture extension
+ *)
+  ALC_CAPTURE_DEVICE_SPECIFIER      = $310;
+  ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER = $311;
+  ALC_CAPTURE_SAMPLES               = $312;
+
+
+(*
+ * Context Management
+ *)
+function alcCreateContext(device: PALCdevice; const attrlist: PALCint): PALCcontext; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alcMakeContextCurrent(context: PALCcontext): ALCboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alcProcessContext(context: PALCcontext); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alcSuspendContext(context: PALCcontext); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alcDestroyContext(context: PALCcontext); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alcGetCurrentContext: PALCcontext; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alcGetContextsDevice(context: PALCcontext): PALCdevice; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(*
+ * Device Management
+ *)
+function alcOpenDevice(const devicename: PALCchar): PALCdevice; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alcCloseDevice(device: PALCdevice): ALCboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(*
+ * Error support.
+ * Obtain the most recent Context error
+ *)
+function alcGetError(device: PALCdevice): ALCenum; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(* 
+ * Extension support.
+ * Query for the presence of an extension, and obtain any appropriate
+ * function pointers and enum values.
+ *)
+function alcIsExtensionPresent(device: PALCdevice; const extname: PALCchar): ALCboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alcGetProcAddress(device: PALCdevice; const funcname: PALCchar): pointer; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alcGetEnumValue(device: PALCdevice; const enumname: PALCchar): ALCenum; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(*
+ * Query functions
+ *)
+function alcGetString(device: PALCdevice; param: ALCenum): PALCchar; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alcGetIntegerv(device: PALCdevice; param: ALCenum; size: ALCsizei; data: PALCint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+
+(*
+ * Capture functions
+ *)
+function alcCaptureOpenDevice(const devicename: PALCchar; frequency: ALCuint; format: ALCenum; buffersize: ALCsizei): PALCdevice; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alcCaptureCloseDevice(device: PALCdevice): ALCboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alcCaptureStart(device: PALCdevice); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alcCaptureStop(device: PALCdevice); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alcCaptureSamples(device: PALCdevice; buffer: PALCvoid; samples: ALCsizei); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(*
+ * Pointer-to-function types, useful for dynamically getting ALC entry points.
+ *)
+{
+type
+  LPALCCREATECONTEXT                = function(ALCdevice *device, const ALCint *attrlist): PALCcontext; cdecl;
+  LPALCMAKECONTEXTCURRENT           = function( ALCcontext *context ): ALCboolean; cdecl;
+  LPALCPROCESSCONTEXT               = procedure( ALCcontext *context ); cdecl;
+  LPALCSUSPENDCONTEXT               = procedure( ALCcontext *context ); cdecl;
+  LPALCDESTROYCONTEXT               = procedure( ALCcontext *context ); cdecl;
+  LPALCGETCURRENTCONTEXT            = function( ALCvoid ): PALCcontext; cdecl;
+  LPALCGETCONTEXTSDEVICE            = function( ALCcontext *context ): PALCdevice; cdecl;
+  LPALCOPENDEVICE                   = function( const ALCchar *devicename ): PALCdevice; cdecl;
+  LPALCCLOSEDEVICE                  = function( ALCdevice *device ): ALCboolean; cdecl;
+  LPALCGETERROR                     = function( ALCdevice *device ): ALCenum; cdecl;
+  LPALCISEXTENSIONPRESENT           = function( ALCdevice *device, const ALCchar *extname ): ALCboolean; cdecl;
+  LPALCGETPROCADDRESS               = function(ALCdevice *device, const ALCchar *funcname ): pointer; cdecl;
+  LPALCGETENUMVALUE                 = function(ALCdevice *device, const ALCchar *enumname ): ALCenum; cdecl;
+  LPALCGETSTRING                    = function( ALCdevice *device, ALCenum param ): PALCchar; cdecl;
+  LPALCGETINTEGERV                  = procedure(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *dest ); cdecl;
+  LPALCCAPTUREOPENDEVICE            = function( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize ): PALCdevice; cdecl;
+  LPALCCAPTURECLOSEDEVICE           = function( ALCdevice *device ): ALCboolean; cdecl;
+  LPALCCAPTURESTART                 = procedure( ALCdevice *device ); cdecl;
+  LPALCCAPTURESTOP                  = procedure( ALCdevice *device ); cdecl;
+  LPALCCAPTURESAMPLES               = procedure( ALCdevice *device, ALCvoid *buffer, ALCsizei samples ); cdecl;
+}
diff --git a/src/lib/openal/alext.inc b/src/lib/openal/alext.inc
new file mode 100644 (file)
index 0000000..4dd8b00
--- /dev/null
@@ -0,0 +1,138 @@
+(* AL_LOKI_IMA_ADPCM_format extension *)
+const
+  AL_FORMAT_IMA_ADPCM_MONO16_EXT            = $10000;
+  AL_FORMAT_IMA_ADPCM_STEREO16_EXT          = $10001;
+
+(* AL_LOKI_WAVE_format extension *)
+const
+  AL_FORMAT_WAVE_EXT                        = $10002;
+
+(* AL_EXT_vorbis extension *)
+const
+  AL_FORMAT_VORBIS_EXT                      = $10003;
+
+(* AL_LOKI_quadriphonic extension *)
+const
+  AL_FORMAT_QUAD8_LOKI                      = $10004;
+  AL_FORMAT_QUAD16_LOKI                     = $10005;
+
+(* AL_EXT_float32 extension *)
+const
+  AL_FORMAT_MONO_FLOAT32                    = $10010;
+  AL_FORMAT_STEREO_FLOAT32                  = $10011;
+
+(* AL_EXT_double extension *)
+const
+  AL_FORMAT_MONO_DOUBLE_EXT                 = $10012;
+  AL_FORMAT_STEREO_DOUBLE_EXT               = $10013;
+
+(* ALC_LOKI_audio_channel extension *)
+const
+  ALC_CHAN_MAIN_LOKI                        = $500001;
+  ALC_CHAN_PCM_LOKI                         = $500002;
+  ALC_CHAN_CD_LOKI                          = $500003;
+
+(* ALC_ENUMERATE_ALL_EXT extension *)
+const
+  ALC_DEFAULT_ALL_DEVICES_SPECIFIER         = $1012;
+  ALC_ALL_DEVICES_SPECIFIER                 = $1013;
+
+(* AL_EXT_MCFORMATS extension *)
+const
+  AL_FORMAT_QUAD8                          = $1204;
+  AL_FORMAT_QUAD16                         = $1205;
+  AL_FORMAT_QUAD32                         = $1206;
+  AL_FORMAT_REAR8                          = $1207;
+  AL_FORMAT_REAR16                         = $1208;
+  AL_FORMAT_REAR32                         = $1209;
+  AL_FORMAT_51CHN8                         = $120A;
+  AL_FORMAT_51CHN16                        = $120B;
+  AL_FORMAT_51CHN32                        = $120C;
+  AL_FORMAT_61CHN8                         = $120D;
+  AL_FORMAT_61CHN16                        = $120E;
+  AL_FORMAT_61CHN32                        = $120F;
+  AL_FORMAT_71CHN8                         = $1210;
+  AL_FORMAT_71CHN16                        = $1211;
+  AL_FORMAT_71CHN32                        = $1212;
+
+(* AL_EXT_IMA4 extension *)
+const
+  AL_FORMAT_MONO_IMA4                      = $1300;
+  AL_FORMAT_STEREO_IMA4                    = $1301;
+
+(* AL_EXT_buffer_sub_data extension *)
+const
+  AL_BYTE_RW_OFFSETS_EXT                   = $1031;
+  AL_SAMPLE_RW_OFFSETS_EXT                 = $1032;
+  AL_SEC_RW_OFFSETS_EXT                    = $1033;
+
+procedure alBufferSubDataEXT(buffer :ALuint; format :ALenum; const data :PALvoid; offset :ALsizei; length :ALsizei); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* AL_EXT_STATIC_BUFFER extension *)
+procedure alBufferDataStatic(buffer :ALint; format :ALenum; data :Pointer; size, freq :ALsizei); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* AL_EXT_sample_buffer_object extension *)
+const
+  AL_SAMPLE_SOURCE_EXT                     = $1040;
+  AL_SAMPLE_SINK_EXT                       = $1041;
+  AL_READ_ONLY_EXT                         = $1042;
+  AL_WRITE_ONLY_EXT                        = $1043;
+  AL_READ_WRITE_EXT                        = $1044;
+  AL_STREAM_WRITE_EXT                      = $1045;
+  AL_STREAM_READ_EXT                       = $1046;
+  AL_STREAM_COPY_EXT                       = $1047;
+  AL_STATIC_WRITE_EXT                      = $1048;
+  AL_STATIC_READ_EXT                       = $1049;
+  AL_STATIC_COPY_EXT                       = $104A;
+  AL_DYNAMIC_WRITE_EXT                     = $104B;
+  AL_DYNAMIC_READ_EXT                      = $104C;
+  AL_DYNAMIC_COPY_EXT                      = $104D;
+
+  procedure alGenDatabuffersEXT(n:ALsizei; puiBuffers:pALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alDeleteDatabuffersEXT(n:ALsizei; puiBuffers:pALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  function  alIsDatabufferEXT(uiBuffer:ALuint):ALboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alDatabufferDataEXT(buffer:ALuint; data:pALvoid; size:ALsizei; usage:ALenum); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alDatabufferSubDataEXT(buffer:ALuint; start:ALuint; length:ALsizei; data:pALvoid); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alGetDatabufferSubDataEXT(buffer:ALuint; start:ALuint; length:ALsizei; data:pALvoid); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alDatabufferfEXT(buffer:ALuint; eParam:ALenum; flValue:ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alDatabufferfvEXT(buffer:ALuint; eParam:ALenum; flValues:pALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alDatabufferiEXT(buffer:ALuint; eParam:ALenum; lValue:ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alDatabufferivEXT(buffer:ALuint; eParam:ALenum; plValues:pALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alGetDatabufferfEXT(buffer:ALuint; eParam:ALenum; pflValue:pALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alGetDatabufferfvEXT(buffer:ALuint; eParam:ALenum; pflValues:pALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alGetDatabufferiEXT(buffer:ALuint; eParam:ALenum; plValue:pALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alGetDatabufferivEXT(buffer:ALuint; eParam:ALenum; plValues:pALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alSelectDatabufferEXT(target:ALenum; uiBuffer:ALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  function  alMapDatabufferEXT(uiBuffer:ALuint; start:ALuint; length:ALsizei; access:ALenum):pALvoid; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+  procedure alUnmapDatabufferEXT(uiBuffer:ALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* ALC_EXT_disconnect extension *)
+const
+  ALC_CONNECTED                            = $0313;
+
+(* ALC_EXT_thread_local_context extension *)
+
+function alcMakeCurrent(context :PALCcontext) :ALCboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+function alcGetThreadContext() :PALCcontext; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+(* AL_EXT_source_distance_model extension *)
+const
+  AL_SOURCE_DISTANCE_MODEL                 = $0200;
+
+(* ALC_SOFT_HRTF extension *)
+const
+  ALC_HRTF_SOFT                            = $1992;
+  ALC_DONT_CARE_SOFT                       = $0002;
+  ALC_HRTF_STATUS_SOFT                     = $1993;
+  ALC_HRTF_DISABLED_SOFT                   = $0000;
+  ALC_HRTF_ENABLED_SOFT                    = $0001;
+  ALC_HRTF_DENIED_SOFT                     = $0002;
+  ALC_HRTF_REQUIRED_SOFT                   = $0003;
+  ALC_HRTF_HEADPHONES_DETECTED_SOFT        = $0004;
+  ALC_HRTF_UNSUPPORTED_FORMAT_SOFT         = $0005;
+  ALC_NUM_HRTF_SPECIFIERS_SOFT             = $1994;
+  ALC_HRTF_SPECIFIER_SOFT                  = $1995;
+  ALC_HRTF_ID_SOFT                         = $1996;
+
+function alcGetStringiSOFT(device: PALCdevice; paramName: ALCenum; index: ALCsizei): PALCchar; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+function alcResetDeviceSOFT(device: PALCdevice; attribs: PALCint): ALCboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
diff --git a/src/lib/openal/efx.inc b/src/lib/openal/efx.inc
new file mode 100644 (file)
index 0000000..517bc09
--- /dev/null
@@ -0,0 +1,634 @@
+const
+  ALC_EXT_EFX_NAME = 'ALC_EXT_EFX'; 
+  ALC_EFX_MAJOR_VERSION = $20001; 
+  ALC_EFX_MINOR_VERSION = $20002; 
+  ALC_MAX_AUXILIARY_SENDS = $20003; 
+  (* Listener properties. *)
+  AL_METERS_PER_UNIT = $20004; 
+  (* Source properties. *)
+  AL_DIRECT_FILTER = $20005; 
+  AL_AUXILIARY_SEND_FILTER = $20006; 
+  AL_AIR_ABSORPTION_FACTOR = $20007; 
+  AL_ROOM_ROLLOFF_FACTOR = $20008; 
+  AL_CONE_OUTER_GAINHF = $20009; 
+  AL_DIRECT_FILTER_GAINHF_AUTO = $2000A; 
+  AL_AUXILIARY_SEND_FILTER_GAIN_AUTO = $2000B; 
+  AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO = $2000C; 
+  (* Effect properties. *)
+  (* Reverb effect parameters *)
+  AL_REVERB_DENSITY = $0001; 
+  AL_REVERB_DIFFUSION = $0002; 
+  AL_REVERB_GAIN = $0003; 
+  AL_REVERB_GAINHF = $0004; 
+  AL_REVERB_DECAY_TIME = $0005; 
+  AL_REVERB_DECAY_HFRATIO = $0006; 
+  AL_REVERB_REFLECTIONS_GAIN = $0007; 
+  AL_REVERB_REFLECTIONS_DELAY = $0008; 
+  AL_REVERB_LATE_REVERB_GAIN = $0009; 
+  AL_REVERB_LATE_REVERB_DELAY = $000A; 
+  AL_REVERB_AIR_ABSORPTION_GAINHF = $000B; 
+  AL_REVERB_ROOM_ROLLOFF_FACTOR = $000C; 
+  AL_REVERB_DECAY_HFLIMIT = $000D; 
+  (* EAX Reverb effect parameters *)
+  AL_EAXREVERB_DENSITY = $0001; 
+  AL_EAXREVERB_DIFFUSION = $0002; 
+  AL_EAXREVERB_GAIN = $0003; 
+  AL_EAXREVERB_GAINHF = $0004; 
+  AL_EAXREVERB_GAINLF = $0005; 
+  AL_EAXREVERB_DECAY_TIME = $0006; 
+  AL_EAXREVERB_DECAY_HFRATIO = $0007; 
+  AL_EAXREVERB_DECAY_LFRATIO = $0008; 
+  AL_EAXREVERB_REFLECTIONS_GAIN = $0009; 
+  AL_EAXREVERB_REFLECTIONS_DELAY = $000A; 
+  AL_EAXREVERB_REFLECTIONS_PAN = $000B; 
+  AL_EAXREVERB_LATE_REVERB_GAIN = $000C; 
+  AL_EAXREVERB_LATE_REVERB_DELAY = $000D; 
+  AL_EAXREVERB_LATE_REVERB_PAN = $000E; 
+  AL_EAXREVERB_ECHO_TIME = $000F; 
+  AL_EAXREVERB_ECHO_DEPTH = $0010; 
+  AL_EAXREVERB_MODULATION_TIME = $0011; 
+  AL_EAXREVERB_MODULATION_DEPTH = $0012; 
+  AL_EAXREVERB_AIR_ABSORPTION_GAINHF = $0013; 
+  AL_EAXREVERB_HFREFERENCE = $0014; 
+  AL_EAXREVERB_LFREFERENCE = $0015; 
+  AL_EAXREVERB_ROOM_ROLLOFF_FACTOR = $0016; 
+  AL_EAXREVERB_DECAY_HFLIMIT = $0017; 
+  (* Chorus effect parameters *)
+  AL_CHORUS_WAVEFORM = $0001; 
+  AL_CHORUS_PHASE = $0002; 
+  AL_CHORUS_RATE = $0003; 
+  AL_CHORUS_DEPTH = $0004; 
+  AL_CHORUS_FEEDBACK = $0005; 
+  AL_CHORUS_DELAY = $0006; 
+  (* Distortion effect parameters *)
+  AL_DISTORTION_EDGE = $0001; 
+  AL_DISTORTION_GAIN = $0002; 
+  AL_DISTORTION_LOWPASS_CUTOFF = $0003; 
+  AL_DISTORTION_EQCENTER = $0004; 
+  AL_DISTORTION_EQBANDWIDTH = $0005; 
+  (* Echo effect parameters *)
+  AL_ECHO_DELAY = $0001; 
+  AL_ECHO_LRDELAY = $0002; 
+  AL_ECHO_DAMPING = $0003; 
+  AL_ECHO_FEEDBACK = $0004; 
+  AL_ECHO_SPREAD = $0005; 
+  (* Flanger effect parameters *)
+  AL_FLANGER_WAVEFORM = $0001; 
+  AL_FLANGER_PHASE = $0002; 
+  AL_FLANGER_RATE = $0003; 
+  AL_FLANGER_DEPTH = $0004; 
+  AL_FLANGER_FEEDBACK = $0005; 
+  AL_FLANGER_DELAY = $0006; 
+  (* Frequency shifter effect parameters *)
+  AL_FREQUENCY_SHIFTER_FREQUENCY = $0001; 
+  AL_FREQUENCY_SHIFTER_LEFT_DIRECTION = $0002; 
+  AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION = $0003; 
+  (* Vocal morpher effect parameters *)
+  AL_VOCAL_MORPHER_PHONEMEA = $0001; 
+  AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING = $0002; 
+  AL_VOCAL_MORPHER_PHONEMEB = $0003; 
+  AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING = $0004; 
+  AL_VOCAL_MORPHER_WAVEFORM = $0005; 
+  AL_VOCAL_MORPHER_RATE = $0006; 
+  (* Pitchshifter effect parameters *)
+  AL_PITCH_SHIFTER_COARSE_TUNE = $0001; 
+  AL_PITCH_SHIFTER_FINE_TUNE = $0002; 
+  (* Ringmodulator effect parameters *)
+  AL_RING_MODULATOR_FREQUENCY = $0001; 
+  AL_RING_MODULATOR_HIGHPASS_CUTOFF = $0002; 
+  AL_RING_MODULATOR_WAVEFORM = $0003; 
+  (* Autowah effect parameters *)
+  AL_AUTOWAH_ATTACK_TIME = $0001; 
+  AL_AUTOWAH_RELEASE_TIME = $0002; 
+  AL_AUTOWAH_RESONANCE = $0003; 
+  AL_AUTOWAH_PEAK_GAIN = $0004; 
+  (* Compressor effect parameters *)
+  AL_COMPRESSOR_ONOFF = $0001; 
+  (* Equalizer effect parameters *)
+  AL_EQUALIZER_LOW_GAIN = $0001; 
+  AL_EQUALIZER_LOW_CUTOFF = $0002; 
+  AL_EQUALIZER_MID1_GAIN = $0003; 
+  AL_EQUALIZER_MID1_CENTER = $0004; 
+  AL_EQUALIZER_MID1_WIDTH = $0005; 
+  AL_EQUALIZER_MID2_GAIN = $0006; 
+  AL_EQUALIZER_MID2_CENTER = $0007; 
+  AL_EQUALIZER_MID2_WIDTH = $0008; 
+  AL_EQUALIZER_HIGH_GAIN = $0009; 
+  AL_EQUALIZER_HIGH_CUTOFF = $000A; 
+  (* Effect type *)
+  AL_EFFECT_FIRST_PARAMETER = $0000; 
+  AL_EFFECT_LAST_PARAMETER = $8000; 
+  AL_EFFECT_TYPE = $8001; 
+  (* Effect types, used with the AL_EFFECT_TYPE property *)
+  AL_EFFECT_NULL = $0000; 
+  AL_EFFECT_REVERB = $0001; 
+  AL_EFFECT_CHORUS = $0002; 
+  AL_EFFECT_DISTORTION = $0003; 
+  AL_EFFECT_ECHO = $0004; 
+  AL_EFFECT_FLANGER = $0005; 
+  AL_EFFECT_FREQUENCY_SHIFTER = $0006; 
+  AL_EFFECT_VOCAL_MORPHER = $0007; 
+  AL_EFFECT_PITCH_SHIFTER = $0008; 
+  AL_EFFECT_RING_MODULATOR = $0009; 
+  AL_EFFECT_AUTOWAH = $000A; 
+  AL_EFFECT_COMPRESSOR = $000B; 
+  AL_EFFECT_EQUALIZER = $000C; 
+  AL_EFFECT_EAXREVERB = $8000; 
+  (* Auxiliary Effect Slot properties. *)
+  AL_EFFECTSLOT_EFFECT = $0001; 
+  AL_EFFECTSLOT_GAIN = $0002; 
+  AL_EFFECTSLOT_AUXILIARY_SEND_AUTO = $0003; 
+  (* NULL Auxiliary Slot ID to disable a source send. *)
+  AL_EFFECTSLOT_NULL = $0000; 
+  (* Filter properties. *)
+  (* Lowpass filter parameters *)
+  AL_LOWPASS_GAIN = $0001; 
+  AL_LOWPASS_GAINHF = $0002; 
+  (* Highpass filter parameters *)
+  AL_HIGHPASS_GAIN = $0001; 
+  AL_HIGHPASS_GAINLF = $0002; 
+  (* Bandpass filter parameters *)
+  AL_BANDPASS_GAIN = $0001; 
+  AL_BANDPASS_GAINLF = $0002; 
+  AL_BANDPASS_GAINHF = $0003; 
+  (* Filter type *)
+  AL_FILTER_FIRST_PARAMETER = $0000; 
+  AL_FILTER_LAST_PARAMETER = $8000; 
+  AL_FILTER_TYPE = $8001; 
+  (* Filter types, used with the AL_FILTER_TYPE property *)
+  AL_FILTER_NULL = $0000; 
+  AL_FILTER_LOWPASS = $0001; 
+  AL_FILTER_HIGHPASS = $0002; 
+  AL_FILTER_BANDPASS = $0003; 
+
+const
+  (* Filter ranges and defaults. *)
+  (* Lowpass filter *)
+  AL_LOWPASS_MIN_GAIN = 0.0; 
+  AL_LOWPASS_MAX_GAIN = 1.0; 
+  AL_LOWPASS_DEFAULT_GAIN = 1.0; 
+  AL_LOWPASS_MIN_GAINHF = 0.0; 
+  AL_LOWPASS_MAX_GAINHF = 1.0; 
+  AL_LOWPASS_DEFAULT_GAINHF = 1.0; 
+  (* Highpass filter *)
+  AL_HIGHPASS_MIN_GAIN = 0.0; 
+  AL_HIGHPASS_MAX_GAIN = 1.0; 
+  AL_HIGHPASS_DEFAULT_GAIN = 1.0; 
+  AL_HIGHPASS_MIN_GAINLF = 0.0; 
+  AL_HIGHPASS_MAX_GAINLF = 1.0; 
+  AL_HIGHPASS_DEFAULT_GAINLF = 1.0; 
+  (* Bandpass filter *)
+  AL_BANDPASS_MIN_GAIN = 0.0; 
+  AL_BANDPASS_MAX_GAIN = 1.0; 
+  AL_BANDPASS_DEFAULT_GAIN = 1.0; 
+  AL_BANDPASS_MIN_GAINHF = 0.0; 
+  AL_BANDPASS_MAX_GAINHF = 1.0; 
+  AL_BANDPASS_DEFAULT_GAINHF = 1.0; 
+  AL_BANDPASS_MIN_GAINLF = 0.0; 
+  AL_BANDPASS_MAX_GAINLF = 1.0; 
+  AL_BANDPASS_DEFAULT_GAINLF = 1.0; 
+  (* Effect parameter ranges and defaults. *)
+  (* Standard reverb effect *)
+  AL_REVERB_MIN_DENSITY = 0.0; 
+  AL_REVERB_MAX_DENSITY = 1.0; 
+  AL_REVERB_DEFAULT_DENSITY = 1.0; 
+  AL_REVERB_MIN_DIFFUSION = 0.0; 
+  AL_REVERB_MAX_DIFFUSION = 1.0; 
+  AL_REVERB_DEFAULT_DIFFUSION = 1.0; 
+  AL_REVERB_MIN_GAIN = 0.0; 
+  AL_REVERB_MAX_GAIN = 1.0; 
+  AL_REVERB_DEFAULT_GAIN = 0.32; 
+  AL_REVERB_MIN_GAINHF = 0.0; 
+  AL_REVERB_MAX_GAINHF = 1.0; 
+  AL_REVERB_DEFAULT_GAINHF = 0.89; 
+  AL_REVERB_MIN_DECAY_TIME = 0.1; 
+  AL_REVERB_MAX_DECAY_TIME = 20.0; 
+  AL_REVERB_DEFAULT_DECAY_TIME = 1.49; 
+  AL_REVERB_MIN_DECAY_HFRATIO = 0.1; 
+  AL_REVERB_MAX_DECAY_HFRATIO = 2.0; 
+  AL_REVERB_DEFAULT_DECAY_HFRATIO = 0.83; 
+  AL_REVERB_MIN_REFLECTIONS_GAIN = 0.0; 
+  AL_REVERB_MAX_REFLECTIONS_GAIN = 3.16; 
+  AL_REVERB_DEFAULT_REFLECTIONS_GAIN = 0.5; 
+  AL_REVERB_MIN_REFLECTIONS_DELAY = 0.0; 
+  AL_REVERB_MAX_REFLECTIONS_DELAY = 0.3; 
+  AL_REVERB_DEFAULT_REFLECTIONS_DELAY = 0.7; 
+  AL_REVERB_MIN_LATE_REVERB_GAIN = 0.0; 
+  AL_REVERB_MAX_LATE_REVERB_GAIN = 10.0; 
+  AL_REVERB_DEFAULT_LATE_REVERB_GAIN = 1.26; 
+  AL_REVERB_MIN_LATE_REVERB_DELAY = 0.0; 
+  AL_REVERB_MAX_LATE_REVERB_DELAY = 0.1; 
+  AL_REVERB_DEFAULT_LATE_REVERB_DELAY = 0.9; 
+  AL_REVERB_MIN_AIR_ABSORPTION_GAINHF = 0.892; 
+  AL_REVERB_MAX_AIR_ABSORPTION_GAINHF = 1.0; 
+  AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF = 0.994; 
+  AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR = 0.0; 
+  AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR = 10.0; 
+  AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR = 0.0; 
+  AL_REVERB_MIN_DECAY_HFLIMIT = AL_FALSE; 
+  AL_REVERB_MAX_DECAY_HFLIMIT = AL_TRUE; 
+  AL_REVERB_DEFAULT_DECAY_HFLIMIT = AL_TRUE; 
+  (* EAX reverb effect *)
+  AL_EAXREVERB_MIN_DENSITY = 0.0; 
+  AL_EAXREVERB_MAX_DENSITY = 1.0; 
+  AL_EAXREVERB_DEFAULT_DENSITY = 1.0; 
+  AL_EAXREVERB_MIN_DIFFUSION = 0.0; 
+  AL_EAXREVERB_MAX_DIFFUSION = 1.0; 
+  AL_EAXREVERB_DEFAULT_DIFFUSION = 1.0; 
+  AL_EAXREVERB_MIN_GAIN = 0.0; 
+  AL_EAXREVERB_MAX_GAIN = 1.0; 
+  AL_EAXREVERB_DEFAULT_GAIN = 0.32; 
+  AL_EAXREVERB_MIN_GAINHF = 0.0; 
+  AL_EAXREVERB_MAX_GAINHF = 1.0; 
+  AL_EAXREVERB_DEFAULT_GAINHF = 0.89; 
+  AL_EAXREVERB_MIN_GAINLF = 0.0; 
+  AL_EAXREVERB_MAX_GAINLF = 1.0; 
+  AL_EAXREVERB_DEFAULT_GAINLF = 1.0; 
+  AL_EAXREVERB_MIN_DECAY_TIME = 0.1; 
+  AL_EAXREVERB_MAX_DECAY_TIME = 20.0; 
+  AL_EAXREVERB_DEFAULT_DECAY_TIME = 1.49; 
+  AL_EAXREVERB_MIN_DECAY_HFRATIO = 0.1; 
+  AL_EAXREVERB_MAX_DECAY_HFRATIO = 2.0; 
+  AL_EAXREVERB_DEFAULT_DECAY_HFRATIO = 0.83; 
+  AL_EAXREVERB_MIN_DECAY_LFRATIO = 0.1; 
+  AL_EAXREVERB_MAX_DECAY_LFRATIO = 2.0; 
+  AL_EAXREVERB_DEFAULT_DECAY_LFRATIO = 1.0; 
+  AL_EAXREVERB_MIN_REFLECTIONS_GAIN = 0.0; 
+  AL_EAXREVERB_MAX_REFLECTIONS_GAIN = 3.16; 
+  AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN = 0.5; 
+  AL_EAXREVERB_MIN_REFLECTIONS_DELAY = 0.0; 
+  AL_EAXREVERB_MAX_REFLECTIONS_DELAY = 0.3; 
+  AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY = 0.7; 
+  AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ = 0.0; 
+  AL_EAXREVERB_MIN_LATE_REVERB_GAIN = 0.0; 
+  AL_EAXREVERB_MAX_LATE_REVERB_GAIN = 10.0; 
+  AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN = 1.26; 
+  AL_EAXREVERB_MIN_LATE_REVERB_DELAY = 0.0; 
+  AL_EAXREVERB_MAX_LATE_REVERB_DELAY = 0.1; 
+  AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY = 0.9; 
+  AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ = 0.0; 
+  AL_EAXREVERB_MIN_ECHO_TIME = 0.3;
+  AL_EAXREVERB_MAX_ECHO_TIME = 0.25; 
+  AL_EAXREVERB_DEFAULT_ECHO_TIME = 0.25; 
+  AL_EAXREVERB_MIN_ECHO_DEPTH = 0.0; 
+  AL_EAXREVERB_MAX_ECHO_DEPTH = 1.0; 
+  AL_EAXREVERB_DEFAULT_ECHO_DEPTH = 0.0; 
+  AL_EAXREVERB_MIN_MODULATION_TIME = 0.4; 
+  AL_EAXREVERB_MAX_MODULATION_TIME = 4.0; 
+  AL_EAXREVERB_DEFAULT_MODULATION_TIME = 0.25; 
+  AL_EAXREVERB_MIN_MODULATION_DEPTH = 0.0; 
+  AL_EAXREVERB_MAX_MODULATION_DEPTH = 1.0; 
+  AL_EAXREVERB_DEFAULT_MODULATION_DEPTH = 0.0; 
+  AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF = 0.892; 
+  AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF = 1.0; 
+  AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF = 0.994; 
+  AL_EAXREVERB_MIN_HFREFERENCE = 1000.0; 
+  AL_EAXREVERB_MAX_HFREFERENCE = 20000.0; 
+  AL_EAXREVERB_DEFAULT_HFREFERENCE = 5000.0; 
+  AL_EAXREVERB_MIN_LFREFERENCE = 20.0; 
+  AL_EAXREVERB_MAX_LFREFERENCE = 1000.0; 
+  AL_EAXREVERB_DEFAULT_LFREFERENCE = 250.0; 
+  AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR = 0.0; 
+  AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR = 10.0; 
+  AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR = 0.0; 
+  AL_EAXREVERB_MIN_DECAY_HFLIMIT = AL_FALSE; 
+  AL_EAXREVERB_MAX_DECAY_HFLIMIT = AL_TRUE; 
+  AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT = AL_TRUE; 
+  (* Chorus effect *)
+  AL_CHORUS_WAVEFORM_SINUSOID = 0; 
+  AL_CHORUS_WAVEFORM_TRIANGLE = 1; 
+  AL_CHORUS_MIN_WAVEFORM = 0; 
+  AL_CHORUS_MAX_WAVEFORM = 1; 
+  AL_CHORUS_DEFAULT_WAVEFORM = 1; 
+  AL_CHORUS_MIN_PHASE = -180; 
+  AL_CHORUS_MAX_PHASE = 180; 
+  AL_CHORUS_DEFAULT_PHASE = 90; 
+  AL_CHORUS_MIN_RATE = 0.0; 
+  AL_CHORUS_MAX_RATE = 10.0; 
+  AL_CHORUS_DEFAULT_RATE = 1.1; 
+  AL_CHORUS_MIN_DEPTH = 0.0; 
+  AL_CHORUS_MAX_DEPTH = 1.0; 
+  AL_CHORUS_DEFAULT_DEPTH = 0.1; 
+  AL_CHORUS_MIN_FEEDBACK = -1.0; 
+  AL_CHORUS_MAX_FEEDBACK = 1.0; 
+  AL_CHORUS_DEFAULT_FEEDBACK = 0.25; 
+  AL_CHORUS_MIN_DELAY = 0.0; 
+  AL_CHORUS_MAX_DELAY = 0.016; 
+  AL_CHORUS_DEFAULT_DELAY = 0.016; 
+  (* Distortion effect *)
+  AL_DISTORTION_MIN_EDGE = 0.0; 
+  AL_DISTORTION_MAX_EDGE = 1.0; 
+  AL_DISTORTION_DEFAULT_EDGE = 0.2; 
+  AL_DISTORTION_MIN_GAIN = 0.1; 
+  AL_DISTORTION_MAX_GAIN = 1.0; 
+  AL_DISTORTION_DEFAULT_GAIN = 0.5; 
+  AL_DISTORTION_MIN_LOWPASS_CUTOFF = 80.0; 
+  AL_DISTORTION_MAX_LOWPASS_CUTOFF = 24000.0; 
+  AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF = 8000.0; 
+  AL_DISTORTION_MIN_EQCENTER = 80.0; 
+  AL_DISTORTION_MAX_EQCENTER = 24000.0; 
+  AL_DISTORTION_DEFAULT_EQCENTER = 3600.0; 
+  AL_DISTORTION_MIN_EQBANDWIDTH = 80.0; 
+  AL_DISTORTION_MAX_EQBANDWIDTH = 24000.0; 
+  AL_DISTORTION_DEFAULT_EQBANDWIDTH = 3600.0; 
+  (* Echo effect *)
+  AL_ECHO_MIN_DELAY = 0.0; 
+  AL_ECHO_MAX_DELAY = 0.207; 
+  AL_ECHO_DEFAULT_DELAY = 0.1; 
+  AL_ECHO_MIN_LRDELAY = 0.0; 
+  AL_ECHO_MAX_LRDELAY = 0.404; 
+  AL_ECHO_DEFAULT_LRDELAY = 0.1; 
+  AL_ECHO_MIN_DAMPING = 0.0; 
+  AL_ECHO_MAX_DAMPING = 0.99; 
+  AL_ECHO_DEFAULT_DAMPING = 0.5; 
+  AL_ECHO_MIN_FEEDBACK = 0.0; 
+  AL_ECHO_MAX_FEEDBACK = 1.0; 
+  AL_ECHO_DEFAULT_FEEDBACK = 0.5; 
+  AL_ECHO_MIN_SPREAD = -1.0; 
+  AL_ECHO_MAX_SPREAD = 1.0; 
+  AL_ECHO_DEFAULT_SPREAD = -1.0; 
+  (* Flanger effect *)
+  AL_FLANGER_WAVEFORM_SINUSOID = 0; 
+  AL_FLANGER_WAVEFORM_TRIANGLE = 1; 
+  AL_FLANGER_MIN_WAVEFORM = 0; 
+  AL_FLANGER_MAX_WAVEFORM = 1; 
+  AL_FLANGER_DEFAULT_WAVEFORM = 1; 
+  AL_FLANGER_MIN_PHASE = -180; 
+  AL_FLANGER_MAX_PHASE = 180; 
+  AL_FLANGER_DEFAULT_PHASE = 0; 
+  AL_FLANGER_MIN_RATE = 0.0; 
+  AL_FLANGER_MAX_RATE = 10.0; 
+  AL_FLANGER_DEFAULT_RATE = 0.27; 
+  AL_FLANGER_MIN_DEPTH = 0.0; 
+  AL_FLANGER_MAX_DEPTH = 1.0; 
+  AL_FLANGER_DEFAULT_DEPTH = 1.0; 
+  AL_FLANGER_MIN_FEEDBACK = -1.0; 
+  AL_FLANGER_MAX_FEEDBACK = 1.0; 
+  AL_FLANGER_DEFAULT_FEEDBACK = -0.5; 
+  AL_FLANGER_MIN_DELAY = 0.0; 
+  AL_FLANGER_MAX_DELAY = 0.4; 
+  AL_FLANGER_DEFAULT_DELAY = 0.2; 
+  (* Frequency shifter effect *)
+  AL_FREQUENCY_SHIFTER_MIN_FREQUENCY = 0.0; 
+  AL_FREQUENCY_SHIFTER_MAX_FREQUENCY = 24000.0; 
+  AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY = 0.0; 
+  AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION = 0; 
+  AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION = 2; 
+  AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION = 0; 
+  AL_FREQUENCY_SHIFTER_DIRECTION_DOWN = 0; 
+  AL_FREQUENCY_SHIFTER_DIRECTION_UP = 1; 
+  AL_FREQUENCY_SHIFTER_DIRECTION_OFF = 2; 
+  AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION = 0; 
+  AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION = 2; 
+  AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION = 0; 
+  (* Vocal morpher effect *)
+  AL_VOCAL_MORPHER_MIN_PHONEMEA = 0; 
+  AL_VOCAL_MORPHER_MAX_PHONEMEA = 29; 
+  AL_VOCAL_MORPHER_DEFAULT_PHONEMEA = 0; 
+  AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING = -24; 
+  AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING = 24; 
+  AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING = 0; 
+  AL_VOCAL_MORPHER_MIN_PHONEMEB = 0; 
+  AL_VOCAL_MORPHER_MAX_PHONEMEB = 29; 
+  AL_VOCAL_MORPHER_DEFAULT_PHONEMEB = 10; 
+  AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING = -24; 
+  AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING = 24; 
+  AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING = 0; 
+  AL_VOCAL_MORPHER_PHONEME_A = 0; 
+  AL_VOCAL_MORPHER_PHONEME_E = 1; 
+  AL_VOCAL_MORPHER_PHONEME_I = 2; 
+  AL_VOCAL_MORPHER_PHONEME_O = 3; 
+  AL_VOCAL_MORPHER_PHONEME_U = 4; 
+  AL_VOCAL_MORPHER_PHONEME_AA = 5; 
+  AL_VOCAL_MORPHER_PHONEME_AE = 6; 
+  AL_VOCAL_MORPHER_PHONEME_AH = 7; 
+  AL_VOCAL_MORPHER_PHONEME_AO = 8; 
+  AL_VOCAL_MORPHER_PHONEME_EH = 9; 
+  AL_VOCAL_MORPHER_PHONEME_ER = 10; 
+  AL_VOCAL_MORPHER_PHONEME_IH = 11; 
+  AL_VOCAL_MORPHER_PHONEME_IY = 12; 
+  AL_VOCAL_MORPHER_PHONEME_UH = 13; 
+  AL_VOCAL_MORPHER_PHONEME_UW = 14; 
+  AL_VOCAL_MORPHER_PHONEME_B = 15; 
+  AL_VOCAL_MORPHER_PHONEME_D = 16; 
+  AL_VOCAL_MORPHER_PHONEME_F = 17; 
+  AL_VOCAL_MORPHER_PHONEME_G = 18; 
+  AL_VOCAL_MORPHER_PHONEME_J = 19; 
+  AL_VOCAL_MORPHER_PHONEME_K = 20; 
+  AL_VOCAL_MORPHER_PHONEME_L = 21; 
+  AL_VOCAL_MORPHER_PHONEME_M = 22; 
+  AL_VOCAL_MORPHER_PHONEME_N = 23; 
+  AL_VOCAL_MORPHER_PHONEME_P = 24; 
+  AL_VOCAL_MORPHER_PHONEME_R = 25; 
+  AL_VOCAL_MORPHER_PHONEME_S = 26; 
+  AL_VOCAL_MORPHER_PHONEME_T = 27; 
+  AL_VOCAL_MORPHER_PHONEME_V = 28; 
+  AL_VOCAL_MORPHER_PHONEME_Z = 29; 
+  AL_VOCAL_MORPHER_WAVEFORM_SINUSOID = 0; 
+  AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE = 1; 
+  AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH = 2; 
+  AL_VOCAL_MORPHER_MIN_WAVEFORM = 0; 
+  AL_VOCAL_MORPHER_MAX_WAVEFORM = 2; 
+  AL_VOCAL_MORPHER_DEFAULT_WAVEFORM = 0; 
+  AL_VOCAL_MORPHER_MIN_RATE = 0.0; 
+  AL_VOCAL_MORPHER_MAX_RATE = 10.0; 
+  AL_VOCAL_MORPHER_DEFAULT_RATE = 1.41; 
+  (* Pitch shifter effect *)
+  AL_PITCH_SHIFTER_MIN_COARSE_TUNE = -12; 
+  AL_PITCH_SHIFTER_MAX_COARSE_TUNE = 12; 
+  AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE = 12; 
+  AL_PITCH_SHIFTER_MIN_FINE_TUNE = -50; 
+  AL_PITCH_SHIFTER_MAX_FINE_TUNE = 50; 
+  AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE = 0; 
+  (* Ring modulator effect *)
+  AL_RING_MODULATOR_MIN_FREQUENCY = 0.0; 
+  AL_RING_MODULATOR_MAX_FREQUENCY = 8000.0; 
+  AL_RING_MODULATOR_DEFAULT_FREQUENCY = 440.0; 
+  AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF = 0.0; 
+  AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF = 24000.0; 
+  AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF = 800.0; 
+  AL_RING_MODULATOR_SINUSOID = 0; 
+  AL_RING_MODULATOR_SAWTOOTH = 1; 
+  AL_RING_MODULATOR_SQUARE = 2; 
+  AL_RING_MODULATOR_MIN_WAVEFORM = 0; 
+  AL_RING_MODULATOR_MAX_WAVEFORM = 2; 
+  AL_RING_MODULATOR_DEFAULT_WAVEFORM = 0; 
+  (* Autowah effect *)
+  AL_AUTOWAH_MIN_ATTACK_TIME = 0.1; 
+  AL_AUTOWAH_MAX_ATTACK_TIME = 1.0; 
+  AL_AUTOWAH_DEFAULT_ATTACK_TIME = 0.6; 
+  AL_AUTOWAH_MIN_RELEASE_TIME = 0.1; 
+  AL_AUTOWAH_MAX_RELEASE_TIME = 1.0; 
+  AL_AUTOWAH_DEFAULT_RELEASE_TIME = 0.6; 
+  AL_AUTOWAH_MIN_RESONANCE = 2.0; 
+  AL_AUTOWAH_MAX_RESONANCE = 1000.0; 
+  AL_AUTOWAH_DEFAULT_RESONANCE = 1000.0; 
+  AL_AUTOWAH_MIN_PEAK_GAIN = 0.3; 
+  AL_AUTOWAH_MAX_PEAK_GAIN = 31621.0; 
+  AL_AUTOWAH_DEFAULT_PEAK_GAIN = 11.22; 
+  (* Compressor effect *)
+  AL_COMPRESSOR_MIN_ONOFF = 0; 
+  AL_COMPRESSOR_MAX_ONOFF = 1; 
+  AL_COMPRESSOR_DEFAULT_ONOFF = 1; 
+  (* Equalizer effect *)
+  AL_EQUALIZER_MIN_LOW_GAIN = 0.126; 
+  AL_EQUALIZER_MAX_LOW_GAIN = 7.943; 
+  AL_EQUALIZER_DEFAULT_LOW_GAIN = 1.0; 
+  AL_EQUALIZER_MIN_LOW_CUTOFF = 50.0; 
+  AL_EQUALIZER_MAX_LOW_CUTOFF = 800.0; 
+  AL_EQUALIZER_DEFAULT_LOW_CUTOFF = 200.0; 
+  AL_EQUALIZER_MIN_MID1_GAIN = 0.126; 
+  AL_EQUALIZER_MAX_MID1_GAIN = 7.943; 
+  AL_EQUALIZER_DEFAULT_MID1_GAIN = 1.0; 
+  AL_EQUALIZER_MIN_MID1_CENTER = 200.0; 
+  AL_EQUALIZER_MAX_MID1_CENTER = 3000.0; 
+  AL_EQUALIZER_DEFAULT_MID1_CENTER = 500.0; 
+  AL_EQUALIZER_MIN_MID1_WIDTH = 0.1; 
+  AL_EQUALIZER_MAX_MID1_WIDTH = 1.0; 
+  AL_EQUALIZER_DEFAULT_MID1_WIDTH = 1.0; 
+  AL_EQUALIZER_MIN_MID2_GAIN = 0.126; 
+  AL_EQUALIZER_MAX_MID2_GAIN = 7.943; 
+  AL_EQUALIZER_DEFAULT_MID2_GAIN = 1.0; 
+  AL_EQUALIZER_MIN_MID2_CENTER = 1000.0; 
+  AL_EQUALIZER_MAX_MID2_CENTER = 8000.0; 
+  AL_EQUALIZER_DEFAULT_MID2_CENTER = 3000.0; 
+  AL_EQUALIZER_MIN_MID2_WIDTH = 0.1; 
+  AL_EQUALIZER_MAX_MID2_WIDTH = 1.0; 
+  AL_EQUALIZER_DEFAULT_MID2_WIDTH = 1.0; 
+  AL_EQUALIZER_MIN_HIGH_GAIN = 0.126; 
+  AL_EQUALIZER_MAX_HIGH_GAIN = 7.943; 
+  AL_EQUALIZER_DEFAULT_HIGH_GAIN = 1.0; 
+  AL_EQUALIZER_MIN_HIGH_CUTOFF = 4000.0; 
+  AL_EQUALIZER_MAX_HIGH_CUTOFF = 16000.0; 
+  AL_EQUALIZER_DEFAULT_HIGH_CUTOFF = 6000.0; 
+  (* Source parameter value ranges and defaults. *)
+  AL_MIN_AIR_ABSORPTION_FACTOR = 0.0; 
+  AL_MAX_AIR_ABSORPTION_FACTOR = 10.0; 
+  AL_DEFAULT_AIR_ABSORPTION_FACTOR = 0.0; 
+  AL_MIN_ROOM_ROLLOFF_FACTOR = 0.0; 
+  AL_MAX_ROOM_ROLLOFF_FACTOR = 10.0; 
+  AL_DEFAULT_ROOM_ROLLOFF_FACTOR = 0.0; 
+  AL_MIN_CONE_OUTER_GAINHF = 0.0; 
+  AL_MAX_CONE_OUTER_GAINHF = 1.0; 
+  AL_DEFAULT_CONE_OUTER_GAINHF = 1.0; 
+  AL_MIN_DIRECT_FILTER_GAINHF_AUTO = AL_FALSE; 
+  AL_MAX_DIRECT_FILTER_GAINHF_AUTO = AL_TRUE; 
+  AL_DEFAULT_DIRECT_FILTER_GAINHF_AUTO = AL_TRUE; 
+  AL_MIN_AUXILIARY_SEND_FILTER_GAIN_AUTO = AL_FALSE; 
+  AL_MAX_AUXILIARY_SEND_FILTER_GAIN_AUTO = AL_TRUE; 
+  AL_DEFAULT_AUXILIARY_SEND_FILTER_GAIN_AUTO = AL_TRUE; 
+  AL_MIN_AUXILIARY_SEND_FILTER_GAINHF_AUTO = AL_FALSE; 
+  AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO = AL_TRUE; 
+  AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO = AL_TRUE; 
+  (* Listener parameter value ranges and defaults. *)
+  AL_MIN_METERS_PER_UNIT = 0.0; // FIXME: was FLT_MIN
+  AL_MAX_METERS_PER_UNIT = 1e10; // FIXME: was FLT_MAX
+  AL_DEFAULT_METERS_PER_UNIT = 1.0;
+
+procedure alGenEffects(n: ALsizei;  effects: pALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alDeleteEffects(n: ALsizei;  effects: pALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alIsEffect(effect: ALuint): ALboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alEffecti(effect: ALuint;  param: ALenum;  iValue: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alEffectiv(effect: ALuint;  param: ALenum;  piValues: pALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alEffectf(effect: ALuint;  param: ALenum;  flValue: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alEffectfv(effect: ALuint;  param: ALenum;  pflValues: pALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetEffecti(effect: ALuint;  param: ALenum;  piValue: pALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetEffectiv(effect: ALuint;  param: ALenum;  piValues: pALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetEffectf(effect: ALuint;  param: ALenum;  pflValue: pALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetEffectfv(effect: ALuint;  param: ALenum;  pflValues: pALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGenFilters(n: ALsizei;  filters: pALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alDeleteFilters(n: ALsizei;  filters: pALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alIsFilter(filter: ALuint): ALboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alFilteri(filter: ALuint;  param: ALenum;  iValue: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alFilteriv(filter: ALuint;  param: ALenum;  piValues: pALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alFilterf(filter: ALuint;  param: ALenum;  flValue: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alFilterfv(filter: ALuint;  param: ALenum;  pflValues: pALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetFilteri(filter: ALuint;  param: ALenum;  piValue: pALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetFilteriv(filter: ALuint;  param: ALenum;  piValues: pALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetFilterf(filter: ALuint;  param: ALenum;  pflValue: pALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetFilterfv(filter: ALuint;  param: ALenum;  pflValues: pALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGenAuxiliaryEffectSlots(n: ALsizei;  effectslots: pALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alDeleteAuxiliaryEffectSlots(n: ALsizei;  effectslots: pALuint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+function alIsAuxiliaryEffectSlot(effectslot: ALuint): ALboolean; cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alAuxiliaryEffectSloti(effectslot: ALuint;  param: ALenum;  iValue: ALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alAuxiliaryEffectSlotiv(effectslot: ALuint;  param: ALenum;  piValues: pALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alAuxiliaryEffectSlotf(effectslot: ALuint;  param: ALenum;  flValue: ALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alAuxiliaryEffectSlotfv(effectslot: ALuint;  param: ALenum;  pflValues: pALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetAuxiliaryEffectSloti(effectslot: ALuint;  param: ALenum;  piValue: pALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetAuxiliaryEffectSlotiv(effectslot: ALuint;  param: ALenum;  piValues: pALint); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetAuxiliaryEffectSlotf(effectslot: ALuint;  param: ALenum;  pflValue: pALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+procedure alGetAuxiliaryEffectSlotfv(effectslot: ALuint;  param: ALenum;  pflValues: pALfloat); cdecl; external {$IFDEF AL_DYNAMIC}openallib{$ENDIF};
+
+{
+type
+  /* Effect object function types. */
+  typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*);
+  typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*);
+  typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint);
+  typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint);
+  typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*);
+  typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat);
+  typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*);
+  typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*);
+  typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*);
+  typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*);
+  typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*);
+
+  /* Filter object function types. */
+  typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*);
+  typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*);
+  typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint);
+  typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint);
+  typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*);
+  typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat);
+  typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*);
+  typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*);
+  typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*);
+  typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*);
+  typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*);
+
+  /* Auxiliary Effect Slot object function types. */
+  typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*);
+  typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*);
+  typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint);
+  typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint);
+  typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*);
+  typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat);
+  typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*);
+  typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*);
+  typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*);
+  typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*);
+  typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*);
+}
\ No newline at end of file