positional audio works now
This commit is contained in:
parent
5c2602d40b
commit
ebde27ab88
5 changed files with 60 additions and 39 deletions
|
|
@ -64,5 +64,4 @@ XRWG.generate = (opts) => {
|
||||||
// sort by n
|
// sort by n
|
||||||
XRWG.sort( (a,b) => a.nodes.length - b.nodes.length )
|
XRWG.sort( (a,b) => a.nodes.length - b.nodes.length )
|
||||||
XRWG = XRWG.reverse() // the cleankey/get functions e.g. will persist
|
XRWG = XRWG.reverse() // the cleankey/get functions e.g. will persist
|
||||||
console.dir(XRWG)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,6 @@ xrf.frag.updatePredefinedView = (opts) => {
|
||||||
let id = v.string || v.fragment
|
let id = v.string || v.fragment
|
||||||
if( id == '#' ) return
|
if( id == '#' ) return
|
||||||
let match = xrf.XRWG.match(id)
|
let match = xrf.XRWG.match(id)
|
||||||
console.dir({id,match,XRWG:xrf.XRWG})
|
|
||||||
// erase previous lines
|
// erase previous lines
|
||||||
xrf.focusLine.lines.map( (line) => scene.remove(line) )
|
xrf.focusLine.lines.map( (line) => scene.remove(line) )
|
||||||
xrf.focusLine.points = []
|
xrf.focusLine.points = []
|
||||||
|
|
@ -94,12 +93,7 @@ xrf.frag.updatePredefinedView = (opts) => {
|
||||||
|
|
||||||
// if this query was triggered by an src-value, lets filter it
|
// if this query was triggered by an src-value, lets filter it
|
||||||
const isSRC = opts.embedded && opts.embedded.fragment == 'src'
|
const isSRC = opts.embedded && opts.embedded.fragment == 'src'
|
||||||
if( isSRC ){ // spec : https://xrfragment.org/#src
|
if( !isSRC ){ // spec : https://xrfragment.org/#src
|
||||||
console.log("filtering predefined view of src")
|
|
||||||
console.dir(frag)
|
|
||||||
}else{
|
|
||||||
console.log("updatePredefinedView")
|
|
||||||
console.dir(frag)
|
|
||||||
for ( let i in frag ) {
|
for ( let i in frag ) {
|
||||||
let v = frag[i]
|
let v = frag[i]
|
||||||
if( v.is( xrf.XRF.PV_EXECUTE ) ){
|
if( v.is( xrf.XRF.PV_EXECUTE ) ){
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ xrf.frag.src = function(v, opts){
|
||||||
let mimetype = res.headers.get('Content-type')
|
let mimetype = res.headers.get('Content-type')
|
||||||
if( url.replace(/#.*/,'').match(/\.(gltf|glb)$/) ) mimetype = 'gltf'
|
if( url.replace(/#.*/,'').match(/\.(gltf|glb)$/) ) mimetype = 'gltf'
|
||||||
//if( url.match(/\.(fbx|stl|obj)$/) ) mimetype =
|
//if( url.match(/\.(fbx|stl|obj)$/) ) mimetype =
|
||||||
console.log("src mimetype: "+mimetype)
|
|
||||||
opts = { ...opts, src, frag }
|
opts = { ...opts, src, frag }
|
||||||
return xrf.frag.src.type[ mimetype ] ? xrf.frag.src.type[ mimetype ](url,opts) : xrf.frag.src.type.unknown(url,opts)
|
return xrf.frag.src.type[ mimetype ] ? xrf.frag.src.type[ mimetype ](url,opts) : xrf.frag.src.type.unknown(url,opts)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -7,26 +7,49 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let loadAudio = (mimetype) => function(url,opts){
|
let loadAudio = (mimetype) => function(url,opts){
|
||||||
let {mesh} = opts
|
let {mesh,src,camera} = opts
|
||||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||||
|
let frag = xrf.URI.parse( url )
|
||||||
|
|
||||||
// global audio
|
/* WebAudio: setup context via THREEjs */
|
||||||
if( mesh.position.x == 0 && mesh.position.y == 0 && mesh.position.z == 0 ){
|
if( !camera.listener ){
|
||||||
let audio = window.document.createElement('audio')
|
camera.listener = new THREE.AudioListener();
|
||||||
// init fallback formats
|
camera.add( camera.listener );
|
||||||
let fallback = ['mp3','ogg','wav','weba','aac']
|
|
||||||
let addSource = (ext) => {
|
|
||||||
const src = window.document.createElement('source')
|
|
||||||
src.setAttribute("src", url)
|
|
||||||
src.setAttribute("type",mimetype)
|
|
||||||
audio.appendChild(src)
|
|
||||||
}
|
|
||||||
fallback
|
|
||||||
.filter( (e) => e != ext )
|
|
||||||
.map( addSource )
|
|
||||||
document.body.appendChild(audio)
|
|
||||||
xrf.audio.push(audio)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let listener = camera.listener
|
||||||
|
let isPositionalAudio = !(mesh.position.x == 0 && mesh.position.y == 0 && mesh.position.z == 0)
|
||||||
|
const audioLoader = new THREE.AudioLoader();
|
||||||
|
let sound = isPositionalAudio ? new THREE.PositionalAudio(listener) : new THREE.Audio(listener)
|
||||||
|
audioLoader.load( url.replace(/#.*/,''), function( buffer ) {
|
||||||
|
sound.setBuffer( buffer );
|
||||||
|
sound.setLoop(true);
|
||||||
|
sound.setVolume(0.5);
|
||||||
|
sound.playXRF = (t) => {
|
||||||
|
if( sound.isPlaying ) sound.stop()
|
||||||
|
let hardcodedLoop = frag.t != undefined
|
||||||
|
t = hardcodedLoop ? { ...frag.t, x: t.x} : t // override with hardcoded metadata except playstate (x)
|
||||||
|
if( t && t.x != 0 ){
|
||||||
|
// *TODO* https://stackoverflow.com/questions/12484052/how-can-i-reverse-playback-in-web-audio-api-but-keep-a-forward-version-as-well
|
||||||
|
sound.setPlaybackRate( Math.abs(t.x) ) // WebAudio does not support negative playback
|
||||||
|
// setting loop
|
||||||
|
sound.setLoop( t.z > 0 )
|
||||||
|
// apply embedded audio/video samplerate/fps or global mixer fps
|
||||||
|
let loopStart = hardcodedLoop ? t.y / buffer.sampleRate : t.y / xrf.model.mixer.loop.fps
|
||||||
|
let loopEnd = hardcodedLoop ? t.z / buffer.sampleRate : t.z / xrf.model.mixer.loop.fps
|
||||||
|
let timeStart = loopStart > 0 ? loopStart : xrf.model.mixer.time
|
||||||
|
|
||||||
|
if( t.y > 0 ) sound.setLoopStart( loopStart )
|
||||||
|
if( t.z > 0 ) sound.setLoopEnd( loopEnd )
|
||||||
|
if( t.x != 0 ){
|
||||||
|
sound.offset = loopStart > 0 ? loopStart : timeStart
|
||||||
|
sound.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mesh.add(sound)
|
||||||
|
xrf.audio.push(sound)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let audioMimeTypes = [
|
let audioMimeTypes = [
|
||||||
|
|
@ -39,4 +62,7 @@ let audioMimeTypes = [
|
||||||
]
|
]
|
||||||
audioMimeTypes.map( (mimetype) => xrf.frag.src.type[ mimetype ] = loadAudio(mimetype) )
|
audioMimeTypes.map( (mimetype) => xrf.frag.src.type[ mimetype ] = loadAudio(mimetype) )
|
||||||
|
|
||||||
// *TODO* https://www.svgrepo.com/svg/20195/play-button should trigger play?
|
xrf.addEventListener('t', (opts) => {
|
||||||
|
let t = opts.frag.t
|
||||||
|
xrf.audio.map( (a) => a.playXRF(t) )
|
||||||
|
})
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,9 @@ xrf.frag.t = function(v, opts){
|
||||||
let frames = model.animations[0].tracks[0].times.length
|
let frames = model.animations[0].tracks[0].times.length
|
||||||
let mixer = model.mixer
|
let mixer = model.mixer
|
||||||
mixer.loop = mixer.loop || {frameStart:0,frameStop:99999999,speed: 1}
|
mixer.loop = mixer.loop || {frameStart:0,frameStop:99999999,speed: 1}
|
||||||
let fps = frames / duration
|
mixer.loop.fps = frames / duration
|
||||||
|
|
||||||
mixer.loop.speed = v.x
|
xrf.frag.t.calculateLoop( v, mixer.loop, mixer.loop.fps )
|
||||||
mixer.loop.speedAbs = Math.abs(v.x)
|
|
||||||
mixer.loop.frameStart = v.y || mixer.loop.frameStart
|
|
||||||
mixer.loop.frameStop = v.z || mixer.loop.frameStop
|
|
||||||
// always recalculate time using frameStart/Stop
|
|
||||||
mixer.loop.timeStart = mixer.loop.frameStart / (fps * mixer.loop.speedAbs)
|
|
||||||
mixer.loop.timeStop = mixer.loop.frameStop / (fps * mixer.loop.speedAbs)
|
|
||||||
|
|
||||||
// update speed
|
// update speed
|
||||||
mixer.timeScale = mixer.loop.speed
|
mixer.timeScale = mixer.loop.speed
|
||||||
|
|
@ -26,12 +20,9 @@ xrf.frag.t = function(v, opts){
|
||||||
mixer.time = Math.abs(mixer.time)
|
mixer.time = Math.abs(mixer.time)
|
||||||
mixer.update(0) // (forgetting) this little buddy costed me lots of time :]
|
mixer.update(0) // (forgetting) this little buddy costed me lots of time :]
|
||||||
// (re)trigger audio
|
// (re)trigger audio
|
||||||
xrf.audio.map( (a) => {
|
|
||||||
a.play()
|
|
||||||
a.currentTime = time
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if( v.x != 0 ) xrf.emit('play',v) *TODO* touchend/usergesture
|
||||||
if( v.y > 0 || v.z > 0 ) updateTime( mixer.loop.timeStart )
|
if( v.y > 0 || v.z > 0 ) updateTime( mixer.loop.timeStart )
|
||||||
|
|
||||||
// update loop when needed
|
// update loop when needed
|
||||||
|
|
@ -49,3 +40,15 @@ xrf.frag.t = function(v, opts){
|
||||||
mixer.update.patched = true
|
mixer.update.patched = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xrf.frag.t.default = {x:1, y:0, z:0}
|
||||||
|
|
||||||
|
xrf.frag.t.calculateLoop = (t,obj,fps) => {
|
||||||
|
obj.speed = t.x
|
||||||
|
obj.speedAbs = Math.abs(t.x)
|
||||||
|
obj.frameStart = t.y || obj.frameStart
|
||||||
|
obj.frameStop = t.z || obj.frameStop
|
||||||
|
// always recalculate time using frameStart/Stop
|
||||||
|
obj.timeStart = obj.frameStart / (fps * obj.speedAbs)
|
||||||
|
obj.timeStop = obj.frameStop / (fps * obj.speedAbs)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue