Hi
So in my project (and maybe in some other), I use audio that change depending on the action of the hero, this is normal, but, to accomplish this, I need to split the audio in many parts. But, trouble are, loading and playing an audio does freeze for some time the game, even if the file's under 1mb
So I suggested an idea of extending the audio script, just like you did Chris by adding audio looping with LOOPSTART
You can see the whole idea here
https://github.com/MetalES/Project-Zelda/issues/17
What do you think ?
No. The real solution should be to fix the slowness in the engine (by just keeping previously read resources in memory). This is an old task I always wanted to do someday.
This is an important thing and should not be forgotten. Is there an issue for this in github? Or should we open it?
I don't think there is one yet.
MetalZelda, are you talking about musics or sounds?
He is talking about music. I started the conversation with him here: https://github.com/MetalES/Project-Zelda/issues/42
Then this is strange because musics are streamed, not completely loaded like sounds. Any music should open very quickly, even large music files, or there is an engine bug.
I was talking about musics, but I also have a huge delay when preloading sounds with a 544 elements, 10mb sound folder (5 seconds of pre-loading), but this might be normal
It truely depends on how the script handling the audio was made
For instance, this is how Hyrule field is done in my project.
return function(game)
local map
local hero
local audio = {}
local path = "hyrule_field/"
local old_music = nil
local enemy_partition_played = 0
function audio:start()
enemy_partition_played = 0
if not game.is_in_field then
self:determine_partition()
game.is_in_field = true
end
end
function audio:get_time_of_day()
local value = game:get_value("time_of_day")
local result = ""
if value == "twilight_sunset" then
result = "dusk"
elseif value == "night" then
result = "night"
elseif (value == "twilight_sunrise" or value == "dawn") then
result = "dawn"
end
return result
end
-- Analyse and determine what to play, depending on the time of day, the player has just entered the map.
function audio:determine_partition()
local tod = self:get_time_of_day()
if tod == "dawn" then
self:play_dawn()
elseif tod == "dusk" then
self:play_dusk()
elseif tod == "night" then
self:play_night()
elseif tod == "" or tod == "midday_" then
self:play_intro()
end
end
function audio:play_dawn()
sol.audio.play_music(path .. "environment_effect/dawn", function()
self:play_dawn()
end)
end
function audio:play_intro()
-- Testing Horse sample, we'll come to that later
-- local epona = hero:is_riding_epona()
-- We've enterred the map. Play a intro
sol.audio.play_music(path .. "intro_foot" .. self:get_time_of_day(), function()
self:check()
end)
end
function audio:play_dusk()
local hour = game:get_value("current_hour")
local minute = game:get_value("current_minute")
if hour < 20 and minute < 30 then
sol.audio.play_music(path .. "environment_effect/twilight", function()
self:play_dusk()
end)
else
self:play_night()
end
end
function audio:play_night()
sol.audio.play_music(path .. "night")
end
function audio:check()
local hero_anim = hero:get_animation()
local hour = game:get_value("current_hour")
local minute = game:get_value("current_minute")
local current_time = hour > 12 and "midday_" or ""
local next_partition = (math.random(0, 4)
if hour == 18 and minute > 29 then
enemy_partition_played = 0
sol.timer.start(math.random(200, 10000), function()
game:get_map():check_night()
end)
local function play_nighttime(self)
sol.audio.play_music(path .. "nighttime_intro", function()
self:play_dusk()
end)
end
if old_music == path .. "stopped_foot_midday_0" then
play_nighttime(self)
else
sol.audio.play_music(path .. "stopped_foot_midday_0", function()
play_nighttime(self)
end)
end
return
end
for e in map:get_entities_by_type("enemy") do
if e:get_distance(hero) <= 64 and e:exists() then
sol.audio.play_music(path .. "walking_foot_" .. current_time .. "near_enemy_" .. enemy_partition_played, function()
enemy_partition_played = enemy_partition_played + 1
if enemy_partition_played == 3 then enemy_partition_played = 0 end
self:check()
end)
old_music = sol.audio.get_music()
return
end
end
enemy_partition_played = 0
if (hero_anim:match("stopped") or game:is_suspended()) then
sol.audio.play_music(path .. "stopped_foot_" .. current_time .. "0", function()
self:check()
end)
else
sol.audio.play_music(path .. "walking_foot_" .. current_time .. next_partition, function()
self:check()
end)
end
old_music = sol.audio.get_music()
end
function game:start_field_audio()
map = game:get_map()
hero = map:get_hero()
audio:start()
end
return audio
end
The script has to analyse what is surrounding the hero and what he is doing (stopped or walking), this might be the cause of the lags, I'm not really sure, because it was remade to optimize the script. This was a real mess before being reworked.
The thing that I'm sure of, is that the lag occurs when the audio stop and reload another audio, it doesn't do this when the same audio has to be replayed.
To be absolutely sure, remove all sol.audio.play_music() calls (and for the ones that have callbacks, replace them with timers). If no longer have any lag then you know it is the music file loading that takes time. If this is the case then maybe it is time for me to implement data file caching and you will be the first tester :)
Using a such method
local lengh = {
["walking_foot_near_enemy_0"] = 15220,
["walking_foot_near_enemy_1"] = 6300,
["walking_foot_near_enemy_2"] = 15794,
["walking_foot_midday_near_enemy_0"] = 15220,
["walking_foot_midday_near_enemy_1"] = 6300,
["walking_foot_midday_near_enemy_2"] = 15794,
}
Decrease the lag, this might be a sol.audio callback issue then ?
Because, when it reloads the function to play another music, it returns nil (this might be normal), but it need to load and play the next track