koda's OpenAL conversion:
- Freezes program for fadein/fadeout time
- Has a problem with quickplay
--- a/CMakeLists.txt Mon Jun 22 13:49:16 2009 +0000
+++ b/CMakeLists.txt Wed Jun 24 15:59:32 2009 +0000
@@ -43,6 +43,7 @@
endif(WITH_SERVER)
add_subdirectory(bin)
+add_subdirectory(openalbridge)
add_subdirectory(QTfrontend)
add_subdirectory(hedgewars)
add_subdirectory(share)
--- a/QTfrontend/CMakeLists.txt Mon Jun 22 13:49:16 2009 +0000
+++ b/QTfrontend/CMakeLists.txt Wed Jun 24 15:59:32 2009 +0000
@@ -17,10 +17,11 @@
# Configure for SDL
find_package(SDL REQUIRED)
-find_package(SDL_mixer REQUIRED)
+find_package(OpenAL REQUIRED)
+find_package(OggVorbis REQUIRED)
include_directories(${SDL_INCLUDE_DIR})
-include_directories(${SDLMIXER_INCLUDE_DIR})
+
if(UNIX)
include_directories("/usr/local/include") # HACK: in freebsd cannot find iconv.h included via SDL.h
endif(UNIX)
@@ -164,13 +165,18 @@
${hwfr_moc_srcs}
${hwfr_hdrs}
${hwfr_rez_src})
-
+
+find_library(OPENALBRIDGE_LIBRARY libopenalbridge.a PATH ${EXECUTABLE_OUTPUT_PATH} )
+
set(HW_LINK_LIBS
${QT_LIBRARIES}
-# ${QCA2_LIBRARIES}
${SDL_LIBRARY}
- ${SDLMIXER_LIBRARY}
- )
+ ${OPENAL_LIBRARY}
+ ${OGG_LIBRARY}
+ ${VORBIS_LIBRARY}
+ ${VORBISFILE_LIBRARY}
+ ${OPENALBRIDGE_LIBRARY}
+)
if(WIN32 AND NOT UNIX)
if(NOT SDL_LIBRARY)
--- a/QTfrontend/SDLs.cpp Mon Jun 22 13:49:16 2009 +0000
+++ b/QTfrontend/SDLs.cpp Wed Jun 24 15:59:32 2009 +0000
@@ -23,14 +23,17 @@
SDLInteraction::SDLInteraction()
{
- music = NULL;
+ music = -1;
SDL_Init(SDL_INIT_VIDEO);
+ openal_init(50);
+
}
SDLInteraction::~SDLInteraction()
{
SDL_Quit();
+ openal_close();
}
QStringList SDLInteraction::getResolutions() const
@@ -53,21 +56,18 @@
return result;
}
+
void SDLInteraction::StartMusic()
{
- if (!music)
- {
- SDL_Init(SDL_INIT_AUDIO);
- Mix_OpenAudio(22050, 0x8010, 2, 512);
-
- Mix_VolumeMusic(33);
- music = Mix_LoadMUS(QString(datadir->absolutePath() + "/Music/main theme.ogg").toLocal8Bit().constData());
+ if (music < 0) {
+ music = openal_loadfile(QString(datadir->absolutePath() + "/Music/main theme.ogg").toLocal8Bit().constData());
+ openal_toggleloop(music);
+ openal_setvolume(music,66);
}
-
- Mix_FadeInMusic(music, -1, 3000);
+ openal_fadein(music, 50);
}
void SDLInteraction::StopMusic()
{
- Mix_FadeOutMusic(2000);
+ openal_fadeout(music, 50);
}
--- a/QTfrontend/SDLs.h Mon Jun 22 13:49:16 2009 +0000
+++ b/QTfrontend/SDLs.h Wed Jun 24 15:59:32 2009 +0000
@@ -21,15 +21,27 @@
#include <QStringList>
-#include "SDL_mixer.h"
+//#include "SDL_mixer.h"
+extern "C" int openal_init (int);
+extern "C" int openal_close (void);
+extern "C" int openal_loadfile (const char*);
+extern "C" int openal_toggleloop (int);
+extern "C" int openal_setvolume (int, unsigned char);
+extern "C" int openal_setglobalvolume (unsigned char);
+extern "C" int openal_togglemute (void);
+extern "C" int openal_fadeout (int, unsigned int);
+extern "C" int openal_fadein (int, unsigned int);
+extern "C" int openal_playsound (int);
+extern "C" int openal_stopsound (int);
+extern "C" int openal_pausesound (int);
class SDLInteraction : public QObject
{
Q_OBJECT
private:
- Mix_Music * music;
+ int music;
public:
SDLInteraction();
--- a/QTfrontend/pages.cpp Mon Jun 22 13:49:16 2009 +0000
+++ b/QTfrontend/pages.cpp Wed Jun 24 15:59:32 2009 +0000
@@ -37,7 +37,6 @@
#include <QTableWidget>
#include <QAction>
#include <QMenu>
-#include <QSound>
#include <QDataWidgetMapper>
@@ -61,6 +60,7 @@
#include "misc.h"
#include "togglebutton.h"
#include "hwform.h"
+#include "SDLs.h"
PageMain::PageMain(QWidget* parent) :
AbstractPage(parent)
@@ -290,9 +290,14 @@
tmpdir.cd(datadir->absolutePath());
tmpdir.cd("Sounds/voices");
tmpdir.cd(CBVoicepack->currentText());
- QStringList list = tmpdir.entryList(QStringList() << "*.wav", QDir::Files);
- if (list.size())
- QSound::play(tmpdir.absolutePath() + "/" + list[rand() % list.size()]);
+ QStringList list = tmpdir.entryList(QStringList() << "Illgetyou.ogg" << "Incoming.ogg" << "Stupid.ogg" << "Coward.ogg" << "Firstblood.ogg", QDir::Files);
+ if (list.size()) {
+ // printf("%s\n", QString(tmpdir.absolutePath() + "/" + list[rand() % list.size()]).toLocal8Bit().constData());
+ int tmp =openal_loadfile(QString(tmpdir.absolutePath() + "/" + list[rand() % list.size()]).toLocal8Bit().constData());
+ openal_playsound(tmp);
+ }
+
+ //QSound::play(tmpdir.absolutePath() + "/" + list[rand() % list.size()]);
}
PageMultiplayer::PageMultiplayer(QWidget* parent) :
--- a/cmake_modules/FindQCA2.cmake Mon Jun 22 13:49:16 2009 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-# - Try to find QCA2 (Qt Cryptography Architecture 2)
-# Once done this will define
-#
-# QCA2_FOUND - system has QCA2
-# QCA2_INCLUDE_DIR - the QCA2 include directory
-# QCA2_LIBRARIES - the libraries needed to use QCA2
-# QCA2_DEFINITIONS - Compiler switches required for using QCA2
-#
-# use pkg-config to get the directories and then use these values
-# in the FIND_PATH() and FIND_LIBRARY() calls
-
-# Copyright (c) 2006, Michael Larouche, <michael.larouche@kdemail.net>
-#
-# Redistribution and use is allowed according to the terms of the BSD license.
-# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
-
-include(FindLibraryWithDebug)
-
-if (QCA2_INCLUDE_DIR AND QCA2_LIBRARIES)
-
- # in cache already
- set(QCA2_FOUND TRUE)
-
-else (QCA2_INCLUDE_DIR AND QCA2_LIBRARIES)
-
-
- if (NOT WIN32)
- find_package(PkgConfig)
- pkg_check_modules(PC_QCA2 qca2)
- set(QCA2_DEFINITIONS ${PC_QCA2_CFLAGS_OTHER})
- endif (NOT WIN32)
-
- find_library_with_debug(QCA2_LIBRARIES
- WIN32_DEBUG_POSTFIX d
- NAMES qca
- HINTS ${PC_QCA2_LIBDIR} ${PC_QCA2_LIBRARY_DIRS}
- )
-
- find_path(QCA2_INCLUDE_DIR qca.h
- HINTS ${PC_QCA2_INCLUDEDIR} ${PC_QCA2_INCLUDE_DIRS}
- PATH_SUFFIXES QtCrypto)
-
- include(FindPackageHandleStandardArgs)
- find_package_handle_standard_args(QCA2 DEFAULT_MSG QCA2_LIBRARIES QCA2_INCLUDE_DIR)
-
- mark_as_advanced(QCA2_INCLUDE_DIR QCA2_LIBRARIES)
-
-endif (QCA2_INCLUDE_DIR AND QCA2_LIBRARIES)
--- a/hedgewars/CMakeLists.txt Mon Jun 22 13:49:16 2009 +0000
+++ b/hedgewars/CMakeLists.txt Wed Jun 24 15:59:32 2009 +0000
@@ -113,7 +113,7 @@
message("Minimum required version of FreePascal is 2.2.0")
else (fpc_ver LESS "020200")
set(pascal_compiler ${fpc_executable})
- set(pascal_compiler_flags ${noexecstack_flags} "-B" "-FE../bin" "-Fl../bin" "-Cs2000000" "-vwi" "-O2" ${hwengine_project})
+ set(pascal_compiler_flags ${noexecstack_flags} "-B" "-FE../bin" "-Fl../bin/" "-Fl../openalbridge/" "-Cs2000000" "-vwi" "-O2" ${hwengine_project})
endif (fpc_ver LESS "020200")
endif (fpc_version)
@@ -154,7 +154,7 @@
add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/hwengine${CMAKE_EXECUTABLE_SUFFIX}"
COMMAND "lipo"
ARGS ${EXECUTABLE_OUTPUT_PATH}/hwengine${CMAKE_EXECUTABLE_SUFFIX}.386 ${EXECUTABLE_OUTPUT_PATH}/hwengine${CMAKE_EXECUTABLE_SUFFIX}.ppc -create -output ${EXECUTABLE_OUTPUT_PATH}/hwengine${CMAKE_EXECUTABLE_SUFFIX}
- DEPENDS "${EXECUTABLE_OUTPUT_PATH}/hwengine${CMAKE_EXECUTABLE_SUFFIX}.386" "${EXECUTABLE_OUTPUT_PATH}/hwengine${CMAKE_EXECUTABLE_SUFFIX}.ppc"
+ DEPENDS "${EXECUTABLE_OUTPUT_PATH}/hwengine${CMAKE_EXECUTABLE_SUFFIX}.386" "${EXECUTABLE_OUTPUT_PATH}/hwengine${CMAKE_EXECUTABLE_SUFFIX}.ppc"
)
ENDIF(NOT APPLE OR NOT universal_build MATCHES "1")
--- a/hedgewars/SDLh.pas Mon Jun 22 13:49:16 2009 +0000
+++ b/hedgewars/SDLh.pas Wed Jun 24 15:59:32 2009 +0000
@@ -40,12 +40,9 @@
{$IFNDEF IPHONEOS}
{$linkframework Cocoa}
{$linkframework SDL}
- {$linkframework SDL_mixer}
{$linkframework SDL_net}
{$linkframework SDL_image}
{$linkframework SDL_ttf}
- {$linkframework Vorbis}
- {$linkframework Ogg}
{$linklib SDLmain}
{$linklib gcc}
{$ENDIF}
@@ -322,70 +319,6 @@
function TTF_OpenFont(const filename: PChar; size: LongInt): PTTF_Font; cdecl; external SDL_TTFLibName;
procedure TTF_SetFontStyle(font: PTTF_Font; style: LongInt); cdecl; external SDL_TTFLibName;
-(* SDL_mixer *)
-
-const {$IFDEF WIN32}
- SDL_MixerLibName = 'SDL_mixer.dll';
- {$ENDIF}
- {$IFDEF UNIX}
- {$IFDEF DARWIN}
- SDL_MixerLibName = 'SDL_mixer';
- {$ELSE}
- SDL_MixerLibName = 'libSDL_mixer.so';
- {$ENDIF}
- {$ENDIF}
-
-const MIX_MAX_VOLUME = 128;
-
-type PMixChunk = ^TMixChunk;
- TMixChunk = record
- allocated: Longword;
- abuf : PByte;
- alen : Longword;
- volume : PByte;
- end;
- TMusic = (MUS_CMD, MUS_WAV, MUS_MOD, MUS_MID, MUS_OGG, MUS_MP3);
- TMix_Fading = (MIX_NO_FADING, MIX_FADING_OUT, MIX_FADING_IN);
-
- TMidiSong = record
- samples : LongInt;
- events : pointer;
- end;
-
- TMusicUnion = record
- case Byte of
- 0: ( midi : TMidiSong );
- 1: ( ogg : pointer);
- end;
-
- PMixMusic = ^TMixMusic;
- TMixMusic = record
- end;
-
-function Mix_OpenAudio(frequency: LongInt; format: Word; channels: LongInt; chunksize: LongInt): LongInt; cdecl; external SDL_MixerLibName;
-procedure Mix_CloseAudio; cdecl; external SDL_MixerLibName;
-
-function Mix_Volume(channel: LongInt; volume: LongInt): LongInt; cdecl; external SDL_MixerLibName;
-function Mix_SetDistance(channel: LongInt; distance: Byte): LongInt; cdecl; external SDL_MixerLibName;
-function Mix_VolumeMusic(volume: LongInt): LongInt; cdecl; external SDL_MixerLibName;
-
-function Mix_AllocateChannels(numchans: LongInt): LongInt; cdecl; external SDL_MixerLibName;
-procedure Mix_FreeChunk(chunk: PMixChunk); cdecl; external SDL_MixerLibName;
-procedure Mix_FreeMusic(music: PMixMusic); cdecl; external SDL_MixerLibName;
-
-function Mix_LoadWAV_RW(src: PSDL_RWops; freesrc: LongInt): PMixChunk; cdecl; external SDL_MixerLibName;
-function Mix_LoadMUS(const filename: PChar): PMixMusic; cdecl; external SDL_MixerLibName;
-
-function Mix_Playing(channel: LongInt): LongInt; cdecl; external SDL_MixerLibName;
-function Mix_PlayingMusic: LongInt; cdecl; external SDL_MixerLibName;
-function Mix_FadeInMusic(music: PMixMusic; loops: LongInt; ms: LongInt): LongInt; cdecl; external SDL_MixerLibName;
-
-function Mix_PlayChannelTimed(channel: LongInt; chunk: PMixChunk; loops: LongInt; ticks: LongInt): LongInt; cdecl; external SDL_MixerLibName;
-function Mix_PlayMusic(music: PMixMusic; loops: LongInt): LongInt; cdecl; external SDL_MixerLibName;
-function Mix_PausedMusic(music: PMixMusic): LongInt; cdecl; external SDL_MixerLibName;
-function Mix_PauseMusic(music: PMixMusic): LongInt; cdecl; external SDL_MixerLibName;
-function Mix_ResumeMusic(music: PMixMusic): LongInt; cdecl; external SDL_MixerLibName;
-function Mix_HaltChannel(channel: LongInt): LongInt; cdecl; external SDL_MixerLibName;
(* SDL_image *)
--- a/hedgewars/hwengine.dpr Mon Jun 22 13:49:16 2009 +0000
+++ b/hedgewars/hwengine.dpr Wed Jun 24 15:59:32 2009 +0000
@@ -169,6 +169,7 @@
repeat
while SDL_PollEvent(@event) <> 0 do
case event.type_ of
+ {thinker here for adding touch events}
SDL_KEYDOWN: if GameState = gsChat then KeyPressChat(event.key.keysym.unicode);
SDL_ACTIVEEVENT: if (event.active.state and SDL_APPINPUTFOCUS) <> 0 then
cHasFocus:= event.active.gain = 1;
--- a/hedgewars/uSound.pas Mon Jun 22 13:49:16 2009 +0000
+++ b/hedgewars/uSound.pas Wed Jun 24 15:59:32 2009 +0000
@@ -18,15 +18,30 @@
unit uSound;
interface
-uses SDLh, uConsts;
+
+{$IFDEF DARWIN}
+ {$linkframework OpenAL}
+ {$linkframework Ogg}
+ {$linkframework Vorbis}
+ {$linklib openalbridge}
+{$ELSE}
+ {$linklib openal}
+ {$linklib ogg}
+ {$linklib vorbis}
+ {$linklib vorbisfile}
+{$ENDIF}
+
+uses uConsts;
{$INCLUDE options.inc}
type PVoicepack = ^TVoicepack;
TVoicepack = record
name: shortstring;
- chunks: array [TSound] of PMixChunk;
+ chunks: array [TSound] of LongInt;
end;
+const OpenALBridge = 'libopenalbridge';
+
procedure InitSound;
procedure ReleaseSound;
procedure SoundLoad;
@@ -36,20 +51,32 @@
procedure ResumeMusic;
procedure StopSound(snd: TSound);
function ChangeVolume(voldelta: LongInt): LongInt;
+function AskForVoicepack(name: shortstring): Pointer;
-function AskForVoicepack(name: shortstring): Pointer;
+
+function openal_init (memsize: LongInt) : boolean; cdecl; external OpenALBridge;
+function openal_close : boolean; cdecl; external OpenALBridge;
+function openal_loadfile (filename: PChar) : LongInt; cdecl; external OpenALBridge;
+function openal_toggleloop (index: LongInt) : boolean; cdecl; external OpenALBridge;
+function openal_setvolume (index: LongInt; percentage: byte) : boolean; cdecl; external OpenALBridge;
+function openal_fadeout (index: LongInt; quantity: byte) : boolean; cdecl; external OpenALBridge;
+function openal_fadein (index: LongInt; quantity: byte) : boolean; cdecl; external OpenALBridge;
+function openal_playsound (index: LongInt) : boolean; cdecl; external OpenALBridge;
+function openal_pausesound (index: LongInt) : boolean; cdecl; external OpenALBridge;
+function openal_stopsound (index: LongInt) : boolean; cdecl; external OpenALBridge;
+function openal_setglobalvolume (percentage: byte) : boolean; cdecl; external OpenALBridge;
var MusicFN: shortstring = '';
implementation
+
uses uMisc, uConsole;
const chanTPU = 12;
-var Volume: LongInt;
- lastChan: array [TSound] of LongInt;
+var lastChan: array [TSound] of LongInt;
voicepacks: array[0..cMaxTeams] of TVoicepack;
defVoicepack: PVoicepack;
- Mus: PMixMusic = nil;
+ Mus: LongInt = 0;
function AskForVoicepack(name: shortstring): Pointer;
var i: Longword;
@@ -66,33 +93,19 @@
end;
procedure InitSound;
+const numSounds = 200;
begin
if not isSoundEnabled then exit;
-WriteToConsole('Init sound...');
-isSoundEnabled:= SDL_Init(SDL_INIT_AUDIO) >= 0;
-if isSoundEnabled then
- isSoundEnabled:= Mix_OpenAudio(22050, $8010, 2, 512) = 0;
+WriteToConsole('Init OpenAL sound...');
+isSoundEnabled:= openal_init(numSounds);
if isSoundEnabled then WriteLnToConsole(msgOK)
else WriteLnToConsole(msgFailed);
-Mix_AllocateChannels(Succ(chanTPU));
-if isMusicEnabled then Mix_VolumeMusic(50);
-
-Volume:= 0;
ChangeVolume(cInitVolume)
end;
procedure ReleaseSound;
-var i: TSound;
- t: Longword;
begin
-for t:= 0 to cMaxTeams do
- if voicepacks[t].name <> '' then
- for i:= Low(TSound) to High(TSound) do
- if voicepacks[t].chunks[i] <> nil then
- Mix_FreeChunk(voicepacks[t].chunks[i]);
-
-Mix_FreeMusic(Mus);
-Mix_CloseAudio
+openal_close();
end;
procedure SoundLoad;
@@ -109,8 +122,8 @@
begin
s:= Pathz[Soundz[i].Path] + '/' + Soundz[i].FileName;
WriteToConsole(msgLoading + s + ' ');
- defVoicepack^.chunks[i]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
- TryDo(defVoicepack^.chunks[i] <> nil, msgFailed, true);
+ defVoicepack^.chunks[i]:= openal_loadfile (Str2PChar(s));
+ TryDo(defVoicepack^.chunks[i] >= 0, msgFailed, true);
WriteLnToConsole(msgOK);
end;
@@ -121,11 +134,8 @@
begin
s:= Pathz[Soundz[i].Path] + '/' + voicepacks[t].name + '/' + Soundz[i].FileName;
WriteToConsole(msgLoading + s + ' ');
- {$IFNDEF IPHONEOS}
- //broken for unknown reasons (most likely poor SDL_Mixer)
- voicepacks[t].chunks[i]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
- {$ENDIF}
- if voicepacks[t].chunks[i] = nil then
+ voicepacks[t].chunks[i]:= openal_loadfile (Str2PChar(s));
+ if voicepacks[t].chunks[i] < 0 then
WriteLnToConsole(msgFailed)
else
WriteLnToConsole(msgOK)
@@ -133,22 +143,28 @@
end;
procedure PlaySound(snd: TSound; infinite: boolean; voicepack: PVoicepack);
-var loops: LongInt;
begin
if (not isSoundEnabled) or fastUntilLag then exit;
-if infinite then loops:= -1 else loops:= 0;
-if (voicepack <> nil) and (voicepack^.chunks[snd] <> nil) then
- lastChan[snd]:= Mix_PlayChannelTimed(-1, voicepack^.chunks[snd], loops, -1)
+if (voicepack <> nil) and (voicepack^.chunks[snd] >= 0) then
+begin
+ if infinite then openal_toggleloop(voicepack^.chunks[snd]);
+ openal_playsound(voicepack^.chunks[snd]);
+ lastChan[snd]:=voicepack^.chunks[snd];
+end
else
- lastChan[snd]:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], loops, -1)
+begin
+ if infinite then openal_toggleloop(defVoicepack^.chunks[snd]);
+ openal_playsound(defVoicepack^.chunks[snd]);
+ lastChan[snd]:=defVoicepack^.chunks[snd];
+
+end
end;
procedure StopSound(snd: TSound);
begin
if not isSoundEnabled then exit;
-if Mix_Playing(lastChan[snd]) <> 0 then
- Mix_HaltChannel(lastChan[snd])
+ openal_stopsound(lastChan[snd])
end;
procedure PlayMusic;
@@ -161,38 +177,30 @@
s:= PathPrefix + '/Music/' + MusicFN;
WriteToConsole(msgLoading + s + ' ');
-Mus:= Mix_LoadMUS(Str2PChar(s));
-TryDo(Mus <> nil, msgFailed, false);
+Mus:= openal_loadfile(Str2PChar(s));
+TryDo(Mus >= 0, msgFailed, false);
WriteLnToConsole(msgOK);
-SDLTry(Mix_FadeInMusic(Mus, -1, 3000) <> -1, false)
+openal_fadein(Mus, 50);
+openal_toggleloop(Mus);
end;
function ChangeVolume(voldelta: LongInt): LongInt;
begin
-if not isSoundEnabled then
- exit(0);
-
-inc(Volume, voldelta);
-if Volume < 0 then Volume:= 0;
-Mix_Volume(-1, Volume);
-Volume:= Mix_Volume(-1, -1);
-if isMusicEnabled then Mix_VolumeMusic(Volume * 4 div 8);
-ChangeVolume:= Volume * 100 div MIX_MAX_VOLUME
+if not isSoundEnabled then exit(0);
+openal_setglobalvolume(voldelta);
end;
procedure PauseMusic;
begin
if (MusicFN = '') or (not isMusicEnabled) then exit;
-
-Mix_PauseMusic(Mus);
+openal_pausesound(Mus);
end;
procedure ResumeMusic;
begin
if (MusicFN = '') or (not isMusicEnabled) then exit;
-
-Mix_ResumeMusic(Mus);
+openal_playsound(Mus);
end;
end.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openalbridge/CMakeLists.txt Wed Jun 24 15:59:32 2009 +0000
@@ -0,0 +1,31 @@
+find_package(OpenAL REQUIRED)
+include_directories(${OPENAL_INCLUDE_DIR})
+
+#add_library (openalbridge openalwrap.c loaders.c endianness.c wrappers.c)
+exec_program(${CMAKE_C_COMPILER}
+ ARGS ${arch_to_build} -o ${EXECUTABLE_OUTPUT_PATH}/loaders.o -c ${hedgewars_SOURCE_DIR}/openalbridge/loaders.c -I ${OPENAL_INCLUDE_DIR} -O2
+ OUTPUT_VARIABLE noout
+)
+exec_program(${CMAKE_C_COMPILER}
+ ARGS ${arch_to_build} -o ${EXECUTABLE_OUTPUT_PATH}/endianness.o -c ${hedgewars_SOURCE_DIR}/openalbridge/endianness.c -I ${OPENAL_INCLUDE_DIR} -O2
+ OUTPUT_VARIABLE noout
+)
+
+exec_program(${CMAKE_C_COMPILER}
+ ARGS ${arch_to_build} -o ${EXECUTABLE_OUTPUT_PATH}/openalwrap.o -c ${hedgewars_SOURCE_DIR}/openalbridge/openalwrap.c -I ${OPENAL_INCLUDE_DIR} -O2
+ OUTPUT_VARIABLE noout
+)
+
+exec_program(${CMAKE_C_COMPILER}
+ ARGS ${arch_to_build} -o ${EXECUTABLE_OUTPUT_PATH}/wrappers.o -c ${hedgewars_SOURCE_DIR}/openalbridge/wrappers.c -I ${OPENAL_INCLUDE_DIR} -O2
+ OUTPUT_VARIABLE noout
+ )
+ exec_program(${CMAKE_AR}
+ ARGS -rvu ${EXECUTABLE_OUTPUT_PATH}/libopenalbridge.a ${EXECUTABLE_OUTPUT_PATH}/loaders.o ${EXECUTABLE_OUTPUT_PATH}/endianness.o ${EXECUTABLE_OUTPUT_PATH}/openalwrap.o ${EXECUTABLE_OUTPUT_PATH}/wrappers.o
+ OUTPUT_VARIABLE noout
+ )
+ exec_program(${CMAKE_RANLIB}
+ ARGS ${EXECUTABLE_OUTPUT_PATH}/libopenalbridge.a
+ OUTPUT_VARIABLE noout
+ )
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openalbridge/endianness.c Wed Jun 24 15:59:32 2009 +0000
@@ -0,0 +1,51 @@
+/*
+ * OpenAL Bridge - a simple portable library for OpenAL interface
+ * Copyright (c) 2009 Vittorio Giovara <vittorio.giovara@gmail.com>
+ *
+ * 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; version 2 of the License
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "endianness.h"
+
+#ifdef __CPLUSPLUS
+extern "C" {
+#endif
+
+ //from big endian to little endian
+ int invert_endianness(int number){
+ uint8_t n1,n2,n3,n4;
+ uint32_t a1,a2,a3,a4;
+ uint32_t done = 0;
+
+ n1 = number;
+ n2 = number >> 8;
+ n3 = number >> 16;
+ n4 = number >> 24;
+
+ //printf("%X, %X, %X, %X\n", n1, n2, n3, n4);
+ a1 = (uint32_t) n1 << 24;
+ a2 = (uint32_t) n2 << 16;
+ a3 = (uint32_t) n3 << 8;
+ a4 = (uint32_t) n4;
+ done = a1 + a2 + a3 + a4;
+ //printf("%08X %08X %08X %08X = %08X\n", a1, a2, a3, a4, done);
+ return done;
+ }
+
+#ifdef __CPLUSPLUS
+}
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openalbridge/endianness.h Wed Jun 24 15:59:32 2009 +0000
@@ -0,0 +1,29 @@
+/*
+ * OpenAL Bridge - a simple portable library for OpenAL interface
+ * Copyright (c) 2009 Vittorio Giovara <vittorio.giovara@gmail.com>
+ *
+ * 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; version 2 of the License
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef __CPLUSPLUS
+extern "C" {
+#endif
+
+#pragma once
+
+int invert_endianness(int number);
+
+#ifdef __CPLUSPLUS
+}
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openalbridge/loaders.c Wed Jun 24 15:59:32 2009 +0000
@@ -0,0 +1,212 @@
+/*
+ * OpenAL Bridge - a simple portable library for OpenAL interface
+ * Copyright (c) 2009 Vittorio Giovara <vittorio.giovara@gmail.com>
+ *
+ * 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; version 2 of the License
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "al.h"
+#include "alc.h"
+#include "loaders.h"
+#include "endianness.h"
+#include "wrappers.h"
+
+#ifdef __CPLUSPLUS
+extern "C" {
+#endif
+
+ extern int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
+ extern long ov_read(OggVorbis_File *vf,char *buffer,int length,int bigendianp,int word,int sgned,int *bitstream);
+ extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i);
+ extern long ov_read(OggVorbis_File *vf,char *buffer,int length,int bigendianp,int word,int sgned,int *bitstream);
+ extern vorbis_info *ov_info(OggVorbis_File *vf,int link);
+ extern vorbis_comment *ov_comment(OggVorbis_File *f, int num);
+
+ int load_WavPcm (const char *filename, ALenum *format, uint8_t** data, ALsizei *bitsize, ALsizei *freq) {
+ WAV_header_t WAVHeader;
+ FILE *wavfile;
+ int t, n = 0;
+
+ wavfile = Fopen(filename, "rb");
+
+ fread(&WAVHeader.ChunkID, sizeof(uint32_t), 1, wavfile);
+ fread(&WAVHeader.ChunkSize, sizeof(uint32_t), 1, wavfile);
+ fread(&WAVHeader.Format, sizeof(uint32_t), 1, wavfile);
+
+#ifdef DEBUG
+ fprintf(stderr, "ChunkID: %X\n", invert_endianness(WAVHeader.ChunkID));
+ fprintf(stderr, "ChunkSize: %d\n", WAVHeader.ChunkSize);
+ fprintf(stderr, "Format: %X\n", invert_endianness(WAVHeader.Format));
+#endif
+
+ fread(&WAVHeader.Subchunk1ID, sizeof(uint32_t), 1, wavfile);
+ fread(&WAVHeader.Subchunk1Size, sizeof(uint32_t), 1, wavfile);
+ fread(&WAVHeader.AudioFormat, sizeof(uint16_t), 1, wavfile);
+ fread(&WAVHeader.NumChannels, sizeof(uint16_t), 1, wavfile);
+ fread(&WAVHeader.SampleRate, sizeof(uint32_t), 1, wavfile);
+ fread(&WAVHeader.ByteRate, sizeof(uint32_t), 1, wavfile);
+ fread(&WAVHeader.BlockAlign, sizeof(uint16_t), 1, wavfile);
+ fread(&WAVHeader.BitsPerSample, sizeof(uint16_t), 1, wavfile);
+
+#ifdef DEBUG
+ fprintf(stderr, "Subchunk1ID: %X\n", invert_endianness(WAVHeader.Subchunk1ID));
+ fprintf(stderr, "Subchunk1Size: %d\n", WAVHeader.Subchunk1Size);
+ fprintf(stderr, "AudioFormat: %d\n", WAVHeader.AudioFormat);
+ fprintf(stderr, "NumChannels: %d\n", WAVHeader.NumChannels);
+ fprintf(stderr, "SampleRate: %d\n", WAVHeader.SampleRate);
+ fprintf(stderr, "ByteRate: %d\n", WAVHeader.ByteRate);
+ fprintf(stderr, "BlockAlign: %d\n", WAVHeader.BlockAlign);
+ fprintf(stderr, "BitsPerSample: %d\n", WAVHeader.BitsPerSample);
+#endif
+
+ do { //remove useless header chunks (plenty room for improvements)
+ t = fread(&WAVHeader.Subchunk2ID, sizeof(uint32_t), 1, wavfile);
+ if (invert_endianness(WAVHeader.Subchunk2ID) == 0x64617461)
+ break;
+ if (t <= 0) { //eof found
+ fprintf(stderr, "ERROR: wrong WAV header\n");
+ return AL_FALSE;
+ }
+ } while (1);
+ fread(&WAVHeader.Subchunk2Size, sizeof(uint32_t), 1, wavfile);
+
+#ifdef DEBUG
+ fprintf(stderr, "Subchunk2ID: %X\n", invert_endianness(WAVHeader.Subchunk2ID));
+ fprintf(stderr, "Subchunk2Size: %d\n", WAVHeader.Subchunk2Size);
+#endif
+
+ *data = (uint8_t*) malloc (sizeof(uint8_t) * WAVHeader.Subchunk2Size);
+
+ //this could be improved
+ do {
+ n += fread(&((*data)[n]), sizeof(uint8_t), 1, wavfile);
+ } while (n < WAVHeader.Subchunk2Size);
+
+ fclose(wavfile);
+
+#ifdef DEBUG
+ fprintf(stderr, "Last two bytes of data: %X%X\n", (*data)[n-2], (*data)[n-1]);
+#endif
+
+ /*remaining parameters*/
+ //Valid formats are AL_FORMAT_MONO8, AL_FORMAT_MONO16, AL_FORMAT_STEREO8, and AL_FORMAT_STEREO16.
+ if (WAVHeader.NumChannels == 1) {
+ if (WAVHeader.BitsPerSample == 8)
+ *format = AL_FORMAT_MONO8;
+ else {
+ if (WAVHeader.BitsPerSample == 16)
+ *format = AL_FORMAT_MONO16;
+ else {
+ fprintf(stderr, "ERROR: wrong WAV header - bitsample value\n");
+ return AL_FALSE;
+ }
+ }
+ } else {
+ if (WAVHeader.NumChannels == 2) {
+ if (WAVHeader.BitsPerSample == 8)
+ *format = AL_FORMAT_STEREO8;
+ else {
+ if (WAVHeader.BitsPerSample == 16)
+ *format = AL_FORMAT_STEREO16;
+ else {
+ fprintf(stderr, "ERROR: wrong WAV header - bitsample value\n");
+ return AL_FALSE;
+ }
+ }
+ } else {
+ fprintf(stderr, "ERROR: wrong WAV header - format value\n");
+ return AL_FALSE;
+ }
+ }
+
+ *bitsize = WAVHeader.Subchunk2Size;
+ *freq = WAVHeader.SampleRate;
+ return AL_TRUE;
+ }
+
+ int load_OggVorbis (const char *filename, ALenum *format, uint8_t**data, ALsizei *bitsize, ALsizei *freq) {
+ //implementation inspired from http://www.devmaster.net/forums/showthread.php?t=1153
+ FILE *oggFile; // ogg handle
+ OggVorbis_File oggStream; // stream handle
+ vorbis_info *vorbisInfo; // some formatting data
+ vorbis_comment *vorbisComment; // other less useful data
+ int64_t pcm_length; // length of the decoded data
+ int size = 0;
+ int section, result, i;
+
+ oggFile = Fopen(filename, "rb");
+ result = ov_open(oggFile, &oggStream, NULL, 0);
+ //TODO: check returning value of result
+
+ vorbisInfo = ov_info(&oggStream, -1);
+ pcm_length = ov_pcm_total(&oggStream,-1) << vorbisInfo->channels;
+
+#ifdef DEBUG
+ vorbisComment = ov_comment(&oggStream, -1);
+ fprintf(stderr, "Version: %d\n", vorbisInfo->version);
+ fprintf(stderr, "Channels: %d\n", vorbisInfo->channels);
+ fprintf(stderr, "Rate (Hz): %d\n", vorbisInfo->rate);
+ fprintf(stderr, "Bitrate Upper: %d\n", vorbisInfo->bitrate_upper);
+ fprintf(stderr, "Bitrate Nominal: %d\n", vorbisInfo->bitrate_nominal);
+ fprintf(stderr, "Bitrate Lower: %d\n", vorbisInfo->bitrate_lower);
+ fprintf(stderr, "Bitrate Windows: %d\n", vorbisInfo->bitrate_window);
+ fprintf(stderr, "Vendor: %s\n", vorbisComment->vendor);
+ fprintf(stderr, "PCM data size: %d\n", pcm_length);
+ fprintf(stderr, "# comment: %d\n", vorbisComment->comments);
+ for (i = 0; i < vorbisComment->comments; i++)
+ fprintf(stderr, "\tComment %d: %s\n", i, vorbisComment->user_comments[i]);
+#endif
+
+ //allocates enough room for the decoded data
+ *data = (uint8_t*) malloc (sizeof(uint8_t) * pcm_length);
+
+ //there *should* not be ogg at 8 bits
+ if (vorbisInfo->channels == 1)
+ *format = AL_FORMAT_MONO16;
+ else {
+ if (vorbisInfo->channels == 2)
+ *format = AL_FORMAT_STEREO16;
+ else {
+ fprintf(stderr, "ERROR: wrong OGG header - channel value (%d)\n", vorbisInfo->channels);
+ return AL_FALSE;
+ }
+ }
+
+ while(size < pcm_length) {
+ //ov_read decodes the ogg stream and storse the pcm in data
+ result = ov_read (&oggStream, *data + size, pcm_length - size, 0, 2, 1, §ion);
+ if(result > 0) {
+ size += result;
+ } else {
+ if (result == 0)
+ break;
+ else {
+ fprintf(stderr, "ERROR: end of file from OGG stream\n");
+ return AL_FALSE;
+ }
+ }
+ }
+
+ //records the last fields
+ *bitsize = size;
+ *freq = vorbisInfo->rate;
+ return AL_TRUE;
+ }
+
+#ifdef __CPLUSPLUS
+}
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openalbridge/loaders.h Wed Jun 24 15:59:32 2009 +0000
@@ -0,0 +1,245 @@
+/*
+ * OpenAL Bridge - a simple portable library for OpenAL interface
+ * Copyright (c) 2009 Vittorio Giovara <vittorio.giovara@gmail.com>
+ *
+ * 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; version 2 of the License
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef __CPLUSPLUS
+extern "C" {
+#endif
+
+#pragma once
+
+#pragma pack(1)
+ typedef struct _WAV_header_t {
+ uint32_t ChunkID;
+ uint32_t ChunkSize;
+ uint32_t Format;
+ uint32_t Subchunk1ID;
+ uint32_t Subchunk1Size;
+ uint16_t AudioFormat;
+ uint16_t NumChannels;
+ uint32_t SampleRate;
+ uint32_t ByteRate;
+ uint16_t BlockAlign;
+ uint16_t BitsPerSample;
+ uint32_t Subchunk2ID;
+ uint32_t Subchunk2Size;
+ } WAV_header_t;
+#pragma pack()
+
+ /*data types for ogg and vorbis*/
+#ifndef ogg_int64_t
+#define ogg_int64_t int64_t
+#endif
+
+ typedef struct {
+ unsigned char *data;
+ int storage;
+ int fill;
+ int returned;
+
+ int unsynced;
+ int headerbytes;
+ int bodybytes;
+ } ogg_sync_state;
+ typedef struct vorbis_info{
+ int version;
+ int channels;
+ long rate;
+
+ /* The below bitrate declarations are *hints*.
+ Combinations of the three values carry the following implications:
+
+ all three set to the same value:
+ implies a fixed rate bitstream
+ only nominal set:
+ implies a VBR stream that averages the nominal bitrate. No hard
+ upper/lower limit
+ upper and or lower set:
+ implies a VBR bitstream that obeys the bitrate limits. nominal
+ may also be set to give a nominal rate.
+ none set:
+ the coder does not care to speculate.
+ */
+
+ long bitrate_upper;
+ long bitrate_nominal;
+ long bitrate_lower;
+ long bitrate_window;
+
+ void *codec_setup;
+ } vorbis_info;
+ typedef struct vorbis_comment{
+ /* unlimited user comment fields. libvorbis writes 'libvorbis'
+ whatever vendor is set to in encode */
+ char **user_comments;
+ int *comment_lengths;
+ int comments;
+ char *vendor;
+
+ } vorbis_comment;
+ typedef struct {
+ unsigned char *body_data; /* bytes from packet bodies */
+ long body_storage; /* storage elements allocated */
+ long body_fill; /* elements stored; fill mark */
+ long body_returned; /* elements of fill returned */
+
+
+ int *lacing_vals; /* The values that will go to the segment table */
+ ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
+ this way, but it is simple coupled to the
+ lacing fifo */
+ long lacing_storage;
+ long lacing_fill;
+ long lacing_packet;
+ long lacing_returned;
+
+ unsigned char header[282]; /* working space for header encode */
+ int header_fill;
+
+ int e_o_s; /* set when we have buffered the last packet in the
+ logical bitstream */
+ int b_o_s; /* set after we've written the initial page
+ of a logical bitstream */
+ long serialno;
+ long pageno;
+ ogg_int64_t packetno; /* sequence number for decode; the framing
+ knows where there's a hole in the data,
+ but we need coupling so that the codec
+ (which is in a seperate abstraction
+ layer) also knows about the gap */
+ ogg_int64_t granulepos;
+
+ } ogg_stream_state;
+ typedef struct vorbis_dsp_state{
+ int analysisp;
+ vorbis_info *vi;
+
+ float **pcm;
+ float **pcmret;
+ int pcm_storage;
+ int pcm_current;
+ int pcm_returned;
+
+ int preextrapolate;
+ int eofflag;
+
+ long lW;
+ long W;
+ long nW;
+ long centerW;
+
+ ogg_int64_t granulepos;
+ ogg_int64_t sequence;
+
+ ogg_int64_t glue_bits;
+ ogg_int64_t time_bits;
+ ogg_int64_t floor_bits;
+ ogg_int64_t res_bits;
+
+ void *backend_state;
+ } vorbis_dsp_state;
+ typedef struct {
+ long endbyte;
+ int endbit;
+
+ unsigned char *buffer;
+ unsigned char *ptr;
+ long storage;
+ } oggpack_buffer;
+ typedef struct vorbis_block{
+ /* necessary stream state for linking to the framing abstraction */
+ float **pcm; /* this is a pointer into local storage */
+ oggpack_buffer opb;
+
+ long lW;
+ long W;
+ long nW;
+ int pcmend;
+ int mode;
+
+ int eofflag;
+ ogg_int64_t granulepos;
+ ogg_int64_t sequence;
+ vorbis_dsp_state *vd; /* For read-only access of configuration */
+
+ /* local storage to avoid remallocing; it's up to the mapping to
+ structure it */
+ void *localstore;
+ long localtop;
+ long localalloc;
+ long totaluse;
+ struct alloc_chain *reap;
+
+ /* bitmetrics for the frame */
+ long glue_bits;
+ long time_bits;
+ long floor_bits;
+ long res_bits;
+
+ void *internal;
+
+ } vorbis_block;
+ typedef struct {
+ size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource);
+ int (*seek_func) (void *datasource, ogg_int64_t offset, int whence);
+ int (*close_func) (void *datasource);
+ long (*tell_func) (void *datasource);
+ } ov_callbacks;
+ typedef struct OggVorbis_File {
+ void *datasource; /* Pointer to a FILE *, etc. */
+ int seekable;
+ ogg_int64_t offset;
+ ogg_int64_t end;
+ ogg_sync_state oy;
+
+ /* If the FILE handle isn't seekable (eg, a pipe), only the current
+ stream appears */
+ int links;
+ ogg_int64_t *offsets;
+ ogg_int64_t *dataoffsets;
+ long *serialnos;
+ ogg_int64_t *pcmlengths; /* overloaded to maintain binary
+ compatability; x2 size, stores both
+ beginning and end values */
+ vorbis_info *vi;
+ vorbis_comment *vc;
+
+ /* Decoding working state local storage */
+ ogg_int64_t pcm_offset;
+ int ready_state;
+ long current_serialno;
+ int current_link;
+
+ double bittrack;
+ double samptrack;
+
+ ogg_stream_state os; /* take physical pages, weld into a logical
+ stream of packets */
+ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
+ vorbis_block vb; /* local working space for packet->PCM decode */
+
+ ov_callbacks callbacks;
+
+ } OggVorbis_File;
+
+
+ int load_WavPcm (const char *filename, ALenum *format, uint8_t **data, ALsizei *bitsize, ALsizei *freq);
+ int load_OggVorbis (const char *filename, ALenum *format, uint8_t **data, ALsizei *bitsize, ALsizei *freq);
+
+#ifdef __CPLUSPLUS
+}
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openalbridge/openalwrap.c Wed Jun 24 15:59:32 2009 +0000
@@ -0,0 +1,386 @@
+/*
+ * OpenAL Bridge - a simple portable library for OpenAL interface
+ * Copyright (c) 2009 Vittorio Giovara <vittorio.giovara@gmail.com>
+ *
+ * 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; version 2 of the License
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "al.h"
+#include "alc.h"
+#include "openalwrap.h"
+#include "loaders.h"
+#include "wrappers.h"
+#include "endianness.h"
+
+#ifdef __CPLUSPLUS
+extern "C" {
+#endif
+
+ // Sources are points emitting sound.
+ ALuint *Sources;
+ // Buffers hold sound data.
+ ALuint *Buffers;
+ //index for Sources and Buffers
+ ALuint globalindex, globalsize;
+ // Position of the source sound.
+ ALfloat **SourcePos;
+ // Velocity of the source sound.
+ ALfloat **SourceVel;
+
+
+ ALint openal_close(void) {
+ /* This function stops all the sounds, deallocates all memory and closes OpenAL */
+ int i;
+ ALCcontext *context;
+ ALCdevice *device;
+
+ alSourceStopv (globalsize, Sources);
+ alDeleteSources (globalsize, Sources);
+ alDeleteBuffers (globalsize, Buffers);
+
+ for (i = 0; i < globalsize; i++) {
+ free(SourcePos[i]);
+ free(SourceVel[i]);
+ }
+ free(SourcePos);
+ free(SourceVel);
+ free(Sources);
+ free(Buffers);
+
+ context = alcGetCurrentContext();
+ device = alcGetContextsDevice(context);
+
+ alcMakeContextCurrent(NULL);
+ alcDestroyContext(context);
+ alcCloseDevice(device);
+ return AL_TRUE;
+ }
+
+
+ ALint openal_init(int memorysize) {
+ /* This function initializes an OpenAL contex, allocates memory space for data and prepares OpenAL buffers*/
+ ALCcontext *context;
+ ALCdevice *device;
+ ALenum error;
+
+ const ALCchar *default_device;
+ // Position of the listener.
+ ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 };
+ // Velocity of the listener.
+ ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 };
+ // Orientation of the listener. (first 3 elements are "at", second 3 are "up")
+ ALfloat ListenerOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 };
+
+ default_device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
+
+ fprintf(stderr, "Using default device: %s\n", default_device);
+
+ if ((device = alcOpenDevice(default_device)) == NULL) {
+ fprintf(stderr, "ERROR %d: Failed to open sound device\n", error);
+ return AL_FALSE;
+ }
+ context = alcCreateContext(device, NULL);
+ alcMakeContextCurrent(context);
+ alcProcessContext(context);
+
+ if (AlGetError("ERROR %d: Creating a new contex\n") != AL_TRUE)
+ return AL_FALSE;
+
+ //allocate memory space for buffers and sources
+ globalsize = memorysize;
+ Buffers = (ALuint*) Malloc(sizeof(ALuint )*globalsize);
+ Sources = (ALuint*) Malloc(sizeof(ALuint )*globalsize);
+ SourcePos = (ALfloat**) Malloc(sizeof(ALfloat*)*globalsize);
+ SourceVel = (ALfloat**) Malloc(sizeof(ALfloat*)*globalsize);
+
+ //set the listener gain, position (on xyz axes), velocity (one value for each axe) and orientation
+ alListenerf (AL_GAIN, 1.0f );
+ alListenerfv(AL_POSITION, ListenerPos);
+ alListenerfv(AL_VELOCITY, ListenerVel);
+ alListenerfv(AL_ORIENTATION, ListenerOri);
+
+ if (AlGetError("ERROR %d: Setting Listener properties\n") != AL_TRUE)
+ return AL_FALSE;
+
+ alGetError(); /* clear any AL errors beforehand */
+ return AL_TRUE;
+ }
+
+
+ int openal_loadfile (const char *filename){
+ /* This function opens a file, loads into memory and allocates the Source buffer for playing*/
+ ALenum format;
+ ALsizei bitsize;
+ ALsizei freq;
+ uint8_t *data;
+ uint32_t fileformat;
+ int i, error;
+ FILE *fp;
+
+
+ /*detect the file format, as written in the first 4 bytes of the header*/
+ fp = Fopen (filename, "rb");
+ if (fp == NULL)
+ return -1;
+ error = fread (&fileformat, sizeof(uint32_t), 1, fp);
+ fclose (fp);
+
+ if (error < 0) {
+ fprintf(stderr, "ERROR: file %s is too short \n", filename);
+ return -2;
+ }
+
+ //prepare the buffers to receive data
+ alGenBuffers(1, &Buffers[globalindex]);
+
+ if (AlGetError("ERROR %d: Allocating memory for buffers\n") != AL_TRUE)
+ return -3;
+
+ //prepare the sources to emit sound
+ alGenSources(1, &Sources[globalindex]);
+
+ if (AlGetError("ERROR %d: Allocating memory for sources\n") != AL_TRUE)
+ return -4;
+
+
+ if (fileformat == 0x5367674F) //check if ogg
+ error = load_OggVorbis (filename, &format, &data, &bitsize, &freq);
+ else {
+ if (fileformat == 0x46464952) //check if wav
+ error = load_WavPcm (filename, &format, &data, &bitsize, &freq);
+ else {
+ fprintf(stderr, "ERROR: File format (%08X) not supported!\n", invert_endianness(fileformat));
+ return -5;
+ }
+ }
+
+ //copy pcm data in one buffer
+ alBufferData(Buffers[globalindex], format, data, bitsize, freq);
+ free(data); //deallocate data to save memory
+
+ if (AlGetError("ERROR %d: Writing data to buffer\n") != AL_TRUE)
+ return -5;
+
+ //memory allocation for source position and velocity
+ SourcePos[globalindex] = (ALfloat*) Malloc(sizeof(ALfloat)*3);
+ SourceVel[globalindex] = (ALfloat*) Malloc(sizeof(ALfloat)*3);
+
+ if (SourcePos[globalindex] == NULL || SourceVel[globalindex] == NULL)
+ return -6;
+
+ //source properties that it will use when it's in playback
+ for (i = 0; i < 3; i++) {
+ SourcePos[globalindex][i] = 0.0;
+ SourceVel[globalindex][i] = 0.1;
+ }
+ alSourcei (Sources[globalindex], AL_BUFFER, Buffers[globalindex] );
+ alSourcef (Sources[globalindex], AL_PITCH, 1.0f );
+ alSourcef (Sources[globalindex], AL_GAIN, 1.0f );
+ alSourcefv(Sources[globalindex], AL_POSITION, SourcePos[globalindex]);
+ alSourcefv(Sources[globalindex], AL_VELOCITY, SourceVel[globalindex]);
+ alSourcei (Sources[globalindex], AL_LOOPING, 0 );
+
+ if (AlGetError("ERROR %d: Setting source properties\n") != AL_TRUE)
+ return -7;
+
+ alGetError(); /* clear any AL errors beforehand */
+
+ //returns the index of the source you just loaded, increments it and exits
+ return globalindex++;
+ }
+
+
+ ALint openal_toggleloop (int index){
+ /*Set or unset looping mode*/
+ ALint loop;
+
+ if (index >= globalsize) {
+ fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
+ return AL_FALSE;
+ }
+
+ alGetSourcei (Sources[index], AL_LOOPING, &loop);
+ alSourcei (Sources[index], AL_LOOPING, !((uint8_t) loop) & 0x00000001);
+ if (AlGetError("ERROR %d: Getting or setting loop property\n") != AL_TRUE)
+ return AL_FALSE;
+
+ alGetError(); /* clear any AL errors beforehand */
+
+ return AL_TRUE;
+ }
+
+
+ ALint openal_setvolume (int index, unsigned char percentage) {
+ /*Set volume for sound number index*/
+ if (index >= globalindex) {
+ fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
+ return AL_FALSE;
+ }
+
+ if (percentage > 100)
+ percentage = 100;
+ alSourcef (Sources[index], AL_GAIN, (ALfloat) percentage/100.0f);
+ if (AlGetError("ERROR %d: Setting volume for last sound\n") != AL_TRUE)
+ return AL_FALSE;
+
+ alGetError(); /* clear any AL errors beforehand */
+
+ return AL_TRUE;
+ }
+
+
+ ALint openal_setglobalvolume (unsigned char percentage) {
+ /*Set volume for all sounds*/
+ if (percentage > 100)
+ percentage = 100;
+ alListenerf (AL_GAIN, (ALfloat) percentage/100.0f);
+ if (AlGetError("ERROR %d: Setting global volume\n") != AL_TRUE)
+ return AL_FALSE;
+
+ alGetError(); /* clear any AL errors beforehand */
+
+ return AL_TRUE;
+ }
+
+
+ ALint openal_togglemute () {
+ /*Mute or unmute sound*/
+ ALfloat mute;
+
+ alGetListenerf (AL_GAIN, &mute);
+ if (mute > 0)
+ mute = 0;
+ else
+ mute = 1.0;
+ alListenerf (AL_GAIN, mute);
+ if (AlGetError("ERROR %d: Setting mute property\n") != AL_TRUE)
+ return AL_FALSE;
+
+ alGetError(); /* clear any AL errors beforehand */
+
+ return AL_TRUE;
+ }
+
+
+ ALint openal_fadeout(int index, unsigned int quantity) {
+ ALfloat gain;
+
+ if (index >= globalindex) {
+ fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
+ return AL_FALSE;
+ }
+
+ alGetSourcef(Sources[index], AL_GAIN, &gain);
+
+ for ( ; gain >= 0.00f; gain -= (float) quantity/10000){
+#ifdef DEBUG
+ fprintf(stderr, "Fade-out: Set gain to: %f\n", gain);
+#endif
+ alSourcef(Sources[index], AL_GAIN, gain);
+ usleep(10000);
+ }
+
+ if (AlGetError("ERROR %d: Setting fade out volume\n") != AL_TRUE)
+ return AL_FALSE;
+
+ //stop that sound and reset its gain
+ alSourceStop (Sources[index]);
+ alSourcef (Sources[index], AL_GAIN, 1.0f);
+
+ alGetError(); /* clear any AL errors beforehand */
+
+ return AL_TRUE;
+ }
+
+
+ ALint openal_fadein(int index, unsigned int quantity) {
+ ALfloat gain;
+
+ if (index >= globalindex) {
+ fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
+ return AL_FALSE;
+ }
+
+ gain = 0.0f;
+ alSourcef(Sources[index], AL_GAIN, gain);
+ alSourcePlay(Sources[index]);
+
+ for ( ; gain <= 1.00f; gain += (float) quantity/10000){
+#ifdef DEBUG
+ fprintf(stderr, "Fade-in: Set gain to: %f\n", gain);
+#endif
+ alSourcef(Sources[index], AL_GAIN, gain);
+ usleep(10000);
+ }
+
+ if (AlGetError("ERROR %d: Setting fade in volume\n") != AL_TRUE)
+ return AL_FALSE;
+
+ alGetError(); /* clear any AL errors beforehand */
+
+ return AL_TRUE;
+ }
+
+
+ ALint openal_playsound(int index){
+ /*Play sound number index*/
+ if (index >= globalindex) {
+ fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
+ return AL_FALSE;
+ }
+ alSourcePlay(Sources[index]);
+ if (AlGetError("ERROR %d: Playing last sound\n") != AL_TRUE)
+ return AL_FALSE;
+
+ alGetError(); /* clear any AL errors beforehand */
+
+ return AL_TRUE;
+ }
+
+
+ ALint openal_pausesound(int index){
+ /*Pause sound number index*/
+ if (index >= globalindex) {
+ fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
+ return AL_FALSE;
+ }
+ alSourcePause(Sources[index]);
+ if (AlGetError("ERROR %d: Pausing last sound\n") != AL_TRUE)
+ return AL_FALSE;
+
+ return AL_TRUE;
+ }
+
+
+ ALint openal_stopsound(int index){
+ /*Stop sound number index*/
+ if (index >= globalindex) {
+ fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
+ return AL_FALSE;
+ }
+ alSourceStop(Sources[index]);
+ if (AlGetError("ERROR %d: Stopping last sound\n") != AL_TRUE)
+ return AL_FALSE;
+
+ alGetError(); /* clear any AL errors beforehand */
+
+ return AL_TRUE;
+ }
+
+#ifdef __CPLUSPLUS
+}
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openalbridge/openalwrap.h Wed Jun 24 15:59:32 2009 +0000
@@ -0,0 +1,64 @@
+/*
+ * OpenAL Bridge - a simple portable library for OpenAL interface
+ * Copyright (c) 2009 Vittorio Giovara <vittorio.giovara@gmail.com>
+ *
+ * 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; version 2 of the License
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef _SLEEP_H
+#define _SLEEP_H
+/** 1.0 02/03/10 - Defines cross-platform sleep, usleep, etc. * By Wu Yongwei **/
+#ifdef _WIN32
+# if defined(_NEED_SLEEP_ONLY) && (defined(_MSC_VER) || defined(__MINGW32__))
+# include <stdlib.h>
+# define sleep(t) _sleep((t) * 1000)
+# else
+# include <windows.h>
+# define sleep(t) Sleep((t) * 1000)
+# endif
+# ifndef _NEED_SLEEP_ONLY
+# define msleep(t) Sleep(t)
+# define usleep(t) Sleep((t) / 1000)
+# endif
+#else
+# include <unistd.h>
+# ifndef _NEED_SLEEP_ONLY
+# define msleep(t) usleep((t) * 1000)
+# endif
+#endif
+
+#endif /* _SLEEP_H */
+
+#ifdef __CPLUSPLUS
+extern "C" {
+#endif
+
+#pragma once
+
+ ALint openal_init (int memorysize);
+ ALint openal_close (void);
+ int openal_loadfile (const char *filename);
+ ALint openal_toggleloop (int index);
+ ALint openal_setvolume (int index, unsigned char percentage);
+ ALint openal_setglobalvolume (unsigned char percentage);
+ ALint openal_togglemute (void);
+ ALint openal_fadeout (int index, unsigned int quantity);
+ ALint openal_fadein (int index, unsigned int quantity);
+ ALint openal_playsound (int index);
+ ALint openal_pausesound (int index);
+ ALint openal_stopsound (int index);
+
+#ifdef __CPLUSPLUS
+}
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openalbridge/wrappers.c Wed Jun 24 15:59:32 2009 +0000
@@ -0,0 +1,57 @@
+/*
+ * OpenAL Bridge - a simple portable library for OpenAL interface
+ * Copyright (c) 2009 Vittorio Giovara <vittorio.giovara@gmail.com>
+ *
+ * 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; version 2 of the License
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "wrappers.h"
+#include "al.h"
+
+#ifdef __CPLUSPLUS
+extern "C" {
+#endif
+
+ void *Malloc (size_t nbytes)
+ {
+ void *aptr;
+ if ( (aptr = malloc(nbytes)) == NULL)
+ fprintf(stderr, "ERROR: not enough memory! malloc() failed");
+ return aptr;
+ }
+
+ FILE *Fopen (const char *fname, char *mode)
+ {
+ FILE *fp;
+ if ((fp=fopen(fname,mode)) == NULL)
+ fprintf (stderr, "ERROR: can't open file %s in mode '%s'", fname, mode);
+ return fp;
+ }
+
+ ALint AlGetError (const char *str) {
+ ALenum error;
+
+ error = alGetError();
+ if (error != AL_NO_ERROR) {
+ fprintf(stderr, str, error);
+ return -2;
+ } else
+ return AL_TRUE;
+ }
+
+#ifdef __CPLUSPLUS
+}
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openalbridge/wrappers.h Wed Jun 24 15:59:32 2009 +0000
@@ -0,0 +1,25 @@
+/*
+ * OpenAL Bridge - a simple portable library for OpenAL interface
+ * Copyright (c) 2009 Vittorio Giovara <vittorio.giovara@gmail.com>
+ *
+ * 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; version 2 of the License
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "al.h"
+
+void *Malloc (size_t nbytes);
+FILE *Fopen (const char *fname, char *mode);
+ALint AlGetError (const char *str);