package Ġcom . h ust unique . v live . ag ora Ċ Ċ import Ġandroid . os . Handler Ċ import Ġandroid . os . Handler Thread Ċ import Ġandroid . util . Log Ċ import Ġcom . h ust unique . res on ance _ audio . Audio Config Ċ import Ġcom . h ust unique . res on ance _ audio . Audio Render Ċ import Ġcom . h ust unique . v live . data . Quaternion Ċ import Ġcom . h ust unique . v live . data . Vector 3 Ċ import Ġjava . nio . ByteBuffer Ċ import Ġjava . util . concurrent . Concurrent Linked Queue Ċ Ċ /** Ċ Ġ* ĠĠĠ Ġauthor Ġ: ĠY ux uan ĠX iao Ċ Ġ* ĠĠĠ Ġe - mail Ġ: Ġq pal wo @ qq . com Ċ Ġ* ĠĠĠ Ġdate ĠĠ Ġ: Ġ 2 0 2 1 / 5 / 1 7 Ċ Ġ*/ Ċ class ĠAudio Module Ġ{ ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠTAG Ġ= Ġ" Audio Module " ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġhandler Thread Ġ= ĠHandler Thread (" v live _ audio _ thread "). apply Ġ{ ĊĠĠĠĠĠĠĠ Ġstart () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġhandler Ġ= ĠHandler ( handler Thread . lo oper ) ĊĊĠĠĠ Ġprivate Ġval Ġaudio Render Ġ= ĠAudio Render () Ċ Ċ // ĠĠĠ Ġprivate Ġvar Ġaudio Player : ĠAudio Player ? Ġ= Ġnull ĊĊĠĠĠ Ġprivate Ġval Ġmember Map Ġ= ĠHashMap < Int , ĠInt >() ĊĊĠĠĠ Ġprivate Ġvar Ġnum Frames Ġ= Ġ 4 8 0 ĊĊĠĠĠ Ġprivate Ġval ĠbufferSize Pre Frame Ġ= ĠAudio Config . NUM _ CHANNEL S Ġ* Ġ 2 ĊĊĠĠĠ Ġ@ Volatile ĊĠĠĠ Ġprivate Ġvar Ġrunning Ġ= Ġfalse ĊĊĠĠĠ Ġprivate Ġval Ġdata Queue Ġ= ĠConcurrent Linked Queue < ByteBuffer >() ĊĊĠĠĠ Ġprivate Ġval Ġempty Queue Ġ= ĠConcurrent Linked Queue < ByteBuffer >() ĊĊĠĠĠ Ġprivate Ġval Ġprocess Runnable Ġ= Ġobject Ġ: ĠRunnable Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġrun () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( data Queue . size Ġ> Ġ 5 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandler . post Delayed ( this , Ġ 1 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbuffer Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġempty Queue . poll () Ġ?: ĠByteBuffer . allocate Direct ( buffer Size Pre Frame Ġ* Ġnum Frames ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuffer . position ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġres Ġ= Ġaudio Render . getOutput ( buffer , Ġnum Frames ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! res ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġempty Queue . offer ( buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" getData : Ġ$ res ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdata Queue . offer ( buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( running ) Ġ{ Ċ // ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandler . post Delayed ( this , Ġif Ġ( res ) Ġ 0 Ġelse Ġ 1 0 ) Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġinit () Ġ{ Ċ // ĠĠĠĠĠĠĠ Ġhandler . post Ġ{ Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġaudio Player Ġ= ĠAudio Player (). apply Ġ{ Ċ // ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstart Play () Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ċ // ĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġrunning Ġ= Ġtrue Ċ // ĠĠĠĠĠĠĠ Ġhandler . post ( process Runnable ) ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġfun Ġfeed Data ( uid : ĠInt , Ġframes : ĠInt , Ġarray : ĠByteArray ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( num Frames Ġ!= Ġframes ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnum Frames Ġ= Ġframes ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġvar Ġsource Id Ġ= Ġmember Map [ uid ] ĊĠĠĠĠĠĠĠ Ġif Ġ( source Id Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsource Id Ġ= Ġaudio Render . create Render Source () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmember Map [ uid ] Ġ= Ġsource Id ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" feed Data : Ġ${ frames } Ġ${ array . size }") ĊĠĠĠĠĠĠĠ Ġhandler . post Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġaudio Render . feed Data ( source Id , Ġarray , Ġframes ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun ĠgetData ( buffer : ĠByteArray , Ġnum Frames : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġhandler . post ( process Runnable ) ĊĠĠĠĠĠĠĠ Ġdata Queue . poll ()?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . position ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . get ( buffer , Ġ 0 , Ġbuffer . size . coerce At Most ( it . capacity ())) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġempty Queue . offer ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" getData : Ġbf Size : Ġ${ buffer . size } Ġdata Size : Ġ${ it . capacity () }") ĊĠĠĠĠĠĠĠ Ġ} Ġ?: ĠLog . i ( TAG , Ġ" audio Ġget data Ġnull ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġset Source Pos Rotation ( uid : ĠInt , Ġpos : ĠVector 3 , Ġquat : ĠQuaternion ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġsource Id Ġ= Ġmember Map [ uid ] Ġ?: Ġreturn ĊĠĠĠĠĠĠĠ Ġhandler . post Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġaudio Render . run Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Source Pos ( source Id , Ġpos . x , Ġpos . y , Ġpos . z ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Source Rotation ( source Id , Ġquat . n . x , Ġquat . n . y , Ġquat . n . z , Ġquat . a ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġset Head Pos Rotation ( pos : ĠVector 3 , Ġquat : ĠQuaternion ) Ġ{ ĊĠĠĠĠĠĠĠ Ġhandler . post Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġaudio Render . run Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Head Pos ( pos . x , Ġpos . y , Ġpos . z ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Head Rotation ( quat . n . x , Ġquat . n . y , Ġquat . n . z , Ġquat . a ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġrelease () Ġ{ ĊĠĠĠĠĠĠĠ Ġrunning Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġhandler . post Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġaudio Render . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmember Map . forEach Ġ{ Ġ(_, Ġu ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrelease Source ( u ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrelease () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġhandler Thread . quit S af ely () Ċ // ĠĠĠĠĠĠĠ Ġaudio Player ?. release () ĊĠĠĠ Ġ} ĊĊ Ċ }