{"id":31456,"date":"2021-01-27T16:27:06","date_gmt":"2021-01-27T21:27:06","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=31456"},"modified":"2021-02-05T14:39:09","modified_gmt":"2021-02-05T19:39:09","slug":"its-over-between-us-avaudioengine","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2021\/01\/27\/its-over-between-us-avaudioengine\/","title":{"rendered":"It&rsquo;s Over Between Us, AVAudioEngine"},"content":{"rendered":"<p><a href=\"https:\/\/supermegaultragroovy.com\/2021\/01\/26\/it-s-over-avaudioengine\/\">Chris Liscio<\/a>:<\/p>\n<blockquote cite=\"https:\/\/supermegaultragroovy.com\/2021\/01\/26\/it-s-over-avaudioengine\/\">\n<p>Looking at the crash logs, I noticed that invoking <code>-[AVAudioEngine mainMixerNode]<\/code> would fire some kind of internal exception. The API does not return any kind of error, nor is it documented that an exception could get raised. <em>Theoretically<\/em>, failure at this stage should be impossible!<\/p>\n<p>Unfortunately for me, I had written the high-level engine management code in Swift (as was common\/prescribed at the time), so I couldn&rsquo;t even <em>attempt<\/em> to handle this exception to patch this behavior.<\/p>\n<p>[&#8230;]<\/p>\n<p>Just as last time, a 10.14.x update re-introduced the bug, but in a slightly different way.<\/p>\n<p>[&#8230;]<\/p>\n<p>Fast-forward to macOS 11, and the AirPods issue is back. In fact, it&rsquo;s <em>even worse<\/em> now because there&rsquo;s no workaround. [&#8230;] If you&rsquo;re listening to the Music app, everything&rsquo;s running at full quality. Then, you load a project in Capo and your already-playing music now sounds like garbage.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/twitter.com\/colincornaby\/status\/1354175622625415169\">Colin Cornaby<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/colincornaby\/status\/1354175622625415169\"><p>AVAudioEngine has always struck me as a API with good intentions (doing what CoreAudio does in Obj-C\/Swift) with questionable execution and missing features.<\/p>\n<p>It&rsquo;s just so strange that Apple would take their extremely impressive and feature rich audio toolbox and replace it with... well... this.<\/p><\/blockquote>\n\n<p id=\"its-over-between-us-avaudioengine-update-2021-01-28\">Update (2021-01-28): <a href=\"https:\/\/twitter.com\/simX\/status\/1354543644573798400\">Simone Manganelli<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/simX\/status\/1354543644573798400\">\n<p>This has happened over and over and over with APIs throughout macOS in the past decade.  PDFKit is a good example.<\/p>\n<p>This is just another symptom of Apple&rsquo;s annual software update cycle and a lack of commitment to fixing anything.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/twitter.com\/tolmasky\/status\/1354546330010492931\">Francisco Tolmasky<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/tolmasky\/status\/1354546330010492931\">\n<p>The Swift\/ObjC relationship is like taking the traditional design of a game engine written in C++ with Lua scripting hooks and flipping it on its head, such that you instead wrote the game engine in JavaScript and provided the scripting interface in Haskell.<\/p>\n<\/blockquote>\n\n<p>You can <a href=\"https:\/\/twitter.com\/tolmasky\/status\/1354867765006372865\">use an Objective-C wrapper<\/a> to catch exceptions, but <a href=\"https:\/\/twitter.com\/mjtsai\/status\/1354876498759577613\">be careful<\/a> trying to make a <a href=\"https:\/\/github.com\/williamFalcon\/SwiftTryCatch\">generic wrapper solution<\/a> because it&rsquo;s not safe to throw exceptions through Swift stack frames.<\/p>\n\n<p><a href=\"https:\/\/twitter.com\/liscio\/status\/1354809110189928452\">Chris Liscio<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/liscio\/status\/1354809110189928452\"><p>Great news: I have found a resolution to the (latest of the) AVAudioEngine issues I&rsquo;ve been seeing with AirPods in Big Sur.<\/p><p>[&#8230;]<\/p><p>I am still unable to work around the problem in my code and stop the error for my users. These are in-the-field configuration issues that I am powerless to resolve with a simple software update.<\/p><p>AVAudioEngine is still too limited in its feature set for me to consider (or advise) adopting it for a &ldquo;pro audio&rdquo; stack like that which powers something like GarageBand or Logic.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/supermegaultragroovy.com\/2021\/01\/26\/it-s-over-avaudioengine\/\">Chris Liscio<\/a>:<\/p>\n<blockquote cite=\"https:\/\/supermegaultragroovy.com\/2021\/01\/26\/it-s-over-avaudioengine\/\">\n<p>I put together a sample project called <a href=\"https:\/\/github.com\/liscio\/CrappifyAudio\">CrappifyAudio<\/a> that demonstrates the problem in a minimal way.<\/p>\n<\/blockquote>\n\n<p id=\"its-over-between-us-avaudioengine-update-2021-02-05\">Update (2021-02-05): <a href=\"https:\/\/supermegaultragroovy.com\/2021\/01\/28\/more-on-avaudioengine-airpods\/\">Chris Liscio<\/a> (<a href=\"https:\/\/twitter.com\/liscio\/status\/1354900636924522496\">tweet<\/a>):<\/p>\n<blockquote cite=\"https:\/\/supermegaultragroovy.com\/2021\/01\/28\/more-on-avaudioengine-airpods\/\"><p><code>AVAudioEngine<\/code> doesn&rsquo;t give me an opportunity to state my &ldquo;intentions&rdquo; for using the engine explicitly on macOS. There is no API that lets me specify that I am building an output-only engine, and don&rsquo;t require its input abilities.<\/p>\n\n<p>The <a href=\"https:\/\/stackoverflow.com\/questions\/44651389\/avaudioengine-uses-wrong-format-when-bluetooth-headset-plugged-in\/46558986\">previous workaround<\/a> was to pull the <code>AUAudioUnit<\/code> instance out of the <code>outputNode<\/code> and set its <code>deviceID<\/code> to override the default device selection behavior. Unfortunately, this workaround no longer works because the aggregate device now appears to get created (activated?) when I call <code>outputNode<\/code>.<\/p>\n<p>[&#8230;]<\/p>\n<p>This is the crux of the problem I&rsquo;m dealing with here, and why I don&rsquo;t want anything to do with this API anymore. It&rsquo;s simply <em>too magical<\/em> for my tastes.<\/p>\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Chris Liscio: Looking at the crash logs, I noticed that invoking -[AVAudioEngine mainMixerNode] would fire some kind of internal exception. The API does not return any kind of error, nor is it documented that an exception could get raised. Theoretically, failure at this stage should be impossible! Unfortunately for me, I had written the high-level [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2021-01-27T21:27:11Z","apple_news_api_id":"d19af589-89f7-4470-b961-53e37a1cc847","apple_news_api_modified_at":"2021-02-05T19:39:13Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAg==","apple_news_api_share_url":"https:\/\/apple.news\/A0Zr1iYn3RHC5YVPjehzIRw","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[95,131,1767,587,30,32,1529,1609,1891,71,901],"class_list":["post-31456","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-audio","tag-bug","tag-capo","tag-core-audio","tag-mac","tag-macapp","tag-macos-10-13","tag-macos-10-14","tag-macos-11-0","tag-programming","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/31456","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=31456"}],"version-history":[{"count":4,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/31456\/revisions"}],"predecessor-version":[{"id":31559,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/31456\/revisions\/31559"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=31456"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=31456"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=31456"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}