|
Arduino A2DP
|
AAC decode support for the managed A2DP decoder framework: wraps any audio_tools::AudioDecoder that decodes AAC - e.g. audio_tools::AACDecoderHelix (arduino-libhelix), AACDecoderFDK (arduino-fdk-aac) or AACDecoderFAAD (arduino-libfaad) - and advertises the AAC SEP capability. Construct your decoder of choice, include its codec header yourself (e.g. "AudioTools/AudioCodecs/CodecAACHelix.h"), and register an A2DPDecoderAAC wrapping it via BluetoothA2DPSink::add_decoder(). More...
#include <A2DPDecoderAAC.h>
Public Member Functions | |
| A2DPDecoderAAC (audio_tools::AudioDecoder &decoder) | |
| virtual bool | begin (const esp_a2d_mcc_t &mcc) |
| void | build_capability (esp_a2d_mcc_t &mcc) override |
| Fills in the SEP capability advertised for this codec at registration. | |
| esp_a2d_mct_t | codec_type () override |
| A2DP codec type this decoder handles (e.g. ESP_A2D_MCT_SBC) | |
| virtual void | end () |
| Closes the wrapped audio_tools decoder. | |
| audio_tools::AudioInfo | get_audio_info () |
| const char * | mime () override |
| MIME type of the codec this decoder handles (e.g. "audio/sbc") | |
| void | set_he_aac (bool active) |
| size_t | write (const uint8_t *data, size_t len) override |
Protected Member Functions | |
| void | parse_audio_info (const esp_a2d_mcc_t &mcc) override |
| void | write_adts_header (size_t adts_frame_len) |
Static Protected Member Functions | |
| static uint8_t | adts_freq_idx (int rate) |
Static Protected Attributes | |
| static const int | kAdtsHeaderSize = 7 |
| static const int | kAdtsMaxFrameLen = 8191 |
AAC decode support for the managed A2DP decoder framework: wraps any audio_tools::AudioDecoder that decodes AAC - e.g. audio_tools::AACDecoderHelix (arduino-libhelix), AACDecoderFDK (arduino-fdk-aac) or AACDecoderFAAD (arduino-libfaad) - and advertises the AAC SEP capability. Construct your decoder of choice, include its codec header yourself (e.g. "AudioTools/AudioCodecs/CodecAACHelix.h"), and register an A2DPDecoderAAC wrapping it via BluetoothA2DPSink::add_decoder().
A2DP delivers raw AAC access units (ISO/IEC 13818-7 / 14496-3 raw_data_block()) with no ADTS header, but most general-purpose AAC decoders (including audio_tools::AACDecoderHelix) expect ADTS framing to find their sync word - so this class synthesizes a 7-byte ADTS header (from the sample rate/channel count negotiated via SEP configuration) and prepends it to every frame before handing it to the wrapped decoder.
By default only AAC-LC is advertised, because the synthesized ADTS header can only describe AAC-LC. Call set_he_aac(true) if the wrapped decoder detects HE-AAC (SBR/PS) implicitly from an AAC-LC labeled stream.
NOTE: registering a non-SBC stream endpoint is only supported by the underlying Bluedroid stack on ESP-IDF >= 6.1 - earlier versions document esp_a2d_sink_register_stream_endpoint() as SBC-only and are expected to reject this registration (see the ESP_A2D_SEP_REG_STATE_EVT log). This class still works on older IDF versions; it just won't get negotiated.
|
inlinestaticprotected |
maps a sample rate to its ADTS sampling_frequency_index; falls back to 44100's index if not one of the 13 well-known rates
|
inlinevirtualinherited |
Opens the wrapped audio_tools decoder for the negotiated SEP capability: calls parse_audio_info(mcc) (implemented per codec - most decoders self-detect sample rate/channels from the encoded stream and can leave sample_rate/channels at their defaults, but codecs whose wire format doesn't carry that info per-frame, e.g. AAC, need it to synthesize the framing their decoder expects - see A2DPDecoderAAC), then wires up the PCM output and audio-info-change notification and starts the decoder.
|
inlineoverridevirtual |
Fills in the SEP capability advertised for this codec at registration.
Implements A2DPDecoder.
|
inlineoverridevirtual |
A2DP codec type this decoder handles (e.g. ESP_A2D_MCT_SBC)
Implements A2DPDecoder.
|
inlineinherited |
Returns the most recently detected sample rate/channels (default AudioInfo values until the wrapped decoder has actually parsed them from the encoded stream)
|
inlineoverridevirtual |
MIME type of the codec this decoder handles (e.g. "audio/sbc")
Implements A2DPDecoder.
|
inlineoverrideprotectedvirtual |
determines sample_rate/channels/freq_idx from the negotiated AAC capability (a single bit is set per field once negotiation completes) - needed to synthesize the ADTS header, since AAC's raw frames don't carry this info themselves
Implements A2DPDecoder.
|
inline |
Also advertise HE-AAC and HE-AAC v2 (default: false). Call before BluetoothA2DPSink::start().
|
inlineoverridevirtual |
prepends a synthesized ADTS header to each frame, since A2DP AAC frames arrive as raw (headerless) access units but the wrapped decoder expects ADTS framing to find its sync word
Reimplemented from A2DPDecoder.
|
inlineprotected |
synthesizes a 7-byte ADTS header (no CRC) for an AAC-LC frame of the given total length (header + payload) at the negotiated sample rate/channel count. NOTE: the ADTS profile field is hardcoded to AAC-LC (profile=1) since it has no room to represent SBR/PS - if the source actually negotiates HE-AAC/HE-AAC v2 (advertised as negotiable in build_capability()), whether the wrapped decoder still recovers the SBR/PS extension from an LC-labeled ADTS stream depends on that decoder's implicit-signaling support and is untested here.