Page 1 of 2

Positional Audio

Posted: Fri Aug 05, 2016 3:52 pm
by murks
Hi there.
Is there a tutorial somewhere that explains how positional audio works?
Is there a way to use basic effects?

Re: Positional Audio

Posted: Fri Aug 05, 2016 8:41 pm
by murks
Is the orientation translated to the löve coordinate system? According to the OpenAL documentation, RHS is used, which means that to move in 2D space I would need to use x and z, which, if untranslated, would make at least the example in https://love2d.org/wiki/Source:setRelative wrong. The example sounds correct though, but I have not seen any mention of the coordinate translation.
Changing the Z position does not seem to do anything audible.

Re: Positional Audio

Posted: Fri Aug 05, 2016 8:42 pm
by palmettos
Check out this post and the articles linked to within. :)

As far as effects go, I haven't explored this topic enough to give you an answer.

Re: Positional Audio

Posted: Sat Aug 06, 2016 9:43 am
by murks
Thanks. I understood that part and tried exactly that, but it seems the listener orientation does not have any effect whatsoever. Any idea what could be wrong?
I use love.audio.getOrientation(), modify the values in the -1, 1 range and set the new value with love.audio.setOrientation(). To experiment I move the listener away from the source and change the orientation. I theory what I hear should change drastically, but it does not seem to change at all.

Here is my test code (originally based on the static/relative example code)

Code: Select all

local sfxr = require("lib/sfxrlua/sfxr")

local xl, yl, zl = 0, 0, 0;
local xs, ys, zs = 0, 0, 0;
local source
local f = 0.5
ox, oy, oz, u1, u2, u3 = 0, 0, -1, 0, 1, 0

function love.load()
    local sound = sfxr.newSound()
    sound:randomize(os.time())
    local sounddata = sound:generateSoundData()
    source = love.audio.newSource(sounddata)
    --snd = love.audio.newSource('bite_00.wav', 'static')
    source:setLooping(true);
    source:play();
end
 
function love.keypressed(key)
    -- Move the listener via WASD.
    if key == 'a' then
        xl = xl - f;
    elseif key == 'd' then
        xl = xl + f;
    elseif key == 'w' then
        yl = yl - f;
    elseif key == 's' then
        yl = yl + f;
    elseif key == 'r' then
        zl = zl + f;
    elseif key == 'f' then
        zl = zl - f;
	end
	
    love.audio.setPosition(xl, yl, lz);
	
	
    ox, oy, oz, u1, u2, u3 = love.audio.getOrientation()
    --orientation experiment
    if key == 'u' then
		if ox < 1 then ox=ox+1 end
    elseif key == 'j' then
		if ox > -1 then ox=ox-1 end
    elseif key == 'i' then
		if oy < 1 then oy=oy+1 end
    elseif key == 'k' then
		if oy > -1 then oy=oy-1 end
    elseif key == 'o' then
		if oz < 1 then oz=oz+1 end
    elseif key == 'l' then
		if oz > -1 then oz=oz-1 end
    end
    love.audio.setOrientation(ox, oy, oz, u1, u2, u3)
end
 
function love.draw()
    love.graphics.print('Listener: (xl = ' .. xl .. ', yl = ' .. yl .. ', zl = ' .. zl .. ')', 20, 40);
    love.graphics.print('Orientation: (ox = ' .. ox .. ', oy = ' .. oy .. ', oz = ' .. oz, 20, 80);
end

Re: Positional Audio

Posted: Sat Aug 06, 2016 10:44 am
by zorg
Just a small question, since it may be relevant; does sfxr generate mono or stereo sounddata? since positional audio only works on monaural, i.e. 1-channel sounds.
(Edit: From a cursory glance at the github repo, it creates mono SoundDatas, but the question still stands since you may have modified the lib to output a stereo one instead)

Re: Positional Audio

Posted: Sat Aug 06, 2016 10:56 am
by murks
As far as I can tell it should be mono.
I tried it with a source that is definitely mono, same result.
Stereo sources caused crashes in my experiments.
Does it work for you Zorg?

Re: Positional Audio

Posted: Sat Aug 06, 2016 11:02 am
by zorg
Can't test at the moment, could only tomorrow.
I don't see you setting the position for the source though, i mean, not even initially.
Maybe it's oriented by default in a way, that it's "omnidirectional"?

Re: Positional Audio

Posted: Sat Aug 06, 2016 11:15 am
by murks
Sources are omnidirectional by default, but that should not matter. Moving around a source works just fine, orientation does not.
If my hearing does not cheat me the y axis has some effect, but it is rather subtle and most likely the lowpass filter of the distance model. This however makes no sense as the z axis should show this effect, unless the coordinates are translated.
I could not see anything wrong in the corresponding löve openAL code. I am no C++ expert, but it is very clean and simple. I guess that either I am doing something wrong or there is something wrong with OpenAL-soft on Linux.

Re: Positional Audio

Posted: Tue Aug 09, 2016 5:17 am
by palmettos
I made this work in one of my games (a top down shooter with a camera locked to the player's position and rotation) by leaving the listener's position at (0, 0, 0) and setting the positions of the sounds based on the position of the objects that created them relative to the player's position/rotation. Your game may have different requirements, but this worked for me, and hopefully can help you: (This is pySFML code, but it also wraps OpenAL, so the functionality is the same)

Code: Select all

class Manager:
    def __init__(self):
        game_path = os.path.dirname(os.path.realpath(__file__) + '/../../')
        sound.sfx_index = json.load(open(game_path + '/gamedata/sfx.json'))
        for snd in sound.sfx_index.values():
            snd['buffer'] = sf.SoundBuffer.from_file(game_path + '/gamedata/' + snd['filename'])
        self.playing = []
        sf.Listener.set_global_volume(100)
        sf.Listener.set_position((0, 0, 0))
        sf.Listener.set_direction((1, 0, 0))

    def update(self):
        player = game.system_objects['game.actors.Player'][0]
        for snd in sound.queue:
            sound.queue.remove(snd)
            snd['ptr'] = sf.Sound(sound.sfx_index[snd['sound']]['buffer'])
            snd['ptr'].volume = sound.sfx_index[snd['sound']]['volume']
            r = random.randint(0, 20)/100.0
            snd['ptr'].pitch = 1-r
            self.playing.append(snd)
            snd['ptr'].play()
        for playing in self.playing:
            #update offset to player and spatialization of sound
            offset_x = playing['creator'].world_pos[0] - player.world_pos[0]
            offset_y = playing['creator'].world_pos[1] - player.world_pos[1]
            v = game.vector.Vector(offset_x, offset_y)
            r = player.direction_vector.get_angle_in_radians()
            v.rotate(-r)
            playing['ptr'].position = (v.x*1/250.0, 0, v.y*1/250.0)
            if playing['ptr'].status == sf.SoundSource.STOPPED:
		self.playing.remove(playing) # I don't know why this isn't indenting properly :(

Re: Positional Audio

Posted: Tue Aug 09, 2016 10:04 pm
by pgimeno
Orientation works for me. For example, love.audio.setOrientation(0,1,0, 0,0,1) toggles left and right as expected (EDIT: on an absolute source, of course). Is that not what you see? What vectors are you using for forward and up?