/* Ċ Ġ* ĠCopyright Ġ 2 0 2 1 ĠThe ĠTensorFlow ĠAuthors . ĠAll ĠRights ĠReserved . Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġorg . tensorflow . lite . examples . sound classifier Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroid . media . Audio Format Ċ import Ġandroid . media . Audio Record Ċ import Ġandroid . media . Media Recorder Ċ import Ġandroid . os . System Clock Ċ import Ġandroid . util . Log Ċ import Ġandroidx . annotation . MainThread Ċ import Ġandroidx . lifecycle . Default Lifecycle Observer Ċ import Ġandroidx . lifecycle . Lifecycle Owner Ċ import Ġandroidx . lifecycle . LiveData Ċ import Ġandroidx . lifecycle . Mutable LiveData Ċ import Ġjava . io . BufferedReader Ċ import Ġjava . io . IOException Ċ import Ġjava . io . InputStream Reader Ċ import Ġjava . nio . Float Buffer Ċ import Ġjava . util . Locale Ċ import Ġjava . util . concurrent . TimeUnit Ċ import Ġkotlin . math . sin Ċ import Ġorg . tensorflow . lite . Interpreter Ċ import Ġorg . tensorflow . lite . support . common . File Util Ċ Ċ /** Ċ Ġ* ĠPerforms Ġclassification Ġon Ġsound . Ċ Ġ* Ċ Ġ* Ġ< p > The ĠAPI Ġsupports Ġmodels Ġwhich Ġaccept Ġsound Ġinput Ġvia Ġ{@ code ĠAudio Record } Ġand Ġone Ġclassification Ġoutput Ġtensor . Ċ Ġ* ĠThe Ġoutput Ġof Ġthe Ġrecognition Ġis Ġemitted Ġas ĠLive Data Ġof ĠMap . Ċ Ġ* Ċ Ġ*/ Ċ class ĠSound Classifier ( context : ĠContext , Ġprivate Ġval Ġoptions : ĠOptions Ġ= ĠOptions ()) Ġ: ĊĠ ĠDefault Lifecycle Observer Ġ{ ĊĠ Ġclass ĠOptions Ġconstructor ( ĊĠĠĠ Ġ/** ĠPath Ġof Ġthe Ġconverted Ġmodel Ġlabel Ġfile , Ġrelative Ġto Ġthe Ġassets / Ġdirectory . Ġ Ġ*/ ĊĠĠĠ Ġval Ġmetadata Path : ĠString Ġ= Ġ" labels . txt ", ĊĠĠĠ Ġ/** ĠPath Ġof Ġthe Ġconverted Ġ. t flite Ġfile , Ġrelative Ġto Ġthe Ġassets / Ġdirectory . Ġ Ġ*/ ĊĠĠĠ Ġval Ġmodel Path : ĠString Ġ= Ġ" sound _ classifier . t flite ", ĊĠĠĠ Ġ/** ĠThe Ġrequired Ġaudio Ġsample Ġrate Ġin ĠHz . Ġ Ġ*/ ĊĠĠĠ Ġval Ġsample Rate : ĠInt Ġ= Ġ 4 4 _ 1 0 0 , ĊĠĠĠ Ġ/** ĠHow Ġmany Ġmilliseconds Ġto Ġsleep Ġbetween Ġsuccess ive Ġaudio Ġsample Ġpull s . Ġ Ġ*/ ĊĠĠĠ Ġval Ġaudio Pull Period : ĠLong Ġ= Ġ 5 0 L , ĊĠĠĠ Ġ/** ĠNumber Ġof Ġwarm Ġup Ġruns Ġto Ġdo Ġafter Ġloading Ġthe ĠT FL ite Ġmodel . Ġ Ġ*/ ĊĠĠĠ Ġval Ġwarm up Runs : ĠInt Ġ= Ġ 3 , ĊĠĠĠ Ġ/** ĠNumber Ġof Ġpoints Ġin Ġaverage Ġto Ġreduce Ġnoise . Ġ*/ ĊĠĠĠ Ġval Ġpoints In Average : ĠInt Ġ= Ġ 1 0 , ĊĠĠĠ Ġ/** ĠOver lap Ġfactor Ġof Ġrecognition Ġperiod Ġ*/ ĊĠĠĠ Ġvar Ġoverlap Factor : ĠFloat Ġ= Ġ 0 . 8 f , ĊĠĠĠ Ġ/** ĠProb ability Ġvalue Ġabove Ġwhich Ġa Ġclass Ġis Ġlabeled Ġas Ġactive Ġ( i . e ., Ġdetected ) Ġthe Ġdisplay . Ġ Ġ*/ ĊĠĠĠ Ġvar Ġprobability Threshold : ĠFloat Ġ= Ġ 0 . 3 f , ĊĠ Ġ) ĊĊĠ Ġvar Ġis Recording : ĠBoolean Ġ= Ġfalse ĊĠĠĠ Ġprivate Ġset ĊĊĠ Ġ/** ĠAs Ġthe Ġresult Ġof Ġsound Ġclassification , Ġthis Ġvalue Ġemits Ġmap Ġof Ġprobabilities Ġ*/ ĊĠ Ġval Ġprobabilities : ĠLive Data < Map < String , ĠFloat >> ĊĠĠĠ Ġget () Ġ= Ġ_ prob abilities ĊĠ Ġprivate Ġval Ġ_ prob abilities Ġ= ĠMutable LiveData < Map < String , ĠFloat >>() ĊĊĠ Ġvar Ġis Closed : ĠBoolean Ġ= Ġtrue ĊĠĠĠ Ġprivate Ġset ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠLifecycle Owner Ġinstance Ġto Ġdeal Ġwith ĠRES UME , ĠPA USE Ġand ĠDEST ROY Ġevents Ġautomatically . ĊĠĠ Ġ* ĠYou Ġcan Ġalso Ġhandle Ġthose Ġevents Ġby Ġcalling Ġ` start ()`, Ġ` stop ()` Ġand Ġ` close ()` Ġmethods ĊĠĠ Ġ* Ġmanually . ĊĠĠ Ġ*/ ĊĠ Ġvar Ġlifecycle Owner : ĠLifecycle Owner ? Ġ= Ġnull ĊĠĠĠ Ġ@ MainThread ĊĠĠĠ Ġset ( value ) Ġ{ ĊĠĠĠĠĠ Ġif Ġ( field Ġ=== Ġvalue ) Ġreturn ĊĠĠĠĠĠ Ġfield ?. lifecycle ?. remove Observer ( this ) ĊĠĠĠĠĠ Ġfield Ġ= Ġvalue ?. also Ġ{ ĊĠĠĠĠĠĠĠ Ġit . lifecycle . add Observer ( this ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġ/** ĠOver lap Ġfactor Ġof Ġrecognition Ġperiod Ġ*/ ĊĠ Ġvar Ġoverlap Factor : ĠFloat ĊĠĠĠ Ġget () Ġ= Ġoptions . overlap Factor ĊĠĠĠ Ġset ( value ) Ġ{ ĊĠĠĠĠĠ Ġoptions . overlap Factor Ġ= Ġvalue . also Ġ{ ĊĠĠĠĠĠĠĠ Ġrecognition Period Ġ= Ġ( 1 0 0 0 L Ġ* Ġ( 1 Ġ- Ġvalue )). to Long () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġ/** ĠProb ability Ġvalue Ġabove Ġwhich Ġa Ġclass Ġis Ġlabeled Ġas Ġactive Ġ( i . e ., Ġdetected ) Ġthe Ġdisplay . Ġ Ġ*/ ĊĠ Ġvar Ġprobability Threshold : ĠFloat ĊĠĠĠ Ġget () Ġ= Ġoptions . probability Threshold ĊĠĠĠ Ġset ( value ) Ġ{ ĊĠĠĠĠĠ Ġoptions . probability Threshold Ġ= Ġvalue ĊĠĠĠ Ġ} ĊĊĠ Ġ/** ĠPause d Ġby Ġuser Ġ*/ ĊĠ Ġvar Ġis Paused : ĠBoolean Ġ= Ġfalse ĊĠĠĠ Ġset ( value ) Ġ{ ĊĠĠĠĠĠ Ġfield Ġ= Ġvalue ĊĠĠĠĠĠ Ġif Ġ( value ) Ġstop () Ġelse Ġstart () ĊĠĠĠ Ġ} ĊĊĠ Ġ/** ĠNames Ġof Ġthe Ġmodel 's Ġoutput Ġclasses . Ġ Ġ*/ ĊĠ Ġlateinit Ġvar Ġlabel List : ĠList < String > ĊĠĠĠ Ġprivate Ġset ĊĊĠ Ġ/** ĠHow Ġmany Ġmilliseconds Ġbetween Ġconsecutive Ġmodel Ġinference Ġcalls . Ġ Ġ*/ ĊĠ Ġprivate Ġvar Ġrecognition Period Ġ= Ġ( 1 0 0 0 L Ġ* Ġ( 1 Ġ- Ġoverlap Factor )). to Long () ĊĊĠ Ġ/** ĠThe ĠT FL ite Ġinterpreter Ġinstance . Ġ Ġ*/ ĊĠ Ġprivate Ġlateinit Ġvar Ġinterpreter : ĠInterpreter ĊĊĠ Ġ/** ĠAudio Ġlength Ġ( in Ġ# Ġof ĠP CM Ġsamples ) Ġrequired Ġby Ġthe ĠT FL ite Ġmodel . Ġ Ġ*/ ĊĠ Ġprivate Ġvar Ġmodel Input Length Ġ= Ġ 0 ĊĊĠ Ġ/** ĠNumber Ġof Ġoutput Ġclasses Ġof Ġthe ĠT FL ite Ġmodel . Ġ Ġ*/ ĊĠ Ġprivate Ġvar Ġmodel Num Classes Ġ= Ġ 0 ĊĊĠ Ġ/** ĠUsed Ġto Ġhold Ġthe Ġreal - time Ġprobabilities Ġpredicted Ġby Ġthe Ġmodel Ġfor Ġthe Ġoutput Ġclasses . Ġ Ġ*/ ĊĠ Ġprivate Ġlateinit Ġvar Ġprediction Pro bs : ĠFloat Array ĊĊĠ Ġ/** ĠLatest Ġprediction Ġlatency Ġin Ġmilliseconds . Ġ Ġ*/ ĊĠ Ġprivate Ġvar Ġlatest Prediction Latency Ms Ġ= Ġ 0 f ĊĊĠ Ġprivate Ġvar Ġrecognition Thread : ĠThread ? Ġ= Ġnull ĊĊĠ Ġ/** ĠUsed Ġto Ġrecord Ġaudio Ġsamples . Ġ*/ ĊĠ Ġprivate Ġlateinit Ġvar Ġaudio Record : ĠAudio Record ĊĊĠ Ġ/** ĠBuffer Ġthat Ġholds Ġaudio ĠP CM Ġsample Ġthat Ġare Ġfed Ġto Ġthe ĠT FL ite Ġmodel Ġfor Ġinference . Ġ Ġ*/ ĊĠ Ġprivate Ġlateinit Ġvar Ġinput Buffer : ĠFloat Buffer ĊĊĠ Ġinit Ġ{ ĊĠĠĠ Ġload Labels ( context ) ĊĠĠĠ Ġsetup Interpreter ( context ) ĊĠĠĠ Ġwarm Up Model () ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġon Resume ( owner : ĠLifecycle Owner ) Ġ= Ġstart () ĊĊĠ Ġoverride Ġfun Ġon Pause ( owner : ĠLifecycle Owner ) Ġ= Ġstop () ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠStarts Ġsound Ġclassification , Ġwhich Ġtriggers Ġrunning Ġof ĊĠĠ Ġ* Ġ` recording Thread ` Ġand Ġ` recognition Thread `. ĊĠĠ Ġ*/ ĊĠ Ġfun Ġstart () Ġ{ ĊĠĠĠ Ġif Ġ(! is Paused ) Ġ{ ĊĠĠĠĠĠ Ġstart Audio Record () ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠSto ps Ġsound Ġclassification , Ġwhich Ġtriggers Ġinter ruption Ġof ĊĠĠ Ġ* Ġ` recognition Thread `. ĊĠĠ Ġ*/ ĊĠ Ġfun Ġstop () Ġ{ ĊĠĠĠ Ġif Ġ( is Closed Ġ|| Ġ! is Recording ) Ġreturn ĊĠĠĠ Ġrecognition Thread ?. interrupt () ĊĠĠĠ Ġaudio Record . stop () ĊĠĠĠ Ġis Recording Ġ= Ġfalse ĊĊĠĠĠ Ġ_ prob abilities . post Value ( label List . associate With Ġ{ Ġ 0 f Ġ}) ĊĠ Ġ} ĊĊĠ Ġfun Ġclose () Ġ{ ĊĠĠĠ Ġstop () ĊĊĠĠĠ Ġif Ġ( is Closed ) Ġreturn ĊĠĠĠ Ġinterpreter . close () ĊĊĠĠĠ Ġis Closed Ġ= Ġtrue ĊĠ Ġ} ĊĊĠ Ġ/** ĠRetrieve Ġlabels Ġfrom Ġ" labels . txt " Ġfile Ġ*/ ĊĠ Ġprivate Ġfun Ġload Labels ( context : ĠContext ) Ġ{ ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠ Ġval Ġreader Ġ= ĊĠĠĠĠĠĠĠ ĠBufferedReader ( InputStream Reader ( context . assets . open ( options . metadata Path ))) ĊĠĠĠĠĠ Ġval Ġword List Ġ= Ġmutable ListOf < String >() ĊĠĠĠĠĠ Ġreader . use Lines Ġ{ Ġlines Ġ-> ĊĠĠĠĠĠĠĠ Ġlines . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġword List . add ( it . split (" Ġ"). last ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġlabel List Ġ= Ġword List . map Ġ{ Ġit . to Title Case () Ġ} ĊĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠ ĠLog . e ( TAG , Ġ" Failed Ġto Ġread Ġmodel Ġ${ options . metadata Path }: Ġ${ e . message }") ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġsetup Interpreter ( context : ĠContext ) Ġ{ ĊĠĠĠ Ġinterpreter Ġ= Ġtry Ġ{ ĊĠĠĠĠĠ Ġval Ġt flite Buffer Ġ= ĠFile Util . load Mapped File ( context , Ġoptions . model Path ) ĊĠĠĠĠĠ ĠLog . i ( TAG , Ġ" Done Ġcreating ĠT FL ite Ġbuffer Ġfrom Ġ${ options . model Path }") ĊĠĠĠĠĠ ĠInterpreter ( t flite Buffer , ĠInterpreter . Options ()) ĊĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠ ĠLog . e ( TAG , Ġ" Failed Ġto Ġload ĠT FL ite Ġmodel Ġ- Ġ${ e . message }") ĊĠĠĠĠĠ Ġreturn ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠIn spect Ġinput Ġand Ġoutput Ġspecs . ĊĠĠĠ Ġval Ġinput Shape Ġ= Ġinterpreter . getInput Tensor ( 0 ). shape () ĊĠĠĠ ĠLog . i ( TAG , Ġ" T FL ite Ġmodel Ġinput Ġshape : Ġ${ input Shape . content ToString () }") ĊĠĠĠ Ġmodel Input Length Ġ= Ġinput Shape [ 1 ] ĊĊĠĠĠ Ġval Ġoutput Shape Ġ= Ġinterpreter . getOutput Tensor ( 0 ). shape () ĊĠĠĠ ĠLog . i ( TAG , Ġ" T FL ite Ġoutput Ġshape : Ġ${ output Shape . content ToString () }") ĊĠĠĠ Ġmodel Num Classes Ġ= Ġoutput Shape [ 1 ] ĊĠĠĠ Ġif Ġ( model Num Classes Ġ!= Ġlabel List . size ) Ġ{ ĊĠĠĠĠĠ ĠLog . e ( ĊĠĠĠĠĠĠĠ ĠTAG , ĊĠĠĠĠĠĠĠ Ġ" Mismatch Ġbetween Ġmetadata Ġnumber Ġof Ġclasses Ġ(${ label List . size })" Ġ+ ĊĠĠĠĠĠĠĠĠĠ Ġ" Ġand Ġmodel Ġoutput Ġlength Ġ($ model Num Classes )" ĊĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġ// ĠFill Ġthe Ġarray Ġwith ĠNaN s Ġinitially . ĊĠĠĠ Ġprediction Pro bs Ġ= ĠFloat Array ( model Num Classes ) Ġ{ ĠFloat . NaN Ġ} ĊĊĠĠĠ Ġinput Buffer Ġ= ĠFloat Buffer . allocate ( model Input Length ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġwarm Up Model () Ġ{ ĊĠĠĠ Ġgenerate Dummy Audio Input ( input Buffer ) ĊĠĠĠ Ġfor Ġ( n Ġin Ġ 0 Ġuntil Ġoptions . warm up Runs ) Ġ{ ĊĠĠĠĠĠ Ġval Ġt 0 Ġ= ĠSystem Clock . elapsed Realtime Nan os () ĊĊĠĠĠĠĠ Ġ// ĠCreate Ġinput Ġand Ġoutput Ġbuffers . ĊĠĠĠĠĠ Ġval Ġoutput Buffer Ġ= ĠFloat Buffer . allocate ( model Num Classes ) ĊĠĠĠĠĠ Ġinput Buffer . rewind () ĊĠĠĠĠĠ Ġoutput Buffer . rewind () ĊĠĠĠĠĠ Ġinterpreter . run ( input Buffer , Ġoutput Buffer ) ĊĊĠĠĠĠĠ ĠLog . i ( ĊĠĠĠĠĠĠĠ ĠTAG , ĊĠĠĠĠĠĠĠ Ġ" Sw itches : ĠDone Ġcalling Ġinterpreter . run (): Ġ% s Ġ(% . 6 f Ġms ) ". format ( ĊĠĠĠĠĠĠĠĠĠ Ġoutput Buffer . array (). content ToString (), ĊĠĠĠĠĠĠĠĠĠ Ġ( System Clock . elapsed Realtime Nan os () Ġ- Ġt 0 ) Ġ/ ĠN AN OS _ IN _ M ILL IS ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġgenerate Dummy Audio Input ( input Buffer : ĠFloat Buffer ) Ġ{ ĊĠĠĠ Ġval Ġtwo Pi Times Freq Ġ= Ġ 2 Ġ* ĠMath . PI . toFloat () Ġ* Ġ 1 0 0 0 f ĊĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġmodel Input Length ) Ġ{ ĊĠĠĠĠĠ Ġval Ġx Ġ= Ġi . toFloat () Ġ/ Ġ( model Input Length Ġ- Ġ 1 ) ĊĠĠĠĠĠ Ġinput Buffer . put ( i , Ġsin ( two Pi Times Freq Ġ* Ġx . toDouble ()). toFloat ()) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĠStart Ġrecording Ġand Ġtriggers Ġrecognition . Ġ Ġ*/ ĊĠ Ġ@ Synchron ized ĊĠ Ġprivate Ġfun Ġstart Audio Record () Ġ{ ĊĠĠĠ Ġif Ġ( is Recording ) Ġreturn ĊĠĠĠ Ġsetup Audio Record () ĊĠĠĠ Ġis Closed Ġ= Ġfalse ĊĠĠĠ Ġis Recording Ġ= Ġtrue ĊĠ Ġ} ĊĊĠ Ġ/** ĠStart Ġa Ġthread Ġthat Ġruns Ġmodel Ġinference Ġ( i . e ., Ġrecognition ) Ġat Ġa Ġregular Ġinterval . Ġ Ġ*/ ĊĠ Ġprivate Ġfun Ġstart Recognition () Ġ{ ĊĠĠĠ ĠLog . i ( TAG , Ġ" Starting ĠRecognition ") ĊĠĠĠ Ġrecognition Thread Ġ= ĠRecognition Thread (). apply Ġ{ ĊĠĠĠĠĠ Ġstart () ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġsetup Audio Record () Ġ{ ĊĠĠĠ Ġvar ĠbufferSize Ġ= ĠAudio Record . getMin BufferSize ( ĊĠĠĠĠĠ Ġoptions . sample Rate , ĊĠĠĠĠĠ ĠAudio Format . CHANNEL _ IN _ MON O , ĊĠĠĠĠĠ ĠAudio Format . ENCODING _ PCM _ 1 6 BIT ĊĠĠĠ Ġ) ĊĠĠĠ ĠLog . i ( TAG , Ġ" min Ġbuffer Ġsize Ġ= Ġ$ buffer Size ") ĊĠĠĠ Ġif Ġ( buffer Size Ġ== ĠAudio Record . ERROR Ġ|| ĠbufferSize Ġ== ĠAudio Record . ERROR _ BAD _ VALUE ) Ġ{ ĊĠĠĠĠĠ ĠbufferSize Ġ= Ġoptions . sample Rate Ġ* Ġ 2 ĊĠĠĠĠĠ ĠLog . w ( TAG , Ġ" buffer Size Ġhas Ġerror Ġor Ġbad Ġvalue ") ĊĠĠĠ Ġ} ĊĠĠĠ Ġ// ĠThe Ġbuffer Ġof ĠAudio Record Ġshould Ġbe Ġlarger Ġthan Ġwhat Ġmodel Ġrequires . ĊĠĠĠ Ġval Ġmodel Required BufferSize Ġ= Ġ 2 Ġ* Ġmodel Input Length Ġ* ĠShort . SIZE _ BYTES ĊĠĠĠ Ġif Ġ( buffer Size Ġ< Ġmodel Required BufferSize ) Ġ{ ĊĠĠĠĠĠ ĠbufferSize Ġ= Ġmodel Required BufferSize ĊĠĠĠ Ġ} ĊĠĠĠ ĠLog . i ( TAG , Ġ" buffer Size Ġ= Ġ$ buffer Size ") ĊĠĠĠ Ġaudio Record Ġ= ĠAudio Record ( ĊĠĠĠĠĠ Ġ// Ġincluding ĠMIC , ĠUN PROC ES SED , Ġand ĠCAM C ORDER . ĊĠĠĠĠĠ ĠMedia Recorder . Audio Source . VOICE _ RE CO GN ITION , ĊĠĠĠĠĠ Ġoptions . sample Rate , ĊĠĠĠĠĠ ĠAudio Format . CHANNEL _ IN _ MON O , ĊĠĠĠĠĠ ĠAudio Format . ENCODING _ PCM _ 1 6 BIT , ĊĠĠĠĠĠ ĠbufferSize ĊĠĠĠ Ġ) ĊĠĠĠ Ġif Ġ( audio Record . state Ġ!= ĠAudio Record . STATE _ INITIAL IZED ) Ġ{ ĊĠĠĠĠĠ ĠLog . e ( TAG , Ġ" Audio Record Ġfailed Ġto Ġinitialize ") ĊĠĠĠĠĠ Ġreturn ĊĠĠĠ Ġ} ĊĠĠĠ ĠLog . i ( TAG , Ġ" Successfully Ġinitialized ĠAudio Record ") ĊĊĠĠĠ Ġaudio Record . start Recording () ĊĠĠĠ ĠLog . i ( TAG , Ġ" Successfully Ġstarted ĠAudio Record Ġrecording ") ĊĊĠĠĠ Ġ// ĠStart Ġrecognition Ġ( model Ġinference ) Ġthread . ĊĠĠĠ Ġstart Recognition () ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġload Audio ( audio Buffer : ĠShort Array ): ĠInt Ġ{ ĊĠĠĠ Ġwhen Ġ( ĊĠĠĠĠĠ Ġval Ġloaded Samples Ġ= Ġaudio Record . read ( ĊĠĠĠĠĠĠĠ Ġaudio Buffer , Ġ 0 , Ġaudio Buffer . size , ĠAudio Record . READ _ NON _ BLOCK ING ĊĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠ ĠAudio Record . ERROR _ INVALID _ OPERATION Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ" Audio Record . ERROR _ INVALID _ OPERATION ") ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠAudio Record . ERROR _ BAD _ VALUE Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ" Audio Record . ERROR _ BAD _ VALUE ") ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠAudio Record . ERROR _ DEAD _ OBJECT Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ" Audio Record . ERROR _ DEAD _ OBJECT ") ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ ĠAudio Record . ERROR Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ" Audio Record . ERROR ") ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġloaded Samples ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġ// ĠNo Ġnew Ġsample Ġwas Ġloaded . ĊĠĠĠ Ġreturn Ġ 0 ĊĠ Ġ} ĊĊĠ Ġprivate Ġinner Ġclass ĠRecognition Thread Ġ: ĠThread () Ġ{ ĊĠĠĠ Ġoverride Ġfun Ġrun () Ġ{ ĊĠĠĠĠĠ Ġif Ġ( model Input Length Ġ<= Ġ 0 Ġ|| Ġmodel Num Classes Ġ<= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġ" Sw itches : ĠCannot Ġstart Ġrecognition Ġbecause Ġmodel Ġis Ġunavailable .") ĊĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġval Ġoutput Buffer Ġ= ĠFloat Buffer . allocate ( model Num Classes ) ĊĠĠĠĠĠ Ġval Ġrecording Buffer Ġ= ĠShort Array ( model Input Length ) ĊĠĠĠĠĠ Ġval Ġcircular Buffer Ġ= ĠShort Array ( model Input Length ) ĊĠĠĠĠĠ Ġvar Ġj Ġ= Ġ 0 Ġ// ĠInd ices Ġfor Ġthe Ġcircular Ġbuffer Ġnext Ġwrite ĊĊĠĠĠĠĠ Ġwhile Ġ(! is Inter rupted ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġ// ĠWait Ġfor Ġthe Ġnext Ġinvocation ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠ ĠTimeUnit . MILLISECONDS . sleep ( recognition Period ) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠInterruptedException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ" Sleep Ġinterrupted Ġin Ġrecognition Ġthread .") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠLoad Ġnew Ġaudio Ġsamples ĊĠĠĠĠĠĠĠ Ġval Ġsample Counts Ġ= Ġload Audio ( recording Buffer ) ĊĠĠĠĠĠĠĠ Ġif Ġ( sample Counts Ġ== Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠCopy Ġnew Ġdata Ġinto Ġthe Ġcircular Ġbuffer ĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġsample Counts ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġcircular Buffer [ j ] Ġ= Ġrecording Buffer [ i ] ĊĠĠĠĠĠĠĠĠĠ Ġj Ġ= Ġ( j Ġ+ Ġ 1 ) Ġ% Ġcircular Buffer . size ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠFeed Ġdata Ġto Ġthe Ġinput Ġbuffer . ĊĠĠĠĠĠĠĠ Ġvar Ġsamples Are All Zero Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġmodel Input Length ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġval Ġs Ġ= Ġif Ġ( i Ġ> Ġoptions . points In Average ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ(( i Ġ- Ġoptions . points In Average Ġ+ Ġ 1 ) .. i ). map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcircular Buffer [( j Ġ+ Ġit ) Ġ% Ġmodel Input Length ] ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. average () ĊĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcircular Buffer [( i Ġ+ Ġj ) Ġ% Ġmodel Input Length ] ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġif Ġ( samples Are All Zero Ġ&& Ġs . toInt () Ġ!= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsamples Are All Zero Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġinput Buffer . put ( i , Ġs . toFloat ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( samples Are All Zero ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ" No Ġaudio Ġinput : ĠAll Ġaudio Ġsamples Ġare Ġzero !") ĊĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġt 0 Ġ= ĠSystem Clock . elapsed Realtime Nan os () ĊĠĠĠĠĠĠĠ Ġinput Buffer . rewind () ĊĠĠĠĠĠĠĠ Ġoutput Buffer . rewind () ĊĠĠĠĠĠĠĠ Ġinterpreter . run ( input Buffer , Ġoutput Buffer ) ĊĠĠĠĠĠĠĠ Ġoutput Buffer . rewind () ĊĠĠĠĠĠĠĠ Ġoutput Buffer . get ( prediction Pro bs ) Ġ// ĠCopy Ġdata Ġto Ġprediction Pro bs . ĊĊĠĠĠĠĠĠĠ Ġval Ġprob List Ġ= Ġprediction Pro bs . map Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġif Ġ( it Ġ> Ġprobability Threshold ) Ġit Ġelse Ġ 0 f ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠLog . i ( TAG , Ġ" inference Ġresult : Ġ$ prob List ") ĊĠĠĠĠĠĠĠ Ġ_ prob abilities . post Value ( label List . zip ( prob List ). toMap ()) ĊĊĠĠĠĠĠĠĠ Ġlatest Prediction Latency Ms Ġ= ĊĠĠĠĠĠĠĠĠĠ Ġ(( System Clock . elapsed Realtime Nan os () Ġ- Ġt 0 ) Ġ/ Ġ 1 e 6 ). toFloat () ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠ Ġprivate Ġconst Ġval ĠTAG Ġ= Ġ" Sound Classifier " ĊĊĠĠĠ Ġ/** ĠNumber Ġof Ġnan oseconds Ġin Ġa Ġmilli second Ġ Ġ*/ ĊĠĠĠ Ġprivate Ġconst Ġval ĠN AN OS _ IN _ M ILL IS Ġ= Ġ 1 _ 0 0 0 _ 0 0 0 . toDouble () ĊĠ Ġ} Ċ } Ċ Ċ private Ġfun ĠString . to Title Case () Ġ= ĊĠ Ġsplit To Sequence ("_ ") ĊĠĠĠ Ġ. map Ġ{ Ġit . capitalize ( Locale . ROOT ) Ġ} ĊĠĠĠ Ġ. join ToString (" Ġ") ĊĠĠĠ Ġ. trim () Ċ