Audio updates

This is an update to how audio is handled:
* Moved the audio context out of each brick and into the app itself
* Bricks now use the app's audio context (if each brick uses their own, we'll run into limits)
* Added load sound and play sound methods to the ceci element base so each brick can just make two simple calls now
* Ported over the button and auidio components to this new style

Fixes #1972


this only works because of single nesting, though. The moment we have a component in a component, this will probably fail because the querySelector won't make it outside the owning component? I think, I'm not 100% sure. It might make sense to tell components what their owning app is if they're added into a `<ceci-app>` element, like a property on the ceci-base-element that can be set with `element.setOwningApp(...)` called from the ceci-app? Not sure if that should be done here or as follow-up