[Question] Audio Features

Started by MetalZelda, July 31, 2016, 10:37:51 PM

Previous topic - Next topic
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?
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

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
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

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.

October 04, 2016, 01:55:43 PM #6 Last Edit: October 04, 2016, 02:03:06 PM by MetalZelda
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.

Code (lua) Select
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