CINXE.COM

<!doctype html><html lang="en"><head><title data-rh="true">Debugging audio glitches on Android | by Don Turner | Medium</title><meta data-rh="true" charset="utf-8"/><meta data-rh="true" name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1,maximum-scale=1"/><meta data-rh="true" name="theme-color" content="#000000"/><meta data-rh="true" name="twitter:app:name:iphone" content="Medium"/><meta data-rh="true" name="twitter:app:id:iphone" content="828256236"/><meta data-rh="true" property="al:ios:app_name" content="Medium"/><meta data-rh="true" property="al:ios:app_store_id" content="828256236"/><meta data-rh="true" property="al:android:package" content="com.medium.reader"/><meta data-rh="true" property="fb:app_id" content="542599432471018"/><meta data-rh="true" property="og:site_name" content="Medium"/><meta data-rh="true" property="og:type" content="article"/><meta data-rh="true" property="article:published_time" content="2019-10-08T18:53:26.739Z"/><meta data-rh="true" name="title" content="Debugging audio glitches on Android | by Don Turner | Medium"/><meta data-rh="true" property="og:title" content="Debugging audio glitches on Android"/><meta data-rh="true" property="al:android:url" content="medium://p/ed10782f9c64"/><meta data-rh="true" property="al:ios:url" content="medium://p/ed10782f9c64"/><meta data-rh="true" property="al:android:app_name" content="Medium"/><meta data-rh="true" name="description" content="In this article I will explain how to identify the causes of audio glitches in your app using systrace and the Android Studio profiler. Background: I wanted to build a one hundred oscillator…"/><meta data-rh="true" property="og:description" content="In this article I will explain how to identify the causes of audio glitches in your app using systrace and the Android Studio profiler."/><meta data-rh="true" property="og:url" content="https://medium.com/@donturner/debugging-audio-glitches-on-android-ed10782f9c64"/><meta data-rh="true" property="al:web:url" content="https://medium.com/@donturner/debugging-audio-glitches-on-android-ed10782f9c64"/><meta data-rh="true" property="og:image" content="https://miro.medium.com/v2/resize:fit:527/1*KnhUyWDY_ehL_lEijOI8-w.png"/><meta data-rh="true" property="article:author" content="https://medium.com/@donturner"/><meta data-rh="true" name="author" content="Don Turner"/><meta data-rh="true" name="robots" content="index,noarchive,follow,max-image-preview:large"/><meta data-rh="true" name="referrer" content="unsafe-url"/><meta data-rh="true" property="twitter:title" content="Debugging audio glitches on Android"/><meta data-rh="true" name="twitter:site" content="@Medium"/><meta data-rh="true" name="twitter:app:url:iphone" content="medium://p/ed10782f9c64"/><meta data-rh="true" property="twitter:description" content="In this article I will explain how to identify the causes of audio glitches in your app using systrace and the Android Studio profiler."/><meta data-rh="true" name="twitter:image:src" content="https://miro.medium.com/v2/resize:fit:527/1*KnhUyWDY_ehL_lEijOI8-w.png"/><meta data-rh="true" name="twitter:card" content="summary_large_image"/><meta data-rh="true" name="twitter:creator" content="@donturner"/><meta data-rh="true" name="twitter:label1" content="Reading time"/><meta data-rh="true" name="twitter:data1" content="5 min read"/><link data-rh="true" rel="icon" href="https://miro.medium.com/v2/5d8de952517e8160e40ef9841c781cdc14a5db313057fa3c3de41c6f5b494b19"/><link data-rh="true" rel="search" type="application/opensearchdescription+xml" title="Medium" href="/osd.xml"/><link data-rh="true" rel="apple-touch-icon" sizes="152x152" href="https://miro.medium.com/v2/resize:fill:304:304/10fd5c419ac61637245384e7099e131627900034828f4f386bdaa47a74eae156"/><link data-rh="true" rel="apple-touch-icon" sizes="120x120" href="https://miro.medium.com/v2/resize:fill:240:240/10fd5c419ac61637245384e7099e131627900034828f4f386bdaa47a74eae156"/><link data-rh="true" rel="apple-touch-icon" sizes="76x76" href="https://miro.medium.com/v2/resize:fill:152:152/10fd5c419ac61637245384e7099e131627900034828f4f386bdaa47a74eae156"/><link data-rh="true" rel="apple-touch-icon" sizes="60x60" href="https://miro.medium.com/v2/resize:fill:120:120/10fd5c419ac61637245384e7099e131627900034828f4f386bdaa47a74eae156"/><link data-rh="true" rel="mask-icon" href="https://miro.medium.com/v2/resize:fill:1000:1000/7*GAOKVe--MXbEJmV9230oOQ.png" color="#171717"/><link data-rh="true" rel="preconnect" href="https://glyph.medium.com" crossOrigin=""/><link data-rh="true" id="glyph_preload_link" rel="preload" as="style" type="text/css" href="https://glyph.medium.com/css/unbound.css"/><link data-rh="true" id="glyph_link" rel="stylesheet" type="text/css" href="https://glyph.medium.com/css/unbound.css"/><link data-rh="true" rel="author" href="https://medium.com/@donturner"/><link data-rh="true" rel="canonical" href="https://medium.com/@donturner/debugging-audio-glitches-on-android-ed10782f9c64"/><link data-rh="true" rel="alternate" href="android-app://com.medium.reader/https/medium.com/p/ed10782f9c64"/><script data-rh="true" type="application/ld+json">{"@context":"http:\u002F\u002Fschema.org","@type":"NewsArticle","image":["https:\u002F\u002Fmiro.medium.com\u002Fv2\u002Fresize:fit:1200\u002F1*KnhUyWDY_ehL_lEijOI8-w.png"],"url":"https:\u002F\u002Fmedium.com\u002F@donturner\u002Fdebugging-audio-glitches-on-android-ed10782f9c64","dateCreated":"2018-05-18T16:13:49.006Z","datePublished":"2018-05-18T16:13:49.006Z","dateModified":"2019-10-08T18:53:27.004Z","headline":"Debugging audio glitches on Android - Don Turner - Medium","name":"Debugging audio glitches on Android - Don Turner - Medium","description":"In this article I will explain how to identify the causes of audio glitches in your app using systrace and the Android Studio profiler. Background: I wanted to build a one hundred oscillator…","identifier":"ed10782f9c64","author":{"@type":"Person","name":"Don Turner","url":"https:\u002F\u002Fmedium.com\u002F@donturner"},"creator":["Don Turner"],"publisher":{"@type":"Organization","name":"Medium","url":"https:\u002F\u002Fmedium.com\u002F","logo":{"@type":"ImageObject","width":272,"height":60,"url":"https:\u002F\u002Fmiro.medium.com\u002Fv2\u002Fresize:fit:544\u002F7*V1_7XP4snlmqrc_0Njontw.png"}},"mainEntityOfPage":"https:\u002F\u002Fmedium.com\u002F@donturner\u002Fdebugging-audio-glitches-on-android-ed10782f9c64"}</script><style type="text/css" data-fela-rehydration="554" data-fela-type="STATIC">html{box-sizing:border-box;-webkit-text-size-adjust:100%}*, *:before, *:after{box-sizing:inherit}body{margin:0;padding:0;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;color:rgba(0,0,0,0.8);position:relative;min-height:100vh}h1, h2, h3, h4, h5, h6, dl, dd, ol, ul, menu, figure, blockquote, p, pre, form{margin:0}menu, ol, ul{padding:0;list-style:none;list-style-image:none}main{display:block}a{color:inherit;text-decoration:none}a, button, input{-webkit-tap-highlight-color:transparent}img, svg{vertical-align:middle}button{background:transparent;overflow:visible}button, input, optgroup, select, textarea{margin:0}:root{--reach-tabs:1;--reach-menu-button:1}#speechify-root{font-family:Sohne, sans-serif}div[data-popper-reference-hidden="true"]{visibility:hidden;pointer-events:none}.grecaptcha-badge{visibility:hidden} /*XCode style (c) Angel Garcia <angelgarcia.mail@gmail.com>*/.hljs {background: #fff;color: black; }/* Gray DOCTYPE selectors like WebKit */ .xml .hljs-meta {color: #c0c0c0; }.hljs-comment, .hljs-quote {color: #007400; }.hljs-tag, .hljs-attribute, .hljs-keyword, .hljs-selector-tag, .hljs-literal, .hljs-name {color: #aa0d91; }.hljs-variable, .hljs-template-variable {color: #3F6E74; }.hljs-code, .hljs-string, .hljs-meta .hljs-string {color: #c41a16; }.hljs-regexp, .hljs-link {color: #0E0EFF; }.hljs-title, .hljs-symbol, .hljs-bullet, .hljs-number {color: #1c00cf; }.hljs-section, .hljs-meta {color: #643820; }.hljs-title.class_, .hljs-class .hljs-title, .hljs-type, .hljs-built_in, .hljs-params {color: #5c2699; }.hljs-attr {color: #836C28; }.hljs-subst {color: #000; }.hljs-formula {background-color: #eee;font-style: italic; }.hljs-addition {background-color: #baeeba; }.hljs-deletion {background-color: #ffc8bd; }.hljs-selector-id, .hljs-selector-class {color: #9b703f; }.hljs-doctag, .hljs-strong {font-weight: bold; }.hljs-emphasis {font-style: italic; } </style><style type="text/css" data-fela-rehydration="554" data-fela-type="KEYFRAME">@-webkit-keyframes k1{0%{opacity:0.8}50%{opacity:0.5}100%{opacity:0.8}}@-moz-keyframes k1{0%{opacity:0.8}50%{opacity:0.5}100%{opacity:0.8}}@keyframes k1{0%{opacity:0.8}50%{opacity:0.5}100%{opacity:0.8}}</style><style type="text/css" data-fela-rehydration="554" data-fela-type="RULE">.a{font-family:medium-content-sans-serif-font, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif}.b{font-weight:400}.c{background-color:rgba(255, 255, 255, 1)}.l{display:block}.m{position:sticky}.n{top:0}.o{z-index:500}.p{padding:0 24px}.q{align-items:center}.r{border-bottom:solid 1px #F2F2F2}.y{height:41px}.z{line-height:20px}.ab{display:flex}.ac{height:57px}.ae{flex:1 0 auto}.af{color:inherit}.ag{fill:inherit}.ah{font-size:inherit}.ai{border:inherit}.aj{font-family:inherit}.ak{letter-spacing:inherit}.al{font-weight:inherit}.am{padding:0}.an{margin:0}.ao{cursor:pointer}.ap:disabled{cursor:not-allowed}.aq:disabled{color:#6B6B6B}.ar:disabled{fill:#6B6B6B}.au{width:auto}.av path{fill:#242424}.aw{height:25px}.ax{margin-left:16px}.ay{border:none}.az{border-radius:20px}.ba{width:240px}.bb{background:#F9F9F9}.bc path{fill:#6B6B6B}.be{outline:none}.bf{font-family:sohne, "Helvetica Neue", Helvetica, Arial, sans-serif}.bg{font-size:14px}.bh{width:100%}.bi{padding:10px 20px 10px 0}.bj{background-color:transparent}.bk{color:#242424}.bl::placeholder{color:#6B6B6B}.bm{display:inline-block}.bn{margin-left:12px}.bo{margin-right:12px}.bp{border-radius:4px}.bq{margin-left:24px}.br{height:24px}.bx{background-color:#F9F9F9}.by{border-radius:50%}.bz{height:32px}.ca{width:32px}.cb{justify-content:center}.ch{max-width:680px}.ci{min-width:0}.cj{animation:k1 1.2s ease-in-out infinite}.ck{height:100vh}.cl{margin-bottom:16px}.cm{margin-top:48px}.cn{align-items:flex-start}.co{flex-direction:column}.cp{justify-content:space-between}.cq{margin-bottom:24px}.cw{width:80%}.cx{background-color:#F2F2F2}.dd{height:44px}.de{width:44px}.df{margin:auto 0}.dg{margin-bottom:4px}.dh{height:16px}.di{width:120px}.dj{width:80px}.dp{margin-bottom:8px}.dq{width:96%}.dr{width:98%}.ds{width:81%}.dt{margin-left:8px}.du{color:#6B6B6B}.dv{font-size:13px}.dw{height:100%}.ep{color:#FFFFFF}.eq{fill:#FFFFFF}.er{background:#1A8917}.es{border-color:#1A8917}.ew:disabled{cursor:inherit !important}.ex:disabled{opacity:0.3}.ey:disabled:hover{background:#1A8917}.ez:disabled:hover{border-color:#1A8917}.fa{border-radius:99em}.fb{border-width:1px}.fc{border-style:solid}.fd{box-sizing:border-box}.fe{text-decoration:none}.ff{text-align:center}.fi{margin-right:32px}.fj{position:relative}.fk{fill:#6B6B6B}.fn{background:transparent}.fo svg{margin-left:4px}.fp svg{fill:#6B6B6B}.fr{box-shadow:inset 0 0 0 1px rgba(0, 0, 0, 0.05)}.fs{position:absolute}.fz{margin:0 24px}.gd{background:rgba(255, 255, 255, 1)}.ge{border:1px solid #F2F2F2}.gf{box-shadow:0 1px 4px #F2F2F2}.gg{max-height:100vh}.gh{overflow-y:auto}.gi{left:0}.gj{top:calc(100vh + 100px)}.gk{bottom:calc(100vh + 100px)}.gl{width:10px}.gm{pointer-events:none}.gn{word-break:break-word}.go{word-wrap:break-word}.gp:after{display:block}.gq:after{content:""}.gr:after{clear:both}.gs{margin-left:auto}.gt{margin-right:auto}.gu{max-width:527px}.ha{clear:both}.hb{max-width:100%}.hc{height:auto}.hd{margin-top:10px}.he{max-width:728px}.hh{line-height:1.23}.hi{letter-spacing:0}.hj{font-style:normal}.hk{font-weight:700}.ip{align-items:baseline}.iq{width:48px}.ir{height:48px}.is{border:2px solid rgba(255, 255, 255, 1)}.it{z-index:0}.iu{box-shadow:none}.iv{border:1px solid rgba(0, 0, 0, 0.05)}.iw{margin-bottom:2px}.ix{flex-wrap:nowrap}.iy{font-size:16px}.iz{line-height:24px}.jb{margin:0 8px}.jc{display:inline}.jd{color:#1A8917}.je{fill:#1A8917}.jh{flex:0 0 auto}.jk{flex-wrap:wrap}.jl{padding-left:8px}.jm{padding-right:8px}.kn> *{flex-shrink:0}.ko{overflow-x:scroll}.kp::-webkit-scrollbar{display:none}.kq{scrollbar-width:none}.kr{-ms-overflow-style:none}.ks{width:74px}.kt{flex-direction:row}.ku{z-index:2}.kv{margin-right:4px}.ky{-webkit-user-select:none}.kz{border:0}.la{fill:rgba(117, 117, 117, 1)}.ld{outline:0}.le{user-select:none}.lf> svg{pointer-events:none}.lo{cursor:progress}.lp{margin-left:4px}.lq{margin-top:0px}.lr{opacity:1}.ls{padding:4px 0}.lv{width:16px}.lx{display:inline-flex}.md{padding:8px 2px}.me svg{color:#6B6B6B}.mv{line-height:1.58}.mw{letter-spacing:-0.004em}.mx{font-family:source-serif-pro, Georgia, Cambria, "Times New Roman", Times, serif}.ns{margin-bottom:-0.46em}.nt{text-decoration:underline}.nu{margin-top:32px}.nv{margin-bottom:14px}.nw{padding-top:24px}.nx{padding-bottom:10px}.ny{background-color:#000000}.nz{height:3px}.oa{width:3px}.ob{margin-right:20px}.oc{line-height:1.12}.od{letter-spacing:-0.022em}.oe{font-weight:600}.oz{margin-bottom:-0.28em}.pf{padding:2px 4px}.pg{font-size:75%}.ph> strong{font-family:inherit}.pi{font-family:source-code-pro, Menlo, Monaco, "Courier New", Courier, monospace}.pj{max-width:1509px}.pq{cursor:zoom-in}.pr{z-index:auto}.pt{font-style:italic}.pu{max-width:593px}.pv{max-width:1940px}.pw{overflow-x:auto}.px{padding:20px}.py{border-radius:0}.pz{background:#F2F2F2}.qa{line-height:1.18}.qb{margin-top:-0.09em}.qc{margin-bottom:-0.09em}.qd{white-space:pre-wrap}.qe{min-width:fit-content}.qf{margin-bottom:26px}.qg{margin-top:6px}.qh{margin-top:8px}.qi{margin-right:8px}.qj{padding:8px 16px}.qk{border-radius:100px}.ql{transition:background 300ms ease}.qn{white-space:nowrap}.qo{border-top:none}.qp{height:52px}.qq{max-height:52px}.qr{box-sizing:content-box}.qs{position:static}.qt{z-index:1}.qv{max-width:155px}.rg{height:0px}.rh{margin-bottom:40px}.rw{height:64px}.rx{width:64px}.ry{align-self:flex-end}.rz{color:rgba(255, 255, 255, 1)}.sa{fill:rgba(255, 255, 255, 1)}.sb{background:rgba(25, 25, 25, 1)}.sc{border-color:rgba(25, 25, 25, 1)}.sf:disabled{opacity:0.1}.sg:disabled:hover{background:rgba(25, 25, 25, 1)}.sh:disabled:hover{border-color:rgba(25, 25, 25, 1)}.si{flex:1 1 auto}.so{padding-right:4px}.sp{font-weight:500}.tc{margin-top:16px}.tl{gap:18px}.tm{fill:rgba(61, 61, 61, 1)}.to{fill:#242424}.tp{background:0}.tq{border-color:#242424}.tr:disabled:hover{color:#242424}.ts:disabled:hover{fill:#242424}.tt:disabled:hover{border-color:#242424}.ue{border-bottom:solid 1px #E5E5E5}.uf{margin-top:72px}.ug{padding:24px 0}.uh{margin-bottom:0px}.ui{margin-right:16px}.as:hover:not(:disabled){color:rgba(25, 25, 25, 1)}.at:hover:not(:disabled){fill:rgba(25, 25, 25, 1)}.et:hover{background:#156D12}.eu:hover{border-color:#156D12}.ev:hover{cursor:pointer}.fl:hover{color:#242424}.fm:hover{fill:#242424}.fq:hover svg{fill:#242424}.ft:hover{background-color:rgba(0, 0, 0, 0.1)}.ja:hover{text-decoration:underline}.jf:hover:not(:disabled){color:#156D12}.jg:hover:not(:disabled){fill:#156D12}.lc:hover{fill:rgba(8, 8, 8, 1)}.lt:hover{fill:#000000}.lu:hover p{color:#000000}.lw:hover{color:#000000}.mf:hover svg{color:#000000}.qm:hover{background-color:#F2F2F2}.rv:hover{background-color:none}.sd:hover{background:#000000}.se:hover{border-color:#242424}.tn:hover{fill:rgba(25, 25, 25, 1)}.bd:focus-within path{fill:#242424}.lb:focus{fill:rgba(8, 8, 8, 1)}.mg:focus svg{color:#000000}.ps:focus{transform:scale(1.01)}.lg:active{border-style:none}</style><style type="text/css" data-fela-rehydration="554" data-fela-type="RULE" media="all and (min-width: 1080px)">.d{display:none}.bw{width:64px}.cg{margin:0 64px}.cv{height:48px}.dc{margin-bottom:52px}.do{margin-bottom:48px}.ef{font-size:14px}.eg{line-height:20px}.em{font-size:13px}.eo{padding:5px 12px}.fh{display:flex}.fy{margin-bottom:68px}.gc{max-width:680px}.gz{margin-top:40px}.if{font-size:42px}.ig{margin-top:1em}.ih{margin-bottom:32px}.ii{line-height:52px}.ij{letter-spacing:-0.011em}.io{align-items:center}.jz{border-top:solid 1px #F2F2F2}.ka{border-bottom:solid 1px #F2F2F2}.kb{margin:32px 0 0}.kc{padding:3px 8px}.kl> *{margin-right:24px}.km> :last-child{margin-right:0}.ln{margin-top:0px}.mc{margin:0}.no{font-size:20px}.np{margin-top:2.14em}.nq{line-height:32px}.nr{letter-spacing:-0.003em}.ov{font-size:24px}.ow{margin-top:1.25em}.ox{line-height:30px}.oy{letter-spacing:-0.016em}.pe{margin-top:0.94em}.po{margin-top:56px}.ra{display:inline-block}.rf{margin-bottom:104px}.ri{flex-direction:row}.rl{margin-bottom:0}.rm{margin-right:20px}.sj{max-width:500px}.ta{line-height:24px}.tb{letter-spacing:0}.th{margin-bottom:88px}.tk{margin-bottom:72px}.ty{width:min-width}.ud{padding-top:72px}</style><style type="text/css" data-fela-rehydration="554" data-fela-type="RULE" media="all and (max-width: 1079.98px)">.e{display:none}.hf{margin-left:auto}.hg{text-align:center}.lm{margin-top:0px}.qz{display:inline-block}</style><style type="text/css" data-fela-rehydration="554" data-fela-type="RULE" media="all and (max-width: 903.98px)">.f{display:none}.ll{margin-top:0px}.qy{display:inline-block}</style><style type="text/css" data-fela-rehydration="554" data-fela-type="RULE" media="all and (max-width: 727.98px)">.g{display:none}.lj{margin-top:0px}.lk{margin-right:0px}.qx{display:inline-block}</style><style type="text/css" data-fela-rehydration="554" data-fela-type="RULE" media="all and (max-width: 551.98px)">.h{display:none}.s{display:flex}.t{justify-content:space-between}.bs{width:24px}.cc{margin:0 24px}.cr{height:40px}.cy{margin-bottom:44px}.dk{margin-bottom:32px}.dx{font-size:13px}.dy{line-height:20px}.eh{padding:0px 8px 1px}.fu{margin-bottom:4px}.gv{margin-top:32px}.hl{font-size:32px}.hm{margin-top:1.01em}.hn{margin-bottom:24px}.ho{line-height:38px}.hp{letter-spacing:-0.014em}.ik{align-items:flex-start}.ji{flex-direction:column}.jn{margin:24px -24px 0}.jo{padding:0}.kd> *{margin-right:8px}.ke> :last-child{margin-right:24px}.kw{margin-left:0px}.lh{margin-top:0px}.li{margin-right:0px}.ly{margin:0}.mh{border:1px solid #F2F2F2}.mi{border-radius:99em}.mj{padding:0px 16px 0px 12px}.mk{height:38px}.ml{align-items:center}.mn svg{margin-right:8px}.my{font-size:18px}.mz{margin-top:1.56em}.na{line-height:28px}.nb{letter-spacing:-0.003em}.of{font-size:20px}.og{margin-top:0.93em}.oh{line-height:24px}.oi{letter-spacing:0}.pa{margin-top:0.67em}.pk{margin-top:40px}.qw{display:inline-block}.rb{margin-bottom:96px}.rt{margin-bottom:20px}.ru{margin-right:0}.sn{max-width:100%}.sq{font-size:24px}.sr{line-height:30px}.ss{letter-spacing:-0.016em}.td{margin-bottom:64px}.tu{width:100%}.tz{padding-top:48px}.mm:hover{border-color:#E5E5E5}</style><style type="text/css" data-fela-rehydration="554" data-fela-type="RULE" media="all and (min-width: 904px) and (max-width: 1079.98px)">.i{display:none}.bv{width:64px}.cf{margin:0 64px}.cu{height:48px}.db{margin-bottom:52px}.dn{margin-bottom:48px}.ed{font-size:14px}.ee{line-height:20px}.ek{font-size:13px}.el{padding:5px 12px}.fg{display:flex}.fx{margin-bottom:68px}.gb{max-width:680px}.gy{margin-top:40px}.ia{font-size:42px}.ib{margin-top:1em}.ic{margin-bottom:32px}.id{line-height:52px}.ie{letter-spacing:-0.011em}.in{align-items:center}.jv{border-top:solid 1px #F2F2F2}.jw{border-bottom:solid 1px #F2F2F2}.jx{margin:32px 0 0}.jy{padding:3px 8px}.kj> *{margin-right:24px}.kk> :last-child{margin-right:0}.mb{margin:0}.nk{font-size:20px}.nl{margin-top:2.14em}.nm{line-height:32px}.nn{letter-spacing:-0.003em}.or{font-size:24px}.os{margin-top:1.25em}.ot{line-height:30px}.ou{letter-spacing:-0.016em}.pd{margin-top:0.94em}.pn{margin-top:56px}.re{margin-bottom:104px}.rj{flex-direction:row}.rn{margin-bottom:0}.ro{margin-right:20px}.sk{max-width:500px}.sy{line-height:24px}.sz{letter-spacing:0}.tg{margin-bottom:88px}.tj{margin-bottom:72px}.tx{width:min-width}.uc{padding-top:72px}</style><style type="text/css" data-fela-rehydration="554" data-fela-type="RULE" media="all and (min-width: 728px) and (max-width: 903.98px)">.j{display:none}.w{display:flex}.x{justify-content:space-between}.bu{width:64px}.ce{margin:0 48px}.ct{height:48px}.da{margin-bottom:52px}.dm{margin-bottom:48px}.eb{font-size:13px}.ec{line-height:20px}.ej{padding:0px 8px 1px}.fw{margin-bottom:68px}.ga{max-width:680px}.gx{margin-top:40px}.hv{font-size:42px}.hw{margin-top:1em}.hx{margin-bottom:32px}.hy{line-height:52px}.hz{letter-spacing:-0.011em}.im{align-items:center}.jr{border-top:solid 1px #F2F2F2}.js{border-bottom:solid 1px #F2F2F2}.jt{margin:32px 0 0}.ju{padding:3px 8px}.kh> *{margin-right:24px}.ki> :last-child{margin-right:0}.ma{margin:0}.ng{font-size:20px}.nh{margin-top:2.14em}.ni{line-height:32px}.nj{letter-spacing:-0.003em}.on{font-size:24px}.oo{margin-top:1.25em}.op{line-height:30px}.oq{letter-spacing:-0.016em}.pc{margin-top:0.94em}.pm{margin-top:56px}.rd{margin-bottom:104px}.rk{flex-direction:row}.rp{margin-bottom:0}.rq{margin-right:20px}.sl{max-width:500px}.sw{line-height:24px}.sx{letter-spacing:0}.tf{margin-bottom:88px}.ti{margin-bottom:72px}.tw{width:min-width}.ub{padding-top:72px}</style><style type="text/css" data-fela-rehydration="554" data-fela-type="RULE" media="all and (min-width: 552px) and (max-width: 727.98px)">.k{display:none}.u{display:flex}.v{justify-content:space-between}.bt{width:24px}.cd{margin:0 24px}.cs{height:40px}.cz{margin-bottom:44px}.dl{margin-bottom:32px}.dz{font-size:13px}.ea{line-height:20px}.ei{padding:0px 8px 1px}.fv{margin-bottom:4px}.gw{margin-top:32px}.hq{font-size:32px}.hr{margin-top:1.01em}.hs{margin-bottom:24px}.ht{line-height:38px}.hu{letter-spacing:-0.014em}.il{align-items:flex-start}.jj{flex-direction:column}.jp{margin:24px 0 0}.jq{padding:0}.kf> *{margin-right:8px}.kg> :last-child{margin-right:8px}.kx{margin-left:0px}.lz{margin:0}.mo{border:1px solid #F2F2F2}.mp{border-radius:99em}.mq{padding:0px 16px 0px 12px}.mr{height:38px}.ms{align-items:center}.mu svg{margin-right:8px}.nc{font-size:18px}.nd{margin-top:1.56em}.ne{line-height:28px}.nf{letter-spacing:-0.003em}.oj{font-size:20px}.ok{margin-top:0.93em}.ol{line-height:24px}.om{letter-spacing:0}.pb{margin-top:0.67em}.pl{margin-top:40px}.rc{margin-bottom:96px}.rr{margin-bottom:20px}.rs{margin-right:0}.sm{max-width:100%}.st{font-size:24px}.su{line-height:30px}.sv{letter-spacing:-0.016em}.te{margin-bottom:64px}.tv{width:100%}.ua{padding-top:48px}.mt:hover{border-color:#E5E5E5}</style><style type="text/css" data-fela-rehydration="554" data-fela-type="RULE" media="print">.qu{display:none}</style><style type="text/css" data-fela-rehydration="554" data-fela-type="RULE" media="(prefers-reduced-motion: no-preference)">.pp{transition:transform 300ms cubic-bezier(0.2, 0, 0.2, 1)}</style></head><body><div id="root"><div class="a b c"><div class="d e f g h i j k"></div><script>document.domain = document.domain;</script><div class="l c"><div class="l m n o c"><div class="p q r s t u v w x i d y z"><a class="du ag dv bf ak b am an ao ap aq ar as at s u w i d q dw z" href="https://rsci.app.link/?%24canonical_url=https%3A%2F%2Fmedium.com%2Fp%2Fed10782f9c64&amp;%7Efeature=LoOpenInAppButton&amp;%7Echannel=ShowPostUnderUser&amp;source=---top_nav_layout_nav----------------------------------" rel="noopener follow">Open in app<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" fill="none" viewBox="0 0 10 10" class="dt"><path fill="currentColor" d="M.985 8.485a.375.375 0 1 0 .53.53zM8.75 1.25h.375A.375.375 0 0 0 8.75.875zM8.375 6.5a.375.375 0 1 0 .75 0zM3.5.875a.375.375 0 1 0 0 .75zm-1.985 8.14 7.5-7.5-.53-.53-7.5 7.5zm6.86-7.765V6.5h.75V1.25zM3.5 1.625h5.25v-.75H3.5z"></path></svg></a><div class="ab q"><p class="bf b dx dy dz ea eb ec ed ee ef eg du"><span><button class="bf b dx dy eh dz ea ei eb ec ej ek ee el em eg eo ep eq er es et eu ev ew ex ey ez fa fb fc fd bm fe ff" data-testid="headerSignUpButton">Sign up</button></span></p><div class="ax l"><p class="bf b dx dy dz ea eb ec ed ee ef eg du"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="headerSignInButton" rel="noopener follow" href="/m/signin?operation=login&amp;redirect=https%3A%2F%2Fmedium.com%2F%40donturner%2Fdebugging-audio-glitches-on-android-ed10782f9c64&amp;source=post_page---top_nav_layout_nav-----------------------global_nav-----------">Sign in</a></span></p></div></div></div><div class="p q r ab ac"><div class="ab q ae"><a class="af ag ah ai aj ak al am an ao ap aq ar as at ab" aria-label="Homepage" data-testid="headerMediumLogo" rel="noopener follow" href="/?source=---top_nav_layout_nav----------------------------------"><svg xmlns="http://www.w3.org/2000/svg" width="719" height="160" fill="none" viewBox="0 0 719 160" class="au av aw"><path fill="#242424" d="m174.104 9.734.215-.047V8.02H130.39L89.6 103.89 48.81 8.021H1.472v1.666l.212.047c8.018 1.81 12.09 4.509 12.09 14.242V137.93c0 9.734-4.087 12.433-12.106 14.243l-.212.047v1.671h32.118v-1.665l-.213-.048c-8.018-1.809-12.089-4.509-12.089-14.242V30.586l52.399 123.305h2.972l53.925-126.743V140.75c-.687 7.688-4.721 10.062-11.982 11.701l-.215.05v1.652h55.948v-1.652l-.215-.05c-7.269-1.639-11.4-4.013-12.087-11.701l-.037-116.774h.037c0-9.733 4.071-12.432 12.087-14.242m25.555 75.488c.915-20.474 8.268-35.252 20.606-35.507 3.806.063 6.998 1.312 9.479 3.714 5.272 5.118 7.751 15.812 7.368 31.793zm-.553 5.77h65.573v-.275c-.186-15.656-4.721-27.834-13.466-36.196-7.559-7.227-18.751-11.203-30.507-11.203h-.263c-6.101 0-13.584 1.48-18.909 4.16-6.061 2.807-11.407 7.003-15.855 12.511-7.161 8.874-11.499 20.866-12.554 34.343q-.05.606-.092 1.212a50 50 0 0 0-.065 1.151 85.807 85.807 0 0 0-.094 5.689c.71 30.524 17.198 54.917 46.483 54.917 25.705 0 40.675-18.791 44.407-44.013l-1.886-.664c-6.557 13.556-18.334 21.771-31.738 20.769-18.297-1.369-32.314-19.922-31.042-42.395m139.722 41.359c-2.151 5.101-6.639 7.908-12.653 7.908s-11.513-4.129-15.418-11.63c-4.197-8.053-6.405-19.436-6.405-32.92 0-28.067 8.729-46.22 22.24-46.22 5.657 0 10.111 2.807 12.236 7.704zm43.499 20.008c-8.019-1.897-12.089-4.722-12.089-14.951V1.309l-48.716 14.353v1.757l.299-.024c6.72-.543 11.278.386 13.925 2.83 2.072 1.915 3.082 4.853 3.082 8.987v18.66c-4.803-3.067-10.516-4.56-17.448-4.56-14.059 0-26.909 5.92-36.176 16.672-9.66 11.205-14.767 26.518-14.767 44.278-.003 31.72 15.612 53.039 38.851 53.039 13.595 0 24.533-7.449 29.54-20.013v16.865h43.711v-1.746zM424.1 19.819c0-9.904-7.468-17.374-17.375-17.374-9.859 0-17.573 7.632-17.573 17.374s7.721 17.374 17.573 17.374c9.907 0 17.375-7.47 17.375-17.374m11.499 132.546c-8.019-1.897-12.089-4.722-12.089-14.951h-.035V43.635l-43.714 12.551v1.705l.263.024c9.458.842 12.047 4.1 12.047 15.152v81.086h43.751v-1.746zm112.013 0c-8.018-1.897-12.089-4.722-12.089-14.951V43.635l-41.621 12.137v1.71l.246.026c7.733.813 9.967 4.257 9.967 15.36v59.279c-2.578 5.102-7.415 8.131-13.274 8.336-9.503 0-14.736-6.419-14.736-18.073V43.638l-43.714 12.55v1.703l.262.024c9.459.84 12.05 4.097 12.05 15.152v50.17a56.3 56.3 0 0 0 .91 10.444l.787 3.423c3.701 13.262 13.398 20.197 28.59 20.197 12.868 0 24.147-7.966 29.115-20.43v17.311h43.714v-1.747zm169.818 1.788v-1.749l-.213-.05c-8.7-2.006-12.089-5.789-12.089-13.49v-63.79c0-19.89-11.171-31.761-29.883-31.761-13.64 0-25.141 7.882-29.569 20.16-3.517-13.01-13.639-20.16-28.606-20.16-13.146 0-23.449 6.938-27.869 18.657V43.643L545.487 55.68v1.715l.263.024c9.345.829 12.047 4.181 12.047 14.95v81.784h40.787v-1.746l-.215-.053c-6.941-1.631-9.181-4.606-9.181-12.239V66.998c1.836-4.289 5.537-9.37 12.853-9.37 9.086 0 13.692 6.296 13.692 18.697v77.828h40.797v-1.746l-.215-.053c-6.94-1.631-9.18-4.606-9.18-12.239V75.066a42 42 0 0 0-.578-7.26c1.947-4.661 5.86-10.177 13.475-10.177 9.214 0 13.691 6.114 13.691 18.696v77.828z"></path></svg></a><div class="ax h"><div class="ab ay az ba bb q bc bd"><div class="bm" aria-hidden="false" aria-describedby="searchResults" aria-labelledby="searchResults"></div><div class="bn bo ab"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M4.092 11.06a6.95 6.95 0 1 1 13.9 0 6.95 6.95 0 0 1-13.9 0m6.95-8.05a8.05 8.05 0 1 0 5.13 14.26l3.75 3.75a.56.56 0 1 0 .79-.79l-3.73-3.73A8.05 8.05 0 0 0 11.042 3z" clip-rule="evenodd"></path></svg></div><input role="combobox" aria-controls="searchResults" aria-expanded="false" aria-label="search" data-testid="headerSearchInput" tabindex="0" class="ay be bf bg z bh bi bj bk bl" placeholder="Search" value=""/></div></div></div><div class="h k w fg fh"><div class="fi ab"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="headerWriteButton" rel="noopener follow" href="/m/signin?operation=register&amp;redirect=https%3A%2F%2Fmedium.com%2Fnew-story&amp;source=---top_nav_layout_nav-----------------------new_post_topnav-----------"><div class="bf b bg z du fj fk ab q fl fm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24" aria-label="Write"><path fill="currentColor" d="M14 4a.5.5 0 0 0 0-1zm7 6a.5.5 0 0 0-1 0zm-7-7H4v1h10zM3 4v16h1V4zm1 17h16v-1H4zm17-1V10h-1v10zm-1 1a1 1 0 0 0 1-1h-1zM3 20a1 1 0 0 0 1 1v-1zM4 3a1 1 0 0 0-1 1h1z"></path><path stroke="currentColor" d="m17.5 4.5-8.458 8.458a.25.25 0 0 0-.06.098l-.824 2.47a.25.25 0 0 0 .316.316l2.47-.823a.25.25 0 0 0 .098-.06L19.5 6.5m-2-2 2.323-2.323a.25.25 0 0 1 .354 0l1.646 1.646a.25.25 0 0 1 0 .354L19.5 6.5m-2-2 2 2"></path></svg><div class="dt l">Write</div></div></a></span></div></div><div class="k j i d"><div class="fi ab"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="headerSearchButton" rel="noopener follow" href="/search?source=---top_nav_layout_nav----------------------------------"><div class="bf b bg z du fj fk ab q fl fm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24" aria-label="Search"><path fill="currentColor" fill-rule="evenodd" d="M4.092 11.06a6.95 6.95 0 1 1 13.9 0 6.95 6.95 0 0 1-13.9 0m6.95-8.05a8.05 8.05 0 1 0 5.13 14.26l3.75 3.75a.56.56 0 1 0 .79-.79l-3.73-3.73A8.05 8.05 0 0 0 11.042 3z" clip-rule="evenodd"></path></svg></div></a></div></div><div class="fi h k j"><div class="ab q"><p class="bf b dx dy dz ea eb ec ed ee ef eg du"><span><button class="bf b dx dy eh dz ea ei eb ec ej ek ee el em eg eo ep eq er es et eu ev ew ex ey ez fa fb fc fd bm fe ff" data-testid="headerSignUpButton">Sign up</button></span></p><div class="ax l"><p class="bf b dx dy dz ea eb ec ed ee ef eg du"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="headerSignInButton" rel="noopener follow" href="/m/signin?operation=login&amp;redirect=https%3A%2F%2Fmedium.com%2F%40donturner%2Fdebugging-audio-glitches-on-android-ed10782f9c64&amp;source=post_page---top_nav_layout_nav-----------------------global_nav-----------">Sign in</a></span></p></div></div></div><div class="l" aria-hidden="false"><button class="ay fn am ab q ao fo fp fq" aria-label="user options menu" data-testid="headerUserIcon"><div class="l fj"><img alt="" class="l fd by bz ca cx" src="https://miro.medium.com/v2/resize:fill:64:64/1*dmbNkD5D-u45r44go_cf0g.png" width="32" height="32" loading="lazy" role="presentation"/><div class="fr by l bz ca fs n ay ft"></div></div></button></div></div></div><div class="l"><div class="fu fv fw fx fy l"><div class="ab cb"><div class="ci bh fz ga gb gc"></div></div><article><div class="l"><div class="l"><span class="l"></span><section><div><div class="fs gi gj gk gl gm"></div><div class="gn go gp gq gr"><div class="ab cb"><div class="ci bh fz ga gb gc"><figure class="gv gw gx gy gz ha gs gt paragraph-image"><div class="gs gt gu"><picture><source srcSet="https://miro.medium.com/v2/resize:fit:640/format:webp/1*KnhUyWDY_ehL_lEijOI8-w.png 640w, https://miro.medium.com/v2/resize:fit:720/format:webp/1*KnhUyWDY_ehL_lEijOI8-w.png 720w, https://miro.medium.com/v2/resize:fit:750/format:webp/1*KnhUyWDY_ehL_lEijOI8-w.png 750w, https://miro.medium.com/v2/resize:fit:786/format:webp/1*KnhUyWDY_ehL_lEijOI8-w.png 786w, https://miro.medium.com/v2/resize:fit:828/format:webp/1*KnhUyWDY_ehL_lEijOI8-w.png 828w, https://miro.medium.com/v2/resize:fit:1100/format:webp/1*KnhUyWDY_ehL_lEijOI8-w.png 1100w, https://miro.medium.com/v2/resize:fit:1054/format:webp/1*KnhUyWDY_ehL_lEijOI8-w.png 1054w" sizes="(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 527px" type="image/webp"/><source data-testid="og" srcSet="https://miro.medium.com/v2/resize:fit:640/1*KnhUyWDY_ehL_lEijOI8-w.png 640w, https://miro.medium.com/v2/resize:fit:720/1*KnhUyWDY_ehL_lEijOI8-w.png 720w, https://miro.medium.com/v2/resize:fit:750/1*KnhUyWDY_ehL_lEijOI8-w.png 750w, https://miro.medium.com/v2/resize:fit:786/1*KnhUyWDY_ehL_lEijOI8-w.png 786w, https://miro.medium.com/v2/resize:fit:828/1*KnhUyWDY_ehL_lEijOI8-w.png 828w, https://miro.medium.com/v2/resize:fit:1100/1*KnhUyWDY_ehL_lEijOI8-w.png 1100w, https://miro.medium.com/v2/resize:fit:1054/1*KnhUyWDY_ehL_lEijOI8-w.png 1054w" sizes="(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 527px"/><img alt="" class="bh hb hc c" width="527" height="377" loading="eager" role="presentation"/></picture></div><figcaption class="hd ff he gs gt hf hg bf b bg z du">Example audio glitch</figcaption></figure><div><h1 id="0102" class="pw-post-title hh hi hj bf hk hl hm hn ho hp hq hr hs ht hu hv hw hx hy hz ia ib ic id ie if ig ih ii ij bk" data-testid="storyTitle">Debugging audio glitches on Android</h1><div><div class="speechify-ignore ab cp"><div class="speechify-ignore bh l"><div class="ik il im in io ab"><div><div class="ab ip"><div><div class="bm" aria-hidden="false"><a rel="noopener follow" href="/@donturner?source=post_page---byline--ed10782f9c64--------------------------------"><div class="l iq ir by is it"><div class="l fj"><img alt="Don Turner" class="l fd by dd de cx" src="https://miro.medium.com/v2/resize:fill:88:88/1*F2tQfS9RL-Br9vcm_ih_NQ.png" width="44" height="44" loading="lazy" data-testid="authorPhoto"/><div class="iu by l dd de fs n iv ft"></div></div></div></a></div></div></div></div><div class="bn bh l"><div class="ab"><div style="flex:1"><span class="bf b bg z bk"><div class="iw ab q"><div class="ab q ix"><div class="ab q"><div><div class="bm" aria-hidden="false"><p class="bf b iy iz bk"><a class="af ag ah ai aj ak al am an ao ap aq ar ja" data-testid="authorName" rel="noopener follow" href="/@donturner?source=post_page---byline--ed10782f9c64--------------------------------">Don Turner</a></p></div></div></div><span class="jb jc" aria-hidden="true"><span class="bf b bg z du">·</span></span><p class="bf b iy iz du"><span><a class="jd je ah ai aj ak al am an ao ap aq ar ex jf jg" rel="noopener follow" href="/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fsubscribe%2Fuser%2F7f5a2cb6598e&amp;operation=register&amp;redirect=https%3A%2F%2Fmedium.com%2F%40donturner%2Fdebugging-audio-glitches-on-android-ed10782f9c64&amp;user=Don+Turner&amp;userId=7f5a2cb6598e&amp;source=post_page-7f5a2cb6598e--byline--ed10782f9c64---------------------post_header-----------">Follow</a></span></p></div></div></span></div></div><div class="l jh"><span class="bf b bg z du"><div class="ab cn ji jj jk"><span class="bf b bg z du"><div class="ab ae"><span data-testid="storyReadTime">5 min read</span><div class="jl jm l" aria-hidden="true"><span class="l" aria-hidden="true"><span class="bf b bg z du">·</span></span></div><span data-testid="storyPublishDate">May 18, 2018</span></div></span></div></span></div></div></div><div class="ab cp jn jo jp jq jr js jt ju jv jw jx jy jz ka kb kc"><div class="h k w fg fh q"><div class="ks l"><div class="ab q kt ku"><div class="pw-multi-vote-icon fj kv kw kx ky"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="headerClapButton" rel="noopener follow" href="/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fvote%2Fp%2Fed10782f9c64&amp;operation=register&amp;redirect=https%3A%2F%2Fmedium.com%2F%40donturner%2Fdebugging-audio-glitches-on-android-ed10782f9c64&amp;user=Don+Turner&amp;userId=7f5a2cb6598e&amp;source=---header_actions--ed10782f9c64---------------------clap_footer-----------"><div><div class="bm" aria-hidden="false"><div class="kz ao la lb lc ld am le lf lg ky"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-label="clap"><path fill-rule="evenodd" d="M11.37.828 12 3.282l.63-2.454zM13.916 3.953l1.523-2.112-1.184-.39zM8.589 1.84l1.522 2.112-.337-2.501zM18.523 18.92c-.86.86-1.75 1.246-2.62 1.33a6 6 0 0 0 .407-.372c2.388-2.389 2.86-4.951 1.399-7.623l-.912-1.603-.79-1.672c-.26-.56-.194-.98.203-1.288a.7.7 0 0 1 .546-.132c.283.046.546.231.728.5l2.363 4.157c.976 1.624 1.141 4.237-1.324 6.702m-10.999-.438L3.37 14.328a.828.828 0 0 1 .585-1.408.83.83 0 0 1 .585.242l2.158 2.157a.365.365 0 0 0 .516-.516l-2.157-2.158-1.449-1.449a.826.826 0 0 1 1.167-1.17l3.438 3.44a.363.363 0 0 0 .516 0 .364.364 0 0 0 0-.516L5.293 9.513l-.97-.97a.826.826 0 0 1 0-1.166.84.84 0 0 1 1.167 0l.97.968 3.437 3.436a.36.36 0 0 0 .517 0 .366.366 0 0 0 0-.516L6.977 7.83a.82.82 0 0 1-.241-.584.82.82 0 0 1 .824-.826c.219 0 .43.087.584.242l5.787 5.787a.366.366 0 0 0 .587-.415l-1.117-2.363c-.26-.56-.194-.98.204-1.289a.7.7 0 0 1 .546-.132c.283.046.545.232.727.501l2.193 3.86c1.302 2.38.883 4.59-1.277 6.75-1.156 1.156-2.602 1.627-4.19 1.367-1.418-.236-2.866-1.033-4.079-2.246M10.75 5.971l2.12 2.12c-.41.502-.465 1.17-.128 1.89l.22.465-3.523-3.523a.8.8 0 0 1-.097-.368c0-.22.086-.428.241-.584a.847.847 0 0 1 1.167 0m7.355 1.705c-.31-.461-.746-.758-1.23-.837a1.44 1.44 0 0 0-1.11.275c-.312.24-.505.543-.59.881a1.74 1.74 0 0 0-.906-.465 1.47 1.47 0 0 0-.82.106l-2.182-2.182a1.56 1.56 0 0 0-2.2 0 1.54 1.54 0 0 0-.396.701 1.56 1.56 0 0 0-2.21-.01 1.55 1.55 0 0 0-.416.753c-.624-.624-1.649-.624-2.237-.037a1.557 1.557 0 0 0 0 2.2c-.239.1-.501.238-.715.453a1.56 1.56 0 0 0 0 2.2l.516.515a1.556 1.556 0 0 0-.753 2.615L7.01 19c1.32 1.319 2.909 2.189 4.475 2.449q.482.08.971.08c.85 0 1.653-.198 2.393-.579.231.033.46.054.686.054 1.266 0 2.457-.52 3.505-1.567 2.763-2.763 2.552-5.734 1.439-7.586z" clip-rule="evenodd"></path></svg></div></div></div></a></span></div><div class="pw-multi-vote-count l lh li lj lk ll lm ln"><p class="bf b dv z du"><span class="lo">--</span></p></div></div></div><div><div class="bm" aria-hidden="false"><button class="ao kz lr ls ab q fk lt lu" aria-label="responses"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="lq"><path d="M18.006 16.803c1.533-1.456 2.234-3.325 2.234-5.321C20.24 7.357 16.709 4 12.191 4S4 7.357 4 11.482c0 4.126 3.674 7.482 8.191 7.482.817 0 1.622-.111 2.393-.327.231.2.48.391.744.559 1.06.693 2.203 1.044 3.399 1.044.224-.008.4-.112.486-.287a.49.49 0 0 0-.042-.518c-.495-.67-.845-1.364-1.04-2.057a4 4 0 0 1-.125-.598zm-3.122 1.055-.067-.223-.315.096a8 8 0 0 1-2.311.338c-4.023 0-7.292-2.955-7.292-6.587 0-3.633 3.269-6.588 7.292-6.588 4.014 0 7.112 2.958 7.112 6.593 0 1.794-.608 3.469-2.027 4.72l-.195.168v.255c0 .056 0 .151.016.295.025.231.081.478.154.733.154.558.398 1.117.722 1.659a5.3 5.3 0 0 1-2.165-.845c-.276-.176-.714-.383-.941-.59z"></path></svg><p class="bf b dv z du"><span class="pw-responses-count lp lq">2</span></p></button></div></div></div><div class="ab q kd ke kf kg kh ki kj kk kl km kn ko kp kq kr"><div class="lv k j i d"></div><div class="h k"><div><div class="bm" aria-hidden="false"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="headerBookmarkButton" rel="noopener follow" href="/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fbookmark%2Fp%2Fed10782f9c64&amp;operation=register&amp;redirect=https%3A%2F%2Fmedium.com%2F%40donturner%2Fdebugging-audio-glitches-on-android-ed10782f9c64&amp;source=---header_actions--ed10782f9c64---------------------bookmark_footer-----------"><svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="none" viewBox="0 0 25 25" class="du lw" aria-label="Add to list bookmark button"><path fill="currentColor" d="M18 2.5a.5.5 0 0 1 1 0V5h2.5a.5.5 0 0 1 0 1H19v2.5a.5.5 0 1 1-1 0V6h-2.5a.5.5 0 0 1 0-1H18zM7 7a1 1 0 0 1 1-1h3.5a.5.5 0 0 0 0-1H8a2 2 0 0 0-2 2v14a.5.5 0 0 0 .805.396L12.5 17l5.695 4.396A.5.5 0 0 0 19 21v-8.5a.5.5 0 0 0-1 0v7.485l-5.195-4.012a.5.5 0 0 0-.61 0L7 19.985z"></path></svg></a></span></div></div></div><div class="fd lx cn"><div class="l ae"><div class="ab cb"><div class="ly lz ma mb mc hb ci bh"><div class="ab"><div class="bm bh" aria-hidden="false"><div><div class="bm" aria-hidden="false"><button aria-label="Listen" data-testid="audioPlayButton" class="af fk ah ai aj ak al md an ao ap ex me mf lu mg mh mi mj mk s ml mm mn mo mp mq mr u ms mt mu"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M3 12a9 9 0 1 1 18 0 9 9 0 0 1-18 0m9-10C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2m3.376 10.416-4.599 3.066a.5.5 0 0 1-.777-.416V8.934a.5.5 0 0 1 .777-.416l4.599 3.066a.5.5 0 0 1 0 .832" clip-rule="evenodd"></path></svg><div class="j i d"><p class="bf b bg z du">Listen</p></div></button></div></div></div></div></div></div></div></div><div class="bm" aria-hidden="false" aria-describedby="postFooterSocialMenu" aria-labelledby="postFooterSocialMenu"><div><div class="bm" aria-hidden="false"><button aria-controls="postFooterSocialMenu" aria-expanded="false" aria-label="Share Post" data-testid="headerSocialShareButton" class="af fk ah ai aj ak al md an ao ap ex me mf lu mg mh mi mj mk s ml mm mn mo mp mq mr u ms mt mu"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M15.218 4.931a.4.4 0 0 1-.118.132l.012.006a.45.45 0 0 1-.292.074.5.5 0 0 1-.3-.13l-2.02-2.02v7.07c0 .28-.23.5-.5.5s-.5-.22-.5-.5v-7.04l-2 2a.45.45 0 0 1-.57.04h-.02a.4.4 0 0 1-.16-.3.4.4 0 0 1 .1-.32l2.8-2.8a.5.5 0 0 1 .7 0l2.8 2.79a.42.42 0 0 1 .068.498m-.106.138.008.004v-.01zM16 7.063h1.5a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-11c-1.1 0-2-.9-2-2v-10a2 2 0 0 1 2-2H8a.5.5 0 0 1 .35.15.5.5 0 0 1 .15.35.5.5 0 0 1-.15.35.5.5 0 0 1-.35.15H6.4c-.5 0-.9.4-.9.9v10.2a.9.9 0 0 0 .9.9h11.2c.5 0 .9-.4.9-.9v-10.2c0-.5-.4-.9-.9-.9H16a.5.5 0 0 1 0-1" clip-rule="evenodd"></path></svg><div class="j i d"><p class="bf b bg z du">Share</p></div></button></div></div></div></div></div></div></div></div></div><p id="5273" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">In this article I will explain how to identify the causes of audio glitches in your app using systrace and the Android Studio profiler.</p><p id="6ad5" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Background: I wanted to build a one hundred oscillator synthesizer app (inspired by <a class="af nt" href="https://www.youtube.com/watch?v=q45FHZLVz2U" rel="noopener ugc nofollow" target="_blank">this amazing project from LOOK MUM NO COMPUTER</a>). A perfectly reasonable thing to do, right?</p><p id="e6c5" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">I had <a class="af nt" href="https://github.com/google/oboe/tree/master/samples/hello-oboe" rel="noopener ugc nofollow" target="_blank">already built an app</a> which would use a single oscillator to produce a sine wave. I updated it to use one hundred oscillators and then summed the outputs of each one.</p><p id="4725" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk"><strong class="mx hk">The result</strong>: horrible clicks and pops in the final audio aka <strong class="mx hk">audio glitches</strong> 😩</p><p id="933b" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">The <strong class="mx hk">problem</strong> is, each oscillator uses a few computations to generate its data, and with one hundred of them my CPU usage was enough to push me over my <a class="af nt" href="https://github.com/google/oboe/blob/master/FullGuide.md#using-a-high-priority-callback" rel="noopener ugc nofollow" target="_blank">audio callback</a> deadline.</p><p id="d397" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">In my case, each callback would request 96 frames of audio data for a 48kHz audio stream. This means I had 96/48000=0.002s or 2 milliseconds to generate 96 frames of data. So my app was probably taking longer than 2 milliseconds to generate those 96 frames, at least some of the time.</p><p id="6f1b" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Well, that was my hypothesis, but how could I know for sure?</p></div></div></div><div class="ab cb nu nv nw nx" role="separator"><span class="ny by bm nz oa ob"></span><span class="ny by bm nz oa ob"></span><span class="ny by bm nz oa"></span></div><div class="gn go gp gq gr"><div class="ab cb"><div class="ci bh fz ga gb gc"><h1 id="0c8e" class="oc od hj bf oe of og oh oi oj ok ol om on oo op oq or os ot ou ov ow ox oy oz bk">Measuring callback times</h1><p id="1b01" class="pw-post-body-paragraph mv mw hj mx b my pa na nb nc pb ne nf ng pc ni nj nk pd nm nn no pe nq nr ns gn bk">Enter <a class="af nt" href="https://developer.android.com/studio/command-line/systrace" rel="noopener ugc nofollow" target="_blank">systrace</a>. Systrace is my #1 go to tool for debugging audio problems. It shows exactly what’s going on across processes and CPU cores. The key is knowing how to use it.</p><p id="b38b" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Here’s the command I use:</p><p id="4429" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk"><code class="cx pf pg ph pi b">systrace.py --time=5 -o trace.html -a com.example.myapp audio sched freq</code></p><p id="5eca" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">This will run a trace for 5 seconds, putting the output into trace.html. The trace will include audio buffer status, CPU frequency and CPU scheduling information.</p><p id="b68f" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Here’s the trace:</p><figure class="pk pl pm pn po ha gs gt paragraph-image"><div role="button" tabindex="0" class="pp pq fj pr bh ps"><div class="gs gt pj"><picture><source srcSet="https://miro.medium.com/v2/resize:fit:640/format:webp/1*jE49l8oKvfYZI2u8bRZ91g.png 640w, https://miro.medium.com/v2/resize:fit:720/format:webp/1*jE49l8oKvfYZI2u8bRZ91g.png 720w, https://miro.medium.com/v2/resize:fit:750/format:webp/1*jE49l8oKvfYZI2u8bRZ91g.png 750w, https://miro.medium.com/v2/resize:fit:786/format:webp/1*jE49l8oKvfYZI2u8bRZ91g.png 786w, https://miro.medium.com/v2/resize:fit:828/format:webp/1*jE49l8oKvfYZI2u8bRZ91g.png 828w, https://miro.medium.com/v2/resize:fit:1100/format:webp/1*jE49l8oKvfYZI2u8bRZ91g.png 1100w, https://miro.medium.com/v2/resize:fit:1400/format:webp/1*jE49l8oKvfYZI2u8bRZ91g.png 1400w" sizes="(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px" type="image/webp"/><source data-testid="og" srcSet="https://miro.medium.com/v2/resize:fit:640/1*jE49l8oKvfYZI2u8bRZ91g.png 640w, https://miro.medium.com/v2/resize:fit:720/1*jE49l8oKvfYZI2u8bRZ91g.png 720w, https://miro.medium.com/v2/resize:fit:750/1*jE49l8oKvfYZI2u8bRZ91g.png 750w, https://miro.medium.com/v2/resize:fit:786/1*jE49l8oKvfYZI2u8bRZ91g.png 786w, https://miro.medium.com/v2/resize:fit:828/1*jE49l8oKvfYZI2u8bRZ91g.png 828w, https://miro.medium.com/v2/resize:fit:1100/1*jE49l8oKvfYZI2u8bRZ91g.png 1100w, https://miro.medium.com/v2/resize:fit:1400/1*jE49l8oKvfYZI2u8bRZ91g.png 1400w" sizes="(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px"/><img alt="" class="bh hb hc c" width="700" height="341" loading="eager" role="presentation"/></picture></div></div><figcaption class="hd ff he gs gt hf hg bf b bg z du">systrace from audio app</figcaption></figure><p id="4acc" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Again, knowing what to look for is the key. The thing I’m most interested in is the <strong class="mx hk">audio buffer status</strong>. This is shown in the <code class="cx pf pg ph pi b">aaRdy</code> line for my app, which presumably stands for <em class="pt">AAudio ready</em> and shows the number of frames which are ready to be read from the <a class="af nt" href="https://developer.android.com/ndk/guides/audio/aaudio/aaudio" rel="noopener ugc nofollow" target="_blank">AAudio</a> internal buffer.</p><p id="a090" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Incidentally, I’m using <a class="af nt" href="https://github.com/google/oboe/blob/master/FullGuide.md#using-a-high-priority-callback" rel="noopener ugc nofollow" target="_blank">Oboe</a> for my audio library which will use AAudio on devices which support it and OpenSL ES on everything else. If OpenSL ES was being used I would look for a row named <code class="cx pf pg ph pi b">fRdy</code>.</p><p id="e6b7" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Let’s zoom in on the <code class="cx pf pg ph pi b">aaRdy</code> line:</p><figure class="pk pl pm pn po ha gs gt paragraph-image"><div class="gs gt pu"><picture><source srcSet="https://miro.medium.com/v2/resize:fit:640/format:webp/1*UCmF6BqiSuK_jFdiAPW-rQ.png 640w, https://miro.medium.com/v2/resize:fit:720/format:webp/1*UCmF6BqiSuK_jFdiAPW-rQ.png 720w, https://miro.medium.com/v2/resize:fit:750/format:webp/1*UCmF6BqiSuK_jFdiAPW-rQ.png 750w, https://miro.medium.com/v2/resize:fit:786/format:webp/1*UCmF6BqiSuK_jFdiAPW-rQ.png 786w, https://miro.medium.com/v2/resize:fit:828/format:webp/1*UCmF6BqiSuK_jFdiAPW-rQ.png 828w, https://miro.medium.com/v2/resize:fit:1100/format:webp/1*UCmF6BqiSuK_jFdiAPW-rQ.png 1100w, https://miro.medium.com/v2/resize:fit:1186/format:webp/1*UCmF6BqiSuK_jFdiAPW-rQ.png 1186w" sizes="(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 593px" type="image/webp"/><source data-testid="og" srcSet="https://miro.medium.com/v2/resize:fit:640/1*UCmF6BqiSuK_jFdiAPW-rQ.png 640w, https://miro.medium.com/v2/resize:fit:720/1*UCmF6BqiSuK_jFdiAPW-rQ.png 720w, https://miro.medium.com/v2/resize:fit:750/1*UCmF6BqiSuK_jFdiAPW-rQ.png 750w, https://miro.medium.com/v2/resize:fit:786/1*UCmF6BqiSuK_jFdiAPW-rQ.png 786w, https://miro.medium.com/v2/resize:fit:828/1*UCmF6BqiSuK_jFdiAPW-rQ.png 828w, https://miro.medium.com/v2/resize:fit:1100/1*UCmF6BqiSuK_jFdiAPW-rQ.png 1100w, https://miro.medium.com/v2/resize:fit:1186/1*UCmF6BqiSuK_jFdiAPW-rQ.png 1186w" sizes="(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 593px"/><img alt="" class="bh hb hc c" width="593" height="138" loading="lazy" role="presentation"/></picture></div></figure><p id="72d1" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">By clicking on any of the individual slices we can see the number of audio frames which are in the buffer at that time. In the slice above there are 192 frames. I’m using a buffer size of 192 frames (which is twice the minimum buffer size and is usually a safe default), so the buffer is currently full.</p><p id="63b2" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">But then the buffer starts empty, first dropping to 96 frames, then….oh dear…to zero! At zero we are guaranteed to have an audio glitch because there’s no data in the buffer.</p><p id="9a70" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Now, we could look at everything else that was going on in the system at this time and it’s likely we’ll see a CPU core migration, some other process come in and stomp all over our audio process or a CPU frequency drop causing a delay in execution of our oscillator’s code.</p><p id="fb11" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">But we can’t really control any of that without jumping through some <a class="af nt" href="https://github.com/googlesamples/android-audio-high-performance/blob/master/SimpleSynth/app/src/main/cpp/audio_player.cc#L289" rel="noopener ugc nofollow" target="_blank">fairly dangerous hoops</a> (setting thread affinity, CPU load stabilization etc).</p><p id="0261" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Instead, let’s take a look at our own code and see what’s taking so long to execute. For this we can use the wonderful <a class="af nt" href="https://developer.android.com/studio/profile/cpu-profiler" rel="noopener ugc nofollow" target="_blank">new native CPU profiler</a> in Android Studio. Here’s the output from a <em class="pt">Sampled (Native)</em> trace, in the <em class="pt">Flame Chart</em> view:</p><figure class="pk pl pm pn po ha gs gt paragraph-image"><div role="button" tabindex="0" class="pp pq fj pr bh ps"><div class="gs gt pv"><picture><source srcSet="https://miro.medium.com/v2/resize:fit:640/format:webp/1*MEH3LKxZMSfGpp-8jj7O1g.png 640w, https://miro.medium.com/v2/resize:fit:720/format:webp/1*MEH3LKxZMSfGpp-8jj7O1g.png 720w, https://miro.medium.com/v2/resize:fit:750/format:webp/1*MEH3LKxZMSfGpp-8jj7O1g.png 750w, https://miro.medium.com/v2/resize:fit:786/format:webp/1*MEH3LKxZMSfGpp-8jj7O1g.png 786w, https://miro.medium.com/v2/resize:fit:828/format:webp/1*MEH3LKxZMSfGpp-8jj7O1g.png 828w, https://miro.medium.com/v2/resize:fit:1100/format:webp/1*MEH3LKxZMSfGpp-8jj7O1g.png 1100w, https://miro.medium.com/v2/resize:fit:1400/format:webp/1*MEH3LKxZMSfGpp-8jj7O1g.png 1400w" sizes="(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px" type="image/webp"/><source data-testid="og" srcSet="https://miro.medium.com/v2/resize:fit:640/1*MEH3LKxZMSfGpp-8jj7O1g.png 640w, https://miro.medium.com/v2/resize:fit:720/1*MEH3LKxZMSfGpp-8jj7O1g.png 720w, https://miro.medium.com/v2/resize:fit:750/1*MEH3LKxZMSfGpp-8jj7O1g.png 750w, https://miro.medium.com/v2/resize:fit:786/1*MEH3LKxZMSfGpp-8jj7O1g.png 786w, https://miro.medium.com/v2/resize:fit:828/1*MEH3LKxZMSfGpp-8jj7O1g.png 828w, https://miro.medium.com/v2/resize:fit:1100/1*MEH3LKxZMSfGpp-8jj7O1g.png 1100w, https://miro.medium.com/v2/resize:fit:1400/1*MEH3LKxZMSfGpp-8jj7O1g.png 1400w" sizes="(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px"/><img alt="" class="bh hb hc c" width="700" height="89" loading="lazy" role="presentation"/></picture></div></div></figure><p id="4a65" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Well, look at that, my app is <strong class="mx hk">spending an awful lot of time in sinf</strong>, a method calculating sine values. This is puzzling because sinf isn’t exactly computationally expensive and whilst 100 oscillators might sound like a lot, any modern CPU should be able to handle this load without breaking a sweat.</p><p id="4d00" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Unless the compiler didn’t optimise the code.</p></div></div></div><div class="ab cb nu nv nw nx" role="separator"><span class="ny by bm nz oa ob"></span><span class="ny by bm nz oa ob"></span><span class="ny by bm nz oa"></span></div><div class="gn go gp gq gr"><div class="ab cb"><div class="ci bh fz ga gb gc"><h1 id="4d77" class="oc od hj bf oe of og oh oi oj ok ol om on oo op oq or os ot ou ov ow ox oy oz bk">Compiler optimisation</h1><p id="58a8" class="pw-post-body-paragraph mv mw hj mx b my pa na nb nc pb ne nf ng pc ni nj nk pd nm nn no pe nq nr ns gn bk">So, how do we know whether the compiler optimised our build? Well there’s a simple way to check. Open the following file:</p><p id="bdfe" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk"><code class="cx pf pg ph pi b">app/.externalNativeBuild/cmake/debug/&lt;architecture&gt;/build.ninja</code></p><p id="3e93" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Now look for a line starting with FLAGS, here’s mine:</p><pre class="pk pl pm pn po pw pi px py ay pz bk"><span id="cafa" class="qa od hj pi b iy qb qc l qd qe">FLAGS = -isystem /Users/donturner/Library/Android/sdk/ndk-bundle/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11 -O0 -fno-limit-debug-info -fPIC</span></pre><p id="cb49" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">And there you have it <code class="cx pf pg ph pi b">-O0</code> <strong class="mx hk">no optimisations</strong>.</p><p id="7cf7" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">This actually makes perfect sense for a debug build because we might want to use step debugging and we don’t want the compiler to mess with the order of code execution.</p><p id="5dfa" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">But now we can try various different optimisation flags to see whether they affect performance. To do this I added the following line to my <code class="cx pf pg ph pi b">app/build.gradle</code> file in the <code class="cx pf pg ph pi b">android.defaultConfig.externalNativeBuild.cmake</code> block:</p><pre class="pk pl pm pn po pw pi px py ay pz bk"><span id="1078" class="qa od hj pi b iy qb qc l qd qe">cppFlags <strong class="pi hk">&quot;-Ofast&quot;</strong></span></pre><p id="519a" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Then recompile and run. And the result was…..</p><p id="332e" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">No difference :(</p><p id="330a" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">I’ll be honest I was stumped at this point and ended up trying all sorts of different things: faster implementations of <code class="cx pf pg ph pi b">sin</code> , switching to a square wave, copy-pasting code from stackoverflow, shouting at Android Studio. Nothing had any effect. Out of interest I re-checked my <code class="cx pf pg ph pi b">build.ninja</code> file to see if there were any obvious flags I’d missed and to my amazement I found this in my build flags:</p><p id="32d6" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk"><code class="cx pf pg ph pi b">-Ofast -O0</code></p><p id="9b00" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">That’s right. Android Studio, CMake and the NDK work together to override your <code class="cx pf pg ph pi b">build.gradle</code> settings and <strong class="mx hk">the compiler will take the <em class="pt">last</em> optimisation flag</strong>, meaning <code class="cx pf pg ph pi b">-Ofast</code> is completely ignored. <a class="af nt" href="https://github.com/android-ndk/ndk/issues/699" rel="noopener ugc nofollow" target="_blank">This is a bug</a>, and it comes from the file <code class="cx pf pg ph pi b">$ANDROID_NDK/build/cmake/android.toolchain.cmake</code>.</p><p id="e9a0" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">To disable this behaviour I searched for <code class="cx pf pg ph pi b">ANDROID_COMPILER_FLAGS_DEBUG</code> and commented out any code relating to optimisation flags.</p><p id="6f1e" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Recompile, run and…..success!! The app runs like clockwork.</p><p id="03fa" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">I can now listen to the sweet, sweet sound of the one hundred mega-drone synth with no horrible glitches 😃</p><p id="2f64" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">UPDATE 21st May: One of my colleagues showed me a different workaround which doesn’t involve changing `android.toolchain.cmake`. All you need to do is add the following to `CMakeLists.txt`:</p><pre class="pk pl pm pn po pw pi px py ay pz bk"><span id="da59" class="qa od hj pi b iy qb qc l qd qe">set(CMAKE_CXX_FLAGS_DEBUG &quot;${CMAKE_CXX_FLAGS_DEBUG} -Ofast&quot;)<!-- --> </span></pre></div></div></div><div class="ab cb nu nv nw nx" role="separator"><span class="ny by bm nz oa ob"></span><span class="ny by bm nz oa ob"></span><span class="ny by bm nz oa"></span></div><div class="gn go gp gq gr"><div class="ab cb"><div class="ci bh fz ga gb gc"><h1 id="d886" class="oc od hj bf oe of og oh oi oj ok ol om on oo op oq or os ot ou ov ow ox oy oz bk">Conclusion</h1><p id="3735" class="pw-post-body-paragraph mv mw hj mx b my pa na nb nc pb ne nf ng pc ni nj nk pd nm nn no pe nq nr ns gn bk">If you’re experiencing audio performance problems, use <a class="af nt" href="https://developer.android.com/studio/command-line/systrace" rel="noopener ugc nofollow" target="_blank">systrace</a> and the Android Studio profiler to figure out what your code is doing. And always check your build flags.</p><p id="7b9d" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">If you’re interested in building real-time audio apps on Android be sure to check out the <a class="af nt" href="https://github.com/google/oboe" rel="noopener ugc nofollow" target="_blank">Oboe library</a> (full disclosure: I am one of the authors).</p><p id="52cf" class="pw-post-body-paragraph mv mw hj mx b my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns gn bk">Got audio performance problems or questions? Would love to hear about them in the comments.</p></div></div></div></div></section></div></div></article></div><div class="ab cb"><div class="ci bh fz ga gb gc"><div class="qf qg ab jk"><div class="qh ab"><a class="qi ay am ao" rel="noopener follow" href="/tag/android?source=post_page-----ed10782f9c64--------------------------------"><div class="qj fj cx qk ge ql qm bf b bg z bk qn">Android</div></a></div><div class="qh ab"><a class="qi ay am ao" rel="noopener follow" href="/tag/audio?source=post_page-----ed10782f9c64--------------------------------"><div class="qj fj cx qk ge ql qm bf b bg z bk qn">Audio</div></a></div><div class="qh ab"><a class="qi ay am ao" rel="noopener follow" href="/tag/c?source=post_page-----ed10782f9c64--------------------------------"><div class="qj fj cx qk ge ql qm bf b bg z bk qn">C</div></a></div><div class="qh ab"><a class="qi ay am ao" rel="noopener follow" href="/tag/low-latency?source=post_page-----ed10782f9c64--------------------------------"><div class="qj fj cx qk ge ql qm bf b bg z bk qn">Low Latency</div></a></div><div class="qh ab"><a class="qi ay am ao" rel="noopener follow" href="/tag/cpu?source=post_page-----ed10782f9c64--------------------------------"><div class="qj fj cx qk ge ql qm bf b bg z bk qn">Cpu</div></a></div></div></div></div><div class="l"></div><footer class="qo nv qp qq qr ab q qs qt c"><div class="l ae"><div class="ab cb"><div class="ci bh fz ga gb gc"><div class="ab cp qu"><div class="ab q kt"><div class="qv l"><span class="l qw qx qy e d"><div class="ab q kt ku"><div class="pw-multi-vote-icon fj kv kw kx ky"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="footerClapButton" rel="noopener follow" href="/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fvote%2Fp%2Fed10782f9c64&amp;operation=register&amp;redirect=https%3A%2F%2Fmedium.com%2F%40donturner%2Fdebugging-audio-glitches-on-android-ed10782f9c64&amp;user=Don+Turner&amp;userId=7f5a2cb6598e&amp;source=---footer_actions--ed10782f9c64---------------------clap_footer-----------"><div><div class="bm" aria-hidden="false"><div class="kz ao la lb lc ld am le lf lg ky"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-label="clap"><path fill-rule="evenodd" d="M11.37.828 12 3.282l.63-2.454zM13.916 3.953l1.523-2.112-1.184-.39zM8.589 1.84l1.522 2.112-.337-2.501zM18.523 18.92c-.86.86-1.75 1.246-2.62 1.33a6 6 0 0 0 .407-.372c2.388-2.389 2.86-4.951 1.399-7.623l-.912-1.603-.79-1.672c-.26-.56-.194-.98.203-1.288a.7.7 0 0 1 .546-.132c.283.046.546.231.728.5l2.363 4.157c.976 1.624 1.141 4.237-1.324 6.702m-10.999-.438L3.37 14.328a.828.828 0 0 1 .585-1.408.83.83 0 0 1 .585.242l2.158 2.157a.365.365 0 0 0 .516-.516l-2.157-2.158-1.449-1.449a.826.826 0 0 1 1.167-1.17l3.438 3.44a.363.363 0 0 0 .516 0 .364.364 0 0 0 0-.516L5.293 9.513l-.97-.97a.826.826 0 0 1 0-1.166.84.84 0 0 1 1.167 0l.97.968 3.437 3.436a.36.36 0 0 0 .517 0 .366.366 0 0 0 0-.516L6.977 7.83a.82.82 0 0 1-.241-.584.82.82 0 0 1 .824-.826c.219 0 .43.087.584.242l5.787 5.787a.366.366 0 0 0 .587-.415l-1.117-2.363c-.26-.56-.194-.98.204-1.289a.7.7 0 0 1 .546-.132c.283.046.545.232.727.501l2.193 3.86c1.302 2.38.883 4.59-1.277 6.75-1.156 1.156-2.602 1.627-4.19 1.367-1.418-.236-2.866-1.033-4.079-2.246M10.75 5.971l2.12 2.12c-.41.502-.465 1.17-.128 1.89l.22.465-3.523-3.523a.8.8 0 0 1-.097-.368c0-.22.086-.428.241-.584a.847.847 0 0 1 1.167 0m7.355 1.705c-.31-.461-.746-.758-1.23-.837a1.44 1.44 0 0 0-1.11.275c-.312.24-.505.543-.59.881a1.74 1.74 0 0 0-.906-.465 1.47 1.47 0 0 0-.82.106l-2.182-2.182a1.56 1.56 0 0 0-2.2 0 1.54 1.54 0 0 0-.396.701 1.56 1.56 0 0 0-2.21-.01 1.55 1.55 0 0 0-.416.753c-.624-.624-1.649-.624-2.237-.037a1.557 1.557 0 0 0 0 2.2c-.239.1-.501.238-.715.453a1.56 1.56 0 0 0 0 2.2l.516.515a1.556 1.556 0 0 0-.753 2.615L7.01 19c1.32 1.319 2.909 2.189 4.475 2.449q.482.08.971.08c.85 0 1.653-.198 2.393-.579.231.033.46.054.686.054 1.266 0 2.457-.52 3.505-1.567 2.763-2.763 2.552-5.734 1.439-7.586z" clip-rule="evenodd"></path></svg></div></div></div></a></span></div><div class="pw-multi-vote-count l lh li lj lk ll lm ln"><p class="bf b dv z du"><span class="lo">--</span></p></div></div></span><span class="l h g f qz ra"><div class="ab q kt ku"><div class="pw-multi-vote-icon fj kv kw kx ky"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="footerClapButton" rel="noopener follow" href="/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fvote%2Fp%2Fed10782f9c64&amp;operation=register&amp;redirect=https%3A%2F%2Fmedium.com%2F%40donturner%2Fdebugging-audio-glitches-on-android-ed10782f9c64&amp;user=Don+Turner&amp;userId=7f5a2cb6598e&amp;source=---footer_actions--ed10782f9c64---------------------clap_footer-----------"><div><div class="bm" aria-hidden="false"><div class="kz ao la lb lc ld am le lf lg ky"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-label="clap"><path fill-rule="evenodd" d="M11.37.828 12 3.282l.63-2.454zM13.916 3.953l1.523-2.112-1.184-.39zM8.589 1.84l1.522 2.112-.337-2.501zM18.523 18.92c-.86.86-1.75 1.246-2.62 1.33a6 6 0 0 0 .407-.372c2.388-2.389 2.86-4.951 1.399-7.623l-.912-1.603-.79-1.672c-.26-.56-.194-.98.203-1.288a.7.7 0 0 1 .546-.132c.283.046.546.231.728.5l2.363 4.157c.976 1.624 1.141 4.237-1.324 6.702m-10.999-.438L3.37 14.328a.828.828 0 0 1 .585-1.408.83.83 0 0 1 .585.242l2.158 2.157a.365.365 0 0 0 .516-.516l-2.157-2.158-1.449-1.449a.826.826 0 0 1 1.167-1.17l3.438 3.44a.363.363 0 0 0 .516 0 .364.364 0 0 0 0-.516L5.293 9.513l-.97-.97a.826.826 0 0 1 0-1.166.84.84 0 0 1 1.167 0l.97.968 3.437 3.436a.36.36 0 0 0 .517 0 .366.366 0 0 0 0-.516L6.977 7.83a.82.82 0 0 1-.241-.584.82.82 0 0 1 .824-.826c.219 0 .43.087.584.242l5.787 5.787a.366.366 0 0 0 .587-.415l-1.117-2.363c-.26-.56-.194-.98.204-1.289a.7.7 0 0 1 .546-.132c.283.046.545.232.727.501l2.193 3.86c1.302 2.38.883 4.59-1.277 6.75-1.156 1.156-2.602 1.627-4.19 1.367-1.418-.236-2.866-1.033-4.079-2.246M10.75 5.971l2.12 2.12c-.41.502-.465 1.17-.128 1.89l.22.465-3.523-3.523a.8.8 0 0 1-.097-.368c0-.22.086-.428.241-.584a.847.847 0 0 1 1.167 0m7.355 1.705c-.31-.461-.746-.758-1.23-.837a1.44 1.44 0 0 0-1.11.275c-.312.24-.505.543-.59.881a1.74 1.74 0 0 0-.906-.465 1.47 1.47 0 0 0-.82.106l-2.182-2.182a1.56 1.56 0 0 0-2.2 0 1.54 1.54 0 0 0-.396.701 1.56 1.56 0 0 0-2.21-.01 1.55 1.55 0 0 0-.416.753c-.624-.624-1.649-.624-2.237-.037a1.557 1.557 0 0 0 0 2.2c-.239.1-.501.238-.715.453a1.56 1.56 0 0 0 0 2.2l.516.515a1.556 1.556 0 0 0-.753 2.615L7.01 19c1.32 1.319 2.909 2.189 4.475 2.449q.482.08.971.08c.85 0 1.653-.198 2.393-.579.231.033.46.054.686.054 1.266 0 2.457-.52 3.505-1.567 2.763-2.763 2.552-5.734 1.439-7.586z" clip-rule="evenodd"></path></svg></div></div></div></a></span></div><div class="pw-multi-vote-count l lh li lj lk ll lm ln"><p class="bf b dv z du"><span class="lo">--</span></p></div></div></span></div><div class="bq ab"><div><div class="bm" aria-hidden="false"><button class="ao kz lr ls ab q fk lt lu" aria-label="responses"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="lq"><path d="M18.006 16.803c1.533-1.456 2.234-3.325 2.234-5.321C20.24 7.357 16.709 4 12.191 4S4 7.357 4 11.482c0 4.126 3.674 7.482 8.191 7.482.817 0 1.622-.111 2.393-.327.231.2.48.391.744.559 1.06.693 2.203 1.044 3.399 1.044.224-.008.4-.112.486-.287a.49.49 0 0 0-.042-.518c-.495-.67-.845-1.364-1.04-2.057a4 4 0 0 1-.125-.598zm-3.122 1.055-.067-.223-.315.096a8 8 0 0 1-2.311.338c-4.023 0-7.292-2.955-7.292-6.587 0-3.633 3.269-6.588 7.292-6.588 4.014 0 7.112 2.958 7.112 6.593 0 1.794-.608 3.469-2.027 4.72l-.195.168v.255c0 .056 0 .151.016.295.025.231.081.478.154.733.154.558.398 1.117.722 1.659a5.3 5.3 0 0 1-2.165-.845c-.276-.176-.714-.383-.941-.59z"></path></svg><p class="bf b bg z du"><span class="pw-responses-count lp lq">2</span></p></button></div></div></div></div><div class="ab q"><div class="ob l jh"><div><div class="bm" aria-hidden="false"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="footerBookmarkButton" rel="noopener follow" href="/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fbookmark%2Fp%2Fed10782f9c64&amp;operation=register&amp;redirect=https%3A%2F%2Fmedium.com%2F%40donturner%2Fdebugging-audio-glitches-on-android-ed10782f9c64&amp;source=---footer_actions--ed10782f9c64---------------------bookmark_footer-----------"><svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="none" viewBox="0 0 25 25" class="du lw" aria-label="Add to list bookmark button"><path fill="currentColor" d="M18 2.5a.5.5 0 0 1 1 0V5h2.5a.5.5 0 0 1 0 1H19v2.5a.5.5 0 1 1-1 0V6h-2.5a.5.5 0 0 1 0-1H18zM7 7a1 1 0 0 1 1-1h3.5a.5.5 0 0 0 0-1H8a2 2 0 0 0-2 2v14a.5.5 0 0 0 .805.396L12.5 17l5.695 4.396A.5.5 0 0 0 19 21v-8.5a.5.5 0 0 0-1 0v7.485l-5.195-4.012a.5.5 0 0 0-.61 0L7 19.985z"></path></svg></a></span></div></div></div><div class="ob l jh"><div class="bm" aria-hidden="false" aria-describedby="postFooterSocialMenu" aria-labelledby="postFooterSocialMenu"><div><div class="bm" aria-hidden="false"><button aria-controls="postFooterSocialMenu" aria-expanded="false" aria-label="Share Post" data-testid="footerSocialShareButton" class="af fk ah ai aj ak al md an ao ap ex me mf lu mg"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M15.218 4.931a.4.4 0 0 1-.118.132l.012.006a.45.45 0 0 1-.292.074.5.5 0 0 1-.3-.13l-2.02-2.02v7.07c0 .28-.23.5-.5.5s-.5-.22-.5-.5v-7.04l-2 2a.45.45 0 0 1-.57.04h-.02a.4.4 0 0 1-.16-.3.4.4 0 0 1 .1-.32l2.8-2.8a.5.5 0 0 1 .7 0l2.8 2.79a.42.42 0 0 1 .068.498m-.106.138.008.004v-.01zM16 7.063h1.5a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-11c-1.1 0-2-.9-2-2v-10a2 2 0 0 1 2-2H8a.5.5 0 0 1 .35.15.5.5 0 0 1 .15.35.5.5 0 0 1-.15.35.5.5 0 0 1-.35.15H6.4c-.5 0-.9.4-.9.9v10.2a.9.9 0 0 0 .9.9h11.2c.5 0 .9-.4.9-.9v-10.2c0-.5-.4-.9-.9-.9H16a.5.5 0 0 1 0-1" clip-rule="evenodd"></path></svg></button></div></div></div></div></div></div></div></div></div></footer><div class="rb rc rd re rf l"><div class="ab cb"><div class="ci bh fz ga gb gc"><div class="rg bh r rh"></div><div class="ab ri rj rk jj ji"><div class="rl rm rn ro rp rq rr rs rt ru ab cp"><div class="h k"><a tabindex="0" rel="noopener follow" href="/@donturner?source=post_page---post_author_info--ed10782f9c64--------------------------------"><div class="l fj"><img alt="Don Turner" class="l fd by ir iq cx" src="https://miro.medium.com/v2/resize:fill:96:96/1*F2tQfS9RL-Br9vcm_ih_NQ.png" width="48" height="48" loading="lazy"/><div class="fr by l ir iq fs n ay rv"></div></div></a></div><div class="j i d"><a tabindex="0" rel="noopener follow" href="/@donturner?source=post_page---post_author_info--ed10782f9c64--------------------------------"><div class="l fj"><img alt="Don Turner" class="l fd by rw rx cx" src="https://miro.medium.com/v2/resize:fill:128:128/1*F2tQfS9RL-Br9vcm_ih_NQ.png" width="64" height="64" loading="lazy"/><div class="fr by l rw rx fs n ay rv"></div></div></a></div><div class="j i d ry jh"><div class="ab"><span><button class="bf b bg z rz qj sa sb sc sd se ev ew sf sg sh fa fb fc fd bm fe ff">Follow</button></span></div></div></div><div class="ab co si"><div class="sj sk sl sm sn l"><a class="af ag ah aj ak al am an ao ap aq ar as at ab q" rel="noopener follow" href="/@donturner?source=post_page---post_author_info--ed10782f9c64--------------------------------"><h2 class="pw-author-name bf sp sq sr ss st su sv ng sw sx nk sy sz no ta tb bk"><span class="gn so">Written by <!-- -->Don Turner</span></h2></a><div class="qh ab ip"><div class="l jh"><span class="pw-follower-count bf b bg z du"><a class="af ag ah ai aj ak al am an ao ap aq ar ja" rel="noopener follow" href="/@donturner/followers?source=post_page---post_author_info--ed10782f9c64--------------------------------">544 Followers</a></span></div><div class="bf b bg z du ab qd"><span class="jb l" aria-hidden="true"><span class="bf b bg z du">·</span></span><a class="af ag ah ai aj ak al am an ao ap aq ar ja" rel="noopener follow" href="/@donturner/following?source=post_page---post_author_info--ed10782f9c64--------------------------------">150 Following</a></div></div><div class="tc l"><p class="bf b bg z bk"><span class="gn">Android Developer Relations Engineer @ Google</span></p></div></div></div><div class="h k"><div class="ab"><span><button class="bf b bg z rz qj sa sb sc sd se ev ew sf sg sh fa fb fc fd bm fe ff">Follow</button></span></div></div></div></div></div></div><div class="td te tf tg th l"><div class="rg bh r td te ti tj tk"></div><div class="ab cb"><div class="ci bh fz ga gb gc"><div class="ab q cp"><h2 class="bf sp of oh oi oj ol om on op oq or ot ou ov ox oy bk">Responses (<!-- -->2<!-- -->)</h2><div class="ab tl"><div><div class="bm" aria-hidden="false"><a class="tm tn" href="https://policy.medium.com/medium-rules-30e5502c4eb4?source=post_page---post_responses--ed10782f9c64--------------------------------" rel="noopener follow" target="_blank"><svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 25 25"><path fill-rule="evenodd" d="M11.987 5.036a.754.754 0 0 1 .914-.01c.972.721 1.767 1.218 2.6 1.543.828.322 1.719.485 2.887.505a.755.755 0 0 1 .741.757c-.018 3.623-.43 6.256-1.449 8.21-1.034 1.984-2.662 3.209-4.966 4.083a.75.75 0 0 1-.537-.003c-2.243-.874-3.858-2.095-4.897-4.074-1.024-1.951-1.457-4.583-1.476-8.216a.755.755 0 0 1 .741-.757c1.195-.02 2.1-.182 2.923-.503.827-.322 1.6-.815 2.519-1.535m.468.903c-.897.69-1.717 1.21-2.623 1.564-.898.35-1.856.527-3.026.565.037 3.45.469 5.817 1.36 7.515.884 1.684 2.25 2.762 4.284 3.571 2.092-.81 3.465-1.89 4.344-3.575.886-1.698 1.299-4.065 1.334-7.512-1.149-.039-2.091-.217-2.99-.567-.906-.353-1.745-.873-2.683-1.561m-.009 9.155a2.672 2.672 0 1 0 0-5.344 2.672 2.672 0 0 0 0 5.344m0 1a3.672 3.672 0 1 0 0-7.344 3.672 3.672 0 0 0 0 7.344m-1.813-3.777.525-.526.916.917 1.623-1.625.526.526-2.149 2.152z" clip-rule="evenodd"></path></svg></a></div></div></div></div><div class="nu l"><button class="bf b bg z bk qj to tp tq lw lt se ev ew ex tr ts tt fa tu tv tw tx ty fb fc fd bm fe ff">See all responses</button></div></div></div></div><div class="tz ua ub uc ud l bx"><div class="h k j"><div class="rg bh ue uf"></div><div class="ab cb"><div class="ci bh fz ga gb gc"><div class="ug ab kt jk"><div class="uh ui l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://help.medium.com/hc/en-us?source=post_page-----ed10782f9c64--------------------------------" rel="noopener follow"><p class="bf b dv z du">Help</p></a></div><div class="uh ui l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://medium.statuspage.io/?source=post_page-----ed10782f9c64--------------------------------" rel="noopener follow"><p class="bf b dv z du">Status</p></a></div><div class="uh ui l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" rel="noopener follow" href="/about?autoplay=1&amp;source=post_page-----ed10782f9c64--------------------------------"><p class="bf b dv z du">About</p></a></div><div class="uh ui l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" rel="noopener follow" href="/jobs-at-medium/work-at-medium-959d1a85284e?source=post_page-----ed10782f9c64--------------------------------"><p class="bf b dv z du">Careers</p></a></div><div class="uh ui l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="pressinquiries@medium.com?source=post_page-----ed10782f9c64--------------------------------" rel="noopener follow"><p class="bf b dv z du">Press</p></a></div><div class="uh ui l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://blog.medium.com/?source=post_page-----ed10782f9c64--------------------------------" rel="noopener follow"><p class="bf b dv z du">Blog</p></a></div><div class="uh ui l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://policy.medium.com/medium-privacy-policy-f03bf92035c9?source=post_page-----ed10782f9c64--------------------------------" rel="noopener follow"><p class="bf b dv z du">Privacy</p></a></div><div class="uh ui l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://policy.medium.com/medium-terms-of-service-9db0094a1e0f?source=post_page-----ed10782f9c64--------------------------------" rel="noopener follow"><p class="bf b dv z du">Terms</p></a></div><div class="uh ui l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://speechify.com/medium?source=post_page-----ed10782f9c64--------------------------------" rel="noopener follow"><p class="bf b dv z du">Text to speech</p></a></div><div class="uh l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" rel="noopener follow" href="/business?source=post_page-----ed10782f9c64--------------------------------"><p class="bf b dv z du">Teams</p></a></div></div></div></div></div></div></div></div></div></div><script>window.__BUILD_ID__="main-20241122-185319-7bcdc08639"</script><script>window.__GRAPHQL_URI__ = "https://medium.com/_/graphql"</script><script>window.__PRELOADED_STATE__ = {"algolia":{"queries":{}},"cache":{"experimentGroupSet":true,"reason":"","group":"enabled","tags":["group-edgeCachePosts","post-ed10782f9c64","user-7f5a2cb6598e"],"serverVariantState":"44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a","middlewareEnabled":true,"cacheStatus":"DYNAMIC","shouldUseCache":true,"vary":[],"lohpSummerUpsellEnabled":false,"publicationHierarchyEnabledWeb":false,"postBottomResponsesEnabled":false},"client":{"hydrated":false,"isUs":false,"isNativeMedium":false,"isSafariMobile":false,"isSafari":false,"isFirefox":false,"routingEntity":{"type":"DEFAULT","explicit":false},"viewerIsBot":false},"debug":{"requestId":"463a277a-dfbc-4d8d-8a65-b43ae86ab0e2","hybridDevServices":[],"originalSpanCarrier":{"traceparent":"00-25c3ec4d960095ebd81a168b18d83063-91cfb36c2ef5a404-01"}},"multiVote":{"clapsPerPost":{}},"navigation":{"branch":{"show":null,"hasRendered":null,"blockedByCTA":false},"hideGoogleOneTap":false,"hasRenderedAlternateUserBanner":null,"currentLocation":"https:\u002F\u002Fmedium.com\u002F@donturner\u002Fdebugging-audio-glitches-on-android-ed10782f9c64","host":"medium.com","hostname":"medium.com","referrer":"","hasSetReferrer":false,"susiModal":{"step":null,"operation":"register"},"postRead":false,"partnerProgram":{"selectedCountryCode":null},"queryString":"","currentHash":""},"config":{"nodeEnv":"production","version":"main-20241122-185319-7bcdc08639","target":"production","productName":"Medium","publicUrl":"https:\u002F\u002Fcdn-client.medium.com\u002Flite","authDomain":"medium.com","authGoogleClientId":"216296035834-k1k6qe060s2tp2a2jam4ljdcms00sttg.apps.googleusercontent.com","favicon":"production","glyphUrl":"https:\u002F\u002Fglyph.medium.com","branchKey":"key_live_ofxXr2qTrrU9NqURK8ZwEhknBxiI6KBm","algolia":{"appId":"MQ57UUUQZ2","apiKeySearch":"394474ced050e3911ae2249ecc774921","indexPrefix":"medium_","host":"-dsn.algolia.net"},"recaptchaKey":"6Lfc37IUAAAAAKGGtC6rLS13R1Hrw_BqADfS1LRk","recaptcha3Key":"6Lf8R9wUAAAAABMI_85Wb8melS7Zj6ziuf99Yot5","recaptchaEnterpriseKeyId":"6Le-uGgpAAAAAPprRaokM8AKthQ9KNGdoxaGUvVp","datadog":{"applicationId":"6702d87d-a7e0-42fe-bbcb-95b469547ea0","clientToken":"pub853ea8d17ad6821d9f8f11861d23dfed","rumToken":"pubf9cc52896502b9413b68ba36fc0c7162","context":{"deployment":{"target":"production","tag":"main-20241122-185319-7bcdc08639","commit":"7bcdc08639c179dc5172558201a3fd3abc1b5db6"}},"datacenter":"us"},"googleAnalyticsCode":"G-7JY7T788PK","googlePay":{"apiVersion":"2","apiVersionMinor":"0","merchantId":"BCR2DN6TV7EMTGBM","merchantName":"Medium","instanceMerchantId":"13685562959212738550"},"applePay":{"version":3},"signInWallCustomDomainCollectionIds":["3a8144eabfe3","336d898217ee","61061eb0c96b","138adf9c44c","819cc2aaeee0"],"mediumMastodonDomainName":"me.dm","mediumOwnedAndOperatedCollectionIds":["8a9336e5bb4","b7e45b22fec3","193b68bd4fba","8d6b8a439e32","54c98c43354d","3f6ecf56618","d944778ce714","92d2092dc598","ae2a65f35510","1285ba81cada","544c7006046e","fc8964313712","40187e704f1c","88d9857e584e","7b6769f2748b","bcc38c8f6edf","cef6983b292","cb8577c9149e","444d13b52878","713d7dbc99b0","ef8e90590e66","191186aaafa0","55760f21cdc5","9dc80918cc93","bdc4052bbdba","8ccfed20cbb2"],"tierOneDomains":["medium.com","thebolditalic.com","arcdigital.media","towardsdatascience.com","uxdesign.cc","codeburst.io","psiloveyou.xyz","writingcooperative.com","entrepreneurshandbook.co","prototypr.io","betterhumans.coach.me","theascent.pub"],"topicsToFollow":["d61cf867d93f","8a146bc21b28","1eca0103fff3","4d562ee63426","aef1078a3ef5","e15e46793f8d","6158eb913466","55f1c20aba7a","3d18b94f6858","4861fee224fd","63c6f1f93ee","1d98b3a9a871","decb52b64abf","ae5d4995e225","830cded25262"],"topicToTagMappings":{"accessibility":"accessibility","addiction":"addiction","android-development":"android-development","art":"art","artificial-intelligence":"artificial-intelligence","astrology":"astrology","basic-income":"basic-income","beauty":"beauty","biotech":"biotech","blockchain":"blockchain","books":"books","business":"business","cannabis":"cannabis","cities":"cities","climate-change":"climate-change","comics":"comics","coronavirus":"coronavirus","creativity":"creativity","cryptocurrency":"cryptocurrency","culture":"culture","cybersecurity":"cybersecurity","data-science":"data-science","design":"design","digital-life":"digital-life","disability":"disability","economy":"economy","education":"education","equality":"equality","family":"family","feminism":"feminism","fiction":"fiction","film":"film","fitness":"fitness","food":"food","freelancing":"freelancing","future":"future","gadgets":"gadgets","gaming":"gaming","gun-control":"gun-control","health":"health","history":"history","humor":"humor","immigration":"immigration","ios-development":"ios-development","javascript":"javascript","justice":"justice","language":"language","leadership":"leadership","lgbtqia":"lgbtqia","lifestyle":"lifestyle","machine-learning":"machine-learning","makers":"makers","marketing":"marketing","math":"math","media":"media","mental-health":"mental-health","mindfulness":"mindfulness","money":"money","music":"music","neuroscience":"neuroscience","nonfiction":"nonfiction","outdoors":"outdoors","parenting":"parenting","pets":"pets","philosophy":"philosophy","photography":"photography","podcasts":"podcast","poetry":"poetry","politics":"politics","privacy":"privacy","product-management":"product-management","productivity":"productivity","programming":"programming","psychedelics":"psychedelics","psychology":"psychology","race":"race","relationships":"relationships","religion":"religion","remote-work":"remote-work","san-francisco":"san-francisco","science":"science","self":"self","self-driving-cars":"self-driving-cars","sexuality":"sexuality","social-media":"social-media","society":"society","software-engineering":"software-engineering","space":"space","spirituality":"spirituality","sports":"sports","startups":"startup","style":"style","technology":"technology","transportation":"transportation","travel":"travel","true-crime":"true-crime","tv":"tv","ux":"ux","venture-capital":"venture-capital","visual-design":"visual-design","work":"work","world":"world","writing":"writing"},"defaultImages":{"avatar":{"imageId":"1*dmbNkD5D-u45r44go_cf0g.png","height":150,"width":150},"orgLogo":{"imageId":"7*V1_7XP4snlmqrc_0Njontw.png","height":110,"width":500},"postLogo":{"imageId":"bd978bb536350a710e8efb012513429cabdc4c28700604261aeda246d0f980b7","height":810,"width":1440},"postPreviewImage":{"imageId":"1*hn4v1tCaJy7cWMyb0bpNpQ.png","height":386,"width":579}},"collectionStructuredData":{"8d6b8a439e32":{"name":"Elemental","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fcdn-images-1.medium.com\u002Fmax\u002F980\u002F1*9ygdqoKprhwuTVKUM0DLPA@2x.png","width":980,"height":159}}},"3f6ecf56618":{"name":"Forge","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fcdn-images-1.medium.com\u002Fmax\u002F596\u002F1*uULpIlImcO5TDuBZ6lm7Lg@2x.png","width":596,"height":183}}},"ae2a65f35510":{"name":"GEN","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fmiro.medium.com\u002Fmax\u002F264\u002F1*RdVZMdvfV3YiZTw6mX7yWA.png","width":264,"height":140}}},"88d9857e584e":{"name":"LEVEL","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fmiro.medium.com\u002Fmax\u002F540\u002F1*JqYMhNX6KNNb2UlqGqO2WQ.png","width":540,"height":108}}},"7b6769f2748b":{"name":"Marker","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fcdn-images-1.medium.com\u002Fmax\u002F383\u002F1*haCUs0wF6TgOOvfoY-jEoQ@2x.png","width":383,"height":92}}},"444d13b52878":{"name":"OneZero","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fmiro.medium.com\u002Fmax\u002F540\u002F1*cw32fIqCbRWzwJaoQw6BUg.png","width":540,"height":123}}},"8ccfed20cbb2":{"name":"Zora","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fmiro.medium.com\u002Fmax\u002F540\u002F1*tZUQqRcCCZDXjjiZ4bDvgQ.png","width":540,"height":106}}}},"embeddedPostIds":{"coronavirus":"cd3010f9d81f"},"sharedCdcMessaging":{"COVID_APPLICABLE_TAG_SLUGS":[],"COVID_APPLICABLE_TOPIC_NAMES":[],"COVID_APPLICABLE_TOPIC_NAMES_FOR_TOPIC_PAGE":[],"COVID_MESSAGES":{"tierA":{"text":"For more information on the novel coronavirus and Covid-19, visit cdc.gov.","markups":[{"start":66,"end":73,"href":"https:\u002F\u002Fwww.cdc.gov\u002Fcoronavirus\u002F2019-nCoV"}]},"tierB":{"text":"Anyone can publish on Medium per our Policies, but we don’t fact-check every story. For more info about the coronavirus, see cdc.gov.","markups":[{"start":37,"end":45,"href":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Fcategories\u002F201931128-Policies-Safety"},{"start":125,"end":132,"href":"https:\u002F\u002Fwww.cdc.gov\u002Fcoronavirus\u002F2019-nCoV"}]},"paywall":{"text":"This article has been made free for everyone, thanks to Medium Members. For more information on the novel coronavirus and Covid-19, visit cdc.gov.","markups":[{"start":56,"end":70,"href":"https:\u002F\u002Fmedium.com\u002Fmembership"},{"start":138,"end":145,"href":"https:\u002F\u002Fwww.cdc.gov\u002Fcoronavirus\u002F2019-nCoV"}]},"unbound":{"text":"This article is free for everyone, thanks to Medium Members. For more information on the novel coronavirus and Covid-19, visit cdc.gov.","markups":[{"start":45,"end":59,"href":"https:\u002F\u002Fmedium.com\u002Fmembership"},{"start":127,"end":134,"href":"https:\u002F\u002Fwww.cdc.gov\u002Fcoronavirus\u002F2019-nCoV"}]}},"COVID_BANNER_POST_ID_OVERRIDE_WHITELIST":["3b31a67bff4a"]},"sharedVoteMessaging":{"TAGS":["politics","election-2020","government","us-politics","election","2020-presidential-race","trump","donald-trump","democrats","republicans","congress","republican-party","democratic-party","biden","joe-biden","maga"],"TOPICS":["politics","election"],"MESSAGE":{"text":"Find out more about the U.S. election results here.","markups":[{"start":46,"end":50,"href":"https:\u002F\u002Fcookpolitical.com\u002F2020-national-popular-vote-tracker"}]},"EXCLUDE_POSTS":["397ef29e3ca5"]},"embedPostRules":[],"recircOptions":{"v1":{"limit":3},"v2":{"limit":8}},"braintreeClientKey":"production_zjkj96jm_m56f8fqpf7ngnrd4","braintree":{"enabled":true,"merchantId":"m56f8fqpf7ngnrd4","merchantAccountId":{"usd":"AMediumCorporation_instant","eur":"amediumcorporation_EUR","cad":"amediumcorporation_CAD"},"publicKey":"ds2nn34bg2z7j5gd","braintreeEnvironment":"production","dashboardUrl":"https:\u002F\u002Fwww.braintreegateway.com\u002Fmerchants","gracePeriodDurationInDays":14,"mediumMembershipPlanId":{"monthly":"ce105f8c57a3","monthlyV2":"e8a5e126-792b-4ee6-8fba-d574c1b02fc5","monthlyWithTrial":"d5ee3dbe3db8","monthlyPremium":"fa741a9b47a2","yearly":"a40ad4a43185","yearlyV2":"3815d7d6-b8ca-4224-9b8c-182f9047866e","yearlyStaff":"d74fb811198a","yearlyWithTrial":"b3bc7350e5c7","yearlyPremium":"e21bd2c12166","monthlyOneYearFree":"e6c0637a-2bad-4171-ab4f-3c268633d83c","monthly25PercentOffFirstYear":"235ecc62-0cdb-49ae-9378-726cd21c504b","monthly20PercentOffFirstYear":"ba518864-9c13-4a99-91ca-411bf0cac756","monthly15PercentOffFirstYear":"594c029b-9f89-43d5-88f8-8173af4e070e","monthly10PercentOffFirstYear":"c6c7bc9a-40f2-4b51-8126-e28511d5bdb0","monthlyForStudents":"629ebe51-da7d-41fd-8293-34cd2f2030a8","yearlyOneYearFree":"78ba7be9-0d9f-4ece-aa3e-b54b826f2bf1","yearly25PercentOffFirstYear":"2dbb010d-bb8f-4eeb-ad5c-a08509f42d34","yearly20PercentOffFirstYear":"47565488-435b-47f8-bf93-40d5fbe0ebc8","yearly15PercentOffFirstYear":"8259809b-0881-47d9-acf7-6c001c7f720f","yearly10PercentOffFirstYear":"9dd694fb-96e1-472c-8d9e-3c868d5c1506","yearlyForStudents":"e29345ef-ab1c-4234-95c5-70e50fe6bc23","monthlyCad":"p52orjkaceei","yearlyCad":"h4q9g2up9ktt"},"braintreeDiscountId":{"oneMonthFree":"MONTHS_FREE_01","threeMonthsFree":"MONTHS_FREE_03","sixMonthsFree":"MONTHS_FREE_06","fiftyPercentOffOneYear":"FIFTY_PERCENT_OFF_ONE_YEAR"},"3DSecureVersion":"2","defaultCurrency":"usd","providerPlanIdCurrency":{"4ycw":"usd","rz3b":"usd","3kqm":"usd","jzw6":"usd","c2q2":"usd","nnsw":"usd","q8qw":"usd","d9y6":"usd","fx7w":"cad","nwf2":"cad"}},"paypalClientId":"AXj1G4fotC2GE8KzWX9mSxCH1wmPE3nJglf4Z2ig_amnhvlMVX87otaq58niAg9iuLktVNF_1WCMnN7v","paypal":{"host":"https:\u002F\u002Fapi.paypal.com:443","clientMode":"production","serverMode":"live","webhookId":"4G466076A0294510S","monthlyPlan":{"planId":"P-9WR0658853113943TMU5FDQA","name":"Medium Membership (Monthly) with setup fee","description":"Unlimited access to the best and brightest stories on Medium. Membership billed monthly."},"yearlyPlan":{"planId":"P-7N8963881P8875835MU5JOPQ","name":"Medium Membership (Annual) with setup fee","description":"Unlimited access to the best and brightest stories on Medium. Membership billed annually."},"oneYearGift":{"name":"Medium Membership (1 Year, Digital Gift Code)","description":"Unlimited access to the best and brightest stories on Medium. Gift codes can be redeemed at medium.com\u002Fredeem.","price":"50.00","currency":"USD","sku":"membership-gift-1-yr"},"oldMonthlyPlan":{"planId":"P-96U02458LM656772MJZUVH2Y","name":"Medium Membership (Monthly)","description":"Unlimited access to the best and brightest stories on Medium. Membership billed monthly."},"oldYearlyPlan":{"planId":"P-59P80963JF186412JJZU3SMI","name":"Medium Membership (Annual)","description":"Unlimited access to the best and brightest stories on Medium. Membership billed annually."},"monthlyPlanWithTrial":{"planId":"P-66C21969LR178604GJPVKUKY","name":"Medium Membership (Monthly) with setup fee","description":"Unlimited access to the best and brightest stories on Medium. Membership billed monthly."},"yearlyPlanWithTrial":{"planId":"P-6XW32684EX226940VKCT2MFA","name":"Medium Membership (Annual) with setup fee","description":"Unlimited access to the best and brightest stories on Medium. Membership billed annually."},"oldMonthlyPlanNoSetupFee":{"planId":"P-4N046520HR188054PCJC7LJI","name":"Medium Membership (Monthly)","description":"Unlimited access to the best and brightest stories on Medium. Membership billed monthly."},"oldYearlyPlanNoSetupFee":{"planId":"P-7A4913502Y5181304CJEJMXQ","name":"Medium Membership (Annual)","description":"Unlimited access to the best and brightest stories on Medium. Membership billed annually."},"sdkUrl":"https:\u002F\u002Fwww.paypal.com\u002Fsdk\u002Fjs"},"stripePublishableKey":"pk_live_7FReX44VnNIInZwrIIx6ghjl","log":{"json":true,"level":"info"},"imageUploadMaxSizeMb":25,"staffPicks":{"title":"Staff Picks","catalogId":"c7bc6e1ee00f"}},"session":{"xsrf":""}}</script><script>window.__APOLLO_STATE__ = {"ROOT_QUERY":{"__typename":"Query","viewer":null,"collectionByDomainOrSlug({\"domainOrSlug\":\"medium.com\"})":null,"postResult({\"id\":\"ed10782f9c64\"})":{"__ref":"Post:ed10782f9c64"}},"LinkedAccounts:7f5a2cb6598e":{"__typename":"LinkedAccounts","mastodon":null,"id":"7f5a2cb6598e"},"UserViewerEdge:userId:7f5a2cb6598e-viewerId:lo_1a4d670e6800":{"__typename":"UserViewerEdge","id":"userId:7f5a2cb6598e-viewerId:lo_1a4d670e6800","isFollowing":false,"isUser":false,"isMuting":false},"NewsletterV3:685586e136c0":{"__typename":"NewsletterV3","id":"685586e136c0","type":"NEWSLETTER_TYPE_AUTHOR","slug":"7f5a2cb6598e","name":"7f5a2cb6598e","collection":null,"user":{"__ref":"User:7f5a2cb6598e"}},"User:7f5a2cb6598e":{"__typename":"User","id":"7f5a2cb6598e","name":"Don Turner","username":"donturner","newsletterV3":{"__ref":"NewsletterV3:685586e136c0"},"linkedAccounts":{"__ref":"LinkedAccounts:7f5a2cb6598e"},"isSuspended":false,"imageId":"1*F2tQfS9RL-Br9vcm_ih_NQ.png","mediumMemberAt":1703442993000,"verifications":{"__typename":"VerifiedInfo","isBookAuthor":false},"socialStats":{"__typename":"SocialStats","followerCount":544,"followingCount":140,"collectionFollowingCount":10},"customDomainState":null,"hasSubdomain":false,"bio":"Android Developer Relations Engineer @ Google","isPartnerProgramEnrolled":false,"viewerEdge":{"__ref":"UserViewerEdge:userId:7f5a2cb6598e-viewerId:lo_1a4d670e6800"},"viewerIsUser":false,"postSubscribeMembershipUpsellShownAt":0,"membership":{"__ref":"Membership:5761d0c988f6"},"allowNotes":true,"twitterScreenName":"donturner"},"Membership:5761d0c988f6":{"__typename":"Membership","tier":"MEMBER","id":"5761d0c988f6"},"ImageMetadata:1*KnhUyWDY_ehL_lEijOI8-w.png":{"__typename":"ImageMetadata","id":"1*KnhUyWDY_ehL_lEijOI8-w.png","originalHeight":377,"originalWidth":527,"focusPercentX":null,"focusPercentY":null,"alt":null},"Paragraph:5528d839de68_0":{"__typename":"Paragraph","id":"5528d839de68_0","name":"8d6f","type":"IMG","href":null,"layout":"INSET_CENTER","metadata":{"__ref":"ImageMetadata:1*KnhUyWDY_ehL_lEijOI8-w.png"},"text":"Example audio glitch","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_1":{"__typename":"Paragraph","id":"5528d839de68_1","name":"0102","type":"H3","href":null,"layout":null,"metadata":null,"text":"Debugging audio glitches on Android","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_2":{"__typename":"Paragraph","id":"5528d839de68_2","name":"5273","type":"P","href":null,"layout":null,"metadata":null,"text":"In this article I will explain how to identify the causes of audio glitches in your app using systrace and the Android Studio profiler.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_3":{"__typename":"Paragraph","id":"5528d839de68_3","name":"6ad5","type":"P","href":null,"layout":null,"metadata":null,"text":"Background: I wanted to build a one hundred oscillator synthesizer app (inspired by this amazing project from LOOK MUM NO COMPUTER). A perfectly reasonable thing to do, right?","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"A","start":84,"end":130,"href":"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=q45FHZLVz2U","anchorType":"LINK","userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_4":{"__typename":"Paragraph","id":"5528d839de68_4","name":"e6c5","type":"P","href":null,"layout":null,"metadata":null,"text":"I had already built an app which would use a single oscillator to produce a sine wave. I updated it to use one hundred oscillators and then summed the outputs of each one.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"A","start":6,"end":26,"href":"https:\u002F\u002Fgithub.com\u002Fgoogle\u002Foboe\u002Ftree\u002Fmaster\u002Fsamples\u002Fhello-oboe","anchorType":"LINK","userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_5":{"__typename":"Paragraph","id":"5528d839de68_5","name":"4725","type":"P","href":null,"layout":null,"metadata":null,"text":"The result: horrible clicks and pops in the final audio aka audio glitches 😩","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":0,"end":10,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"STRONG","start":60,"end":74,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_6":{"__typename":"Paragraph","id":"5528d839de68_6","name":"933b","type":"P","href":null,"layout":null,"metadata":null,"text":"The problem is, each oscillator uses a few computations to generate its data, and with one hundred of them my CPU usage was enough to push me over my audio callback deadline.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"A","start":150,"end":164,"href":"https:\u002F\u002Fgithub.com\u002Fgoogle\u002Foboe\u002Fblob\u002Fmaster\u002FFullGuide.md#using-a-high-priority-callback","anchorType":"LINK","userId":null,"linkMetadata":null},{"__typename":"Markup","type":"STRONG","start":4,"end":11,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_7":{"__typename":"Paragraph","id":"5528d839de68_7","name":"d397","type":"P","href":null,"layout":null,"metadata":null,"text":"In my case, each callback would request 96 frames of audio data for a 48kHz audio stream. This means I had 96\u002F48000=0.002s or 2 milliseconds to generate 96 frames of data. So my app was probably taking longer than 2 milliseconds to generate those 96 frames, at least some of the time.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_8":{"__typename":"Paragraph","id":"5528d839de68_8","name":"6f1b","type":"P","href":null,"layout":null,"metadata":null,"text":"Well, that was my hypothesis, but how could I know for sure?","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_9":{"__typename":"Paragraph","id":"5528d839de68_9","name":"0c8e","type":"H3","href":null,"layout":null,"metadata":null,"text":"Measuring callback times","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_10":{"__typename":"Paragraph","id":"5528d839de68_10","name":"1b01","type":"P","href":null,"layout":null,"metadata":null,"text":"Enter systrace. Systrace is my #1 go to tool for debugging audio problems. It shows exactly what’s going on across processes and CPU cores. The key is knowing how to use it.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"A","start":6,"end":14,"href":"https:\u002F\u002Fdeveloper.android.com\u002Fstudio\u002Fcommand-line\u002Fsystrace","anchorType":"LINK","userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_11":{"__typename":"Paragraph","id":"5528d839de68_11","name":"b38b","type":"P","href":null,"layout":null,"metadata":null,"text":"Here’s the command I use:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_12":{"__typename":"Paragraph","id":"5528d839de68_12","name":"4429","type":"P","href":null,"layout":null,"metadata":null,"text":"systrace.py --time=5 -o trace.html -a com.example.myapp audio sched freq","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":0,"end":72,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_13":{"__typename":"Paragraph","id":"5528d839de68_13","name":"5eca","type":"P","href":null,"layout":null,"metadata":null,"text":"This will run a trace for 5 seconds, putting the output into trace.html. The trace will include audio buffer status, CPU frequency and CPU scheduling information.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_14":{"__typename":"Paragraph","id":"5528d839de68_14","name":"b68f","type":"P","href":null,"layout":null,"metadata":null,"text":"Here’s the trace:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"ImageMetadata:1*jE49l8oKvfYZI2u8bRZ91g.png":{"__typename":"ImageMetadata","id":"1*jE49l8oKvfYZI2u8bRZ91g.png","originalHeight":735,"originalWidth":1509,"focusPercentX":null,"focusPercentY":null,"alt":null},"Paragraph:5528d839de68_15":{"__typename":"Paragraph","id":"5528d839de68_15","name":"5fe1","type":"IMG","href":null,"layout":"INSET_CENTER","metadata":{"__ref":"ImageMetadata:1*jE49l8oKvfYZI2u8bRZ91g.png"},"text":"systrace from audio app","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_16":{"__typename":"Paragraph","id":"5528d839de68_16","name":"4acc","type":"P","href":null,"layout":null,"metadata":null,"text":"Again, knowing what to look for is the key. The thing I’m most interested in is the audio buffer status. This is shown in the aaRdy line for my app, which presumably stands for AAudio ready and shows the number of frames which are ready to be read from the AAudio internal buffer.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":126,"end":131,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"A","start":257,"end":263,"href":"https:\u002F\u002Fdeveloper.android.com\u002Fndk\u002Fguides\u002Faudio\u002Faaudio\u002Faaudio","anchorType":"LINK","userId":null,"linkMetadata":null},{"__typename":"Markup","type":"STRONG","start":84,"end":103,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"EM","start":177,"end":189,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_17":{"__typename":"Paragraph","id":"5528d839de68_17","name":"a090","type":"P","href":null,"layout":null,"metadata":null,"text":"Incidentally, I’m using Oboe for my audio library which will use AAudio on devices which support it and OpenSL ES on everything else. If OpenSL ES was being used I would look for a row named fRdy.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":191,"end":195,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"A","start":24,"end":28,"href":"https:\u002F\u002Fgithub.com\u002Fgoogle\u002Foboe\u002Fblob\u002Fmaster\u002FFullGuide.md#using-a-high-priority-callback","anchorType":"LINK","userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_18":{"__typename":"Paragraph","id":"5528d839de68_18","name":"e6b7","type":"P","href":null,"layout":null,"metadata":null,"text":"Let’s zoom in on the aaRdy line:","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":21,"end":26,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"ImageMetadata:1*UCmF6BqiSuK_jFdiAPW-rQ.png":{"__typename":"ImageMetadata","id":"1*UCmF6BqiSuK_jFdiAPW-rQ.png","originalHeight":138,"originalWidth":593,"focusPercentX":null,"focusPercentY":null,"alt":null},"Paragraph:5528d839de68_19":{"__typename":"Paragraph","id":"5528d839de68_19","name":"0d6b","type":"IMG","href":null,"layout":"INSET_CENTER","metadata":{"__ref":"ImageMetadata:1*UCmF6BqiSuK_jFdiAPW-rQ.png"},"text":"","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_20":{"__typename":"Paragraph","id":"5528d839de68_20","name":"72d1","type":"P","href":null,"layout":null,"metadata":null,"text":"By clicking on any of the individual slices we can see the number of audio frames which are in the buffer at that time. In the slice above there are 192 frames. I’m using a buffer size of 192 frames (which is twice the minimum buffer size and is usually a safe default), so the buffer is currently full.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_21":{"__typename":"Paragraph","id":"5528d839de68_21","name":"63b2","type":"P","href":null,"layout":null,"metadata":null,"text":"But then the buffer starts empty, first dropping to 96 frames, then….oh dear…to zero! At zero we are guaranteed to have an audio glitch because there’s no data in the buffer.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_22":{"__typename":"Paragraph","id":"5528d839de68_22","name":"9a70","type":"P","href":null,"layout":null,"metadata":null,"text":"Now, we could look at everything else that was going on in the system at this time and it’s likely we’ll see a CPU core migration, some other process come in and stomp all over our audio process or a CPU frequency drop causing a delay in execution of our oscillator’s code.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_23":{"__typename":"Paragraph","id":"5528d839de68_23","name":"fb11","type":"P","href":null,"layout":null,"metadata":null,"text":"But we can’t really control any of that without jumping through some fairly dangerous hoops (setting thread affinity, CPU load stabilization etc).","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"A","start":69,"end":91,"href":"https:\u002F\u002Fgithub.com\u002Fgooglesamples\u002Fandroid-audio-high-performance\u002Fblob\u002Fmaster\u002FSimpleSynth\u002Fapp\u002Fsrc\u002Fmain\u002Fcpp\u002Faudio_player.cc#L289","anchorType":"LINK","userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_24":{"__typename":"Paragraph","id":"5528d839de68_24","name":"0261","type":"P","href":null,"layout":null,"metadata":null,"text":"Instead, let’s take a look at our own code and see what’s taking so long to execute. For this we can use the wonderful new native CPU profiler in Android Studio. Here’s the output from a Sampled (Native) trace, in the Flame Chart view:","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"A","start":119,"end":142,"href":"https:\u002F\u002Fdeveloper.android.com\u002Fstudio\u002Fprofile\u002Fcpu-profiler","anchorType":"LINK","userId":null,"linkMetadata":null},{"__typename":"Markup","type":"EM","start":187,"end":203,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"EM","start":218,"end":229,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"ImageMetadata:1*MEH3LKxZMSfGpp-8jj7O1g.png":{"__typename":"ImageMetadata","id":"1*MEH3LKxZMSfGpp-8jj7O1g.png","originalHeight":244,"originalWidth":1940,"focusPercentX":null,"focusPercentY":null,"alt":null},"Paragraph:5528d839de68_25":{"__typename":"Paragraph","id":"5528d839de68_25","name":"87d8","type":"IMG","href":null,"layout":"INSET_CENTER","metadata":{"__ref":"ImageMetadata:1*MEH3LKxZMSfGpp-8jj7O1g.png"},"text":"","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_26":{"__typename":"Paragraph","id":"5528d839de68_26","name":"4a65","type":"P","href":null,"layout":null,"metadata":null,"text":"Well, look at that, my app is spending an awful lot of time in sinf, a method calculating sine values. This is puzzling because sinf isn’t exactly computationally expensive and whilst 100 oscillators might sound like a lot, any modern CPU should be able to handle this load without breaking a sweat.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":30,"end":67,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_27":{"__typename":"Paragraph","id":"5528d839de68_27","name":"4d00","type":"P","href":null,"layout":null,"metadata":null,"text":"Unless the compiler didn’t optimise the code.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_28":{"__typename":"Paragraph","id":"5528d839de68_28","name":"4d77","type":"H3","href":null,"layout":null,"metadata":null,"text":"Compiler optimisation","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_29":{"__typename":"Paragraph","id":"5528d839de68_29","name":"58a8","type":"P","href":null,"layout":null,"metadata":null,"text":"So, how do we know whether the compiler optimised our build? Well there’s a simple way to check. Open the following file:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_30":{"__typename":"Paragraph","id":"5528d839de68_30","name":"bdfe","type":"P","href":null,"layout":null,"metadata":null,"text":"app\u002F.externalNativeBuild\u002Fcmake\u002Fdebug\u002F\u003Carchitecture\u003E\u002Fbuild.ninja","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":0,"end":63,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_31":{"__typename":"Paragraph","id":"5528d839de68_31","name":"3e93","type":"P","href":null,"layout":null,"metadata":null,"text":"Now look for a line starting with FLAGS, here’s mine:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_32":{"__typename":"Paragraph","id":"5528d839de68_32","name":"cafa","type":"PRE","href":null,"layout":null,"metadata":null,"text":"FLAGS = -isystem \u002FUsers\u002Fdonturner\u002FLibrary\u002FAndroid\u002Fsdk\u002Fndk-bundle\u002Fsysroot\u002Fusr\u002Finclude\u002Faarch64-linux-android -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11 -O0 -fno-limit-debug-info -fPIC","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_33":{"__typename":"Paragraph","id":"5528d839de68_33","name":"cb49","type":"P","href":null,"layout":null,"metadata":null,"text":"And there you have it -O0 no optimisations.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":22,"end":25,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"STRONG","start":26,"end":42,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_34":{"__typename":"Paragraph","id":"5528d839de68_34","name":"7cf7","type":"P","href":null,"layout":null,"metadata":null,"text":"This actually makes perfect sense for a debug build because we might want to use step debugging and we don’t want the compiler to mess with the order of code execution.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_35":{"__typename":"Paragraph","id":"5528d839de68_35","name":"5dfa","type":"P","href":null,"layout":null,"metadata":null,"text":"But now we can try various different optimisation flags to see whether they affect performance. To do this I added the following line to my app\u002Fbuild.gradle file in the android.defaultConfig.externalNativeBuild.cmake block:","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":140,"end":156,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":169,"end":216,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_36":{"__typename":"Paragraph","id":"5528d839de68_36","name":"1078","type":"PRE","href":null,"layout":null,"metadata":null,"text":"cppFlags \"-Ofast\"","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":9,"end":17,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_37":{"__typename":"Paragraph","id":"5528d839de68_37","name":"519a","type":"P","href":null,"layout":null,"metadata":null,"text":"Then recompile and run. And the result was…..","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_38":{"__typename":"Paragraph","id":"5528d839de68_38","name":"332e","type":"P","href":null,"layout":null,"metadata":null,"text":"No difference :(","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_39":{"__typename":"Paragraph","id":"5528d839de68_39","name":"330a","type":"P","href":null,"layout":null,"metadata":null,"text":"I’ll be honest I was stumped at this point and ended up trying all sorts of different things: faster implementations of sin , switching to a square wave, copy-pasting code from stackoverflow, shouting at Android Studio. Nothing had any effect. Out of interest I re-checked my build.ninja file to see if there were any obvious flags I’d missed and to my amazement I found this in my build flags:","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":120,"end":123,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":276,"end":287,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_40":{"__typename":"Paragraph","id":"5528d839de68_40","name":"32d6","type":"P","href":null,"layout":null,"metadata":null,"text":"-Ofast -O0","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":0,"end":10,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_41":{"__typename":"Paragraph","id":"5528d839de68_41","name":"9b00","type":"P","href":null,"layout":null,"metadata":null,"text":"That’s right. Android Studio, CMake and the NDK work together to override your build.gradle settings and the compiler will take the last optimisation flag, meaning -Ofast is completely ignored. This is a bug, and it comes from the file $ANDROID_NDK\u002Fbuild\u002Fcmake\u002Fandroid.toolchain.cmake.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":79,"end":91,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":164,"end":170,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":236,"end":284,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"A","start":194,"end":207,"href":"https:\u002F\u002Fgithub.com\u002Fandroid-ndk\u002Fndk\u002Fissues\u002F699","anchorType":"LINK","userId":null,"linkMetadata":null},{"__typename":"Markup","type":"STRONG","start":105,"end":154,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"EM","start":132,"end":136,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_42":{"__typename":"Paragraph","id":"5528d839de68_42","name":"e9a0","type":"P","href":null,"layout":null,"metadata":null,"text":"To disable this behaviour I searched for ANDROID_COMPILER_FLAGS_DEBUG and commented out any code relating to optimisation flags.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":41,"end":69,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_43":{"__typename":"Paragraph","id":"5528d839de68_43","name":"6f1e","type":"P","href":null,"layout":null,"metadata":null,"text":"Recompile, run and…..success!! The app runs like clockwork.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_44":{"__typename":"Paragraph","id":"5528d839de68_44","name":"03fa","type":"P","href":null,"layout":null,"metadata":null,"text":"I can now listen to the sweet, sweet sound of the one hundred mega-drone synth with no horrible glitches 😃","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_45":{"__typename":"Paragraph","id":"5528d839de68_45","name":"2f64","type":"P","href":null,"layout":null,"metadata":null,"text":"UPDATE 21st May: One of my colleagues showed me a different workaround which doesn’t involve changing `android.toolchain.cmake`. All you need to do is add the following to `CMakeLists.txt`:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_46":{"__typename":"Paragraph","id":"5528d839de68_46","name":"da59","type":"PRE","href":null,"layout":null,"metadata":null,"text":"set(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} -Ofast\") ","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":0,"end":60,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_47":{"__typename":"Paragraph","id":"5528d839de68_47","name":"d886","type":"H3","href":null,"layout":null,"metadata":null,"text":"Conclusion","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_48":{"__typename":"Paragraph","id":"5528d839de68_48","name":"3735","type":"P","href":null,"layout":null,"metadata":null,"text":"If you’re experiencing audio performance problems, use systrace and the Android Studio profiler to figure out what your code is doing. And always check your build flags.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"A","start":55,"end":63,"href":"https:\u002F\u002Fdeveloper.android.com\u002Fstudio\u002Fcommand-line\u002Fsystrace","anchorType":"LINK","userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_49":{"__typename":"Paragraph","id":"5528d839de68_49","name":"7b9d","type":"P","href":null,"layout":null,"metadata":null,"text":"If you’re interested in building real-time audio apps on Android be sure to check out the Oboe library (full disclosure: I am one of the authors).","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"A","start":90,"end":102,"href":"https:\u002F\u002Fgithub.com\u002Fgoogle\u002Foboe","anchorType":"LINK","userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:5528d839de68_50":{"__typename":"Paragraph","id":"5528d839de68_50","name":"52cf","type":"P","href":null,"layout":null,"metadata":null,"text":"Got audio performance problems or questions? Would love to hear about them in the comments.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"PostViewerEdge:postId:ed10782f9c64-viewerId:lo_1a4d670e6800":{"__typename":"PostViewerEdge","shouldIndexPostForExternalSearch":true,"id":"postId:ed10782f9c64-viewerId:lo_1a4d670e6800"},"Tag:android":{"__typename":"Tag","id":"android","displayTitle":"Android","normalizedTagSlug":"android"},"Tag:audio":{"__typename":"Tag","id":"audio","displayTitle":"Audio","normalizedTagSlug":"audio"},"Tag:c":{"__typename":"Tag","id":"c","displayTitle":"C","normalizedTagSlug":"c"},"Tag:low-latency":{"__typename":"Tag","id":"low-latency","displayTitle":"Low Latency","normalizedTagSlug":"low-latency"},"Tag:cpu":{"__typename":"Tag","id":"cpu","displayTitle":"Cpu","normalizedTagSlug":"cpu"},"Post:ed10782f9c64":{"__typename":"Post","id":"ed10782f9c64","collection":null,"content({\"postMeteringOptions\":{}})":{"__typename":"PostContent","isLockedPreviewOnly":false,"bodyModel":{"__typename":"RichText","sections":[{"__typename":"Section","name":"cc56","startIndex":0,"textLayout":null,"imageLayout":null,"backgroundImage":null,"videoLayout":null,"backgroundVideo":null},{"__typename":"Section","name":"6c82","startIndex":9,"textLayout":null,"imageLayout":null,"backgroundImage":null,"videoLayout":null,"backgroundVideo":null},{"__typename":"Section","name":"a6b2","startIndex":28,"textLayout":null,"imageLayout":null,"backgroundImage":null,"videoLayout":null,"backgroundVideo":null},{"__typename":"Section","name":"6945","startIndex":47,"textLayout":null,"imageLayout":null,"backgroundImage":null,"videoLayout":null,"backgroundVideo":null}],"paragraphs":[{"__ref":"Paragraph:5528d839de68_0"},{"__ref":"Paragraph:5528d839de68_1"},{"__ref":"Paragraph:5528d839de68_2"},{"__ref":"Paragraph:5528d839de68_3"},{"__ref":"Paragraph:5528d839de68_4"},{"__ref":"Paragraph:5528d839de68_5"},{"__ref":"Paragraph:5528d839de68_6"},{"__ref":"Paragraph:5528d839de68_7"},{"__ref":"Paragraph:5528d839de68_8"},{"__ref":"Paragraph:5528d839de68_9"},{"__ref":"Paragraph:5528d839de68_10"},{"__ref":"Paragraph:5528d839de68_11"},{"__ref":"Paragraph:5528d839de68_12"},{"__ref":"Paragraph:5528d839de68_13"},{"__ref":"Paragraph:5528d839de68_14"},{"__ref":"Paragraph:5528d839de68_15"},{"__ref":"Paragraph:5528d839de68_16"},{"__ref":"Paragraph:5528d839de68_17"},{"__ref":"Paragraph:5528d839de68_18"},{"__ref":"Paragraph:5528d839de68_19"},{"__ref":"Paragraph:5528d839de68_20"},{"__ref":"Paragraph:5528d839de68_21"},{"__ref":"Paragraph:5528d839de68_22"},{"__ref":"Paragraph:5528d839de68_23"},{"__ref":"Paragraph:5528d839de68_24"},{"__ref":"Paragraph:5528d839de68_25"},{"__ref":"Paragraph:5528d839de68_26"},{"__ref":"Paragraph:5528d839de68_27"},{"__ref":"Paragraph:5528d839de68_28"},{"__ref":"Paragraph:5528d839de68_29"},{"__ref":"Paragraph:5528d839de68_30"},{"__ref":"Paragraph:5528d839de68_31"},{"__ref":"Paragraph:5528d839de68_32"},{"__ref":"Paragraph:5528d839de68_33"},{"__ref":"Paragraph:5528d839de68_34"},{"__ref":"Paragraph:5528d839de68_35"},{"__ref":"Paragraph:5528d839de68_36"},{"__ref":"Paragraph:5528d839de68_37"},{"__ref":"Paragraph:5528d839de68_38"},{"__ref":"Paragraph:5528d839de68_39"},{"__ref":"Paragraph:5528d839de68_40"},{"__ref":"Paragraph:5528d839de68_41"},{"__ref":"Paragraph:5528d839de68_42"},{"__ref":"Paragraph:5528d839de68_43"},{"__ref":"Paragraph:5528d839de68_44"},{"__ref":"Paragraph:5528d839de68_45"},{"__ref":"Paragraph:5528d839de68_46"},{"__ref":"Paragraph:5528d839de68_47"},{"__ref":"Paragraph:5528d839de68_48"},{"__ref":"Paragraph:5528d839de68_49"},{"__ref":"Paragraph:5528d839de68_50"}]},"validatedShareKey":"","shareKeyCreator":null},"creator":{"__ref":"User:7f5a2cb6598e"},"inResponseToEntityType":null,"isLocked":false,"isMarkedPaywallOnly":false,"lockedSource":"LOCKED_POST_SOURCE_NONE","mediumUrl":"https:\u002F\u002Fmedium.com\u002F@donturner\u002Fdebugging-audio-glitches-on-android-ed10782f9c64","primaryTopic":null,"topics":[{"__typename":"Topic","slug":"programming"}],"isPublished":true,"latestPublishedVersion":"5528d839de68","visibility":"PUBLIC","postResponses":{"__typename":"PostResponses","count":2},"clapCount":84,"allowResponses":true,"isLimitedState":false,"title":"Debugging audio glitches on Android","isSeries":false,"sequence":null,"uniqueSlug":"debugging-audio-glitches-on-android-ed10782f9c64","socialTitle":"","socialDek":"","canonicalUrl":"","metaDescription":"","latestPublishedAt":1570560806739,"readingTime":4.673584905660377,"previewContent":{"__typename":"PreviewContent","subtitle":"In this article I will explain how to identify the causes of audio glitches in your app using systrace and the Android Studio profiler."},"previewImage":{"__ref":"ImageMetadata:1*KnhUyWDY_ehL_lEijOI8-w.png"},"isShortform":false,"seoTitle":"","firstPublishedAt":1526660029006,"updatedAt":1570560807004,"shortformType":"SHORTFORM_TYPE_LINK","seoDescription":"","viewerEdge":{"__ref":"PostViewerEdge:postId:ed10782f9c64-viewerId:lo_1a4d670e6800"},"isSuspended":false,"license":"ALL_RIGHTS_RESERVED","tags":[{"__ref":"Tag:android"},{"__ref":"Tag:audio"},{"__ref":"Tag:c"},{"__ref":"Tag:low-latency"},{"__ref":"Tag:cpu"}],"isNewsletter":false,"statusForCollection":null,"pendingCollection":null,"detectedLanguage":"en","wordCount":1053,"layerCake":0,"responsesLocked":false}}</script><script>window.__MIDDLEWARE_STATE__={"session":{"xsrf":""},"cache":{"cacheStatus":"MISS"}}</script><script src="https://cdn-client.medium.com/lite/static/js/manifest.b2314f6d.js"></script><script src="https://cdn-client.medium.com/lite/static/js/9865.1496d74a.js"></script><script src="https://cdn-client.medium.com/lite/static/js/main.24534aeb.js"></script><script src="https://cdn-client.medium.com/lite/static/js/instrumentation.d9108df7.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/reporting.ff22a7a5.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/5049.d1ead72d.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/4810.6318add7.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/6618.db187378.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/2707.b0942613.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/9977.5b3eb23a.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/8599.1ab63137.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/5250.9f9e01d2.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/6349.b071a958.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/2648.26563adf.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/8393.826a25fb.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/7079.67349d50.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/3735.afb7e926.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/5642.a2d9f6a1.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/6546.cd03f950.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/6834.08de95de.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/7346.72622eb9.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/2420.2a5e2d95.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/839.ca7937c2.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/7975.d195c6f1.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/2106.21ff89d3.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/7394.3d049572.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/2961.00a48598.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/8204.c4082863.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/4391.59acaed3.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/PostPage.MainContent.c8a11795.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/8414.6565ad5f.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/3974.8d3e0217.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/2527.a0afad8a.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/PostResponsesContent.36c2ecf4.chunk.js"></script><script>window.main();</script><script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'8e73ca41aae54a2f',t:'MTczMjM5MjQ5NS4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body></html>

Pages: 1 2 3 4 5 6 7 8 9 10