diff --git a/build/te4core.lua b/build/te4core.lua index f794dcd76f285d7461154a762d3a4f092dbbedcc..86a010d6365ef3d1ded09f13c7f411eddd5e4b1b 100644 --- a/build/te4core.lua +++ b/build/te4core.lua @@ -44,7 +44,7 @@ project "TEngine" links { "IOKit" } configuration "windows" - links { "mingw32", "SDLmain", "SDL", "SDL_ttf", "SDL_image", "SDL_mixer", "OPENGL32", "GLU32", "wsock32" } + links { "mingw32", "SDLmain", "SDL", "SDL_ttf", "SDL_image", "openal", "OPENGL32", "GLU32", "wsock32" } defines { [[TENGINE_HOME_PATH='"T-Engine"']], 'SELFEXE_WINDOWS' } prebuildcommands { "windres ../src/windows/icon.rc -O coff -o ../src/windows/icon.res" } linkoptions { "../src/windows/icon.res" } @@ -53,7 +53,7 @@ project "TEngine" configuration "linux" - links { "dl", "SDL", "SDL_ttf", "SDL_image", "SDL_mixer", "GL", "GLU", "m", "pthread" } + links { "dl", "SDL", "SDL_ttf", "SDL_image", "openal", "vorbisfile", "GL", "GLU", "m", "pthread" } defines { [[TENGINE_HOME_PATH='".t-engine"']], 'SELFEXE_LINUX' } configuration {"Debug"} diff --git a/game/engines/default/engine/Game.lua b/game/engines/default/engine/Game.lua index c6f017e628b0d86351fd0a5be522885d1b7dc4c3..88545dfb6be89553dae5134e542628b346498f97 100644 --- a/game/engines/default/engine/Game.lua +++ b/game/engines/default/engine/Game.lua @@ -92,7 +92,7 @@ function _M:defaultSavedFields(t) w=true, h=true, zone=true, player=true, level=true, entities=true, energy_to_act=true, energy_per_tick=true, turn=true, paused=true, save_name=true, always_target=true, gfxmode=true, uniques=true, object_known_types=true, - current_music=true, memory_levels=true, achievement_data=true, factions=true, + memory_levels=true, achievement_data=true, factions=true, playing_musics=true, state=true, __savefile_version_tokens = true, } diff --git a/game/engines/default/engine/init.lua b/game/engines/default/engine/init.lua index 0bcd72accfdf804c1471f4b036c7b8d1bccafce6..a8b1f1991c8f16c6dee3439a1bf816afca0706bd 100644 --- a/game/engines/default/engine/init.lua +++ b/game/engines/default/engine/init.lua @@ -99,10 +99,6 @@ core.display.setGamma(config.settings.gamma_correction / 100) if not config.settings.fbo_active then core.display.disableFBO() print("Disabling FBO") end if not config.settings.shaders_active then core.shader.disable() print("Disabling Shaders") end --- Setup musics -engine.interface.GameMusic:soundSystemStatus(config.settings.sound.enabled, true) -core.sound.activateMusicCallback() - -- Load profile configs core.profile.createThread() profile = engine.PlayerProfile.new() diff --git a/game/engines/default/engine/interface/GameMusic.lua b/game/engines/default/engine/interface/GameMusic.lua index 49d3e0054de58a7ef4fe6eb29975615642c98ffe..df4fceda5467f3cecab2db6e4dc6d9b4b9c1d949 100644 --- a/game/engines/default/engine/interface/GameMusic.lua +++ b/game/engines/default/engine/interface/GameMusic.lua @@ -27,39 +27,51 @@ function _M:init() self.current_music = nil self.next_music = nil self.loaded_musics = {} + self.playing_musics = {} end function _M:loaded() + self.playing_musics = self.playing_musics or {} self.loaded_musics = self.loaded_musics or {} end -function _M:playMusic(name, loop) - name = name or self.current_music - if not name then return end - local m = self.loaded_musics[name] - if not m then - self.loaded_musics[name] = core.sound.newMusic("/data/music/"..name) - m = self.loaded_musics[name] +function _M:playMusic(name) + if not name then + for name, data in pairs(self.playing_musics) do self:playMusic(name, data.loop) end + return end + if self.loaded_musics[name] then return end + self.loaded_musics[name] = core.sound.load("/data/music/"..name) + local m = self.loaded_musics[name] if not m then return end + print("[MUSIC] playing", name, m, " :: current ? ", self.playing_music) - if self.current_music == name and self.playing_music then return end - if self.current_music then - core.sound.musicStop() + m:loop(true) + m:play() + self.playing_musics[name] = {loop=true} +end + +function _M:stopMusic(name) + if not name then + for name, _ in pairs(self.loaded_musics) do self:stopMusic(name) end + return end - m:play(loop or -1) - self.current_music = name - self.playing_music = true + + if not self.loaded_musics[name] then return end + self.loaded_musics[name]:stop() + self.loaded_musics[name] = nil + self.playing_musics[name] = nil + print("[MUSIC] stoping", name) end -function _M:stopMusic(fadeout) - if not self.loaded_musics[self.current_music] then return end - core.sound.musicStop(fadeout) - self.current_music = nil - self.playing_music = false +function _M:playAndStopMusic(...) + local keep = table.reverse{...} + for name, _ in pairs(self.loaded_musics) do if not keep[name] then self:stopMusic(name) end end + for name, _ in pairs(keep) do if not self.loaded_musics[name] then self:playMusic(name) end end end function _M:volumeMusic(vol) +do return end if vol then self:saveSettings("music", ("music.volume = %q\n"):format(vol)) end @@ -69,21 +81,3 @@ end --- Called by the C core when the current music stops function _M:onMusicStop() end - -function _M:soundSystemStatus(act, init_setup) - if type(act) == "boolean" then - core.sound.soundSystemStatus(act) - if not init_setup then - self:saveSettings("sound", ("sound.enabled = %s\n"):format(act and "true" or "false")) - if act then - self:playMusic() - else - local o = self.current_music - self:stopMusic() - self.current_music = o - end - end - else - return core.sound.soundSystemStatus() - end -end diff --git a/game/engines/default/engine/interface/GameSound.lua b/game/engines/default/engine/interface/GameSound.lua index c4309960b3606d653e863e525af67d3000edb5bc..150b91591606b3fc1acb275a460118e6b23e9e81 100644 --- a/game/engines/default/engine/interface/GameSound.lua +++ b/game/engines/default/engine/interface/GameSound.lua @@ -25,27 +25,32 @@ module(..., package.seeall, class.make) --- Initializes function _M:init() self.loaded_sounds = {} +-- setmetatable(self.loaded_sounds, {__mode="v"}) end function _M:loaded() self.loaded_sounds = self.loaded_sounds or {} +-- setmetatable(self.loaded_sounds, {__mode="v"}) end function _M:playSound(name) local s = self.loaded_sounds[name] if not s then - local def + local def, ok if fs.exists("/data/sound/"..name..".lua") then local f = loadfile("/data/sound/"..name..".lua") setfenv(f, setmetatable({}, {__index=_G})) def = f() print("[SOUND] loading from", "/data/sound/"..name..".lua", ":=:", "/data/sound/"..def.file, ":>") - def.file = core.sound.newSound("/data/sound/"..def.file) - print("[SOUND] :=>", def.file) - if def.volume and def.file then def.file:setVolume(def.volume) end - elseif fs.exists("/data/sound/"..name..".wav") then - def = {file = core.sound.newSound("/data/sound/"..name..".wav")} - print("[SOUND] loading from", "/data/sound/"..name..".wav", ":=:", def.file) + ok, def.sample = pcall(core.sound.load, "/data/sound/"..def.file) + if not ok then return end + print("[SOUND] :=>", def.sample) + if def.volume and def.sample then def.sample:volume(def.volume / 100) end + elseif fs.exists("/data/sound/"..name..".ogg") then + def = {} + ok, def.sample = pcall(core.sound.load, "/data/sound/"..name..".ogg") + if not ok then return end + print("[SOUND] loading from", "/data/sound/"..name..".ogg", ":=:", def.sample) else def = {} end @@ -53,7 +58,7 @@ function _M:playSound(name) self.loaded_sounds[name] = def s = self.loaded_sounds[name] end - if not s or not s.file then return end - local chan = s.file:play(s.loop, s.timed) - if chan and s.fadeout then core.sound.channelFadeOut(chan, s.fadeout) end + if not s or not s.sample then return end + s.sample:play(s.loop) + return s end diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 2b8c65ad0ae278325bb6712e634bc499bfc2c15a..98e43e668750d89d282180722026f7d39d356f1a 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -148,9 +148,6 @@ function _M:run() -- Ok everything is good to go, activate the game in the engine! self:setCurrent() - -- Run the current music if any - self:playMusic() - -- Start time self.real_starttime = os.time() @@ -169,6 +166,9 @@ function _M:run() self.hotkeys_display.actor = self.player self.npcs_display.actor = self.player + + -- Run the current music if any + self:onTickEnd(function() self:playMusic() end) end --- Checks if the current character is "tainted" by cheating @@ -609,13 +609,19 @@ function _M:changeLevel(lev, zone, keep_old_lev, force_down) act.last_act_turn = math.floor(self.turn / (self.zone.wilderness and 1000 or 10)) end + local musics = {} + local keep_musics = false if self.level.data.ambient_music then if self.level.data.ambient_music ~= "last" then - self:playMusic(self.level.data.ambient_music) + if type(self.level.data.ambient_music) == "string" then musics[#musics+1] = self.level.data.ambient_music + elseif type(self.level.data.ambient_music) == "table" then for i, name in ipairs(self.level.data.ambient_music) do musics[#musics+1] = name end + elseif type(self.level.data.ambient_music) == "function" then for i, name in ipairs{self.level.data.ambient_music()} do musics[#musics+1] = name end + end + elseif self.level.data.ambient_music == "last" then + keep_musics = true end - else - self:stopMusic() end + if not keep_musics then self:playAndStopMusic(unpack(musics)) end -- Update the minimap self:setupMiniMap() diff --git a/game/modules/tome/data/quests/arena.lua b/game/modules/tome/data/quests/arena.lua index 851759fb492057d7ea06c2cac22c1fafb56014ac..2aad27de2f6886489b40348b837abe0ddf91ad66 100644 --- a/game/modules/tome/data/quests/arena.lua +++ b/game/modules/tome/data/quests/arena.lua @@ -26,7 +26,7 @@ desc = function(self, who) end function win(self) - game:playMusic("Lords of the Sky.ogg") + game:playAndStopMusic("Lords of the Sky.ogg") game.player.winner = "arena" game:registerDialog(require("engine.dialogs.ShowText").new("Winner", "win", {playername=game.player.name, how="arena"}, game.w * 0.6)) diff --git a/game/modules/tome/data/quests/high-peak.lua b/game/modules/tome/data/quests/high-peak.lua index f61d90551dbe5fd9da964a2f986af7e4b3ed5d5e..b2a897a9a37cd838afe6cb3b1c341d8a4429b998 100644 --- a/game/modules/tome/data/quests/high-peak.lua +++ b/game/modules/tome/data/quests/high-peak.lua @@ -109,7 +109,7 @@ function failed_charred_scar(self, level) end function win(self, how) - game:playMusic("Lords of the Sky.ogg") + game:playAndStopMusic("Lords of the Sky.ogg") if how == "full" then world:gainAchievement("WIN_FULL", game.player) elseif how == "aeryn-sacrifice" then world:gainAchievement("WIN_AERYN", game.player) diff --git a/game/modules/tome/data/sound/actions/arrow.lua b/game/modules/tome/data/sound/actions/arrow.lua index b1adf89997b8c8c70994039375d52ddd57f3713b..50875a65e6603ec960c83f73e916684bd1b0e018 100644 --- a/game/modules/tome/data/sound/actions/arrow.lua +++ b/game/modules/tome/data/sound/actions/arrow.lua @@ -1,4 +1,4 @@ return { - file = "actions/arrow.wav", + file = "actions/arrow.ogg", volume = 30, } diff --git a/game/modules/tome/data/sound/actions/arrow.ogg b/game/modules/tome/data/sound/actions/arrow.ogg new file mode 100644 index 0000000000000000000000000000000000000000..8f329c2a180dd136c38c9d1620f421bf298f7af5 Binary files /dev/null and b/game/modules/tome/data/sound/actions/arrow.ogg differ diff --git a/game/modules/tome/data/sound/actions/arrow.wav b/game/modules/tome/data/sound/actions/arrow.wav deleted file mode 100755 index 7d80dc6dfaf2de875affe3834611df4152869669..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/actions/arrow.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/actions/eagle_scream.ogg b/game/modules/tome/data/sound/actions/eagle_scream.ogg new file mode 100644 index 0000000000000000000000000000000000000000..7fdff572b62e913f4aa46d4e9bcf35fcbd4685a8 Binary files /dev/null and b/game/modules/tome/data/sound/actions/eagle_scream.ogg differ diff --git a/game/modules/tome/data/sound/actions/eagle_scream.wav b/game/modules/tome/data/sound/actions/eagle_scream.wav deleted file mode 100644 index 57d1460ffac1fc7b39d0415edf7a98c7308fe1a9..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/actions/eagle_scream.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/actions/melee.lua b/game/modules/tome/data/sound/actions/melee.lua index 44dfe2b2e2c462ab23fb7b44dbfb515788bb3944..b595513722896e4049a301406a02d78864e285fc 100644 --- a/game/modules/tome/data/sound/actions/melee.lua +++ b/game/modules/tome/data/sound/actions/melee.lua @@ -1,4 +1,4 @@ return { - file = "actions/melee.wav", + file = "actions/melee.ogg", volume = 30, } diff --git a/game/modules/tome/data/sound/actions/melee.ogg b/game/modules/tome/data/sound/actions/melee.ogg new file mode 100644 index 0000000000000000000000000000000000000000..004e45aa517b7155468f4b2574767f97081f3601 Binary files /dev/null and b/game/modules/tome/data/sound/actions/melee.ogg differ diff --git a/game/modules/tome/data/sound/actions/melee.wav b/game/modules/tome/data/sound/actions/melee.wav deleted file mode 100755 index c54b29723cd15b1719ca6869a918330dc198eeb9..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/actions/melee.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/actions/melee_miss.lua b/game/modules/tome/data/sound/actions/melee_miss.lua index 9c6d62483dbbdf145167686556905221a3204672..1aa0d0835f9cd6d924433e8dd8c440859500f6c2 100644 --- a/game/modules/tome/data/sound/actions/melee_miss.lua +++ b/game/modules/tome/data/sound/actions/melee_miss.lua @@ -1,4 +1,4 @@ return { - file = "actions/melee_miss.wav", + file = "actions/melee_miss.ogg", volume = 30, } diff --git a/game/modules/tome/data/sound/actions/melee_miss.ogg b/game/modules/tome/data/sound/actions/melee_miss.ogg new file mode 100644 index 0000000000000000000000000000000000000000..5504d5b30d02f7f4ce77fc389a0e86aeec36b6d0 Binary files /dev/null and b/game/modules/tome/data/sound/actions/melee_miss.ogg differ diff --git a/game/modules/tome/data/sound/actions/melee_miss.wav b/game/modules/tome/data/sound/actions/melee_miss.wav deleted file mode 100755 index fad2ce4bf8856da336272b79be50fde0fbbb6eda..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/actions/melee_miss.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/actions/quaff.ogg b/game/modules/tome/data/sound/actions/quaff.ogg new file mode 100644 index 0000000000000000000000000000000000000000..7d89e09c5d48a1398e3c0dc1a1bd48b0f730cfe6 Binary files /dev/null and b/game/modules/tome/data/sound/actions/quaff.ogg differ diff --git a/game/modules/tome/data/sound/actions/quaff.wav b/game/modules/tome/data/sound/actions/quaff.wav deleted file mode 100755 index c4a6148cf65a5e7814fc3aff3d88c9f2b51a5525..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/actions/quaff.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/actions/read.ogg b/game/modules/tome/data/sound/actions/read.ogg new file mode 100644 index 0000000000000000000000000000000000000000..51100c0e41406a8b716e181b2dc58a353bea0d7d Binary files /dev/null and b/game/modules/tome/data/sound/actions/read.ogg differ diff --git a/game/modules/tome/data/sound/actions/read.wav b/game/modules/tome/data/sound/actions/read.wav deleted file mode 100755 index 00606dd57a52567e082af3c3ce0e2b44d99ed288..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/actions/read.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/arcane.lua b/game/modules/tome/data/sound/talents/arcane.lua index 26bbbe1ca21c51fedca8f17adfb8441218e48af4..47cf9ffaa92423b27955b80f54cc4297d357a5e3 100644 --- a/game/modules/tome/data/sound/talents/arcane.lua +++ b/game/modules/tome/data/sound/talents/arcane.lua @@ -1,4 +1,4 @@ return { - file = "talents/arcane.wav", + file = "talents/arcane.ogg", volume = 50, } diff --git a/game/modules/tome/data/sound/talents/arcane.ogg b/game/modules/tome/data/sound/talents/arcane.ogg new file mode 100644 index 0000000000000000000000000000000000000000..bbf40410756deb0459d54589892396c0c6f2d6d0 Binary files /dev/null and b/game/modules/tome/data/sound/talents/arcane.ogg differ diff --git a/game/modules/tome/data/sound/talents/arcane.wav b/game/modules/tome/data/sound/talents/arcane.wav deleted file mode 100755 index 37069a0d4c1e7fea69efeaaa5c724eebd7475b39..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/arcane.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/breath.ogg b/game/modules/tome/data/sound/talents/breath.ogg new file mode 100644 index 0000000000000000000000000000000000000000..74c06c058b3d165c38835e8dd9f3a338ef08f162 Binary files /dev/null and b/game/modules/tome/data/sound/talents/breath.ogg differ diff --git a/game/modules/tome/data/sound/talents/breath.wav b/game/modules/tome/data/sound/talents/breath.wav deleted file mode 100755 index 2f6a8625f669e81f3112002fa275abc2a7f10333..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/breath.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/cloud.ogg b/game/modules/tome/data/sound/talents/cloud.ogg new file mode 100644 index 0000000000000000000000000000000000000000..a18f31082568f9f2b16e4b5d42e72fb2f8bb3aa1 Binary files /dev/null and b/game/modules/tome/data/sound/talents/cloud.ogg differ diff --git a/game/modules/tome/data/sound/talents/cloud.wav b/game/modules/tome/data/sound/talents/cloud.wav deleted file mode 100755 index ea43b20c80e9109e93fcf4ae2c88ae81b7143cbe..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/cloud.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/devouringflame.ogg b/game/modules/tome/data/sound/talents/devouringflame.ogg new file mode 100644 index 0000000000000000000000000000000000000000..ebe098d66ffc112cc9e8af84a8aa70ed65e2d8c7 Binary files /dev/null and b/game/modules/tome/data/sound/talents/devouringflame.ogg differ diff --git a/game/modules/tome/data/sound/talents/devouringflame.wav b/game/modules/tome/data/sound/talents/devouringflame.wav deleted file mode 100755 index 11ce6322fadcf253d16e9937688c2a895cf59663..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/devouringflame.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/earth.ogg b/game/modules/tome/data/sound/talents/earth.ogg new file mode 100644 index 0000000000000000000000000000000000000000..7800855e71fcc736af088a96b5955fbca2eb15d4 Binary files /dev/null and b/game/modules/tome/data/sound/talents/earth.ogg differ diff --git a/game/modules/tome/data/sound/talents/earth.wav b/game/modules/tome/data/sound/talents/earth.wav deleted file mode 100755 index dffec9530904127820f3f25292e807499bd05246..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/earth.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/fire.lua b/game/modules/tome/data/sound/talents/fire.lua index 09bc754b88fbdabb1d6673809004668a187cd6f8..9552124dbf1b3f05bacfb5fb46d1bf42ad6e7a31 100644 --- a/game/modules/tome/data/sound/talents/fire.lua +++ b/game/modules/tome/data/sound/talents/fire.lua @@ -1,4 +1,4 @@ return { - file = "talents/fire.wav", + file = "talents/fire.ogg", volume = 50, } diff --git a/game/modules/tome/data/sound/talents/fire.ogg b/game/modules/tome/data/sound/talents/fire.ogg new file mode 100644 index 0000000000000000000000000000000000000000..321703361287e25ed06e763dad38b44ec66cc000 Binary files /dev/null and b/game/modules/tome/data/sound/talents/fire.ogg differ diff --git a/game/modules/tome/data/sound/talents/fire.wav b/game/modules/tome/data/sound/talents/fire.wav deleted file mode 100755 index ac692f6245e67a5dd94f20df655d97bb3b73ce47..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/fire.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/fireflash.lua b/game/modules/tome/data/sound/talents/fireflash.lua index 4072abddb9da41d291cd8d88fbfc6411ca763907..40d67b537ca5b9645157740976e5ebbabb9ae343 100644 --- a/game/modules/tome/data/sound/talents/fireflash.lua +++ b/game/modules/tome/data/sound/talents/fireflash.lua @@ -1,4 +1,4 @@ return { - file = "talents/fireflash.wav", + file = "talents/fireflash.ogg", volume = 50, } diff --git a/game/modules/tome/data/sound/talents/fireflash.ogg b/game/modules/tome/data/sound/talents/fireflash.ogg new file mode 100644 index 0000000000000000000000000000000000000000..7340eb9ef66ff7febd109e7465018b30dbb35c1e Binary files /dev/null and b/game/modules/tome/data/sound/talents/fireflash.ogg differ diff --git a/game/modules/tome/data/sound/talents/fireflash.wav b/game/modules/tome/data/sound/talents/fireflash.wav deleted file mode 100755 index cb2ddc219d8ce21c859e351e3f18ce6c10742789..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/fireflash.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/heal.ogg b/game/modules/tome/data/sound/talents/heal.ogg new file mode 100644 index 0000000000000000000000000000000000000000..ceac286b541a01a60b7597e76a99a0721754b1db Binary files /dev/null and b/game/modules/tome/data/sound/talents/heal.ogg differ diff --git a/game/modules/tome/data/sound/talents/heal.wav b/game/modules/tome/data/sound/talents/heal.wav deleted file mode 100755 index a29d78d214cc852723dcadb63330d00a89fb9c26..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/heal.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/ice.lua b/game/modules/tome/data/sound/talents/ice.lua index 14c86ff077a815c28b2f8d66a3a764c332628bde..3938395a300a249b7b4a99ce064a2444132689c3 100644 --- a/game/modules/tome/data/sound/talents/ice.lua +++ b/game/modules/tome/data/sound/talents/ice.lua @@ -1,5 +1,5 @@ return { - file = "talents/ice.wav", + file = "talents/ice.ogg", volume = 70, fadeout = 700, } diff --git a/game/modules/tome/data/sound/talents/ice.ogg b/game/modules/tome/data/sound/talents/ice.ogg new file mode 100644 index 0000000000000000000000000000000000000000..9114a78716d1342db8778b92b264992b24cf91e4 Binary files /dev/null and b/game/modules/tome/data/sound/talents/ice.ogg differ diff --git a/game/modules/tome/data/sound/talents/ice.wav b/game/modules/tome/data/sound/talents/ice.wav deleted file mode 100755 index a8d173d96d37b4cab3a0c1b2b12cc61afe84d5d8..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/ice.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/lightning.lua b/game/modules/tome/data/sound/talents/lightning.lua index 02c63aa076f36f6da8ca6e4562c77bf845a72d76..f50b0c4fd11b731800faec7178f1554ced39d96f 100644 --- a/game/modules/tome/data/sound/talents/lightning.lua +++ b/game/modules/tome/data/sound/talents/lightning.lua @@ -1,4 +1,4 @@ return { - file = "talents/lightning.wav", + file = "talents/lightning.ogg", volume = 30, } diff --git a/game/modules/tome/data/sound/talents/lightning.ogg b/game/modules/tome/data/sound/talents/lightning.ogg new file mode 100644 index 0000000000000000000000000000000000000000..def967903217df3b815df9a5854f84f8b612dc1e Binary files /dev/null and b/game/modules/tome/data/sound/talents/lightning.ogg differ diff --git a/game/modules/tome/data/sound/talents/lightning.wav b/game/modules/tome/data/sound/talents/lightning.wav deleted file mode 100755 index 796da68300f304565ddde8bf16375c123b8a1f59..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/lightning.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/slime.ogg b/game/modules/tome/data/sound/talents/slime.ogg new file mode 100644 index 0000000000000000000000000000000000000000..b13187a4c147db4a1caf5546f02cd9cc70296b7b Binary files /dev/null and b/game/modules/tome/data/sound/talents/slime.ogg differ diff --git a/game/modules/tome/data/sound/talents/slime.wav b/game/modules/tome/data/sound/talents/slime.wav deleted file mode 100755 index 754cf203bc939cd63e2c110692d6372b0fa9293c..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/slime.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/spell_generic.ogg b/game/modules/tome/data/sound/talents/spell_generic.ogg new file mode 100644 index 0000000000000000000000000000000000000000..c458e786b127b93818eb552d6aa6240610576e24 Binary files /dev/null and b/game/modules/tome/data/sound/talents/spell_generic.ogg differ diff --git a/game/modules/tome/data/sound/talents/spell_generic.wav b/game/modules/tome/data/sound/talents/spell_generic.wav deleted file mode 100755 index 571c4310626b7e6c1f35e5dafff0c4a8a6824cd2..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/spell_generic.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/spell_generic2.ogg b/game/modules/tome/data/sound/talents/spell_generic2.ogg new file mode 100644 index 0000000000000000000000000000000000000000..49947dab75111065effb712ed21ae1f974020299 Binary files /dev/null and b/game/modules/tome/data/sound/talents/spell_generic2.ogg differ diff --git a/game/modules/tome/data/sound/talents/spell_generic2.wav b/game/modules/tome/data/sound/talents/spell_generic2.wav deleted file mode 100755 index d9f1145db164bea5319932528b7f695f64a10bf3..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/spell_generic2.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/teleport.ogg b/game/modules/tome/data/sound/talents/teleport.ogg new file mode 100644 index 0000000000000000000000000000000000000000..39fecd315f3207b4931d9d88cd52933366307bb2 Binary files /dev/null and b/game/modules/tome/data/sound/talents/teleport.ogg differ diff --git a/game/modules/tome/data/sound/talents/teleport.wav b/game/modules/tome/data/sound/talents/teleport.wav deleted file mode 100755 index c9aea5206b20cc8b9bd0f4e5c6fde0d10d5a3a1f..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/teleport.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/thunderstorm.ogg b/game/modules/tome/data/sound/talents/thunderstorm.ogg new file mode 100644 index 0000000000000000000000000000000000000000..eef1b79a390ea48bd73487b2d9074eb6b4578c3e Binary files /dev/null and b/game/modules/tome/data/sound/talents/thunderstorm.ogg differ diff --git a/game/modules/tome/data/sound/talents/thunderstorm.wav b/game/modules/tome/data/sound/talents/thunderstorm.wav deleted file mode 100755 index ccff9ecab16bbef909b0f6eb2baba86749e57089..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/thunderstorm.wav and /dev/null differ diff --git a/game/modules/tome/data/sound/talents/tidalwave.ogg b/game/modules/tome/data/sound/talents/tidalwave.ogg new file mode 100644 index 0000000000000000000000000000000000000000..bbea25735103b61487f084df91136a61a489290f Binary files /dev/null and b/game/modules/tome/data/sound/talents/tidalwave.ogg differ diff --git a/game/modules/tome/data/sound/talents/tidalwave.wav b/game/modules/tome/data/sound/talents/tidalwave.wav deleted file mode 100755 index f61d4d4a1bf45062e79f5e58fb450ad1a75788b6..0000000000000000000000000000000000000000 Binary files a/game/modules/tome/data/sound/talents/tidalwave.wav and /dev/null differ diff --git a/game/modules/tome/data/zones/charred-scar/npcs.lua b/game/modules/tome/data/zones/charred-scar/npcs.lua index c37d3ab0a42b1c91a165c71f7d988846f6acc8a0..3b49c883e5aa13e2d41716158e9f4edddb220337 100644 --- a/game/modules/tome/data/zones/charred-scar/npcs.lua +++ b/game/modules/tome/data/zones/charred-scar/npcs.lua @@ -132,7 +132,7 @@ newEntity{ } newEntity{ base = "BASE_NPC_ORC_ATTACKER", define_as = "ORC_ATTACK", - name = "orc", color=colors.DARK_RED, + name = "orc warrior", color=colors.DARK_RED, desc = [[A fierce soldier-orc.]], level_range = {42, nil}, exp_worth = 1, max_life = resolvers.rngavg(120,140), diff --git a/game/modules/tome/data/zones/heart-gloom/grids.lua b/game/modules/tome/data/zones/heart-gloom/grids.lua index 70526e1e795ab1af46ebf44254449d8eb36cf11f..3045c3bae141dad06236ef8ab0a3e939355c8ee2 100644 --- a/game/modules/tome/data/zones/heart-gloom/grids.lua +++ b/game/modules/tome/data/zones/heart-gloom/grids.lua @@ -18,6 +18,6 @@ -- darkgod@te4.org load("/data/general/grids/basic.lua") -load("/data/general/grids/forest.lua", function(e) if e.image == "terrain/grass.png" then e.image = "terrain/underground_floor.png" end end) +load("/data/general/grids/forest.lua") load("/data/general/grids/underground.lua") diff --git a/game/modules/tome/data/zones/old-forest/zone.lua b/game/modules/tome/data/zones/old-forest/zone.lua index 4e54efadd93d8103d39ad32f860f5960a3833e3e..6aedf7ef9bbdcb1e991a642d0ca9ded8a329dc2d 100644 --- a/game/modules/tome/data/zones/old-forest/zone.lua +++ b/game/modules/tome/data/zones/old-forest/zone.lua @@ -31,7 +31,7 @@ return { persistent = "zone", color_shown = {0.7, 0.7, 0.7, 1}, color_obscure = {0.7*0.6, 0.7*0.6, 0.7*0.6, 0.6}, - ambient_music = "Woods of Eremae.ogg", + ambient_music = {"Woods of Eremae.ogg", "weather/rain.ogg"}, min_material_level = function() return game.state:isAdvanced() and 3 or 1 end, max_material_level = function() return game.state:isAdvanced() and 4 or 2 end, generator = { diff --git a/src/main.c b/src/main.c index a2b0d8cdc603a9806840ce64892d8dbcc86a1c6e..c2f1a552ce92fc511087b72a4a36d5fab9a777b9 100644 --- a/src/main.c +++ b/src/main.c @@ -881,7 +881,7 @@ int main(int argc, char *argv[]) SDL_EnableUNICODE(TRUE); SDL_EnableKeyRepeat(300, 10); TTF_Init(); - if (Mix_OpenAudio(22050, AUDIO_S16, 2, 2048) == -1) +/* if (Mix_OpenAudio(22050, AUDIO_S16, 2, 2048) == -1) { no_sound = TRUE; printf("Disabling sounds: %s", SDL_GetError()); @@ -892,6 +892,7 @@ int main(int argc, char *argv[]) Mix_Volume(-1, SDL_MIX_MAXVOLUME); Mix_AllocateChannels(16); } + */ /* Sets up OpenGL double buffering */ resizeWindow(WIDTH, HEIGHT); @@ -914,6 +915,7 @@ int main(int argc, char *argv[]) boot_lua(2, FALSE, argc, argv); pass_command_args(argc, argv); + init_openal(); SDL_Event event; while (!exit_engine) diff --git a/src/music.c b/src/music.c index 43e45695f310d3f801b17ed06a14a461b7e34f35..6ed0b9657fcef05e8a0d8c01868570e2fb616588 100644 --- a/src/music.c +++ b/src/music.c @@ -1,231 +1,438 @@ /* - TE4 - T-Engine 4 - Copyright (C) 2009, 2010, 2011 Nicolas Casalini - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - - Nicolas Casalini "DarkGod" - darkgod@te4.org -*/ -#include "display.h" + + audio.c, part of the Pipmak Game Engine + Copyright (c) 2006-2007 Christian Walther + + Modified for: + TE4 - T-Engine 4 + Copyright (C) 2009, 2010, 2011 Nicolas Casalini + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + */ + +#include "music.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include "tSDL.h" +#include "physfs.h" #include "lua.h" #include "lauxlib.h" #include "lualib.h" #include "auxiliar.h" -#include "types.h" -#include "music.h" -#include "script.h" -#include "physfs.h" -#include "physfsrwops.h" -bool sound_active = TRUE; -static int music_new(lua_State *L) -{ - if (no_sound) return 0; - const char *name = luaL_checkstring(L, 1); +static ALCdevice *audioDevice; +static ALCcontext *audioContext; - Mix_Music **m = (Mix_Music**)lua_newuserdata(L, sizeof(Mix_Music*)); - auxiliar_setclass(L, "core{music}", -1); - SDL_RWops *rops = PHYSFSRWOPS_openRead(name); - if (!rops) - { - *m = NULL; - return 0; - } - *m = Mix_LoadMUS_RW(rops); - if (!*m) return 0; +static size_t physfsOvRead(void *ptr, size_t size, size_t nmemb, void *datasource) { + PHYSFS_sint64 result = PHYSFS_read((PHYSFS_file *)datasource, ptr, (PHYSFS_uint32)size, (PHYSFS_uint32)nmemb); + if (result < 0) return 0; + else return (size_t)result; +} - return 1; +static int physfsOvSeek(void *datasource, ogg_int64_t offset, int whence) { + PHYSFS_uint64 start = 0; + if (whence == SEEK_CUR) start = PHYSFS_tell((PHYSFS_file *)datasource); + else if (whence == SEEK_END) start = PHYSFS_fileLength((PHYSFS_file *)datasource); + return (PHYSFS_seek((PHYSFS_file *)datasource, start + offset)) ? 0 : -1; } -static int music_free(lua_State *L) -{ - Mix_Music **m = (Mix_Music**)auxiliar_checkclass(L, "core{music}", 1); - if (*m) Mix_FreeMusic(*m); - lua_pushnumber(L, 1); - return 1; +static int physfsOvClose(void *datasource) { + PHYSFS_close((PHYSFS_file *)datasource); + return 0; } -static int music_play(lua_State *L) -{ - if (!sound_active) return 0; - Mix_Music **m = (Mix_Music**)auxiliar_checkclass(L, "core{music}", 1); - int loop = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : 1; - int fadein = lua_isnumber(L, 3) ? lua_tonumber(L, 3) : 0; +static long physfsOvTell(void *datasource) { + return (long)PHYSFS_tell((PHYSFS_file *)datasource); +} - lua_pushboolean(L, (Mix_FadeInMusic(*m, loop, fadein) == -1) ? FALSE : TRUE); +static ov_callbacks physfsOvCallbacks = { + physfsOvRead, + physfsOvSeek, + physfsOvClose, + physfsOvTell +}; + + +int init_openal() { + audioDevice = alcOpenDevice(NULL); + if (audioDevice == NULL) return 0; + audioContext = alcCreateContext(audioDevice, NULL); + if (audioContext == NULL) { + alcCloseDevice(audioDevice); + return 0; + } + alcMakeContextCurrent(audioContext); + alDistanceModel(AL_NONE); return 1; } -static int music_stop(lua_State *L) -{ - if (no_sound) return 0; - int fadeout = lua_isnumber(L, 1) ? lua_tonumber(L, 1) : 0; - Mix_FadeOutMusic(fadeout); +void deinit_openal() { + alcMakeContextCurrent(NULL); + alcDestroyContext(audioContext); + alcCloseDevice(audioDevice); +} + +static int readSoundData(Sound *sound, ALvoid *data, ALsizei size) { + int section, readBytes, result; + readBytes = 0; + while ((ALsizei)readBytes < size) { + result = ov_read(sound->vorbisFile, (char *)data + readBytes, size - readBytes, (SDL_BYTEORDER == SDL_BIG_ENDIAN) ? 1 : 0, 2, 1, §ion); + if (result == 0) { + if (sound->loop) ov_raw_seek_lap(sound->vorbisFile, 0); + else break; + } + if (result < 0 && result != OV_HOLE) break; + readBytes += result; + } + return readBytes; +} + +static int staticLoader(void *sound) { + int bufferSize; + vorbis_info *info; + ALvoid *data; + + info = ov_info(((Sound *)sound)->vorbisFile, -1); + bufferSize = 2*info->channels*(int)ov_pcm_total(((Sound *)sound)->vorbisFile, -1); + data = malloc(bufferSize); + if (data == NULL) return 1; + bufferSize = readSoundData((Sound *)sound, data, bufferSize); + alBufferData(((Sound *)sound)->buffers[0], (info->channels > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, data, bufferSize, info->rate); + free(data); + ov_clear(((Sound *)sound)->vorbisFile); + free(((Sound *)sound)->vorbisFile); + ((Sound *)sound)->vorbisFile = NULL; + alSourcei(((Sound *)sound)->source, AL_BUFFER, ((Sound *)sound)->buffers[0]); return 0; } -static int music_volume(lua_State *L) -{ - if (no_sound) return 0; - int vol = lua_isnumber(L, 1) ? lua_tonumber(L, 1) : -1; - - if (vol == -1) - vol = Mix_VolumeMusic(-1); - else - vol = Mix_VolumeMusic(SDL_MIX_MAXVOLUME * vol / 100); - lua_pushnumber(L, vol * 100 / SDL_MIX_MAXVOLUME); - return 1; +static int streamingLoader(void *sound) { +#define STREAMING_BUFFER_SIZE (1*2*2*44100) + ALint i; + ALuint buffer; + vorbis_info *info; + ALvoid *data; + int readBytes; + int testRest; /*what to do after the job is done: 0 = go to sleep right away, 1 = rest for a while if playing, else sleep*/ + + data = malloc(STREAMING_BUFFER_SIZE); + if (data == NULL) return 1; + SDL_LockMutex(((Sound *)sound)->mutex); + info = ov_info(((Sound *)sound)->vorbisFile, -1); + + do { + testRest = 1; + alGetSourcei(((Sound *)sound)->source, AL_BUFFERS_QUEUED, &i); +// printf("==1: %d\n", i); + if (i == 0) { /*fill and queue initial buffers*/ + readBytes = readSoundData((Sound *)sound, data, STREAMING_BUFFER_SIZE); + alBufferData(((Sound *)sound)->buffers[0], (info->channels > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, data, readBytes, info->rate); +// printf("==read: %d : %s\n", i, alGetString(alGetError())); + readBytes = readSoundData((Sound *)sound, data, STREAMING_BUFFER_SIZE); + alBufferData(((Sound *)sound)->buffers[1], (info->channels > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, data, readBytes, info->rate); +// printf("==read: %d : %s\n", i, alGetString(alGetError())); + alSourceQueueBuffers(((Sound *)sound)->source, 2, ((Sound *)sound)->buffers); +// printf("==read: %d : %s\n", i, alGetString(alGetError())); + } + else { /*refill processed buffers*/ + alGetSourcei(((Sound *)sound)->source, AL_BUFFERS_PROCESSED, &i); + while (i-- != 0) { + readBytes = readSoundData((Sound *)sound, data, STREAMING_BUFFER_SIZE); + if (readBytes == 0) { + testRest = 0; + break; + } + else { + alSourceUnqueueBuffers(((Sound *)sound)->source, 1, &buffer); + alBufferData(buffer, (info->channels > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, data, readBytes, info->rate); + alSourceQueueBuffers(((Sound *)sound)->source, 1, &buffer); + } + } + } +// printf("==2: %d\n", i); + SDL_CondSignal(((Sound *)sound)->cond); /*tell the main thread we're done, in case it's waiting for us*/ +// printf("==3: %d\n", i); + if (testRest) { + alGetSourcei(((Sound *)sound)->source, AL_SOURCE_STATE, &i); + testRest = (i == AL_PLAYING); + } + if (testRest) { +// printf("==4a: %d\n", i); + SDL_CondWaitTimeout(((Sound *)sound)->cond, ((Sound *)sound)->mutex, 400); + } + else { +// printf("==4b: %d\n", i); +// SDL_CondWait(((Sound *)sound)->cond, ((Sound *)sound)->mutex); + SDL_CondWaitTimeout(((Sound *)sound)->cond, ((Sound *)sound)->mutex, 400); + } +// printf("streamlooping read %d\n", ((Sound *)sound)->loaderShouldExit); + } while (!(((Sound *)sound)->loaderShouldExit)); +// printf(">>streamlooping read %d\n", ((Sound *)sound)->loaderShouldExit); + + SDL_UnlockMutex(((Sound *)sound)->mutex); + free(data); + return 0; } -static int sound_new(lua_State *L) -{ - if (no_sound) return 0; - const char *name = luaL_checkstring(L, 1); +static int loadsoundLua(lua_State *L) { + PHYSFS_file *file; + const char *s; + + luaL_checktype(L, 1, LUA_TSTRING); + s = lua_tostring(L, 1); + + Sound *sound = (Sound*)lua_newuserdata(L, sizeof(Sound)); + auxiliar_setclass(L, "sound{source}", -1); + sound->type = SOUND_STATIC; + sound->loop = 0; + sound->loaderShouldExit = 0; + sound->loaderThread = NULL; + sound->vorbisFile = NULL; + sound->path = malloc(strlen(s) + 1); + if (sound->path == NULL) luaL_error(L, "out of memory"); + strcpy(sound->path, s); + alGenSources(1, &sound->source); + alGenBuffers(2, sound->buffers); + sound->vorbisFile = malloc(sizeof(OggVorbis_File)); + if (sound->vorbisFile == NULL) luaL_error(L, "out of memory"); + if ((file = PHYSFS_openRead(s)) == NULL) { + free(sound->vorbisFile); + sound->vorbisFile = NULL; + luaL_error(L, "Error loading sound \"%s\": %s", s, PHYSFS_getLastError()); + } + if (ov_open_callbacks(file, sound->vorbisFile, NULL, 0, physfsOvCallbacks) < 0) { + free(sound->vorbisFile); + sound->vorbisFile = NULL; + PHYSFS_close(file); + luaL_error(L, "Error loading sound \"%s\": not an Ogg Vorbis file", s); + } - Mix_Chunk **m = (Mix_Chunk**)lua_newuserdata(L, sizeof(Mix_Chunk*)); - auxiliar_setclass(L, "core{sound}", -1); + if (ov_streams(sound->vorbisFile) > 1) luaL_error(L, "Error loading sound \"%s\": Ogg files containing multiple logical bitstreams are not supported", s); - SDL_RWops *rops = PHYSFSRWOPS_openRead(name); - if (!rops) - { - *m = NULL; - return 0; + if (ov_time_total(sound->vorbisFile, -1) > 10.0) { + sound->type = SOUND_STREAMING; + sound->mutex = SDL_CreateMutex(); + if (sound->mutex == NULL) luaL_error(L, "out of memory"); + sound->cond = SDL_CreateCond(); + if (sound->cond == NULL) luaL_error(L, "out of memory"); + sound->loaderThread = SDL_CreateThread(streamingLoader, sound); + } + else { + sound->loaderThread = SDL_CreateThread(staticLoader, sound); } - *m = Mix_LoadWAV_RW(rops, 1); - if (!*m) return 0; - Mix_VolumeChunk(*m, SDL_MIX_MAXVOLUME); return 1; } -static int sound_free(lua_State *L) -{ - Mix_Chunk **m = (Mix_Chunk**)auxiliar_checkclass(L, "core{sound}", 1); - if (*m) Mix_FreeChunk(*m); - lua_pushnumber(L, 1); +const luaL_reg soundlib[] = { + {"load", loadsoundLua}, + {NULL, NULL} +}; + +static int soundTostringLua(lua_State *L) { + Sound *s; + s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1); + lua_pushfstring(L, "sound \"%s\" : %s", s->path, (s->type == SOUND_STREAMING) ? "<stream>" : "<static>"); return 1; } -static int sound_play(lua_State *L) -{ - if (!sound_active) return 0; - Mix_Chunk **m = (Mix_Chunk**)auxiliar_checkclass(L, "core{sound}", 1); - int loop = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : 0; - int ms = lua_isnumber(L, 3) ? lua_tonumber(L, 3) : 0; - int chan; - if (!ms) - chan = Mix_PlayChannel(-1, *m, loop); - else - chan = Mix_PlayChannelTimed(-1, *m, loop , ms); - if (chan == -1) lua_pushnil(L); - else lua_pushnumber(L, chan); - return 1; +static int soundCollectLua(lua_State *L) { + Sound *s; + s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1); + + if (s->type == SOUND_STREAMING) { + s->loaderShouldExit = 1; + SDL_CondSignal(s->cond); + SDL_WaitThread(s->loaderThread, NULL); + SDL_DestroyCond(s->cond); + SDL_DestroyMutex(s->mutex); + } + else { + if (s->loaderThread != NULL) SDL_WaitThread(s->loaderThread, NULL); + } + + alDeleteSources(1, &s->source); + alDeleteBuffers(2, s->buffers); + if (s->path != NULL) free(s->path); + if (s->vorbisFile != NULL) { + ov_clear(s->vorbisFile); + free(s->vorbisFile); + } + return 0; } -static int sound_volume(lua_State *L) -{ - Mix_Chunk **m = (Mix_Chunk**)auxiliar_checkclass(L, "core{sound}", 1); - int vol = lua_isnumber(L, 2) ? lua_tonumber(L, 2) : 100; - Mix_VolumeChunk(*m, SDL_MIX_MAXVOLUME * vol / 100); +static int soundPlayLua(lua_State *L) { + Sound *s; + ALint i; + s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1); + if (s->type == SOUND_STREAMING) { + alGetSourcei(s->source, AL_SOURCE_STATE, &i); + printf("====>>play %d\n",i); + switch (i) { + case AL_PLAYING: + alSourceStop(s->source); + case AL_STOPPED: + ov_raw_seek(s->vorbisFile, 0); + alSourcei(s->source, AL_BUFFER, AL_NONE); /*unqueue all buffers*/ + case AL_INITIAL: + case AL_PAUSED: + SDL_LockMutex(s->mutex); + SDL_CondSignal(s->cond); /*wake up loader*/ + SDL_CondWait(s->cond, s->mutex); /*wait until loader has queued initial buffers (if necessary), it will have gone to sleep when this returns because the source isn't playing yet*/ + alSourcePlay(s->source); + SDL_CondSignal(s->cond); /*wake up loader again (it will stay awake this time since the source is playing now)*/ + SDL_UnlockMutex(s->mutex); + break; + } + } + else { + if (s->loaderThread != NULL) { + SDL_WaitThread(s->loaderThread, NULL); + s->loaderThread = NULL; + } + alSourcePlay(s->source); + } return 0; } -static int channel_fadeout(lua_State *L) -{ - if (no_sound) return 0; - int chan = luaL_checknumber(L, 1); - int ms = luaL_checknumber(L, 2); +static int soundPauseLua(lua_State *L) { + Sound *s; + s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1); + alSourcePause(s->source); + return 0; +} - Mix_FadeOutChannel(chan, ms); +static int soundStopLua(lua_State *L) { + Sound *s; + s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1); + alSourceStop(s->source); return 0; } -static int sound_status(lua_State *L) -{ - if (lua_isboolean(L, 1)) - { - int act = lua_toboolean(L, 1); - sound_active = act; - return 0; +static int soundLoopLua(lua_State *L) { + Sound *s; + ALint old; + s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1); + alGetSourcei(s->source, AL_LOOPING, &old); + if (!lua_isnone(L, 2)) { + if (s->type == SOUND_STATIC) alSourcei(s->source, AL_LOOPING, lua_toboolean(L, 2)); + else s->loop = lua_toboolean(L, 2); } - else - { - lua_pushboolean(L, sound_active); - return 1; + lua_pushboolean(L, old); + return 1; +} + +static int soundVolumeLua(lua_State *L) { + Sound *s; + ALfloat old, new; + s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1); + new = (ALfloat)luaL_optnumber(L, 2, -2893.0); + alGetSourcef(s->source, AL_GAIN, &old); + if (new != -2893.0) { + alSourcef(s->source, AL_GAIN, new); } + lua_pushnumber(L, old); + return 1; } -static void music_finished() -{ - SDL_Event event; - SDL_UserEvent userevent; +static int soundPitchLua(lua_State *L) { + Sound *s; + ALfloat old, new; + s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1); + new = (ALfloat)luaL_optnumber(L, 2, -2893.0); + alGetSourcef(s->source, AL_PITCH, &old); + if (new != -2893.0) { + alSourcef(s->source, AL_PITCH, new); + } + lua_pushnumber(L, old); + return 1; +} - /* In this example, our callback pushes an SDL_USEREVENT event - into the queue, and causes ourself to be called again at the - same interval: */ +static int soundLocationLua(lua_State *L) { + Sound *s; + ALfloat x, y, z; + float oldaz, oldel, newaz = 0, newel = 0; + int choice; - userevent.type = SDL_USEREVENT; - userevent.code = 1; - userevent.data1 = NULL; - userevent.data2 = NULL; + s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1); + if (lua_isnoneornil(L, 2)) { + choice = 0; + } + else if (lua_isboolean(L, 2) && !lua_toboolean(L, 2)) { + choice = 1; + } + else { + newaz = (float)luaL_checknumber(L, 2)*M_PI/180; + newel = (float)luaL_checknumber(L, 3)*M_PI/180; + choice = 2; + } - event.type = SDL_USEREVENT; - event.user = userevent; + alGetSource3f(s->source, AL_POSITION, &x, &y, &z); + if (x == 0 && y == 0 && z == 0) { + lua_pushboolean(L, 0); + lua_pushnil(L); + } + else { + oldaz = atan2(x, -z)/M_PI*180; + if (oldaz < 0) oldaz += 360; + oldel = atan2(y, sqrt(x*x+z*z))/M_PI*180; + lua_pushnumber(L, oldaz); + lua_pushnumber(L, oldel); + } - SDL_PushEvent(&event); + if (choice == 1) { + alSource3f(s->source, AL_POSITION, 0, 0, 0); + } + else if (choice == 2) { + alSource3f(s->source, AL_POSITION, cosf(newel)*sinf(newaz), sinf(newel), -cosf(newel)*cosf(newaz)); + } + return 2; } -static int music_callback(lua_State *L) -{ - Mix_HookMusicFinished(music_finished); - return 0; +static int soundPlayingLua(lua_State *L) { + Sound *s; + ALint i; + s = (Sound*)auxiliar_checkclass(L, "sound{source}", 1); + alGetSourcei(s->source, AL_SOURCE_STATE, &i); + lua_pushboolean(L, (i == AL_PLAYING)); + return 1; } -static const struct luaL_reg soundlib[] = -{ - {"soundSystemStatus", sound_status}, - {"newMusic", music_new}, - {"newSound", sound_new}, - {"musicStop", music_stop}, - {"musicVolume", music_volume}, - {"channelFadeOut", channel_fadeout}, - {"activateMusicCallback", music_callback}, - {NULL, NULL}, -}; - -static const struct luaL_reg music_reg[] = -{ - {"__gc", music_free}, - {"play", music_play}, - {NULL, NULL}, -}; - -static const struct luaL_reg sound_reg[] = -{ - {"__gc", sound_free}, - {"play", sound_play}, - {"setVolume", sound_volume}, - {NULL, NULL}, +const luaL_reg soundFuncs[] = { + {"__tostring", soundTostringLua}, + {"__gc", soundCollectLua}, + {"play", soundPlayLua}, + {"pause", soundPauseLua}, + {"stop", soundStopLua}, + {"loop", soundLoopLua}, + {"volume", soundVolumeLua}, + {"pitch", soundPitchLua}, + {"location", soundLocationLua}, + {"playing", soundPlayingLua}, + {NULL, NULL} }; int luaopen_sound(lua_State *L) { - auxiliar_newclass(L, "core{music}", music_reg); - auxiliar_newclass(L, "core{sound}", sound_reg); + auxiliar_newclass(L, "sound{source}", soundFuncs); luaL_openlib(L, "core.sound", soundlib, 0); lua_pop(L, 1); return 1; diff --git a/src/music.h b/src/music.h index 583f89f5574f57526f953b1e7a4577e39fe7e88b..cb8710408ed03920e6167286850b94deded7b7b9 100644 --- a/src/music.h +++ b/src/music.h @@ -21,7 +21,40 @@ #ifndef _MUSIC_H_ #define _MUSIC_H_ -extern bool no_sound; +#if defined(MACOSX) +#include <OpenAL/al.h> +#include <OpenAL/alc.h> +#include <Vorbis/vorbisfile.h> +#elif defined(WIN32) +#include <al.h> +#include <alc.h> +#include <vorbis/vorbisfile.h> +#else +#include <AL/al.h> +#include <AL/alc.h> +#include <vorbis/vorbisfile.h> +#endif + +#include "SDL.h" +#include "SDL_thread.h" +#include "lua.h" +#include "lauxlib.h" + + +typedef struct Sound { + enum { SOUND_STATIC, SOUND_STREAMING } type; + char *path; + ALuint source; + ALuint buffers[2]; + unsigned loop:1, loaderShouldExit:1; + SDL_Thread *loaderThread; + SDL_mutex *mutex; /*used by cond, held by the loader thread while it is working*/ + SDL_cond *cond; /*used by the main thread to wake up the loader thread, and by the loader thread to signal the main thread that it is done*/ + OggVorbis_File *vorbisFile; +} Sound; + +int init_openal(); +void deinit_openal(); #endif diff --git a/src/shaders.c b/src/shaders.c index dcc32da09be844a76c2c943bf0641113d587f104..1e0bfa5551f0706f81f8e0e834b503cd41e52114 100644 --- a/src/shaders.c +++ b/src/shaders.c @@ -24,7 +24,6 @@ #include "lualib.h" #include "auxiliar.h" #include "types.h" -#include "music.h" #include "script.h" #include "useshader.h" #include "shaders.h" diff --git a/src/tSDL.h b/src/tSDL.h index 8b7b9cb426e0345c0fcb838a1fc705429f3c7f60..0310a1c4f518fcfc02c752cb13feb3ac4f865315 100644 --- a/src/tSDL.h +++ b/src/tSDL.h @@ -1,11 +1,11 @@ #ifdef __APPLE__ #include <SDL/SDL.h> #include <SDL_ttf/SDL_ttf.h> -#include <SDL_mixer/SDL_mixer.h> +//#include <SDL_mixer/SDL_mixer.h> #include <SDL_image/SDL_image.h> #else #include <SDL.h> #include <SDL_ttf.h> -#include <SDL_mixer.h> +//#include <SDL_mixer.h> #include <SDL_image.h> #endif