Jump to content

Fade Sound


MTA.Castiel

Recommended Posts

Hi there. ? Below is a simple client-side code that allows us to play a song by command. For our stopMusic function I've made an array of setTimer's to bring down the volume ? before stopping the song completely, ? thus achieving a fadeout effect. It works alright but i feel like there must be a much cleaner or simplified way of doing this: Which would be the best? ?

 

function playMusic()
	song = playSound("music/track_05.mp3", true)
	setSoundVolume(song, 1)
end
addCommandHandler("pmusic", playMusic)

function stopMusic()
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.95) end end, 100, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.90) end end, 200, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.85) end end, 300, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.80) end end, 400, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.75) end end, 500, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.70) end end, 600, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.65) end end, 700, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.60) end end, 800, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.55) end end, 900, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.50) end end, 1000, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.45) end end, 1100, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.40) end end, 1200, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.35) end end, 1300, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.30) end end, 1400, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.25) end end, 1500, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.20) end end, 1600, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.15) end end, 1700, 1)

	setTimer(function() if isElement(song) then setSoundVolume(song, 0.10) end end, 1800, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.09) end end, 1900, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.08) end end, 2000, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.07) end end, 2100, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.06) end end, 2200, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.05) end end, 2300, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.04) end end, 2400, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.03) end end, 2500, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.02) end end, 2600, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.01) end end, 2700, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0) end end, 2800, 1)

	setTimer(function() if isElement(song) then	--Destroy the sound element
		destroyElement(song) 
	end 
	end, 2900, 1) 
end
addCommandHandler("smusic", stopMusic)

 

Link to comment

Hi. I'm on my phone at the moment so it's a bit awkward. But you could make this a lot cleaner by making the volume a variable and only using 1 timer. 

 

Local soundVolume = 1 at the top, set your timer to 100 * 10, put if soundVolume > 0 then soundVolume = soundVolume - 0.1 end above the playSound, and set the Volume argument to the soundVolume variable. 

  • Thanks 1
Link to comment
  • Scripting Moderators
20 hours ago, MTA.Castiel said:

Hi there. ? Below is a simple client-side code that allows us to play a song by command. For our stopMusic function I've made an array of setTimer's to bring down the volume ? before stopping the song completely, ? thus achieving a fadeout effect. It works alright but i feel like there must be a much cleaner or simplified way of doing this: Which would be the best? ?

 

function playMusic()
	song = playSound("music/track_05.mp3", true)
	setSoundVolume(song, 1)
end
addCommandHandler("pmusic", playMusic)

function stopMusic()
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.95) end end, 100, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.90) end end, 200, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.85) end end, 300, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.80) end end, 400, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.75) end end, 500, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.70) end end, 600, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.65) end end, 700, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.60) end end, 800, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.55) end end, 900, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.50) end end, 1000, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.45) end end, 1100, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.40) end end, 1200, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.35) end end, 1300, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.30) end end, 1400, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.25) end end, 1500, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.20) end end, 1600, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.15) end end, 1700, 1)

	setTimer(function() if isElement(song) then setSoundVolume(song, 0.10) end end, 1800, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.09) end end, 1900, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.08) end end, 2000, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.07) end end, 2100, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.06) end end, 2200, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.05) end end, 2300, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.04) end end, 2400, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.03) end end, 2500, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.02) end end, 2600, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0.01) end end, 2700, 1)
	setTimer(function() if isElement(song) then setSoundVolume(song, 0) end end, 2800, 1)

	setTimer(function() if isElement(song) then	--Destroy the sound element
		destroyElement(song) 
	end 
	end, 2900, 1) 
end
addCommandHandler("smusic", stopMusic)

 

You can use https://wiki.multitheftauto.com/wiki/Animate

In order to smoothly change volume.

  • Thanks 1
Link to comment

@TheManTheMythTheLegend I don't really understand how your method is suppose to work, here's what I've followed on:
 

local soundVolume = 1
function playMusic()

	if soundVolume > 0 then 
		soundVolume = soundVolume - 0.1 
	end

	song = playSound("music/track.mp3", true)
	setSoundVolume(song, soundVolume)
end
addCommandHandler("pmusic", playMusic)

function stopMusic()
	setTimer(function() if isElement(song) then destroyElement(song) end end, 100*10, 1 )
end 
addCommandHandler("smusic", stopMusic)

 

Link to comment
local soundVolume = 1

function playMusic()
	song = playSound("music/track.mp3", true)
	setSoundVolume(song, soundVolume)
	
	setTimer(fadeSound, 100, 10)
end
addCommandHandler("pmusic", playMusic)

function fadeSound()
	if soundVolume > 0 then
		soundVolume = soundVolume - 0.1
		setSoundVolume(song, soundVolume)
	else
		destroyElement(song)
	end
end 
addCommandHandler("smusic", fadeSound)


Untested but this should do the trick.

Link to comment
7 minutes ago, MTA.Castiel said:

Alright so there's a fade now and it's quite short, also the fade starts as soon as the song starts then stays silent, I don't think the setTimer for the fadeSound belongs within the playMusic function

I did say it was untested. Well the barebones of how to do it are there, and you are along the right lines. Now have your own attempt at resolving it. 

You asked for help, I won't write the script for you

Link to comment

hi i have tested the animate function for you you can test the example i made here but i am not sure if this is what you want

local test = playSound("music.wav", true)
setSoundVolume(test, 1.0)

local anims, builtins = {}, {"Linear", "InQuad", "OutQuad", "InOutQuad", "OutInQuad", "InElastic", "OutElastic", "InOutElastic", "OutInElastic", "InBack", "OutBack", "InOutBack", "OutInBack", "InBounce", "OutBounce", "InOutBounce", "OutInBounce", "SineCurve", "CosineCurve"}

function table.find(t, v)
	for k, a in ipairs(t) do
		if a == v then
			return k
		end
	end
	return false
end

function animate(f, t, easing, duration, onChange, onEnd)
	assert(type(f) == "number", "Bad argument @ 'animate' [expected number at argument 1, got "..type(f).."]")
	assert(type(t) == "number", "Bad argument @ 'animate' [expected number at argument 2, got "..type(t).."]")
	assert(type(easing) == "string" or (type(easing) == "number" and (easing >= 1 or easing <= #builtins)), "Bad argument @ 'animate' [Invalid easing at argument 3]")
	assert(type(duration) == "number", "Bad argument @ 'animate' [expected number at argument 4, got "..type(duration).."]")
	assert(type(onChange) == "function", "Bad argument @ 'animate' [expected function at argument 5, got "..type(onChange).."]")
	table.insert(anims, {from = f, to = t, easing = table.find(builtins, easing) and easing or builtins[easing], duration = duration, start = getTickCount( ), onChange = onChange, onEnd = onEnd})
	return #anims
end

function destroyAnimation(a)
	if anims[a] then
		table.remove(anims, a)
	end
end

addEventHandler("onClientRender", root, function( )
	local now = getTickCount( )
	for k,v in ipairs(anims) do
		v.onChange(interpolateBetween(v.from, 0, 0, v.to, 0, 0, (now - v.start) / v.duration, v.easing))
		if now >= v.start+v.duration then
			if type(v.onEnd) == "function" then
				v.onEnd( )
			end
			table.remove(anims, k)
		end
	end
end)

function fadeOutSound(sound, fadeTime)
   animate(1.0, 0, 1, fadeTime, function(volumeValue)
     setSoundVolume(sound, volumeValue)
     if(sound and getSoundVolume(sound) == 0) then stopSound(sound) end
   end)
end

addCommandHandler("fadesound", function()
   fadeOutSound(test, 3000) -- Completely mute in 3 seconds
end)
Edited by Burak5312
  • Thanks 1
Link to comment

Why don't you use this to stop the sound slowly:

l

function stopSoundSlowly (sElement)
    if not isElement(sElement) then return false end
    local sound_timer_quant = getSoundVolume(sElement)
    local slowlyStop = setTimer(
      function ()
        local soundVolume = getSoundVolume(sElement)
        setSoundVolume(sElement,soundVolume - 0.5)
	if soundVolume >= 0 then 
          stopSound(sElement) end
	end,400,sound_timer_quant*2
    )
end

https://wiki.multitheftauto.com/wiki/StopSoundSlowly

 

You can also make something like startSoundSlowly with this function

Link to comment

@Burak5312 Although the code looks more a bit more than my array of setTimers ? Your method on fading sound using the Animate function really helped a lot. I didn't actually know about it since Srslyyyy quoted it, but it was great working from this example thanks man i appreciate it ? ?

local test = playSound("music.wav", true)
setSoundVolume(test, 1.0)

local anims, builtins = {}, {"Linear", "InQuad", "OutQuad", "InOutQuad", "OutInQuad", "InElastic", "OutElastic", "InOutElastic", "OutInElastic", "InBack", "OutBack", "InOutBack", "OutInBack", "InBounce", "OutBounce", "InOutBounce", "OutInBounce", "SineCurve", "CosineCurve"}

function table.find(t, v)
	for k, a in ipairs(t) do
		if a == v then
			return k
		end
	end
	return false
end

function animate(f, t, easing, duration, onChange, onEnd)
	assert(type(f) == "number", "Bad argument @ 'animate' [expected number at argument 1, got "..type(f).."]")
	assert(type(t) == "number", "Bad argument @ 'animate' [expected number at argument 2, got "..type(t).."]")
	assert(type(easing) == "string" or (type(easing) == "number" and (easing >= 1 or easing <= #builtins)), "Bad argument @ 'animate' [Invalid easing at argument 3]")
	assert(type(duration) == "number", "Bad argument @ 'animate' [expected number at argument 4, got "..type(duration).."]")
	assert(type(onChange) == "function", "Bad argument @ 'animate' [expected function at argument 5, got "..type(onChange).."]")
	table.insert(anims, {from = f, to = t, easing = table.find(builtins, easing) and easing or builtins[easing], duration = duration, start = getTickCount( ), onChange = onChange, onEnd = onEnd})
	return #anims
end

function destroyAnimation(a)
	if anims[a] then
		table.remove(anims, a)
	end
end

addEventHandler("onClientRender", root, function( )
	local now = getTickCount( )
	for k,v in ipairs(anims) do
		v.onChange(interpolateBetween(v.from, 0, 0, v.to, 0, 0, (now - v.start) / v.duration, v.easing))
		if now >= v.start+v.duration then
			if type(v.onEnd) == "function" then
				v.onEnd( )
			end
			table.remove(anims, k)
		end
	end
end)

function fadeOutSound(sound, fadeTime)
   animate(1.0, 0, 1, fadeTime, function(volumeValue)
     setSoundVolume(sound, volumeValue)
     if(sound and getSoundVolume(sound) == 0) then stopSound(sound) end
   end)
end

addCommandHandler("fadesound", function()
   fadeOutSound(test, 3000) -- Completely mute in 3 seconds
end)


 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...