Rule #1 of using boot instead of begin is to make sure you know what begin normally does so you know which parts you need to add manually. E.g. no arduboy.flashlight() means no ‘flashlight’ mode.
It seems kind of silly considering how far abstracted beep is out that it can’t properly construct itself. I’d agree with you if I was asking about doing arduboy.beep() or something but I’ve already defined and init a class already.
I’m not sure I’d call BeepPin1 and BeepPin2 particularly abstract, they’re just collections of static functions.
If they were both responsible for implementing what Arduboy2Audio::begin does then if you tried to use both BeepPin1::begin() and BeepPin2::begin() you’d end up calling the audio initialisation code twice.
By having it separate:
You can be sure to only initialise general audio only once
Audio libraries don’t have to concern themselves with whether audio is enabled or disabled, or what the mechanism for determining that is
I.e. they don’t need to know about EEPROM, let alone which flag is responsible for determining if audio should be enabled - see “Separation of Concerns”
Either way, it’s not an issue when using arduboy.begin(), you only need to know about audio.begin() if you’re not using arduboy.begin().