package Ġcom . d ail yst udio . dev br icks x . audio Ċ Ċ import Ġandroid . media . Audio Format Ċ import Ġandroid . media . Audio Record Ċ import Ġandroid . media . Media Recorder Ċ import Ġandroid . os . Bundle Ċ import Ġandroid . os . Process Ċ import Ġandroid . view . LayoutInflater Ċ import Ġandroid . view . View Ċ import Ġandroid . view . ViewGroup Ċ import Ġandroidx . lifecycle . lifecycle Scope Ċ import Ġcom . d ail yst udio . dev br icks x . async . Managed Thread Ċ import Ġcom . d ail yst udio . dev br icks x . audio . visual izer . Raw Audio Data Visualizer Ċ import Ġcom . d ail yst udio . dev br icks x . development . Logger Ċ import Ġkotlinx . coroutines . Dispatch ers Ċ import Ġkotlinx . coroutines . launch Ċ import Ġjava . util . concurrent . locks . Re entrant Lock Ċ import Ġkotlin . math . max Ċ Ċ data Ġclass ĠAudio Config ( val Ġaudio Source : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsample Rate : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsample Duration In Ms : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġchannel Config : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġaudio Format : ĠInt ) Ġ{ ĊĊĠĠĠ Ġfun Ġget Recording Buffer Length (): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġ( sample Rate Ġ* Ġsample Duration In Ms Ġ/ Ġ 1 0 0 0 ) ĊĠĠĠ Ġ} Ċ Ċ } Ċ Ċ abstract Ġclass ĠAudio Process Fragment Ġ: ĠAbs Audio Fragment () Ġ{ ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠDEFAULT _ SAMPLE _ RATE Ġ= Ġ 1 6 0 0 0 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠDEFAULT _ SAMPLE _ DURATION _ MS Ġ= Ġ 1 0 0 0 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠMIN IMUM _ TIME _ B ETWEEN _ SAMPLES _ MS : ĠLong Ġ= Ġ 3 0 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġrecording Buffer : ĠShort Array ĊĠĠĠ Ġprivate Ġvar Ġrecording Offset Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġval Ġrecording Buffer Lock Ġ= ĠRe entrant Lock () ĊĊĠĠĠ Ġprivate Ġvar Ġprocessing Started Ġ= Ġfalse ĊĊĠĠĠ Ġprivate Ġvar Ġvisual izer : ĠRaw Audio Data Visualizer ? Ġ= Ġnull ĊĊĠĠĠ Ġoverride Ġfun ĠonCreate View ( in flater : ĠLayoutInflater , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontainer : ĠViewGroup ?, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠsavedInstanceState : ĠBundle ?): ĠView ? Ġ= ĊĠĠĠĠĠĠĠ Ġinflater . inflate ( R . layout . fragment _ audio _ process , Ġcontainer , Ġfalse ) ĊĊĊĠĠĠ Ġoverride Ġfun Ġon View Created ( view : ĠView , ĠsavedInstanceState : ĠBundle ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on View Created ( view , ĠsavedInstanceState ) ĊĊĠĠĠĠĠĠĠ Ġvisual izer Ġ= Ġview . findViewById ( R . id . visual izer ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Permissions Granted ( new ly Granted : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġstart Processing () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Resume () Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on Resume () ĊĊĠĠĠĠĠĠĠ Ġif Ġ( is Permissions Granted ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart Processing () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon Pause () Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on Pause () ĊĊĠĠĠĠĠĠĠ Ġstop Processing () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprotected Ġopen Ġfun Ġget Audio Config (): ĠAudio Config Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠAudio Config ( Media Recorder . Audio Source . DEFAULT , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDEFAULT _ SAMPLE _ RATE , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDEFAULT _ SAMPLE _ DURATION _ MS , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠAudio Format . CHANNEL _ IN _ MON O , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠAudio Format . ENCODING _ PCM _ 1 6 BIT ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġstart Processing () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( processing Started ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . warn (" processing Ġis Ġalready Ġstarted . Ġskip ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġaudio Config Ġ= Ġget Audio Config () ĊĊĠĠĠĠĠĠĠ Ġrecording Buffer Lock . lock () ĊĠĠĠĠĠĠĠ Ġrecording Buffer Ġ= ĠShort Array ( audio Config . get Recording Buffer Length ()) ĊĠĠĠĠĠĠĠ Ġrecording Offset Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġrecording Buffer Lock . unlock () ĊĊĠĠĠĠĠĠĠ Ġrecording Thread . start () ĊĠĠĠĠĠĠĠ Ġprocess Thread . start () ĊĊĠĠĠĠĠĠĠ Ġprocessing Started Ġ= Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġstop Processing () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! processing Started ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . warn (" processing Ġis Ġalready Ġstopped . Ġskip ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprocessing Started Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠ Ġrecording Thread . stop () ĊĠĠĠĠĠĠĠ Ġprocess Thread . stop () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġvar Ġrecording Thread Ġ= Ġobject Ġ: ĠManaged Thread () Ġ{ ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġrun In Background () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠProcess . set Thread Priority ( Process . THREAD _ PRIORITY _ AUDIO ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġaudio Config Ġ= Ġget Audio Config () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠEst imate Ġthe Ġbuffer Ġsize Ġwe 'll Ġneed Ġfor Ġthis Ġdevice . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar ĠbufferSize Ġ= ĠAudio Record . getMin BufferSize ( audio Config . sample Rate , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaudio Config . channel Config , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaudio Config . audio Format ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( buffer Size Ġ== ĠAudio Record . ERROR Ġ|| ĠbufferSize Ġ== ĠAudio Record . ERROR _ BAD _ VALUE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbufferSize Ġ= Ġaudio Config . sample Rate Ġ* Ġ 2 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġaudio Buffer Ġ= ĠShort Array ( buffer Size Ġ/ Ġ 2 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrecord Ġ= ĠAudio Record ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaudio Config . audio Source , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaudio Config . sample Rate , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaudio Config . channel Config , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaudio Config . audio Format , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbufferSize ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( record . state Ġ!= ĠAudio Record . STATE _ INITIAL IZED ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . error (" audio Ġrecord Ġinitialization Ġfailed : Ġstate Ġ= Ġ${ record . state }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġrecord . start Recording () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠLoop , Ġgather ing Ġaudio Ġdata Ġand Ġcopying Ġit Ġto Ġa Ġround - ro bin Ġbuffer . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( isRunning ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnumber Read Ġ= Ġrecord . read ( audio Buffer , Ġ 0 , Ġaudio Buffer . size ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠmaxLength : ĠInt Ġ= Ġrecording Buffer . size ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Recording Offset : ĠInt Ġ= Ġrecording Offset Ġ+ Ġnumber Read ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsecond Copy Length Ġ= Ġmax ( 0 , Ġnew Recording Offset Ġ- ĠmaxLength ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfirst Copy Length Ġ= Ġnumber Read Ġ- Ġsecond Copy Length ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġstore Ġoff Ġall Ġthe Ġdata Ġfor Ġthe Ġrecognition Ġthread Ġto Ġaccess . ĠThe ĠML ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġthread Ġwill Ġcopy Ġout Ġof Ġthis Ġbuffer Ġinto Ġits Ġown , Ġwhile Ġholding Ġthe ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġlock , Ġso Ġthis Ġshould Ġbe Ġthread Ġsafe . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrecording Buffer Lock . lock () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSystem . arraycopy ( audio Buffer , Ġ 0 , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrecording Buffer , Ġrecording Offset , Ġfirst Copy Length ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSystem . arraycopy ( audio Buffer , Ġfirst Copy Length , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrecording Buffer , Ġ 0 , Ġsecond Copy Length ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrecording Offset Ġ= Ġnew Recording Offset Ġ% ĠmaxLength ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrecording Buffer Lock . unlock () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . info (" stop Ġrecording : Ġrecord Ġ= Ġ$ record ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġrecord . stop () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrecord . release () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġvar Ġprocess Thread Ġ= Ġobject Ġ: ĠManaged Thread () Ġ{ ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġrun In Background () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġaudio Config Ġ= Ġget Audio Config () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġinput Buffer Ġ= ĠShort Array ( audio Config . get Recording Buffer Length ()) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( isRunning ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrecording Buffer Lock . lock () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠmaxLength Ġ= Ġrecording Buffer . size ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfirst Copy Length Ġ= ĠmaxLength Ġ- Ġrecording Offset ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsecond Copy Length Ġ= Ġrecording Offset ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSystem . arraycopy ( recording Buffer , Ġrecording Offset , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinput Buffer , Ġ 0 , Ġfirst Copy Length ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSystem . arraycopy ( recording Buffer , Ġ 0 , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinput Buffer , Ġfirst Copy Length , Ġsecond Copy Length ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrecording Buffer Lock . unlock () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvisual izer ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlifecycle Scope . launch ( Dispatch ers . Main ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . set Audio Frame Data ( input Buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġon Process Audio Data ( audio Config , Ġinput Buffer ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġdon 't Ġneed Ġto Ġrun Ġtoo Ġfrequently , Ġso Ġsn oo ze Ġfor Ġa Ġbit . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠThread . sleep ( MIN IMUM _ TIME _ B ETWEEN _ SAMPLES _ MS ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠInterruptedException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIgnore ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġabstract Ġfun Ġon Process Audio Data ( audio Config : ĠAudio Config , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaudio Data : ĠShort Array ) Ċ Ċ }