# HG changeset patch # User unc0rr # Date 1245859172 0 # Node ID 20c62f787a4d34be0e5237c0176bfa500db0e01d # Parent cfcad6142d48aabc38f7c5a2d09fe74e5f52f076 koda's OpenAL conversion: - Freezes program for fadein/fadeout time - Has a problem with quickplay diff -r cfcad6142d48 -r 20c62f787a4d CMakeLists.txt --- 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) diff -r cfcad6142d48 -r 20c62f787a4d QTfrontend/CMakeLists.txt --- 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) diff -r cfcad6142d48 -r 20c62f787a4d QTfrontend/SDLs.cpp --- 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); } diff -r cfcad6142d48 -r 20c62f787a4d QTfrontend/SDLs.h --- 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 -#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(); diff -r cfcad6142d48 -r 20c62f787a4d QTfrontend/pages.cpp --- 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 #include #include -#include #include @@ -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) : diff -r cfcad6142d48 -r 20c62f787a4d cmake_modules/FindQCA2.cmake --- 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, -# -# 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) diff -r cfcad6142d48 -r 20c62f787a4d hedgewars/CMakeLists.txt --- 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") diff -r cfcad6142d48 -r 20c62f787a4d hedgewars/SDLh.pas --- 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 *) diff -r cfcad6142d48 -r 20c62f787a4d hedgewars/hwengine.dpr --- 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; diff -r cfcad6142d48 -r 20c62f787a4d hedgewars/uSound.pas --- 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. diff -r cfcad6142d48 -r 20c62f787a4d openalbridge/CMakeLists.txt --- /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 + ) + diff -r cfcad6142d48 -r 20c62f787a4d openalbridge/endianness.c --- /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 + * + * 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 +#include +#include +#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 diff -r cfcad6142d48 -r 20c62f787a4d openalbridge/endianness.h --- /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 + * + * 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 diff -r cfcad6142d48 -r 20c62f787a4d openalbridge/loaders.c --- /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 + * + * 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 +#include +#include +#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 diff -r cfcad6142d48 -r 20c62f787a4d openalbridge/loaders.h --- /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 + * + * 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 diff -r cfcad6142d48 -r 20c62f787a4d openalbridge/openalwrap.c --- /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 + * + * 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 +#include +#include +#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 diff -r cfcad6142d48 -r 20c62f787a4d openalbridge/openalwrap.h --- /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 + * + * 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 +# define sleep(t) _sleep((t) * 1000) +# else +# include +# 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 +# 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 diff -r cfcad6142d48 -r 20c62f787a4d openalbridge/wrappers.c --- /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 + * + * 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 +#include +#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 diff -r cfcad6142d48 -r 20c62f787a4d openalbridge/wrappers.h --- /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 + * + * 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 +#include +#include "al.h" + +void *Malloc (size_t nbytes); +FILE *Fopen (const char *fname, char *mode); +ALint AlGetError (const char *str);