id | title |
---|---|
vn/sound.lua |
vn/sound.lua |
{% include sourcecode.html id="textnotation" lang="lua" class="full-screen" content=" ---Functions related to audio playback (music, sound effects, voice clips)
module("vn.sound", package.seeall)
local function tosound(soundOrChannel) if type(soundOrChannel) == "number" then return Sound.findByChannel(soundOrChannel) end return soundOrChannel end
local MUSIC_CHANNEL = 9000 local DEFAULT_SOUND_CHANNEL = 9100
--Default fade-out time when stopping music, can be changed using setDefaultMusicFadeTime() local defaultMusicStopFrames = 60
---Global declarations -------------------------------------------------------------------------------------------------------------- @section globals
---Music functions -------------------------------------------------------------------------------------------------------------- @section music
---Changes the background music.
-- @string filename Path to a valid audio file, relative to /snd
.
-- @number[opt=1.0] volume Loudness of the music between 0.0
and 1.0
.
-- @see sound
function music(filename, volume)
musicStopAndWait()
return sound(filename, -1, volume or 1.0, MUSIC_CHANNEL, SoundType.MUSIC)
end
---Stops background music started with the music
function.
-- @number fadeTimeFrames Optional argument specifying the duration (in frames) of a slow fade-out instead of
-- stopping playback immediately.
-- @see music
-- @see musicStopAndWait
function musicStop(fadeTimeFrames)
local s = tosound(MUSIC_CHANNEL)
if s == nil then
return
end
if fadeTimeFrames == nil then
fadeTimeFrames = defaultMusicStopFrames
end
return soundStop(s, fadeTimeFrames)
end
---Stops background music started with the music
function, blocking until the music has finished stopping.
-- @number[opt=defaultMusicStopFrames] fadeTimeFrames Optional argument specifying the duration (in frames) of a slow
-- fade-out instead of stopping playback immediately.
-- @see music
-- @see musicStop
function musicStopAndWait(fadeTimeFrames)
if fadeTimeFrames == nil then
fadeTimeFrames = defaultMusicStopFrames
end
local s = musicStop(fadeTimeFrames)
if s ~= nil and fadeTimeFrames > 0 then
-- Wait for music top finish stopping
yield(fadeTimeFrames / getEffectSpeed())
end
end
---Sets the default fade-out time when music is stopped. -- @see musicStop function setDefaultMusicFadeTime(fadeTimeFrames) defaultMusicStopFrames = fadeTimeFrames or 0 end
---Voice functions -------------------------------------------------------------------------------------------------------------- @section voice
---Plays a voice clip.
-- @string filename Path to a valid audio file, relative to /snd
.
-- @int[opt=9200] channel The audio channel to use. Each channel can only play one sound at a time.
-- @see sound
function voice(filename, channel)
return sound(filename, 1, 1.0, channel or 9200, SoundType.VOICE)
end
---Sound functions -------------------------------------------------------------------------------------------------------------- @section sound
---Starts playing a sound effect, voice clip or background music.
-- @string filename Path to a valid audio file, relative to /snd
.
-- @int[opt=1] loops The number of times the sound should repeat. Default is 1
(play it only
-- once). Use -1
for infinite looping.
-- @number[opt=1.0] volume Loudness of the sound between 0.0
and 1.0
.
-- @int[opt=9100] channel The audio channel to use. Each channel can only play one sound at a time. Use
-- -1
to use a random free channel.
-- @tparam[opt=SoundType.SOUND] SoundType type The sound type:
-- SoundType.SOUND
, SoundType.MUSIC
or
-- SoundType.VOICE
.
-- @treturn ISound A sound object with which to control playback, or nil
if for whatever reason
-- no sound could be started.
function sound(filename, loops, volume, channel, type)
if loops == 0 then
--Playing a sound zero times is easy, just don't do anything
return
end
loops = loops or 1
if volume == nil then
volume = volume or 1.0
end
if channel == nil then
channel = DEFAULT_SOUND_CHANNEL
end
type = type or SoundType.SOUND
local s = Sound.create(filename, type)
if s ~= nil then
s:setPrivateVolume(volume)
s:setPreferredChannel(channel)
s:start(loops)
end
return s
end
---Stops a playing sound. -- @param soundOrChannel[opt=9100] The Sound object or audio channel to stop. -- @number fadeTimeFrames Optional argument specifying the duration (in frames) -- of a slow fade-out instead of stopping playback immediately. -- @return The sound which had stopped, or is now in the process of stopping -- @see sound function soundStop(soundOrChannel, fadeTimeFrames) local sound = tosound(soundOrChannel or DEFAULT_SOUND_CHANNEL) if sound == nil then Log.warn("Attempt to stop invalid sound effect or music: {}", soundOrChannel) return end
fadeTimeFrames = fadeTimeFrames or 0
sound:stop(fadeTimeFrames / getEffectSpeed())
return sound
end
---Changes the volume of playing sound/music/voice.
-- @param soundOrChannel The Sound object or audio channel to change the volume of.
-- @number[opt=1.0] targetVolume The target volume for the Sound.
-- @number[opt=0] durationFrames If specified, the number of frames over which to gradually change the sound's
-- volume to the targetVolume
.
function changeVolume(soundOrChannel, targetVolume, durationFrames)
local sound = tosound(soundOrChannel)
if sound == nil then
Log.warn("Attempt to change volume of invalid sound effect or music: {}", soundOrChannel)
return
end
if targetVolume == nil then
targetVolume = 1
end
durationFrames = durationFrames or 0
local vol = sound:getPrivateVolume()
if durationFrames > 0 then
local delta = (targetVolume - vol) / durationFrames
while math.abs(targetVolume - vol) > math.abs(delta * getEffectSpeed()) do
vol = vol + delta * getEffectSpeed()
sound:setPrivateVolume(vol)
yield()
end
end
sound:setPrivateVolume(targetVolume)
end
" %}