xrfragment-haxe/src/3rd/js/three/xrf/src/audio.js

84 lines
2.7 KiB
JavaScript

/*
* mimetype: audio/aac
* mimetype: audio/mpeg
* mimetype: audio/ogg
* mimetype: audio/weba
* mimetype: audio/wav
*/
let loadAudio = (mimetype) => function(url,opts){
let {mesh,src,camera,THREE} = opts
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
let frag = xrf.URI.parse( url )
/* WebAudio: setup context via THREEjs */
if( !camera.listener ){
camera.listener = new THREE.AudioListener();
// *FIXME* camera vs camerarig conflict
(camera.getCam ? camera.getCam() : camera).add( 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( camera.listener)
: new THREE.Audio( camera.listener )
audioLoader.load( url.replace(/#.*/,''), function( buffer ) {
sound.setBuffer( buffer );
sound.setLoop(false);
sound.setVolume(1.0);
if( isPositionalAudio ){
sound.setRefDistance( mesh.scale.x);
sound.setRolloffFactor(20.0)
//sound.setDirectionalCone( 360, 360, 0.01 );
}
sound.playXRF = (t) => {
if( sound.isPlaying && t.y != undefined ) sound.stop()
if( sound.isPlaying && t.y == undefined ) sound.pause()
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
t.x = Math.abs(t.x)
sound.setPlaybackRate( t.x ) // WebAudio does not support negative playback
// setting loop
if( t.z ) sound.setLoop( true )
// apply embedded audio/video samplerate/fps or global mixer fps
let loopStart = hardcodedLoop ? t.y : t.y * buffer.sampleRate;
let loopEnd = hardcodedLoop ? t.z : t.z * buffer.sampleRate;
let timeStart = loopStart > 0 ? loopStart : (t.y == undefined ? xrf.model.mixer.time : t.y)
if( t.z > 0 ) sound.setLoopEnd( loopEnd )
if( t.y != undefined ){
console.dir({loopStart,t})
sound.setLoopStart( loopStart )
sound.offset = loopStart
}
sound.play()
}
}
mesh.add(sound)
});
mesh.audio = sound
}
let audioMimeTypes = [
'audio/wav',
'audio/mpeg',
'audio/mp3',
'audio/weba',
'audio/aac',
'application/ogg'
]
audioMimeTypes.map( (mimetype) => xrf.frag.src.type[ mimetype ] = loadAudio(mimetype) )
// listen to t XR fragment changes
xrf.addEventListener('t', (opts) => {
let t = opts.frag.t
xrf.scene.traverse( (n) => n.audio && n.audio.playXRF && (n.audio.playXRF(t)) )
})