Page 1 of 5

Trying the new stuff in 0.11.0

Posted: Thu Jul 27, 2017 5:42 pm
by Santos
LÖVE 0.11.0 hasn't been released yet, but we can still try some of the new stuff in progress by using the nightly builds (Windows, Linux (the ones with "minor" in the name), and I'm not sure if this Mac build is for 0.11.0 or the current version).

You can read some of the changes here: http://www.love2d.org/wiki/0.11.0
And about some of the audio stuff here: https://love2d.org/wiki/Effect_Constant ... Candidates

So here's some of the stuff I've been checking out...

You can now press Ctrl+C to copy error messages. Neat!
error.PNG
error.PNG (7.97 KiB) Viewed 4272 times

You can use QueueableSources to play sounds (from SoundData) seamlessly one after the other.
queueablesource.love
(175.09 KiB) Downloaded 105 times

Code: Select all

function love.load()
	sd1 = love.sound.newSoundData('1.mp3')
	sd2 = love.sound.newSoundData('2.mp3')
	sd3 = love.sound.newSoundData('3.mp3')
	sd4 = love.sound.newSoundData('4.mp3')

	qs = love.audio.newQueueableSource(sd1:getSampleRate(), sd1:getBitDepth(), sd1:getChannels())

	qs:queue(sd1)
	qs:queue(sd2)
	qs:queue(sd3)
	qs:queue(sd4)

	love.audio.play(qs)
end
You can use RecordingDevices to record sound, and turn it into SoundData for playing. This example records for a couple of seconds (based on the number of samples that I've set) when you press a key, then when you press a key again it stops recording and plays back what it recorded.

Code: Select all

function love.load()
	rds = love.audio.getRecordingDevices()
	rd = rds[1]
end

function love.keypressed()
	if rd:isRecording() then
		local sounddata = rd:getData()
		rd:stop()
		local source = love.audio.newSource(sounddata)
		love.audio.play(source)
	else
		local sampleRate = 8000
		local bitDepth = 16
		local channels = 1
		local samples = sampleRate * 2

		rd:start(samples, sampleRate, bitDepth, channels)
	end
end

function love.draw()
	love.graphics.print(
		'is recording: '..tostring(rd:isRecording())..'\n'..
		'samples: '..rd:getSampleCount()..'\n\n'..
		'sample rate: '..rd:getSampleRate()..'\n'..
		'bit depth: '..rd:getBitDepth()..'\n'..
		'channels: '..rd:getChannels()
	)
end
This example uses recording and a QueueableSource to play back what is recorded after a delay.

Code: Select all

function love.load()
	rds = love.audio.getRecordingDevices()
	rd = rds[1]

	qs = love.audio.newQueueableSource(rd:getSampleRate(), rd:getBitDepth(), rd:getChannels())

	rd:start()
end

function love.update(dt)
	if rd:getSampleCount() > 4000 then
		qs:queue(rd:getData())
		qs:play()
	end
end

function love.draw()
	love.graphics.print('sample count: '..rd:getSampleCount())
end
Filters and effects can be put on audio. This example attenuates higher frequencies, hold the down or up arrow to change the amount (I've including a white noise file in the .love file too so you can hear what it sounds like on that if you want).
filter.love
(200.34 KiB) Downloaded 99 times

Code: Select all

function love.load()
	love.keyboard.setKeyRepeat(true)

	source = love.audio.newSource('loop.mp3', 'static')
	source:setLooping(true)
	love.audio.play(source)

	highgain = 1
end

function love.keypressed(key)
	if key == 'up' then
		highgain = math.min(highgain + 0.01, 1)
	elseif key == 'down' then
		highgain = math.max(highgain - 0.01, 0)
	end

	source:setFilter({ type = "lowpass", highgain = highgain })
end

function love.draw()
	love.graphics.print(highgain)
end
Maybe someone could give an example for audio effects?

Re: Trying the new stuff in 0.11.0

Posted: Thu Jul 27, 2017 6:22 pm
by zorg
One more use case: Audio Generation
https://github.com/zorggn/LoveTracker

Re: Trying the new stuff in 0.11.0

Posted: Thu Jul 27, 2017 7:53 pm
by raidho36
Using effects is similar to using filters. Differences are that you set effects globally using the audio module, and you make each individual source use initialized effects, optionally with a filter in between.

Code: Select all

love.audio.setEffect ( "foo", { type = "reverb", volume = 1 } )
source:setEffect ( "foo" )
source2:setEffect ( "foo", { type = "highpass", lowgain = 0 } )

Re: Trying the new stuff in 0.11.0

Posted: Thu Jul 27, 2017 9:14 pm
by slime
Keep in mind APIs may change between now and 0.11.0's release (and someone may end up looking at this thread after 0.11.0 is released, and wondering why the code snippets are broken). Not that you shouldn't post code, this is just a disclaimer. :)

Re: Trying the new stuff in 0.11.0

Posted: Fri Jul 28, 2017 1:11 am
by Ikroth
I made a video for a friend a while ago that showed raidho's audio demo which briefly covers all of the audio effects. It captures the gist of what you can do with some of the new audio APIs.


Re: Trying the new stuff in 0.11.0

Posted: Fri Jul 28, 2017 1:45 am
by raidho36
You didn't showcase the most important aspect - mixing. You don't have direct mixer control but you can mix wet, dry and filtered signals by adjusting corresponding volume levels. When you leave all levels at 100% you get 50/50 dry to wet ratio. You can get 100% wet if you set direct filter volume to 0, and you can get 100% dry if you set effect volume to 0. Also the selection of sample sound is not very good - it has neither low nor high frequency content, so you couldn't hear much of a difference even when it was cut completely.

In general, you should set all those values programmatically, computed from some formulas and pre-defined constants based on audio environment in current level, such as objects' spatial layout and material acoustic properties. Hence you don't get direct control over mixing but you get direct control over each effect and filter volume instead. I guess the wiki manual entry for effects should come with entire OpenAL EAX handbook, because people just tend to think it's the same thing as equalizer settings in your audio player and not a tool to emulate a realistic soundstage.

Re: Trying the new stuff in 0.11.0

Posted: Fri Jul 28, 2017 3:19 am
by yetneverdone
Wow. Love is getting better and better by each release. Anyways, is the new update mostly on audio functionality?

Re: Trying the new stuff in 0.11.0

Posted: Fri Jul 28, 2017 5:20 am
by Ikroth
raidho36 wrote:
Fri Jul 28, 2017 1:45 am
You didn't showcase the most important aspect - mixing. You don't have direct mixer control but you can mix wet, dry and filtered signals by adjusting corresponding volume levels. When you leave all levels at 100% you get 50/50 dry to wet ratio. You can get 100% wet if you set direct filter volume to 0, and you can get 100% dry if you set effect volume to 0. Also the selection of sample sound is not very good - it has neither low nor high frequency content, so you couldn't hear much of a difference even when it was cut completely.

In general, you should set all those values programmatically, computed from some formulas and pre-defined constants based on audio environment in current level, such as objects' spatial layout and material acoustic properties. Hence you don't get direct control over mixing but you get direct control over each effect and filter volume instead. I guess the wiki manual entry for effects should come with entire OpenAL EAX handbook, because people just tend to think it's the same thing as equalizer settings in your audio player and not a tool to emulate a realistic soundstage.
I agree. The video is not an ideal showing and the sample sound is not great, but the point is that it is possible to achieve theses things which were impossible before. To realize the potential of the OpenAL system would take some modeling of a real environment and adding that to your game's levels. Changing effect parameters based on the game environment is a great tool to have. I suspect someone will write a library to automate that process.

Re: Trying the new stuff in 0.11.0

Posted: Fri Jul 28, 2017 7:18 am
by Santos
Edit: I think I get this error in the current version of LOVE, so it's not really related to 0.11.0.

I get an error sometimes when I start the Windows nightly build. I think this happens when this computer hasn't been playing sound for a while, it's like something turns off behind the scenes (and it's "on" there's a faint noise even when no applications are making sound, and when nothing has been playing for a while and it goes "off" the noise is gone). Running LOVE again straight after this error works fine.

Code: Select all

AL lib: (EE) ALCmmdevPlayback_resetProxy: Failed to initialize audio client: 0x8889000f
Could not create context.
It seems that slots are deregistered by passing the slot name but no effect to the function, is this right?

i.e. setting the 5th effect here has no effect:

Code: Select all

love.audio.setEffect( "1", {type = "reverb"})
love.audio.setEffect( "2", {type = "echo"})
love.audio.setEffect( "3", {type = "chorus"})
love.audio.setEffect( "4", {type = "distortion"})
love.audio.setEffect( "5", {type = "flanger"})
source:setEffect("5")
but it does when another effect is deregistered:

Code: Select all

love.audio.setEffect( "1", {type = "reverb"})
love.audio.setEffect( "2", {type = "echo"})
love.audio.setEffect( "3", {type = "chorus"})
love.audio.setEffect( "4", {type = "distortion"})
love.audio.setEffect( "5", {type = "flanger"})
love.audio.setEffect( "1")
source:setEffect("5")
Maybe source:setEffect should accept multiple slots with optional filters?

Code: Select all

source:setEffect(slot1, filter1 [optional])
source:setEffect(slot1, filter1 [optional], slot2, filter2 [optional])
source:setEffect(slot1, filter1 [optional], slot2, filter2 [optional], slot3, filter3 [optional])
source:setEffect(slot1, filter1 [optional], slot2, filter2 [optional], slot3, filter3 [optional], slot4, filter4 [optional])
(and the above but with all the arguments in a table, which is generally how LOVE does varargs.)

Maybe love.audio.setEffect should error when setting a fifth effect?

And also maybe Source:setEffect and love.audio.getEffect should error when setting/getting a non-existent slot?

I think that love.audio.getEffectsList should be love.audio.getEffects or more descriptively love.audio.getActiveEffects (i.e. without the "List" at the end) to be consistent with other functions returning lists (outside of love.physics), e.g. love.joystick.getJoysticks, love.touch.getTouches and love.window.getFullscreenModes.

Why do love.audio.getMaxSceneEffects and love.audio.getMaxSourceEffects exist? Can these numbers change? Or, why doesn't love.audio.getMaxSources exist?

I don't think there is the concept of named slots elsewhere in the LOVE API (Edit: I had forgotten about Channels). What are the alternatives? How would it compare to something similar to the SpriteBatch API with identifiers?

Code: Select all

id = love.audio.addEffect({type = "reverb"})
source:setEffect(id, filter)
love.audio.removeEffect(id)
love.audio.clearEffects()
idList = love.audio.getEffectsList()
I think all this new audio stuff is really cool by the way! :)

Re: Trying the new stuff in 0.11.0

Posted: Fri Jul 28, 2017 2:07 pm
by raidho36
All of this have been discussed thoroughly in the pull request feed and in other appropriate places; there's a reason all of those things are made that way. Maybe the "getEffects" is a better option than "getEffectsList" but nobody objected in the review process.