~aleteoryx/muditaos

muditaos/module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.hpp -rw-r--r-- 3.9 KiB
a405cad6Aleteoryx trim readme 6 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/blob/master/LICENSE.md

#pragma once

#include <Audio/Endpoint.hpp>
#include <Audio/AudioDevice.hpp>
#include <Audio/AudioFormat.hpp>
#include <Audio/Stream.hpp>
#include <interface/profiles/A2DP/MediaContext.hpp>
#include <interface/profiles/AudioProfile.hpp>

extern "C"
{
#include "classic/btstack_cvsd_plc.h"
}

namespace bluetooth
{
    class BluetoothAudioDevice : public audio::AudioDevice
    {
      public:
        explicit BluetoothAudioDevice(AudioProfile audioProfile);
        virtual ~BluetoothAudioDevice();

        virtual auto getProfileType() const -> AudioProfile;

        auto setInputGain(float gain) -> audio::AudioDevice::RetCode override;

        // Endpoint control methods
        void enableInput() override;
        void enableOutput() override;
        void disableInput() override;
        void disableOutput() override;

      protected:
        [[nodiscard]] auto isInputEnabled() const -> bool;
        [[nodiscard]] auto isOutputEnabled() const -> bool;
        auto fillSbcAudioBuffer() -> int;
        auto scaleVolume(audio::Stream::Span &dataSpan) const -> void;

        float outputVolume;

      private:
        bool outputEnabled   = false;
        bool inputEnabled    = false;
        AudioProfile profile = AudioProfile::None;
    };

    class A2DPAudioDevice : public BluetoothAudioDevice
    {
      public:
        explicit A2DPAudioDevice(const float volume) : BluetoothAudioDevice(AudioProfile::A2DP)
        {
            outputVolume = volume;
        }

        auto setOutputVolume(float vol) -> audio::AudioDevice::RetCode override;
        void onDataSend() override;
        void onDataReceive() override;
        auto getSupportedFormats() -> std::vector<audio::AudioFormat> override;
        [[nodiscard]] auto getTraits() const -> Traits override;
        auto getSourceFormat() -> ::audio::AudioFormat override;

        audio::AudioDevice::RetCode Start() override;
        audio::AudioDevice::RetCode Stop() override;
        audio::AudioDevice::RetCode Resume() override;
        audio::AudioDevice::RetCode Pause() override;

      private:
        [[nodiscard]] audio::AudioDevice::RetCode waitUntilStreamPaused() const;
    };

    class CVSDAudioDevice : public BluetoothAudioDevice
    {
      public:
        explicit CVSDAudioDevice(const float volume, const AudioProfile &profile) : BluetoothAudioDevice(profile)
        {
            outputVolume = volume;
            btstack_cvsd_plc_init(&cvsdPlcState);
        }

        auto setOutputVolume(float vol) -> audio::AudioDevice::RetCode override;
        void onDataSend() override;
        void onDataSend(std::uint16_t scoHandle);
        void onDataReceive() override;
        auto getSupportedFormats() -> std::vector<audio::AudioFormat> override;
        [[nodiscard]] auto getTraits() const -> Traits override;
        auto getSourceFormat() -> ::audio::AudioFormat override;
        void enableInput() override;
        void setAclHandle(hci_con_handle_t handle);

        void receiveCVSD(audio::AbstractStream::Span receivedData);

      private:
        static constexpr std::size_t scratchBufferSize = 128;

        static constexpr auto packetHandleOffset = 0;
        static constexpr auto packetStatusOffset = 1;
        static constexpr auto packetLengthOffset = 2;
        static constexpr auto packetDataOffset   = 3;

        static constexpr auto supportedBitWidth = 16U;
        static constexpr auto supportedChannels = 1;

        static constexpr auto allGoodMask = 0x30;

        auto decodeCVSD(audio::AbstractStream::Span dataToDecode) -> audio::AbstractStream::Span;

        std::unique_ptr<std::uint8_t[]> rxLeftovers;
        std::unique_ptr<std::int16_t[]> decoderBuffer;
        std::size_t leftoversSize = 0;
        btstack_cvsd_plc_state_t cvsdPlcState;
        hci_con_handle_t aclHandle;
    };
} // namespace bluetooth